summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files3
-rw-r--r--sys/conf/files.sparc641
-rw-r--r--sys/conf/options2
-rw-r--r--sys/contrib/ipfilter/netinet/ip_nat.c4
-rw-r--r--sys/dev/hyperv/vmbus/hv_channel_mgmt.c2
-rw-r--r--sys/dev/if_ndis/if_ndis_pci.c3
-rw-r--r--sys/dev/isp/isp.c69
-rw-r--r--sys/dev/isp/isp_freebsd.c95
-rw-r--r--sys/dev/isp/isp_freebsd.h15
-rw-r--r--sys/dev/isp/isp_library.c13
-rw-r--r--sys/dev/isp/isp_pci.c294
-rw-r--r--sys/dev/isp/isp_sbus.c16
-rw-r--r--sys/dev/isp/ispmbox.h17
-rw-r--r--sys/dev/isp/ispvar.h12
-rw-r--r--sys/dev/md/md.c40
-rw-r--r--sys/dev/mii/rgephy.c2
-rw-r--r--sys/dev/mii/rlphy.c2
-rw-r--r--sys/dev/mii/rlswitch.c2
-rw-r--r--sys/dev/mpt/mpt.c11
-rw-r--r--sys/dev/mpt/mpt.h12
-rw-r--r--sys/dev/qlxgbe/ql_hw.c3
-rw-r--r--sys/dev/qlxgbe/ql_os.c2
-rw-r--r--sys/dev/qlxgbe/ql_ver.h2
-rw-r--r--sys/dev/re/if_re.c60
-rw-r--r--sys/dev/rl/if_rl.c (renamed from sys/pci/if_rl.c)2
-rw-r--r--sys/dev/rl/if_rlreg.h (renamed from sys/pci/if_rlreg.h)4
-rw-r--r--sys/dev/usb/net/if_urndis.c178
-rw-r--r--sys/dev/vt/colors/vt_termcolors.c11
-rw-r--r--sys/modules/hyperv/netvsc/Makefile2
-rw-r--r--sys/modules/rl/Makefile2
-rw-r--r--sys/netgraph/ng_base.c2
-rw-r--r--sys/netinet/tcp.h5
-rw-r--r--sys/netinet/tcp_fastopen.c442
-rw-r--r--sys/netinet/tcp_fastopen.h47
-rw-r--r--sys/netinet/tcp_input.c92
-rw-r--r--sys/netinet/tcp_output.c71
-rw-r--r--sys/netinet/tcp_subr.c21
-rw-r--r--sys/netinet/tcp_syncache.c137
-rw-r--r--sys/netinet/tcp_syncache.h6
-rw-r--r--sys/netinet/tcp_timer.c3
-rw-r--r--sys/netinet/tcp_usrreq.c57
-rw-r--r--sys/netinet/tcp_var.h16
-rw-r--r--sys/sparc64/ebus/ebus.c35
-rw-r--r--sys/sparc64/include/md_var.h2
-rw-r--r--sys/sparc64/include/smp.h20
-rw-r--r--sys/sparc64/pci/fire.c335
-rw-r--r--sys/sparc64/pci/firereg.h1
-rw-r--r--sys/sparc64/pci/firevar.h20
-rw-r--r--sys/sparc64/pci/ofw_pci.c412
-rw-r--r--sys/sparc64/pci/ofw_pci.h43
-rw-r--r--sys/sparc64/pci/psycho.c340
-rw-r--r--sys/sparc64/pci/psychoreg.h6
-rw-r--r--sys/sparc64/pci/psychovar.h47
-rw-r--r--sys/sparc64/pci/schizo.c349
-rw-r--r--sys/sparc64/pci/schizoreg.h5
-rw-r--r--sys/sparc64/pci/schizovar.h37
-rw-r--r--sys/sparc64/sparc64/machdep.c10
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c52
-rw-r--r--sys/ufs/ffs/ffs_softdep.c64
-rw-r--r--sys/x86/x86/busdma_bounce.c73
60 files changed, 2169 insertions, 1462 deletions
diff --git a/sys/conf/files b/sys/conf/files
index f6456a7..ec77e97 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2258,6 +2258,7 @@ dev/random/hash.c optional random
dev/random/rwfile.c optional random
dev/rc/rc.c optional rc
dev/re/if_re.c optional re
+dev/rl/if_rl.c optional rl pci
dev/rndtest/rndtest.c optional rndtest
dev/rp/rp.c optional rp
dev/rp/rp_isa.c optional rp isa
@@ -3552,6 +3553,7 @@ netinet/sctp_usrreq.c optional inet sctp | inet6 sctp
netinet/sctputil.c optional inet sctp | inet6 sctp
netinet/siftr.c optional inet siftr alq | inet6 siftr alq
netinet/tcp_debug.c optional tcpdebug
+netinet/tcp_fastopen.c optional inet tcp_rfc7413 | inet6 tcp_rfc7413
netinet/tcp_hostcache.c optional inet | inet6
netinet/tcp_input.c optional inet | inet6
netinet/tcp_lro.c optional inet | inet6
@@ -4046,7 +4048,6 @@ opencrypto/xform.c optional crypto
pci/alpm.c optional alpm pci
pci/amdpm.c optional amdpm pci | nfpm pci
pci/amdsmb.c optional amdsmb pci
-pci/if_rl.c optional rl pci
pci/intpm.c optional intpm pci
pci/ncr.c optional ncr pci \
compile-with "${NORMAL_C} -Wno-unused"
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 5775d9b..9fbc226 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -81,6 +81,7 @@ sparc64/isa/isa_dma.c optional isa
sparc64/isa/ofw_isa.c optional ebus | isa
sparc64/pci/apb.c optional pci
sparc64/pci/fire.c optional pci
+sparc64/pci/ofw_pci.c optional pci
sparc64/pci/ofw_pcib.c optional pci
sparc64/pci/ofw_pcib_subr.c optional pci
sparc64/pci/ofw_pcibus.c optional pci
diff --git a/sys/conf/options b/sys/conf/options
index 96253be..d8dffe9 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -444,6 +444,8 @@ SLIP_IFF_OPTS opt_slip.h
TCPDEBUG
SIFTR
TCP_OFFLOAD opt_inet.h # Enable code to dispatch TCP offloading
+TCP_RFC7413 opt_inet.h
+TCP_RFC7413_MAX_KEYS opt_inet.h
TCP_SIGNATURE opt_inet.h
VLAN_ARRAY opt_vlan.h
XBONEHACK
diff --git a/sys/contrib/ipfilter/netinet/ip_nat.c b/sys/contrib/ipfilter/netinet/ip_nat.c
index 6c93810..6ca938a 100644
--- a/sys/contrib/ipfilter/netinet/ip_nat.c
+++ b/sys/contrib/ipfilter/netinet/ip_nat.c
@@ -5123,7 +5123,7 @@ ipf_nat_out(fin, nat, natadd, nflags)
ipf_fix_outcksum(0, &fin->fin_ip->ip_sum, msumd, 0);
}
#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
- defined(linux) || defined(BRIDGE_IPF)
+ defined(linux) || defined(BRIDGE_IPF) || defined(__FreeBSD__)
else {
/*
* Strictly speaking, this isn't necessary on BSD
@@ -5235,7 +5235,7 @@ ipf_nat_out(fin, nat, natadd, nflags)
uh->uh_ulen += fin->fin_plen;
uh->uh_ulen = htons(uh->uh_ulen);
#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
- defined(linux) || defined(BRIDGE_IPF)
+ defined(linux) || defined(BRIDGE_IPF) || defined(__FreeBSD)
ipf_fix_outcksum(0, &ip->ip_sum, sumd, 0);
#endif
diff --git a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
index d13ece5..d17d696 100644
--- a/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
+++ b/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
@@ -53,8 +53,6 @@ static void vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr);
static void vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr);
static void vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr);
static void vmbus_channel_process_offer(void *context);
-struct hv_vmbus_channel*
- vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
/**
* Channel message dispatch table
diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c
index 8ed6c5a..326e3de 100644
--- a/sys/dev/if_ndis/if_ndis_pci.c
+++ b/sys/dev/if_ndis/if_ndis_pci.c
@@ -295,8 +295,7 @@ ndis_attach_pci(dev)
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
- NDIS_NSEG_NEW, /* nsegments */
+ DFLTPHYS, NDIS_NSEG_NEW,/* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
NULL, NULL, /* lockfunc, lockarg */
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 18c41e9..d394011 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -277,6 +277,9 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
case ISP_HA_FC_2500:
btype = "2532";
break;
+ case ISP_HA_FC_2600:
+ btype = "2031";
+ break;
default:
break;
}
@@ -655,8 +658,10 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
ISP_WRITE(isp, isp->isp_respinrp, 0);
ISP_WRITE(isp, isp->isp_respoutrp, 0);
if (IS_24XX(isp)) {
- ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
- ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
+ if (!IS_26XX(isp)) {
+ ISP_WRITE(isp, BIU2400_PRI_REQINP, 0);
+ ISP_WRITE(isp, BIU2400_PRI_REQOUTP, 0);
+ }
ISP_WRITE(isp, BIU2400_ATIO_RSPINP, 0);
ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0);
}
@@ -761,6 +766,7 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
code_org = ISP_CODE_ORG;
}
+ isp->isp_loaded_fw = 0;
if (dodnld && IS_24XX(isp)) {
const uint32_t *ptr = isp->isp_mdvec->dv_ispfw;
int wordload;
@@ -956,8 +962,17 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
ISP_RESET0(isp);
return;
}
+ } else if (IS_26XX(isp)) {
+ MBSINIT(&mbs, MBOX_LOAD_FLASH_FIRMWARE, MBLOGALL, 5000000);
+ mbs.ibitm = 0x01;
+ mbs.obitm = 0x07;
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ isp_prt(isp, ISP_LOGERR, "Flash F/W load failed");
+ ISP_RESET0(isp);
+ return;
+ }
} else {
- isp->isp_loaded_fw = 0;
isp_prt(isp, ISP_LOGDEBUG2, "skipping f/w download");
}
@@ -966,7 +981,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
*/
if (isp->isp_loaded_fw) {
MBSINIT(&mbs, MBOX_VERIFY_CHECKSUM, MBLOGNONE, 0);
- mbs.param[0] = MBOX_VERIFY_CHECKSUM;
if (IS_24XX(isp)) {
mbs.param[1] = code_org >> 16;
mbs.param[2] = code_org;
@@ -998,9 +1012,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
} else {
mbs.param[3] = 1;
}
- if (IS_25XX(isp)) {
- mbs.ibits |= 0x10;
- }
} else if (IS_2322(isp)) {
mbs.param[1] = code_org;
if (isp->isp_loaded_fw) {
@@ -1861,16 +1872,16 @@ isp_fibre_init(ispsoftc_t *isp)
icbp->icb_idelaytimer = 10;
}
icbp->icb_zfwoptions = fcp->isp_zfwoptions;
- if (isp->isp_confopts & ISP_CFG_ONEGB) {
+ if (isp->isp_confopts & ISP_CFG_1GB) {
icbp->icb_zfwoptions &= ~ICBZOPT_RATE_MASK;
- icbp->icb_zfwoptions |= ICBZOPT_RATE_ONEGB;
- } else if (isp->isp_confopts & ISP_CFG_TWOGB) {
+ icbp->icb_zfwoptions |= ICBZOPT_RATE_1GB;
+ } else if (isp->isp_confopts & ISP_CFG_2GB) {
icbp->icb_zfwoptions &= ~ICBZOPT_RATE_MASK;
- icbp->icb_zfwoptions |= ICBZOPT_RATE_TWOGB;
+ icbp->icb_zfwoptions |= ICBZOPT_RATE_2GB;
} else {
switch (icbp->icb_zfwoptions & ICBZOPT_RATE_MASK) {
- case ICBZOPT_RATE_ONEGB:
- case ICBZOPT_RATE_TWOGB:
+ case ICBZOPT_RATE_1GB:
+ case ICBZOPT_RATE_2GB:
case ICBZOPT_RATE_AUTO:
break;
default:
@@ -2122,18 +2133,26 @@ isp_fibre_init_2400(ispsoftc_t *isp)
break;
}
+ if (IS_26XX(isp)) {
+ /* We don't support MSI-X yet, so set this unconditionally. */
+ icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHR;
+ icbp->icb_fwoptions2 |= ICB2400_OPT2_ENA_IHA;
+ }
+
if ((icbp->icb_fwoptions3 & ICB2400_OPT3_RSPSZ_MASK) == 0) {
icbp->icb_fwoptions3 |= ICB2400_OPT3_RSPSZ_24;
}
icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_AUTO;
- if (isp->isp_confopts & ISP_CFG_ONEGB) {
- icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_ONEGB;
- } else if (isp->isp_confopts & ISP_CFG_TWOGB) {
- icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_TWOGB;
- } else if (isp->isp_confopts & ISP_CFG_FOURGB) {
- icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_FOURGB;
- } else if (IS_25XX(isp) && (isp->isp_confopts & ISP_CFG_EIGHTGB)) {
- icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_EIGHTGB;
+ if (isp->isp_confopts & ISP_CFG_1GB) {
+ icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_1GB;
+ } else if (isp->isp_confopts & ISP_CFG_2GB) {
+ icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_2GB;
+ } else if (isp->isp_confopts & ISP_CFG_4GB) {
+ icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_4GB;
+ } else if (isp->isp_confopts & ISP_CFG_8GB) {
+ icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_8GB;
+ } else if (isp->isp_confopts & ISP_CFG_16GB) {
+ icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_16GB;
} else {
icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_AUTO;
}
@@ -6828,7 +6847,7 @@ static const char *scsi_mbcmd_names[] = {
static const uint32_t mbpfc[] = {
ISP_FC_OPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */
ISP_FC_OPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */
- ISP_FC_OPMAP(0x0f, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */
+ ISP_FC_OPMAP_HALF(0x07, 0xff, 0x00, 0x03), /* 0x02: MBOX_EXEC_FIRMWARE */
ISP_FC_OPMAP(0xdf, 0x01), /* 0x03: MBOX_DUMP_RAM */
ISP_FC_OPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */
ISP_FC_OPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */
@@ -7602,6 +7621,8 @@ isp_setdfltfcparm(ispsoftc_t *isp, int chan)
fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp, chan);
fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp, chan);
fcp->isp_fwoptions = 0;
+ fcp->isp_xfwoptions = 0;
+ fcp->isp_zfwoptions = 0;
fcp->isp_lasthdl = NIL_HANDLE;
if (IS_24XX(isp)) {
@@ -7899,7 +7920,9 @@ isp_rd_2400_nvram(ispsoftc_t *isp, uint32_t addr, uint32_t *rp)
uint32_t base = 0x7ffe0000;
uint32_t tmp = 0;
- if (IS_25XX(isp)) {
+ if (IS_26XX(isp)) {
+ base = 0x7fe7c000; /* XXX: Observation, may be wrong. */
+ } else if (IS_25XX(isp)) {
base = 0x7ff00000 | 0x48000;
}
ISP_WRITE(isp, BIU2400_FLASH_ADDR, base | addr);
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 73741eb..c533d69 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -4550,91 +4550,52 @@ isp_uninit(ispsoftc_t *isp)
ISP_DISABLE_INTS(isp);
}
-/*
- * When we want to get the 'default' WWNs (when lacking NVRAM), we pick them
- * up from our platform default (defww{p|n}n) and morph them based upon
- * channel.
- *
- * When we want to get the 'active' WWNs, we get NVRAM WWNs and then morph them
- * based upon channel.
- */
-
uint64_t
isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn)
{
uint64_t seed;
struct isp_fc *fc = ISP_FC_PC(isp, chan);
- /*
- * If we're asking for a active WWN, the default overrides get
- * returned, otherwise the NVRAM value is picked.
- *
- * If we're asking for a default WWN, we just pick the default override.
- */
+ /* First try to use explicitly configured WWNs. */
+ seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
+ if (seed)
+ return (seed);
+
+ /* Otherwise try to use WWNs from NVRAM. */
if (isactive) {
- seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
- if (seed) {
- return (seed);
- }
- seed = iswwnn ? FCPARAM(isp, chan)->isp_wwnn_nvram : FCPARAM(isp, chan)->isp_wwpn_nvram;
- if (seed) {
+ seed = iswwnn ? FCPARAM(isp, chan)->isp_wwnn_nvram :
+ FCPARAM(isp, chan)->isp_wwpn_nvram;
+ if (seed)
return (seed);
- }
- return (0x400000007F000009ull);
}
- seed = iswwnn ? fc->def_wwnn : fc->def_wwpn;
-
- /*
- * For channel zero just return what we have. For either ACTIVE or
- * DEFAULT cases, we depend on default override of NVRAM values for
- * channel zero.
- */
- if (chan == 0) {
- return (seed);
+ /* If still no WWNs, try to steal them from the first channel. */
+ if (chan > 0) {
+ seed = iswwnn ? ISP_FC_PC(isp, 0)->def_wwnn :
+ ISP_FC_PC(isp, 0)->def_wwpn;
+ if (seed == 0) {
+ seed = iswwnn ? FCPARAM(isp, 0)->isp_wwnn_nvram :
+ FCPARAM(isp, 0)->isp_wwpn_nvram;
+ }
}
- /*
- * For other channels, we are doing one of three things:
- *
- * 1. If what we have now is non-zero, return it. Otherwise we morph
- * values from channel 0. 2. If we're here for a WWPN we synthesize
- * it if Channel 0's wwpn has a type 2 NAA. 3. If we're here for a
- * WWNN we synthesize it if Channel 0's wwnn has a type 2 NAA.
- */
-
- if (seed) {
- return (seed);
+ /* If still nothing -- improvise. */
+ if (seed == 0) {
+ seed = 0x400000007F000000ull + device_get_unit(isp->isp_dev);
+ if (!iswwnn)
+ seed ^= 0x0100000000000000ULL;
}
- seed = iswwnn ? ISP_FC_PC(isp, 0)->def_wwnn : ISP_FC_PC(isp, 0)->def_wwpn;
- if (seed == 0)
- seed = iswwnn ? FCPARAM(isp, 0)->isp_wwnn_nvram : FCPARAM(isp, 0)->isp_wwpn_nvram;
- if (((seed >> 60) & 0xf) == 2) {
+ /* For additional channels we have to improvise even more. */
+ if (!iswwnn && chan > 0) {
/*
- * The type 2 NAA fields for QLogic cards appear be laid out
- * thusly:
- *
- * bits 63..60 NAA == 2 bits 59..57 unused/zero bit 56
- * port (1) or node (0) WWN distinguishor bit 48
- * physical port on dual-port chips (23XX/24XX)
- *
- * This is somewhat nutty, particularly since bit 48 is
- * irrelevant as they assign separate serial numbers to
- * different physical ports anyway.
- *
* We'll stick our channel number plus one first into bits
* 57..59 and thence into bits 52..55 which allows for 8 bits
- * of channel which is comfortably more than our maximum
- * (126) now.
+ * of channel which is enough for our maximum of 255 channels.
*/
- seed &= ~0x0FF0000000000000ULL;
- if (iswwnn == 0) {
- seed |= ((uint64_t) (chan + 1) & 0xf) << 56;
- seed |= ((uint64_t) ((chan + 1) >> 4) & 0xf) << 52;
- }
- } else {
- seed = 0;
+ seed ^= 0x0100000000000000ULL;
+ seed ^= ((uint64_t) (chan + 1) & 0xf) << 56;
+ seed ^= ((uint64_t) ((chan + 1) >> 4) & 0xf) << 52;
}
return (seed);
}
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index ff9a5a3..9a9093a 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -38,6 +38,7 @@
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
+#include <sys/rman.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
@@ -286,9 +287,9 @@ struct isposinfo {
/*
* DMA related sdtuff
*/
- bus_space_tag_t bus_tag;
+ struct resource * regs;
+ struct resource * regs2;
bus_dma_tag_t dmat;
- bus_space_handle_t bus_handle;
bus_dma_tag_t cdmat;
bus_dmamap_t cdmap;
@@ -361,8 +362,8 @@ struct isposinfo {
#define FCP_NEXT_CRN isp_fcp_next_crn
#define isp_lock isp_osinfo.lock
-#define isp_bus_tag isp_osinfo.bus_tag
-#define isp_bus_handle isp_osinfo.bus_handle
+#define isp_regs isp_osinfo.regs
+#define isp_regs2 isp_osinfo.regs2
/*
* Locking macros...
@@ -430,8 +431,7 @@ case SYNC_RESULT: \
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \
break; \
case SYNC_REG: \
- bus_space_barrier(isp->isp_osinfo.bus_tag, \
- isp->isp_osinfo.bus_handle, offset, size, \
+ bus_barrier(isp->isp_osinfo.regs, offset, size, \
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \
break; \
default: \
@@ -463,8 +463,7 @@ case SYNC_RESULT: \
isp->isp_osinfo.cdmap, BUS_DMASYNC_POSTWRITE); \
break; \
case SYNC_REG: \
- bus_space_barrier(isp->isp_osinfo.bus_tag, \
- isp->isp_osinfo.bus_handle, offset, size, \
+ bus_barrier(isp->isp_osinfo.regs, offset, size, \
BUS_SPACE_BARRIER_WRITE); \
break; \
default: \
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 9e8f3ab..ec99244 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -1402,7 +1402,9 @@ isp_put_icb_2400(ispsoftc_t *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst)
for (i = 0; i < 4; i++) {
ISP_IOXPUT_16(isp, src->icb_priaddr[i], &dst->icb_priaddr[i]);
}
- for (i = 0; i < 4; i++) {
+ ISP_IOXPUT_16(isp, src->icb_msixresp, &dst->icb_msixresp);
+ ISP_IOXPUT_16(isp, src->icb_msixatio, &dst->icb_msixatio);
+ for (i = 0; i < 2; i++) {
ISP_IOXPUT_16(isp, src->icb_reserved1[i], &dst->icb_reserved1[i]);
}
ISP_IOXPUT_16(isp, src->icb_atio_in, &dst->icb_atio_in);
@@ -1415,9 +1417,14 @@ isp_put_icb_2400(ispsoftc_t *isp, isp_icb_2400_t *src, isp_icb_2400_t *dst)
ISP_IOXPUT_32(isp, src->icb_fwoptions1, &dst->icb_fwoptions1);
ISP_IOXPUT_32(isp, src->icb_fwoptions2, &dst->icb_fwoptions2);
ISP_IOXPUT_32(isp, src->icb_fwoptions3, &dst->icb_fwoptions3);
- for (i = 0; i < 12; i++) {
+ ISP_IOXPUT_16(isp, src->icb_qos, &dst->icb_qos);
+ for (i = 0; i < 3; i++)
ISP_IOXPUT_16(isp, src->icb_reserved2[i], &dst->icb_reserved2[i]);
- }
+ for (i = 0; i < 3; i++)
+ ISP_IOXPUT_16(isp, src->icb_enodemac[i], &dst->icb_enodemac[i]);
+ ISP_IOXPUT_16(isp, src->icb_disctime, &dst->icb_disctime);
+ for (i = 0; i < 4; i++)
+ ISP_IOXPUT_16(isp, src->icb_reserved3[i], &dst->icb_reserved3[i]);
}
void
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 55cb034..e5ea359 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -59,6 +59,8 @@ static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t);
static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int);
static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t);
+static uint32_t isp_pci_rd_reg_2600(ispsoftc_t *, int);
+static void isp_pci_wr_reg_2600(ispsoftc_t *, int, uint32_t);
static int isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
static int isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
static int isp_pci_rd_isr_2400(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
@@ -172,6 +174,18 @@ static struct ispmdvec mdvec_2500 = {
NULL
};
+static struct ispmdvec mdvec_2600 = {
+ isp_pci_rd_isr_2400,
+ isp_pci_rd_reg_2600,
+ isp_pci_wr_reg_2600,
+ isp_pci_mbxdma,
+ isp_pci_dmasetup,
+ isp_common_dmateardown,
+ isp_pci_reset0,
+ isp_pci_reset1,
+ NULL
+};
+
#ifndef PCIM_CMD_INVEN
#define PCIM_CMD_INVEN 0x10
#endif
@@ -276,6 +290,14 @@ static struct ispmdvec mdvec_2500 = {
#define PCI_PRODUCT_QLOGIC_ISP5432 0x5432
#endif
+#ifndef PCI_PRODUCT_QLOGIC_ISP2031
+#define PCI_PRODUCT_QLOGIC_ISP2031 0x2031
+#endif
+
+#ifndef PCI_PRODUCT_QLOGIC_ISP8031
+#define PCI_PRODUCT_QLOGIC_ISP8031 0x8031
+#endif
+
#define PCI_QLOGIC_ISP5432 \
((PCI_PRODUCT_QLOGIC_ISP5432 << 16) | PCI_VENDOR_QLOGIC)
@@ -327,14 +349,17 @@ static struct ispmdvec mdvec_2500 = {
#define PCI_QLOGIC_ISP6322 \
((PCI_PRODUCT_QLOGIC_ISP6322 << 16) | PCI_VENDOR_QLOGIC)
+#define PCI_QLOGIC_ISP2031 \
+ ((PCI_PRODUCT_QLOGIC_ISP2031 << 16) | PCI_VENDOR_QLOGIC)
+
+#define PCI_QLOGIC_ISP8031 \
+ ((PCI_PRODUCT_QLOGIC_ISP8031 << 16) | PCI_VENDOR_QLOGIC)
+
/*
* Odd case for some AMI raid cards... We need to *not* attach to this.
*/
#define AMI_RAID_SUBVENDOR_ID 0x101e
-#define IO_MAP_REG 0x10
-#define MEM_MAP_REG 0x14
-
#define PCI_DFLT_LTNCY 0x40
#define PCI_DFLT_LNSZ 0x10
@@ -348,10 +373,16 @@ struct isp_pcisoftc {
ispsoftc_t pci_isp;
device_t pci_dev;
struct resource * regs;
+ struct resource * regs1;
+ struct resource * regs2;
void * irq;
int iqd;
int rtp;
int rgd;
+ int rtp1;
+ int rgd1;
+ int rtp2;
+ int rgd2;
void * ih;
int16_t pci_poff[_NREG_BLKS];
bus_dma_tag_t dmat;
@@ -434,6 +465,12 @@ isp_pci_probe(device_t dev)
case PCI_QLOGIC_ISP6322:
device_set_desc(dev, "Qlogic ISP 6322 PCI FC-AL Adapter");
break;
+ case PCI_QLOGIC_ISP2031:
+ device_set_desc(dev, "Qlogic ISP 2031 PCI FC-AL Adapter");
+ break;
+ case PCI_QLOGIC_ISP8031:
+ device_set_desc(dev, "Qlogic ISP 8031 PCI FCoE Adapter");
+ break;
default:
return (ENXIO);
}
@@ -485,31 +522,6 @@ isp_get_generic_options(device_t dev, ispsoftc_t *isp)
}
static void
-isp_get_pci_options(device_t dev, int *m1, int *m2)
-{
- int tval;
- /*
- * Which we should try first - memory mapping or i/o mapping?
- *
- * We used to try memory first followed by i/o on alpha, otherwise
- * the reverse, but we should just try memory first all the time now.
- */
- *m1 = PCIM_CMD_MEMEN;
- *m2 = PCIM_CMD_PORTEN;
-
- tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_iomap", &tval) == 0 && tval != 0) {
- *m1 = PCIM_CMD_PORTEN;
- *m2 = PCIM_CMD_MEMEN;
- }
- tval = 0;
- if (resource_int_value(device_get_name(dev), device_get_unit(dev), "prefer_memmap", &tval) == 0 && tval != 0) {
- *m1 = PCIM_CMD_MEMEN;
- *m2 = PCIM_CMD_PORTEN;
- }
-}
-
-static void
isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
{
const char *sptr;
@@ -662,7 +674,7 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
static int
isp_pci_attach(device_t dev)
{
- int i, m1, m2, locksetup = 0;
+ int i, locksetup = 0;
uint32_t data, cmd, linesz, did;
struct isp_pcisoftc *pcs;
ispsoftc_t *isp;
@@ -689,33 +701,10 @@ isp_pci_attach(device_t dev)
isp_nvports = 0;
isp_get_generic_options(dev, isp);
- /*
- * Get PCI options- which in this case are just mapping preferences.
- */
- isp_get_pci_options(dev, &m1, &m2);
-
linesz = PCI_DFLT_LNSZ;
- pcs->irq = pcs->regs = NULL;
+ pcs->irq = pcs->regs = pcs->regs2 = NULL;
pcs->rgd = pcs->rtp = pcs->iqd = 0;
- pcs->rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
- pcs->rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
- pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE);
- if (pcs->regs == NULL) {
- pcs->rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
- pcs->rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
- pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE);
- }
- if (pcs->regs == NULL) {
- device_printf(dev, "unable to map any ports\n");
- goto bad;
- }
- if (bootverbose) {
- device_printf(dev, "using %s space register mapping\n", (pcs->rgd == IO_MAP_REG)? "I/O" : "Memory");
- }
- isp->isp_bus_tag = rman_get_bustag(pcs->regs);
- isp->isp_bus_handle = rman_get_bushandle(pcs->regs);
-
pcs->pci_dev = dev;
pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
@@ -823,6 +812,14 @@ isp_pci_attach(device_t dev)
isp->isp_type = ISP_HA_FC_2500;
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
break;
+ case PCI_QLOGIC_ISP2031:
+ case PCI_QLOGIC_ISP8031:
+ did = 0x2600;
+ isp->isp_nchan += isp_nvports;
+ isp->isp_mdvec = &mdvec_2600;
+ isp->isp_type = ISP_HA_FC_2600;
+ pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS2400_OFF;
+ break;
default:
device_printf(dev, "unknown device type\n");
goto bad;
@@ -830,6 +827,42 @@ isp_pci_attach(device_t dev)
}
isp->isp_revision = pci_get_revid(dev);
+ if (IS_26XX(isp)) {
+ pcs->rtp = SYS_RES_MEMORY;
+ pcs->rgd = PCIR_BAR(0);
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd,
+ RF_ACTIVE);
+ pcs->rtp1 = SYS_RES_MEMORY;
+ pcs->rgd1 = PCIR_BAR(2);
+ pcs->regs1 = bus_alloc_resource_any(dev, pcs->rtp1, &pcs->rgd1,
+ RF_ACTIVE);
+ pcs->rtp2 = SYS_RES_MEMORY;
+ pcs->rgd2 = PCIR_BAR(4);
+ pcs->regs2 = bus_alloc_resource_any(dev, pcs->rtp2, &pcs->rgd2,
+ RF_ACTIVE);
+ } else {
+ pcs->rtp = SYS_RES_MEMORY;
+ pcs->rgd = PCIR_BAR(1);
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd,
+ RF_ACTIVE);
+ if (pcs->regs == NULL) {
+ pcs->rtp = SYS_RES_IOPORT;
+ pcs->rgd = PCIR_BAR(0);
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp,
+ &pcs->rgd, RF_ACTIVE);
+ }
+ }
+ if (pcs->regs == NULL) {
+ device_printf(dev, "Unable to map any ports\n");
+ goto bad;
+ }
+ if (bootverbose) {
+ device_printf(dev, "Using %s space register mapping\n",
+ (pcs->rtp == SYS_RES_IOPORT)? "I/O" : "Memory");
+ }
+ isp->isp_regs = pcs->regs;
+ isp->isp_regs2 = pcs->regs2;
+
if (IS_FC(isp)) {
psize = sizeof (fcparam);
xsize = sizeof (struct isp_fc);
@@ -910,20 +943,28 @@ isp_pci_attach(device_t dev)
data &= ~1;
pci_write_config(dev, PCIR_ROMADDR, data, 4);
- /*
- * Do MSI
- *
- * NB: MSI-X needs to be disabled for the 2432 (PCI-Express)
- */
- if (IS_24XX(isp) || IS_2322(isp)) {
- pcs->msicount = pci_msi_count(dev);
- if (pcs->msicount > 1) {
- pcs->msicount = 1;
+ if (IS_26XX(isp)) {
+ /* 26XX chips support only MSI-X, so start from them. */
+ pcs->msicount = imin(pci_msix_count(dev), 1);
+ if (pcs->msicount > 0 &&
+ (i = pci_alloc_msix(dev, &pcs->msicount)) == 0) {
+ pcs->iqd = 1;
+ } else {
+ pcs->msicount = 0;
}
- if (pci_alloc_msi(dev, &pcs->msicount) == 0) {
+ }
+ if (pcs->msicount == 0 && (IS_24XX(isp) || IS_2322(isp))) {
+ /*
+ * Older chips support both MSI and MSI-X, but I have
+ * feeling that older firmware may not support MSI-X,
+ * but we have no way to check the firmware flag here.
+ */
+ pcs->msicount = imin(pci_msi_count(dev), 1);
+ if (pcs->msicount > 0 &&
+ pci_alloc_msi(dev, &pcs->msicount) == 0) {
pcs->iqd = 1;
} else {
- pcs->iqd = 0;
+ pcs->msicount = 0;
}
}
pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE);
@@ -978,9 +1019,12 @@ bad:
if (pcs->msicount) {
pci_release_msi(dev);
}
- if (pcs->regs) {
+ if (pcs->regs)
(void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
- }
+ if (pcs->regs1)
+ (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1);
+ if (pcs->regs2)
+ (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2);
if (pcs->pci_isp.isp_param) {
free(pcs->pci_isp.isp_param, M_DEVBUF);
pcs->pci_isp.isp_param = NULL;
@@ -1019,6 +1063,10 @@ isp_pci_detach(device_t dev)
pci_release_msi(dev);
}
(void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
+ if (pcs->regs1)
+ (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1);
+ if (pcs->regs2)
+ (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2);
/*
* XXX: THERE IS A LOT OF LEAKAGE HERE
*/
@@ -1037,15 +1085,12 @@ isp_pci_detach(device_t dev)
(((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
_BLK_REG_SHFT] + ((x) & 0xfff))
-#define BXR2(isp, off) \
- bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off)
-#define BXW2(isp, off, v) \
- bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, off, v)
-#define BXR4(isp, off) \
- bus_space_read_4(isp->isp_bus_tag, isp->isp_bus_handle, off)
-#define BXW4(isp, off, v) \
- bus_space_write_4(isp->isp_bus_tag, isp->isp_bus_handle, off, v)
-
+#define BXR2(isp, off) bus_read_2((isp)->isp_regs, (off))
+#define BXW2(isp, off, v) bus_write_2((isp)->isp_regs, (off), (v))
+#define BXR4(isp, off) bus_read_4((isp)->isp_regs, (off))
+#define BXW4(isp, off, v) bus_write_4((isp)->isp_regs, (off), (v))
+#define B2R4(isp, off) bus_read_4((isp)->isp_regs2, (off))
+#define B2W4(isp, off, v) bus_write_4((isp)->isp_regs2, (off), (v))
static ISP_INLINE int
isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
@@ -1308,20 +1353,19 @@ isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
case MBOX_BLOCK:
return (BXR2(isp, IspVirt2Off(isp, regoff)));
case SXP_BLOCK:
- isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "SXP_BLOCK read at 0x%x", regoff);
return (0xffffffff);
case RISC_BLOCK:
- isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "RISC_BLOCK read at 0x%x", regoff);
return (0xffffffff);
case DMA_BLOCK:
- isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "DMA_BLOCK read at 0x%x", regoff);
return (0xffffffff);
default:
- isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "unknown block read at 0x%x", regoff);
return (0xffffffff);
}
-
switch (regoff) {
case BIU2400_FLASH_ADDR:
case BIU2400_FLASH_DATA:
@@ -1349,8 +1393,8 @@ isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
rv = BXR4(isp, IspVirt2Off(isp, regoff)) >> 16;
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "isp_pci_rd_reg_2400: unknown offset %x", regoff);
+ isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x",
+ regoff);
rv = 0xffffffff;
break;
}
@@ -1370,17 +1414,16 @@ isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 2, -1);
return;
case SXP_BLOCK:
- isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "SXP_BLOCK write at 0x%x", regoff);
return;
case RISC_BLOCK:
- isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "RISC_BLOCK write at 0x%x", regoff);
return;
case DMA_BLOCK:
- isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "DMA_BLOCK write at 0x%x", regoff);
return;
default:
- isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x",
- regoff);
+ isp_prt(isp, ISP_LOGERR, "unknown block write at 0x%x", regoff);
break;
}
@@ -1415,10 +1458,83 @@ isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
MEMORYBARRIER(isp, SYNC_REG, IspVirt2Off(isp, regoff), 4, -1);
break;
default:
- isp_prt(isp, ISP_LOGERR,
- "isp_pci_wr_reg_2400: bad offset 0x%x", regoff);
+ isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x",
+ regoff);
+ break;
+ }
+}
+
+static uint32_t
+isp_pci_rd_reg_2600(ispsoftc_t *isp, int regoff)
+{
+ uint32_t rv;
+
+ switch (regoff) {
+ case BIU2400_PRI_REQINP:
+ case BIU2400_PRI_REQOUTP:
+ isp_prt(isp, ISP_LOGERR, "unknown register read at 0x%x",
+ regoff);
+ rv = 0xffffffff;
+ break;
+ case BIU2400_REQINP:
+ rv = B2R4(isp, 0x00);
+ break;
+ case BIU2400_REQOUTP:
+ rv = B2R4(isp, 0x04);
break;
+ case BIU2400_RSPINP:
+ rv = B2R4(isp, 0x08);
+ break;
+ case BIU2400_RSPOUTP:
+ rv = B2R4(isp, 0x0c);
+ break;
+ case BIU2400_ATIO_RSPINP:
+ rv = B2R4(isp, 0x10);
+ break;
+ case BIU2400_ATIO_RSPOUTP:
+ rv = B2R4(isp, 0x14);
+ break;
+ default:
+ rv = isp_pci_rd_reg_2400(isp, regoff);
+ break;
+ }
+ return (rv);
+}
+
+static void
+isp_pci_wr_reg_2600(ispsoftc_t *isp, int regoff, uint32_t val)
+{
+ int off;
+
+ switch (regoff) {
+ case BIU2400_PRI_REQINP:
+ case BIU2400_PRI_REQOUTP:
+ isp_prt(isp, ISP_LOGERR, "unknown register write at 0x%x",
+ regoff);
+ return;
+ case BIU2400_REQINP:
+ off = 0x00;
+ break;
+ case BIU2400_REQOUTP:
+ off = 0x04;
+ break;
+ case BIU2400_RSPINP:
+ off = 0x08;
+ break;
+ case BIU2400_RSPOUTP:
+ off = 0x0c;
+ break;
+ case BIU2400_ATIO_RSPINP:
+ off = 0x10;
+ break;
+ case BIU2400_ATIO_RSPOUTP:
+ off = 0x14;
+ break;
+ default:
+ isp_pci_wr_reg_2400(isp, regoff, val);
+ return;
}
+ B2W4(isp, off, val);
}
diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c
index cb8f169..2abfc64 100644
--- a/sys/dev/isp/isp_sbus.c
+++ b/sys/dev/isp/isp_sbus.c
@@ -180,8 +180,7 @@ isp_sbus_attach(device_t dev)
sbs->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
sbs->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
isp = &sbs->sbus_isp;
- isp->isp_bus_tag = rman_get_bustag(sbs->regs);
- isp->isp_bus_handle = rman_get_bushandle(sbs->regs);
+ isp->isp_regs = sbs->regs;
isp->isp_mdvec = &sbs->sbus_mdvec;
isp->isp_bustype = ISP_BT_SBUS;
isp->isp_type = ISP_HA_SCSI_UNKNOWN;
@@ -367,16 +366,15 @@ isp_sbus_detach(device_t dev)
(((struct isp_sbussoftc *)a)->sbus_poff[((x) & _BLK_REG_MASK) >> \
_BLK_REG_SHFT] + ((x) & 0xff))
-#define BXR2(sbc, off) \
- bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, off)
+#define BXR2(isp, off) bus_read_2((isp)->isp_regs, (off))
static int
isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info)
{
uint16_t isr, sema;
- isr = BXR2(sbc, IspVirt2Off(isp, BIU_ISR));
- sema = BXR2(sbc, IspVirt2Off(isp, BIU_SEMA));
+ isr = BXR2(isp, IspVirt2Off(isp, BIU_ISR));
+ sema = BXR2(isp, IspVirt2Off(isp, BIU_SEMA));
isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
isr &= INT_PENDING_MASK(isp);
sema &= BIU_SEMA_LOCK;
@@ -385,7 +383,7 @@ isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp, uint16_t *semap, uint16_t *info
}
*isrp = isr;
if ((*semap = sema) != 0)
- *info = BXR2(sbc, IspVirt2Off(isp, OUTMAILBOX0));
+ *info = BXR2(isp, IspVirt2Off(isp, OUTMAILBOX0));
return (1);
}
@@ -396,7 +394,7 @@ isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
offset += (regoff & 0xff);
- rval = bus_space_read_2(isp->isp_bus_tag, isp->isp_bus_handle, offset);
+ rval = BXR2(isp, offset);
isp_prt(isp, ISP_LOGDEBUG3,
"isp_sbus_rd_reg(off %x) = %x", regoff, rval);
return (rval);
@@ -410,7 +408,7 @@ isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
offset += (regoff & 0xff);
isp_prt(isp, ISP_LOGDEBUG3,
"isp_sbus_wr_reg(off %x) = %x", regoff, val);
- bus_space_write_2(isp->isp_bus_tag, isp->isp_bus_handle, offset, val);
+ bus_write_2(isp->isp_regs, offset, val);
MEMORYBARRIER(isp, SYNC_REG, offset, 2, -1);
}
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index d724679..a89228b 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -122,6 +122,7 @@
#define MBOX_GET_TARGET_STATUS 0x0056
/* These are for the ISP2X00 FC cards */
+#define MBOX_LOAD_FLASH_FIRMWARE 0x0003
#define MBOX_WRITE_FC_SERDES_REG 0x0003 /* FC only */
#define MBOX_READ_FC_SERDES_REG 0x0004 /* FC only */
#define MBOX_GET_IO_STATUS 0x0012
@@ -1007,9 +1008,9 @@ typedef struct {
#define ICBXOPT_TIMER_MASK 0x7
#define ICBZOPT_RATE_MASK 0xC000
-#define ICBZOPT_RATE_ONEGB 0x0000
+#define ICBZOPT_RATE_1GB 0x0000
#define ICBZOPT_RATE_AUTO 0x8000
-#define ICBZOPT_RATE_TWOGB 0x4000
+#define ICBZOPT_RATE_2GB 0x4000
#define ICBZOPT_50_OHM 0x2000
#define ICBZOPT_NO_LOCAL_PLOGI 0x0080
#define ICBZOPT_ENA_OOF 0x0040 /* out of order frame handling */
@@ -1058,14 +1059,14 @@ typedef struct {
#define ICB2400_OPT3_ENA_ETH_RESP 0x08000000
#define ICB2400_OPT3_ENA_ETH_ATIO 0x04000000
#define ICB2400_OPT3_ENA_MFCF 0x00020000
-#define ICB2400_OPT3_SKIP_FOURGB 0x00010000
+#define ICB2400_OPT3_SKIP_4GB 0x00010000
#define ICB2400_OPT3_RATE_MASK 0x0000E000
-#define ICB2400_OPT3_RATE_ONEGB 0x00000000
-#define ICB2400_OPT3_RATE_TWOGB 0x00002000
+#define ICB2400_OPT3_RATE_1GB 0x00000000
+#define ICB2400_OPT3_RATE_2GB 0x00002000
#define ICB2400_OPT3_RATE_AUTO 0x00004000
-#define ICB2400_OPT3_RATE_FOURGB 0x00006000
-#define ICB2400_OPT3_RATE_EIGHTGB 0x00008000
-#define ICB2400_OPT3_RATE_SIXTEENGB 0x0000A000
+#define ICB2400_OPT3_RATE_4GB 0x00006000
+#define ICB2400_OPT3_RATE_8GB 0x00008000
+#define ICB2400_OPT3_RATE_16GB 0x0000A000
#define ICB2400_OPT3_ENA_OOF_XFRDY 0x00000200
#define ICB2400_OPT3_NO_N2N_LOGI 0x00000100
#define ICB2400_OPT3_NO_LOCAL_PLOGI 0x00000080
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 10060e1..0c42642 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -653,8 +653,8 @@ struct ispsoftc {
#define ISP_CFG_NPORT 0x04 /* prefer {N/F}-Port connection */
#define ISP_CFG_NPORT_ONLY 0x08 /* insist on {N/F}-Port connection */
#define ISP_CFG_LPORT_ONLY 0x0c /* insist on {N/F}L-Port connection */
-#define ISP_CFG_ONEGB 0x10 /* force 1GB connection (23XX only) */
-#define ISP_CFG_TWOGB 0x20 /* force 2GB connection (23XX only) */
+#define ISP_CFG_1GB 0x10 /* force 1GB connection (23XX only) */
+#define ISP_CFG_2GB 0x20 /* force 2GB connection (23XX only) */
#define ISP_CFG_NORELOAD 0x80 /* don't download f/w */
#define ISP_CFG_NONVRAM 0x40 /* ignore NVRAM */
#define ISP_CFG_NOFCTAPE 0x100 /* disable FC-Tape */
@@ -662,9 +662,9 @@ struct ispsoftc {
#define ISP_CFG_OWNFSZ 0x400 /* override NVRAM frame size */
#define ISP_CFG_OWNLOOPID 0x800 /* override NVRAM loopid */
#define ISP_CFG_OWNEXCTHROTTLE 0x1000 /* override NVRAM execution throttle */
-#define ISP_CFG_FOURGB 0x2000 /* force 4GB connection (24XX only) */
-#define ISP_CFG_EIGHTGB 0x4000 /* force 8GB connection (25XX only) */
-#define ISP_CFG_SIXTEENGB 0x8000 /* force 16GB connection (82XX only) */
+#define ISP_CFG_4GB 0x2000 /* force 4GB connection (24XX only) */
+#define ISP_CFG_8GB 0x4000 /* force 8GB connection (25XX only) */
+#define ISP_CFG_16GB 0x8000 /* force 16GB connection (82XX only) */
/*
* For each channel, the outer layers should know what role that channel
@@ -764,6 +764,7 @@ struct ispsoftc {
#define ISP_HA_FC_2322 0x50
#define ISP_HA_FC_2400 0x60
#define ISP_HA_FC_2500 0x70
+#define ISP_HA_FC_2600 0x80
#define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI)
#define IS_1020(isp) (isp->isp_type < ISP_HA_SCSI_1240)
@@ -789,6 +790,7 @@ struct ispsoftc {
#define IS_2322(isp) ((isp)->isp_type == ISP_HA_FC_2322)
#define IS_24XX(isp) ((isp)->isp_type >= ISP_HA_FC_2400)
#define IS_25XX(isp) ((isp)->isp_type >= ISP_HA_FC_2500)
+#define IS_26XX(isp) ((isp)->isp_type >= ISP_HA_FC_2600)
/*
* DMA related macros
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index 27ef8b3..693f000 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -825,8 +825,8 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
struct buf *pb;
bus_dma_segment_t *vlist;
struct thread *td;
- off_t len, zerosize;
- int ma_offs;
+ off_t iolen, len, zerosize;
+ int ma_offs, npages;
switch (bp->bio_cmd) {
case BIO_READ:
@@ -847,6 +847,7 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
pb = NULL;
piov = NULL;
ma_offs = bp->bio_ma_offset;
+ len = bp->bio_length;
/*
* VNODE I/O
@@ -879,7 +880,6 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
auio.uio_iovcnt = howmany(bp->bio_length, zerosize);
piov = malloc(sizeof(*piov) * auio.uio_iovcnt, M_MD, M_WAITOK);
auio.uio_iov = piov;
- len = bp->bio_length;
while (len > 0) {
piov->iov_base = __DECONST(void *, zero_region);
piov->iov_len = len;
@@ -893,7 +893,6 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
piov = malloc(sizeof(*piov) * bp->bio_ma_n, M_MD, M_WAITOK);
auio.uio_iov = piov;
vlist = (bus_dma_segment_t *)bp->bio_data;
- len = bp->bio_length;
while (len > 0) {
piov->iov_base = (void *)(uintptr_t)(vlist->ds_addr +
ma_offs);
@@ -909,11 +908,20 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
piov = auio.uio_iov;
} else if ((bp->bio_flags & BIO_UNMAPPED) != 0) {
pb = getpbuf(&md_vnode_pbuf_freecnt);
- pmap_qenter((vm_offset_t)pb->b_data, bp->bio_ma, bp->bio_ma_n);
- aiov.iov_base = (void *)((vm_offset_t)pb->b_data + ma_offs);
- aiov.iov_len = bp->bio_length;
+ bp->bio_resid = len;
+unmapped_step:
+ npages = atop(min(MAXPHYS, round_page(len + (ma_offs &
+ PAGE_MASK))));
+ iolen = min(ptoa(npages) - (ma_offs & PAGE_MASK), len);
+ KASSERT(iolen > 0, ("zero iolen"));
+ pmap_qenter((vm_offset_t)pb->b_data,
+ &bp->bio_ma[atop(ma_offs)], npages);
+ aiov.iov_base = (void *)((vm_offset_t)pb->b_data +
+ (ma_offs & PAGE_MASK));
+ aiov.iov_len = iolen;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
+ auio.uio_resid = iolen;
} else {
aiov.iov_base = bp->bio_data;
aiov.iov_len = bp->bio_length;
@@ -937,15 +945,21 @@ mdstart_vnode(struct md_s *sc, struct bio *bp)
vn_finished_write(mp);
}
- if (pb) {
- pmap_qremove((vm_offset_t)pb->b_data, bp->bio_ma_n);
+ if (pb != NULL) {
+ pmap_qremove((vm_offset_t)pb->b_data, npages);
+ if (error == 0) {
+ len -= iolen;
+ bp->bio_resid -= iolen;
+ ma_offs += iolen;
+ if (len > 0)
+ goto unmapped_step;
+ }
relpbuf(pb, &md_vnode_pbuf_freecnt);
}
- if (piov != NULL)
- free(piov, M_MD);
-
- bp->bio_resid = auio.uio_resid;
+ free(piov, M_MD);
+ if (pb == NULL)
+ bp->bio_resid = auio.uio_resid;
return (error);
}
diff --git a/sys/dev/mii/rgephy.c b/sys/dev/mii/rgephy.c
index 2c28068..ff7c470 100644
--- a/sys/dev/mii/rgephy.c
+++ b/sys/dev/mii/rgephy.c
@@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$");
#include "miibus_if.h"
#include <machine/bus.h>
-#include <pci/if_rlreg.h>
+#include <dev/rl/if_rlreg.h>
static int rgephy_probe(device_t);
static int rgephy_attach(device_t);
diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c
index ddf8d73..308ee22 100644
--- a/sys/dev/mii/rlphy.c
+++ b/sys/dev/mii/rlphy.c
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
#include "miidevs.h"
#include <machine/bus.h>
-#include <pci/if_rlreg.h>
+#include <dev/rl/if_rlreg.h>
#include "miibus_if.h"
diff --git a/sys/dev/mii/rlswitch.c b/sys/dev/mii/rlswitch.c
index b158fd4..2e9188e 100644
--- a/sys/dev/mii/rlswitch.c
+++ b/sys/dev/mii/rlswitch.c
@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$");
#include "miidevs.h"
#include <machine/bus.h>
-#include <pci/if_rlreg.h>
+#include <dev/rl/if_rlreg.h>
#include "miibus_if.h"
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index d5b2a18..9317965 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -1423,7 +1423,7 @@ mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd)
/* Send the command */
for (i = 0; i < len; i++) {
- mpt_write(mpt, MPT_OFFSET_DOORBELL, htole32(*data32++));
+ mpt_write_stream(mpt, MPT_OFFSET_DOORBELL, *data32++);
if (mpt_wait_db_ack(mpt) != MPT_OK) {
mpt_prt(mpt,
"mpt_send_handshake_cmd: timeout @ index %d\n", i);
@@ -1457,7 +1457,7 @@ mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply)
*data16++ = le16toh(data & MPT_DB_DATA_MASK);
mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
- /* Get Second Word */
+ /* Get second word */
if (mpt_wait_db_int(mpt) != MPT_OK) {
mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2\n");
return ETIMEDOUT;
@@ -1481,18 +1481,13 @@ mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply)
left = (hdr->MsgLength << 1) - 2;
reply_left = reply_len - 2;
while (left--) {
- u_int16_t datum;
-
if (mpt_wait_db_int(mpt) != MPT_OK) {
mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3\n");
return ETIMEDOUT;
}
data = mpt_read(mpt, MPT_OFFSET_DOORBELL);
- datum = le16toh(data & MPT_DB_DATA_MASK);
-
if (reply_left-- > 0)
- *data16++ = datum;
-
+ *data16++ = le16toh(data & MPT_DB_DATA_MASK);
mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
}
diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h
index 1dcd76f..57dbe7b 100644
--- a/sys/dev/mpt/mpt.h
+++ b/sys/dev/mpt/mpt.h
@@ -329,7 +329,6 @@ typedef struct mpt_config_params {
} cfgparms_t;
/**************************** MPI Target State Info ***************************/
-
typedef struct {
uint32_t reply_desc; /* current reply descriptor */
uint32_t resid; /* current data residual */
@@ -784,6 +783,7 @@ mpt_assign_serno(struct mpt_softc *mpt, request_t *req)
/******************************* Register Access ******************************/
static __inline void mpt_write(struct mpt_softc *, size_t, uint32_t);
+static __inline void mpt_write_stream(struct mpt_softc *, size_t, uint32_t);
static __inline uint32_t mpt_read(struct mpt_softc *, int);
static __inline void mpt_pio_write(struct mpt_softc *, size_t, uint32_t);
static __inline uint32_t mpt_pio_read(struct mpt_softc *, int);
@@ -794,6 +794,12 @@ mpt_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val);
}
+static __inline void
+mpt_write_stream(struct mpt_softc *mpt, size_t offset, uint32_t val)
+{
+ bus_space_write_stream_4(mpt->pci_st, mpt->pci_sh, offset, val);
+}
+
static __inline uint32_t
mpt_read(struct mpt_softc *mpt, int offset)
{
@@ -818,6 +824,7 @@ mpt_pio_read(struct mpt_softc *mpt, int offset)
KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource"));
return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset));
}
+
/*********************** Reply Frame/Request Management ***********************/
/* Max MPT Reply we are willing to accept (must be power of 2) */
#define MPT_REPLY_SIZE 256
@@ -958,6 +965,7 @@ mpt_cdblen(uint8_t cdb0, int maxlen)
return (16);
}
}
+
#ifdef INVARIANTS
static __inline request_t * mpt_tag_2_req(struct mpt_softc *, uint32_t);
static __inline request_t *
@@ -1136,6 +1144,7 @@ mpt_write_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress,
PageAddress, hdr, len, sleep_ok,
timeout_ms));
}
+
/* mpt_debug.c functions */
void mpt_print_reply(void *vmsg);
void mpt_print_db(uint32_t mb);
@@ -1145,4 +1154,5 @@ void mpt_req_state(mpt_req_state_t state);
void mpt_print_config_request(void *vmsg);
void mpt_print_request(void *vmsg);
void mpt_dump_sgl(SGE_IO_UNION *se, int offset);
+
#endif /* _MPT_H_ */
diff --git a/sys/dev/qlxgbe/ql_hw.c b/sys/dev/qlxgbe/ql_hw.c
index 0e389d6..3efca30 100644
--- a/sys/dev/qlxgbe/ql_hw.c
+++ b/sys/dev/qlxgbe/ql_hw.c
@@ -387,6 +387,7 @@ ql_hw_add_sysctls(qla_host_t *ha)
"Minidump Utility can start minidump process");
#ifdef QL_DBG
+ ha->err_inject = 0;
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
OID_AUTO, "err_inject",
@@ -3057,7 +3058,7 @@ ql_hw_check_health(qla_host_t *ha)
val = READ_REG32(ha, Q8_FIRMWARE_HEARTBEAT);
if ((val != ha->hw.hbeat_value) &&
- (!(QL_ERR_INJECT(ha, INJCT_TEMPERATURE_FAILURE)))) {
+ (!(QL_ERR_INJECT(ha, INJCT_HEARTBEAT_FAILURE)))) {
ha->hw.hbeat_value = val;
return 0;
}
diff --git a/sys/dev/qlxgbe/ql_os.c b/sys/dev/qlxgbe/ql_os.c
index ecc6cce..5190ff5 100644
--- a/sys/dev/qlxgbe/ql_os.c
+++ b/sys/dev/qlxgbe/ql_os.c
@@ -289,8 +289,6 @@ qla_pci_attach(device_t dev)
int i;
uint32_t num_rcvq = 0;
- QL_DPRINT2(ha, (dev, "%s: enter\n", __func__));
-
if ((ha = device_get_softc(dev)) == NULL) {
device_printf(dev, "cannot get softc\n");
return (ENOMEM);
diff --git a/sys/dev/qlxgbe/ql_ver.h b/sys/dev/qlxgbe/ql_ver.h
index 061e368..0d86db9 100644
--- a/sys/dev/qlxgbe/ql_ver.h
+++ b/sys/dev/qlxgbe/ql_ver.h
@@ -36,6 +36,6 @@
#define QLA_VERSION_MAJOR 3
#define QLA_VERSION_MINOR 10
-#define QLA_VERSION_BUILD 24
+#define QLA_VERSION_BUILD 25
#endif /* #ifndef _QL_VER_H_ */
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 20d47e2..3812962 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -147,7 +147,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <pci/if_rlreg.h>
+#include <dev/rl/if_rlreg.h>
MODULE_DEPEND(re, pci, 1, 1, 1);
MODULE_DEPEND(re, ether, 1, 1, 1);
@@ -237,6 +237,7 @@ static const struct rl_hwrev re_hwrevs[] = {
{ RL_HWREV_8168F, RL_8169, "8168F/8111F", RL_JUMBO_MTU_9K},
{ RL_HWREV_8168G, RL_8169, "8168G/8111G", RL_JUMBO_MTU_9K},
{ RL_HWREV_8168GU, RL_8169, "8168GU/8111GU", RL_JUMBO_MTU_9K},
+ { RL_HWREV_8168H, RL_8169, "8168H/8111H", RL_JUMBO_MTU_9K},
{ RL_HWREV_8411, RL_8169, "8411", RL_JUMBO_MTU_9K},
{ RL_HWREV_8411B, RL_8169, "8411B", RL_JUMBO_MTU_9K},
{ 0, 0, NULL, 0 }
@@ -633,9 +634,8 @@ re_miibus_statchg(device_t dev)
}
}
/*
- * RealTek controllers does not provide any interface to
- * Tx/Rx MACs for resolved speed, duplex and flow-control
- * parameters.
+ * RealTek controllers do not provide any interface to the RX/TX
+ * MACs for resolved speed, duplex and flow-control parameters.
*/
}
@@ -657,7 +657,7 @@ re_set_rxmode(struct rl_softc *sc)
rxfilt = RL_RXCFG_CONFIG | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_BROAD;
if ((sc->rl_flags & RL_FLAG_EARLYOFF) != 0)
rxfilt |= RL_RXCFG_EARLYOFF;
- else if ((sc->rl_flags & RL_FLAG_EARLYOFFV2) != 0)
+ else if ((sc->rl_flags & RL_FLAG_8168G_PLUS) != 0)
rxfilt |= RL_RXCFG_EARLYOFFV2;
if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
@@ -1204,11 +1204,10 @@ re_attach(device_t dev)
struct rl_softc *sc;
struct ifnet *ifp;
const struct rl_hwrev *hw_rev;
+ int capmask, error = 0, hwrev, i, msic, msixc,
+ phy, reg, rid;
u_int32_t cap, ctl;
- int hwrev;
u_int16_t devid, re_did = 0;
- int error = 0, i, phy, rid;
- int msic, msixc, reg;
uint8_t cfg;
sc = device_get_softc(dev);
@@ -1488,11 +1487,12 @@ re_attach(device_t dev)
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 |
RL_FLAG_CMDSTOP_WAIT_TXQ | RL_FLAG_WOL_MANLINK |
- RL_FLAG_EARLYOFFV2 | RL_FLAG_RXDV_GATED;
+ RL_FLAG_8168G_PLUS;
break;
case RL_HWREV_8168GU:
+ case RL_HWREV_8168H:
if (pci_get_device(dev) == RT_DEVICEID_8101E) {
- /* RTL8106EUS */
+ /* RTL8106E(US), RTL8107E */
sc->rl_flags |= RL_FLAG_FASTETHER;
} else
sc->rl_flags |= RL_FLAG_JUMBOV2 | RL_FLAG_WOL_MANLINK;
@@ -1500,7 +1500,7 @@ re_attach(device_t dev)
sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR |
RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP |
RL_FLAG_AUTOPAD | RL_FLAG_CMDSTOP_WAIT_TXQ |
- RL_FLAG_EARLYOFFV2 | RL_FLAG_RXDV_GATED;
+ RL_FLAG_8168G_PLUS;
break;
case RL_HWREV_8169_8110SB:
case RL_HWREV_8169_8110SBL:
@@ -1650,8 +1650,11 @@ re_attach(device_t dev)
phy = RE_PHYAD_INTERNAL;
if (sc->rl_type == RL_8169)
phy = 1;
+ capmask = BMSR_DEFCAPMASK;
+ if ((sc->rl_flags & RL_FLAG_FASTETHER) != 0)
+ capmask &= ~BMSR_EXTSTAT;
error = mii_attach(dev, &sc->rl_miibus, ifp, re_ifmedia_upd,
- re_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, MIIF_DOPAUSE);
+ re_ifmedia_sts, capmask, phy, MII_OFFSET_ANY, MIIF_DOPAUSE);
if (error != 0) {
device_printf(dev, "attaching PHYs failed\n");
goto fail;
@@ -1691,13 +1694,13 @@ re_attach(device_t dev)
#ifdef DEV_NETMAP
re_netmap_attach(sc);
#endif /* DEV_NETMAP */
+
#ifdef RE_DIAG
/*
* Perform hardware diagnostic on the original RTL8169.
* Some 32-bit cards were incorrectly wired and would
* malfunction if plugged into a 64-bit slot.
*/
-
if (hwrev == RL_HWREV_8169) {
error = re_diag(sc);
if (error) {
@@ -1729,7 +1732,6 @@ re_attach(device_t dev)
}
fail:
-
if (error)
re_detach(dev);
@@ -2935,6 +2937,7 @@ re_start_locked(struct ifnet *ifp)
return;
}
#endif /* DEV_NETMAP */
+
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0)
return;
@@ -3190,9 +3193,18 @@ re_init_locked(struct rl_softc *sc)
CSR_WRITE_4(sc, RL_TXLIST_ADDR_LO,
RL_ADDR_LO(sc->rl_ldata.rl_tx_list_addr));
- if ((sc->rl_flags & RL_FLAG_RXDV_GATED) != 0)
+ if ((sc->rl_flags & RL_FLAG_8168G_PLUS) != 0) {
+ /* Disable RXDV gate. */
CSR_WRITE_4(sc, RL_MISC, CSR_READ_4(sc, RL_MISC) &
~0x00080000);
+ }
+
+ /*
+ * Enable transmit and receive for pre-RTL8168G controllers.
+ * RX/TX MACs should be enabled before RX/TX configuration.
+ */
+ if ((sc->rl_flags & RL_FLAG_8168G_PLUS) == 0)
+ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB | RL_CMD_RX_ENB);
/*
* Set the initial TX configuration.
@@ -3221,9 +3233,11 @@ re_init_locked(struct rl_softc *sc)
}
/*
- * Enable transmit and receive.
+ * Enable transmit and receive for RTL8168G and later controllers.
+ * RX/TX MACs should be enabled after RX/TX configuration.
*/
- CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB | RL_CMD_RX_ENB);
+ if ((sc->rl_flags & RL_FLAG_8168G_PLUS) != 0)
+ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB | RL_CMD_RX_ENB);
#ifdef DEVICE_POLLING
/*
@@ -3579,6 +3593,12 @@ re_stop(struct rl_softc *sc)
~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_INDIV | RL_RXCFG_RX_MULTI |
RL_RXCFG_RX_BROAD));
+ if ((sc->rl_flags & RL_FLAG_8168G_PLUS) != 0) {
+ /* Enable RXDV gate. */
+ CSR_WRITE_4(sc, RL_MISC, CSR_READ_4(sc, RL_MISC) |
+ 0x00080000);
+ }
+
if ((sc->rl_flags & RL_FLAG_WAIT_TXPOLL) != 0) {
for (i = RL_TIMEOUT; i > 0; i--) {
if ((CSR_READ_1(sc, sc->rl_txstart) &
@@ -3830,6 +3850,11 @@ re_setwol(struct rl_softc *sc)
CSR_READ_1(sc, RL_GPIO) & ~0x01);
}
if ((ifp->if_capenable & IFCAP_WOL) != 0) {
+ if ((sc->rl_flags & RL_FLAG_8168G_PLUS) != 0) {
+ /* Disable RXDV gate. */
+ CSR_WRITE_4(sc, RL_MISC, CSR_READ_4(sc, RL_MISC) &
+ ~0x00080000);
+ }
re_set_rxmode(sc);
if ((sc->rl_flags & RL_FLAG_WOL_MANLINK) != 0)
re_set_linkspeed(sc);
@@ -3942,7 +3967,6 @@ re_add_sysctls(struct rl_softc *sc)
sc->rl_int_rx_mod = RL_TIMER_DEFAULT;
}
}
-
}
static int
diff --git a/sys/pci/if_rl.c b/sys/dev/rl/if_rl.c
index 4f91d1f..2ff1310 100644
--- a/sys/pci/if_rl.c
+++ b/sys/dev/rl/if_rl.c
@@ -126,7 +126,7 @@ MODULE_DEPEND(rl, miibus, 1, 1, 1);
/* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
-#include <pci/if_rlreg.h>
+#include <dev/rl/if_rlreg.h>
/*
* Various supported device vendors/types and their names.
diff --git a/sys/pci/if_rlreg.h b/sys/dev/rl/if_rlreg.h
index b0de60f..5a5c5f5 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/dev/rl/if_rlreg.h
@@ -195,6 +195,7 @@
#define RL_HWREV_8168G 0x4C000000
#define RL_HWREV_8168EP 0x50000000
#define RL_HWREV_8168GU 0x50800000
+#define RL_HWREV_8168H 0x54000000
#define RL_HWREV_8411B 0x5C800000
#define RL_HWREV_8139 0x60000000
#define RL_HWREV_8139A 0x70000000
@@ -930,8 +931,7 @@ struct rl_softc {
#define RL_FLAG_CMDSTOP_WAIT_TXQ 0x00008000
#define RL_FLAG_WOL_MANLINK 0x00010000
#define RL_FLAG_EARLYOFF 0x00020000
-#define RL_FLAG_EARLYOFFV2 0x00040000
-#define RL_FLAG_RXDV_GATED 0x00080000
+#define RL_FLAG_8168G_PLUS 0x00040000
#define RL_FLAG_PCIE 0x40000000
#define RL_FLAG_LINK 0x80000000
};
diff --git a/sys/dev/usb/net/if_urndis.c b/sys/dev/usb/net/if_urndis.c
index 6509e78..5d2a637 100644
--- a/sys/dev/usb/net/if_urndis.c
+++ b/sys/dev/usb/net/if_urndis.c
@@ -78,12 +78,20 @@ static uether_fn_t urndis_start;
static uether_fn_t urndis_setmulti;
static uether_fn_t urndis_setpromisc;
-static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, const void **, uint16_t *);
-static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, struct urndis_set_req *, uint16_t);
-static uint32_t urndis_ctrl_handle_init(struct urndis_softc *, const struct urndis_comp_hdr *);
-static uint32_t urndis_ctrl_handle_query(struct urndis_softc *, const struct urndis_comp_hdr *, const void **, uint16_t *);
-static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *, const struct urndis_comp_hdr *);
-static uint32_t urndis_ctrl_init(struct urndis_softc *);
+static uint32_t urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_query_req *msg, uint16_t len,
+ const void **rbuf, uint16_t *rbufsz);
+static uint32_t urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_set_req *msg, uint16_t len);
+static uint32_t urndis_ctrl_handle_init(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr);
+static uint32_t urndis_ctrl_handle_query(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr, const void **buf,
+ uint16_t *bufsz);
+static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *sc,
+ const struct urndis_comp_hdr *hdr);
+static uint32_t urndis_ctrl_init(struct urndis_softc *sc);
+static uint32_t urndis_ctrl_halt(struct urndis_softc *sc);
#ifdef USB_DEBUG
static int urndis_debug = 0;
@@ -93,7 +101,6 @@ SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RW, &urndis_debug, 0,
#endif
static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = {
-
[URNDIS_BULK_RX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
@@ -154,7 +161,7 @@ static driver_t urndis_driver = {
static devclass_t urndis_devclass;
-DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, 0);
+DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, NULL);
MODULE_VERSION(urndis, 1);
MODULE_DEPEND(urndis, uether, 1, 1, 1);
MODULE_DEPEND(urndis, usb, 1, 1, 1);
@@ -171,6 +178,9 @@ static const struct usb_ether_methods urndis_ue_methods = {
static const STRUCT_USB_HOST_ID urndis_host_devs[] = {
/* Generic RNDIS class match */
+ {USB_IFACE_CLASS(UICLASS_CDC),
+ USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
+ USB_IFACE_PROTOCOL(0xff)},
{USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
{USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
@@ -192,21 +202,27 @@ urndis_probe(device_t dev)
static void
urndis_attach_post(struct usb_ether *ue)
{
+
/* no-op */
- return;
}
static int
urndis_attach(device_t dev)
{
+ static struct {
+ union {
+ struct urndis_query_req query;
+ struct urndis_set_req set;
+ } hdr;
+ union {
+ uint8_t eaddr[ETHER_ADDR_LEN];
+ uint32_t filter;
+ } ibuf;
+ } msg;
struct urndis_softc *sc = device_get_softc(dev);
struct usb_ether *ue = &sc->sc_ue;
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct usb_cdc_cm_descriptor *cmd;
- struct {
- struct urndis_set_req hdr;
- uint32_t filter;
- } msg_filter;
const void *buf;
uint16_t bufsz;
uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
@@ -228,9 +244,7 @@ urndis_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
/* scan the alternate settings looking for a valid one */
-
for (i = 0; i != 32; i++) {
-
error = usbd_set_alt_interface_index(uaa->device,
iface_index[0], i);
@@ -244,16 +258,27 @@ urndis_attach(device_t dev)
if (error == 0)
break;
}
-
if ((error != 0) || (i == 32)) {
- device_printf(dev, "No valid alternate "
- "setting found\n");
+ device_printf(dev, "No valid alternate setting found\n");
goto detach;
}
+
+ /* Initialize device - must be done before even querying it */
URNDIS_LOCK(sc);
- error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, &buf, &bufsz);
+ error = urndis_ctrl_init(sc);
URNDIS_UNLOCK(sc);
+ if (error != (int)RNDIS_STATUS_SUCCESS) {
+ device_printf(dev, "Unable to initialize hardware\n");
+ goto detach;
+ }
+ /* Determine MAC address */
+ memset(msg.ibuf.eaddr, 0, sizeof(msg.ibuf.eaddr));
+ URNDIS_LOCK(sc);
+ error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS,
+ &msg.hdr.query, sizeof(msg.hdr.query) + sizeof(msg.ibuf.eaddr),
+ &buf, &bufsz);
+ URNDIS_UNLOCK(sc);
if (error != (int)RNDIS_STATUS_SUCCESS) {
device_printf(dev, "Unable to get hardware address\n");
goto detach;
@@ -267,17 +292,16 @@ urndis_attach(device_t dev)
/* Initialize packet filter */
sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
RNDIS_PACKET_TYPE_ALL_MULTICAST;
- msg_filter.filter = htole32(sc->sc_filter);
-
+ msg.ibuf.filter = htole32(sc->sc_filter);
URNDIS_LOCK(sc);
error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
- &msg_filter.hdr, sizeof(msg_filter));
+ &msg.hdr.set, sizeof(msg.hdr.set) + sizeof(msg.ibuf.filter));
URNDIS_UNLOCK(sc);
-
if (error != (int)RNDIS_STATUS_SUCCESS) {
device_printf(dev, "Unable to set data filters\n");
goto detach;
}
+
ue->ue_sc = sc;
ue->ue_dev = dev;
ue->ue_udev = uaa->device;
@@ -298,7 +322,7 @@ urndis_attach(device_t dev)
return (0); /* success */
detach:
- urndis_detach(dev);
+ (void)urndis_detach(dev);
return (ENXIO); /* failure */
}
@@ -313,6 +337,10 @@ urndis_detach(device_t dev)
uether_ifdetach(ue);
+ URNDIS_LOCK(sc);
+ (void)urndis_ctrl_halt(sc);
+ URNDIS_UNLOCK(sc);
+
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -340,8 +368,6 @@ urndis_init(struct usb_ether *ue)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- urndis_ctrl_init(sc);
-
/* stall data write direction, which depends on USB mode */
usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
@@ -369,20 +395,21 @@ urndis_stop(struct usb_ether *ue)
static void
urndis_setmulti(struct usb_ether *ue)
{
+
/* no-op */
- return;
}
static void
urndis_setpromisc(struct usb_ether *ue)
{
+
/* no-op */
- return;
}
static int
urndis_suspend(device_t dev)
{
+
device_printf(dev, "Suspending\n");
return (0);
}
@@ -390,6 +417,7 @@ urndis_suspend(device_t dev)
static int
urndis_resume(device_t dev)
{
+
device_printf(dev, "Resuming\n");
return (0);
}
@@ -416,8 +444,8 @@ urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
{
usb_error_t err;
- err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
- sc->sc_ifaceno_ctl, 0, buf, len);
+ err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE,
+ UCDC_SEND_ENCAPSULATED_COMMAND, sc->sc_ifaceno_ctl, 0, buf, len);
DPRINTF("%s\n", usbd_errstr(err));
@@ -430,8 +458,9 @@ urndis_ctrl_recv(struct urndis_softc *sc)
struct urndis_comp_hdr *hdr;
usb_error_t err;
- err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
- sc->sc_ifaceno_ctl, 0, sc->sc_response_buf, RNDIS_RESPONSE_LEN);
+ err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE,
+ UCDC_GET_ENCAPSULATED_RESPONSE, sc->sc_ifaceno_ctl, 0,
+ sc->sc_response_buf, RNDIS_RESPONSE_LEN);
if (err != USB_ERR_NORMAL_COMPLETION)
return (NULL);
@@ -480,7 +509,8 @@ urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
break;
default:
- DPRINTF("ctrl message error: unknown event 0x%x\n",
+ device_printf(sc->sc_ue.ue_dev,
+ "ctrl message error: unknown event 0x%x\n",
le32toh(hdr->rm_type));
rval = RNDIS_STATUS_FAILURE;
break;
@@ -548,10 +578,8 @@ urndis_ctrl_handle_query(struct urndis_softc *sc,
le32toh(msg->rm_infobuflen),
le32toh(msg->rm_infobufoffset));
- if (buf != NULL && bufsz != NULL) {
- *buf = NULL;
- *bufsz = 0;
- }
+ *buf = NULL;
+ *bufsz = 0;
if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
return (le32toh(msg->rm_status));
@@ -571,10 +599,10 @@ urndis_ctrl_handle_query(struct urndis_softc *sc,
le32toh(msg->rm_len));
return (RNDIS_STATUS_FAILURE);
}
- if (buf != NULL && bufsz != NULL) {
- *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET + le32toh(msg->rm_infobufoffset);
- *bufsz = le32toh(msg->rm_infobuflen);
- }
+ *buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET +
+ le32toh(msg->rm_infobufoffset);
+ *bufsz = le32toh(msg->rm_infobuflen);
+
return (le32toh(msg->rm_status));
}
@@ -627,7 +655,7 @@ urndis_ctrl_init(struct urndis_softc *sc)
msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
msg.rm_len = htole32(sizeof(msg));
- msg.rm_rid = htole32(0);
+ msg.rm_rid = 0;
msg.rm_ver_major = htole32(1);
msg.rm_ver_minor = htole32(1);
msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
@@ -656,7 +684,6 @@ urndis_ctrl_init(struct urndis_softc *sc)
return (rval);
}
-#if 0
static uint32_t
urndis_ctrl_halt(struct urndis_softc *sc)
{
@@ -675,39 +702,48 @@ urndis_ctrl_halt(struct urndis_softc *sc)
rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
if (rval != RNDIS_STATUS_SUCCESS)
- printf("halt failed\n");
+ DPRINTF("halt failed\n");
return (rval);
}
-#endif
-
+/*
+ * NB: Querying a device has the requirment of using an input buffer the size
+ * of the expected reply or larger, except for variably sized replies.
+ */
static uint32_t
-urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint16_t *rbufsz)
+urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_query_req *msg, uint16_t len, const void **rbuf,
+ uint16_t *rbufsz)
{
- struct urndis_query_req msg;
- uint32_t rval;
struct urndis_comp_hdr *hdr;
+ uint32_t datalen, rval;
- msg.rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
- msg.rm_len = htole32(sizeof(msg));
- msg.rm_rid = 0; /* XXX */
- msg.rm_oid = htole32(oid);
- msg.rm_infobuflen = htole32(0);
- msg.rm_infobufoffset = 0;
- msg.rm_devicevchdl = 0;
+ msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
+ msg->rm_len = htole32(len);
+ msg->rm_rid = 0; /* XXX */
+ msg->rm_oid = htole32(oid);
+ datalen = len - sizeof(*msg);
+ msg->rm_infobuflen = htole32(datalen);
+ if (datalen != 0) {
+ msg->rm_infobufoffset = htole32(sizeof(*msg) -
+ RNDIS_HEADER_OFFSET);
+ } else {
+ msg->rm_infobufoffset = 0;
+ }
+ msg->rm_devicevchdl = 0;
DPRINTF("type %u len %u rid %u oid 0x%x "
"infobuflen %u infobufoffset %u devicevchdl %u\n",
- le32toh(msg.rm_type),
- le32toh(msg.rm_len),
- le32toh(msg.rm_rid),
- le32toh(msg.rm_oid),
- le32toh(msg.rm_infobuflen),
- le32toh(msg.rm_infobufoffset),
- le32toh(msg.rm_devicevchdl));
+ le32toh(msg->rm_type),
+ le32toh(msg->rm_len),
+ le32toh(msg->rm_rid),
+ le32toh(msg->rm_oid),
+ le32toh(msg->rm_infobuflen),
+ le32toh(msg->rm_infobufoffset),
+ le32toh(msg->rm_devicevchdl));
- rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
+ rval = urndis_ctrl_send(sc, msg, len);
if (rval != RNDIS_STATUS_SUCCESS) {
DPRINTF("query failed\n");
@@ -723,19 +759,21 @@ urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, const void **rbuf, uint
}
static uint32_t
-urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, struct urndis_set_req *msg, uint16_t len)
+urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
+ struct urndis_set_req *msg, uint16_t len)
{
struct urndis_comp_hdr *hdr;
- uint32_t rval;
- uint32_t datalen = len - sizeof(*msg);
+ uint32_t datalen, rval;
msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
msg->rm_len = htole32(len);
msg->rm_rid = 0; /* XXX */
msg->rm_oid = htole32(oid);
+ datalen = len - sizeof(*msg);
msg->rm_infobuflen = htole32(datalen);
if (datalen != 0) {
- msg->rm_infobufoffset = htole32(sizeof(*msg) - RNDIS_HEADER_OFFSET);
+ msg->rm_infobufoffset = htole32(sizeof(*msg) -
+ RNDIS_HEADER_OFFSET);
} else {
msg->rm_infobufoffset = 0;
}
@@ -782,13 +820,11 @@ urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
-
/* copy out header */
usbd_copy_out(pc, offset, &msg, sizeof(msg));
@@ -930,7 +966,7 @@ tr_setup:
usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
- next_pkt:
+next_pkt:
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
diff --git a/sys/dev/vt/colors/vt_termcolors.c b/sys/dev/vt/colors/vt_termcolors.c
index d8a5909..5075619 100644
--- a/sys/dev/vt/colors/vt_termcolors.c
+++ b/sys/dev/vt/colors/vt_termcolors.c
@@ -25,15 +25,16 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <dev/vt/colors/vt_termcolors.h>
-static struct {
+static const struct {
unsigned char r; /* Red percentage value. */
unsigned char g; /* Green percentage value. */
unsigned char b; /* Blue percentage value. */
@@ -68,8 +69,8 @@ static const int cons_to_vga_colors[16] = {
};
int
-vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax, int roffset,
- uint32_t gmax, int goffset, uint32_t bmax, int boffset)
+vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
+ int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
int i;
diff --git a/sys/modules/hyperv/netvsc/Makefile b/sys/modules/hyperv/netvsc/Makefile
index 472be16..857df82 100644
--- a/sys/modules/hyperv/netvsc/Makefile
+++ b/sys/modules/hyperv/netvsc/Makefile
@@ -6,7 +6,7 @@ KMOD= hv_netvsc
SRCS= hv_net_vsc.c \
hv_netvsc_drv_freebsd.c \
hv_rndis_filter.c
-SRCS+= bus_if.h device_if.h
+SRCS+= bus_if.h device_if.h opt_inet.h opt_inet6.h
CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/netvsc
diff --git a/sys/modules/rl/Makefile b/sys/modules/rl/Makefile
index e846579..16046ad 100644
--- a/sys/modules/rl/Makefile
+++ b/sys/modules/rl/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../pci
+.PATH: ${.CURDIR}/../../dev/rl
KMOD= if_rl
SRCS= if_rl.c device_if.h bus_if.h pci_if.h
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index e681bcd..693b3ac 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -2971,7 +2971,7 @@ uma_zone_t ng_qzone;
uma_zone_t ng_qdzone;
static int numthreads = 0; /* number of queue threads */
static int maxalloc = 4096;/* limit the damage of a leak */
-static int maxdata = 512; /* limit the damage of a DoS */
+static int maxdata = 4096; /* limit the damage of a DoS */
TUNABLE_INT("net.graph.threads", &numthreads);
SYSCTL_INT(_net_graph, OID_AUTO, threads, CTLFLAG_RDTUN, &numthreads,
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index fb2f810..7e3a1a3 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -97,6 +97,10 @@ struct tcphdr {
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
#define TCPOPT_SIGNATURE 19 /* Keyed MD5: RFC 2385 */
#define TCPOLEN_SIGNATURE 18
+#define TCPOPT_FAST_OPEN 34
+#define TCPOLEN_FAST_OPEN_EMPTY 2
+#define TCPOLEN_FAST_OPEN_MIN 6
+#define TCPOLEN_FAST_OPEN_MAX 18
/* Miscellaneous constants */
#define MAX_SACK_BLKS 6 /* Max # SACK blocks stored at receiver side */
@@ -165,6 +169,7 @@ struct tcphdr {
#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */
#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */
#define TCP_KEEPCNT 1024 /* L,N number of keepalives before close */
+#define TCP_FASTOPEN 1025 /* enable TFO / was created via TFO */
/* Start of reserved space for third-party user-settable options. */
#define TCP_VENDOR SO_VENDOR
diff --git a/sys/netinet/tcp_fastopen.c b/sys/netinet/tcp_fastopen.c
new file mode 100644
index 0000000..482320e
--- /dev/null
+++ b/sys/netinet/tcp_fastopen.c
@@ -0,0 +1,442 @@
+/*-
+ * Copyright (c) 2015 Patrick Kelsey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This is a server-side implementation of TCP Fast Open (TFO) [RFC7413].
+ *
+ * This implementation is currently considered to be experimental and is not
+ * included in kernel builds by default. To include this code, add the
+ * following line to your kernel config:
+ *
+ * options TCP_RFC7413
+ *
+ * The generated TFO cookies are the 64-bit output of
+ * SipHash24(<16-byte-key><client-ip>). Multiple concurrent valid keys are
+ * supported so that time-based rolling cookie invalidation policies can be
+ * implemented in the system. The default number of concurrent keys is 2.
+ * This can be adjusted in the kernel config as follows:
+ *
+ * options TCP_RFC7413_MAX_KEYS=<num-keys>
+ *
+ *
+ * The following TFO-specific sysctls are defined:
+ *
+ * net.inet.tcp.fastopen.acceptany (RW, default 0)
+ * When non-zero, all client-supplied TFO cookies will be considered to
+ * be valid.
+ *
+ * net.inet.tcp.fastopen.autokey (RW, default 120)
+ * When this and net.inet.tcp.fastopen.enabled are non-zero, a new key
+ * will be automatically generated after this many seconds.
+ *
+ * net.inet.tcp.fastopen.enabled (RW, default 0)
+ * When zero, no new TFO connections can be created. On the transition
+ * from enabled to disabled, all installed keys are removed. On the
+ * transition from disabled to enabled, if net.inet.tcp.fastopen.autokey
+ * is non-zero and there are no keys installed, a new key will be
+ * generated immediately. The transition from enabled to disabled does
+ * not affect any TFO connections in progress; it only prevents new ones
+ * from being made.
+ *
+ * net.inet.tcp.fastopen.keylen (RO)
+ * The key length in bytes.
+ *
+ * net.inet.tcp.fastopen.maxkeys (RO)
+ * The maximum number of keys supported.
+ *
+ * net.inet.tcp.fastopen.numkeys (RO)
+ * The current number of keys installed.
+ *
+ * net.inet.tcp.fastopen.setkey (WO)
+ * Install a new key by writing net.inet.tcp.fastopen.keylen bytes to this
+ * sysctl.
+ *
+ *
+ * In order for TFO connections to be created via a listen socket, that
+ * socket must have the TCP_FASTOPEN socket option set on it. This option
+ * can be set on the socket either before or after the listen() is invoked.
+ * Clearing this option on a listen socket after it has been set has no
+ * effect on existing TFO connections or TFO connections in progress; it
+ * only prevents new TFO connections from being made.
+ *
+ * For passively-created sockets, the TCP_FASTOPEN socket option can be
+ * queried to determine whether the connection was established using TFO.
+ * Note that connections that are established via a TFO SYN, but that fall
+ * back to using a non-TFO SYN|ACK will have the TCP_FASTOPEN socket option
+ * set.
+ *
+ * Per the RFC, this implementation limits the number of TFO connections
+ * that can be in the SYN_RECEIVED state on a per listen-socket basis.
+ * Whenever this limit is exceeded, requests for new TFO connections are
+ * serviced as non-TFO requests. Without such a limit, given a valid TFO
+ * cookie, an attacker could keep the listen queue in an overflow condition
+ * using a TFO SYN flood. This implementation sets the limit at half the
+ * configured listen backlog.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_inet.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+
+#include <crypto/siphash/siphash.h>
+
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+#include <netinet/tcp_fastopen.h>
+#include <netinet/tcp_var.h>
+
+
+#define TCP_FASTOPEN_KEY_LEN SIPHASH_KEY_LENGTH
+
+#if !defined(TCP_RFC7413_MAX_KEYS) || (TCP_RFC7413_MAX_KEYS < 1)
+#define TCP_FASTOPEN_MAX_KEYS 2
+#else
+#define TCP_FASTOPEN_MAX_KEYS TCP_RFC7413_MAX_KEYS
+#endif
+
+struct tcp_fastopen_keylist {
+ unsigned int newest;
+ uint8_t key[TCP_FASTOPEN_MAX_KEYS][TCP_FASTOPEN_KEY_LEN];
+};
+
+struct tcp_fastopen_callout {
+ struct callout c;
+ struct vnet *v;
+};
+
+SYSCTL_NODE(_net_inet_tcp, OID_AUTO, fastopen, CTLFLAG_RW, 0, "TCP Fast Open");
+
+static VNET_DEFINE(int, tcp_fastopen_acceptany) = 0;
+#define V_tcp_fastopen_acceptany VNET(tcp_fastopen_acceptany)
+SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, acceptany,
+ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_fastopen_acceptany), 0,
+ "Accept any non-empty cookie");
+
+static VNET_DEFINE(unsigned int, tcp_fastopen_autokey) = 120;
+#define V_tcp_fastopen_autokey VNET(tcp_fastopen_autokey)
+static int sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, autokey,
+ CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
+ &sysctl_net_inet_tcp_fastopen_autokey, "IU",
+ "Number of seconds between auto-generation of a new key; zero disables");
+
+VNET_DEFINE(unsigned int, tcp_fastopen_enabled) = 0;
+static int sysctl_net_inet_tcp_fastopen_enabled(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, enabled,
+ CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW, NULL, 0,
+ &sysctl_net_inet_tcp_fastopen_enabled, "IU",
+ "Enable/disable TCP Fast Open processing");
+
+SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, keylen,
+ CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_KEY_LEN,
+ "Key length in bytes");
+
+SYSCTL_INT(_net_inet_tcp_fastopen, OID_AUTO, maxkeys,
+ CTLFLAG_RD, SYSCTL_NULL_INT_PTR, TCP_FASTOPEN_MAX_KEYS,
+ "Maximum number of keys supported");
+
+static VNET_DEFINE(unsigned int, tcp_fastopen_numkeys) = 0;
+#define V_tcp_fastopen_numkeys VNET(tcp_fastopen_numkeys)
+SYSCTL_UINT(_net_inet_tcp_fastopen, OID_AUTO, numkeys,
+ CTLFLAG_VNET | CTLFLAG_RD, &VNET_NAME(tcp_fastopen_numkeys), 0,
+ "Number of keys installed");
+
+static int sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_net_inet_tcp_fastopen, OID_AUTO, setkey,
+ CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_WR, NULL, 0,
+ &sysctl_net_inet_tcp_fastopen_setkey, "",
+ "Install a new key");
+
+static VNET_DEFINE(struct rmlock, tcp_fastopen_keylock);
+#define V_tcp_fastopen_keylock VNET(tcp_fastopen_keylock)
+
+#define TCP_FASTOPEN_KEYS_RLOCK(t) rm_rlock(&V_tcp_fastopen_keylock, (t))
+#define TCP_FASTOPEN_KEYS_RUNLOCK(t) rm_runlock(&V_tcp_fastopen_keylock, (t))
+#define TCP_FASTOPEN_KEYS_WLOCK() rm_wlock(&V_tcp_fastopen_keylock)
+#define TCP_FASTOPEN_KEYS_WUNLOCK() rm_wunlock(&V_tcp_fastopen_keylock)
+
+static VNET_DEFINE(struct tcp_fastopen_keylist, tcp_fastopen_keys);
+#define V_tcp_fastopen_keys VNET(tcp_fastopen_keys)
+
+static VNET_DEFINE(struct tcp_fastopen_callout, tcp_fastopen_autokey_ctx);
+#define V_tcp_fastopen_autokey_ctx VNET(tcp_fastopen_autokey_ctx)
+
+static VNET_DEFINE(uma_zone_t, counter_zone);
+#define V_counter_zone VNET(counter_zone)
+
+void
+tcp_fastopen_init(void)
+{
+ V_counter_zone = uma_zcreate("tfo", sizeof(unsigned int),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ rm_init(&V_tcp_fastopen_keylock, "tfo_keylock");
+ callout_init_rm(&V_tcp_fastopen_autokey_ctx.c,
+ &V_tcp_fastopen_keylock, 0);
+ V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
+}
+
+void
+tcp_fastopen_destroy(void)
+{
+ callout_drain(&V_tcp_fastopen_autokey_ctx.c);
+ rm_destroy(&V_tcp_fastopen_keylock);
+ uma_zdestroy(V_counter_zone);
+}
+
+unsigned int *
+tcp_fastopen_alloc_counter(void)
+{
+ unsigned int *counter;
+ counter = uma_zalloc(V_counter_zone, M_NOWAIT);
+ if (counter)
+ *counter = 1;
+ return (counter);
+}
+
+void
+tcp_fastopen_decrement_counter(unsigned int *counter)
+{
+ if (*counter == 1)
+ uma_zfree(V_counter_zone, counter);
+ else
+ atomic_subtract_int(counter, 1);
+}
+
+static void
+tcp_fastopen_addkey_locked(uint8_t *key)
+{
+
+ V_tcp_fastopen_keys.newest++;
+ if (V_tcp_fastopen_keys.newest == TCP_FASTOPEN_MAX_KEYS)
+ V_tcp_fastopen_keys.newest = 0;
+ memcpy(V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest], key,
+ TCP_FASTOPEN_KEY_LEN);
+ if (V_tcp_fastopen_numkeys < TCP_FASTOPEN_MAX_KEYS)
+ V_tcp_fastopen_numkeys++;
+}
+
+static void
+tcp_fastopen_autokey_locked(void)
+{
+ uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
+
+ arc4rand(newkey, TCP_FASTOPEN_KEY_LEN, 0);
+ tcp_fastopen_addkey_locked(newkey);
+}
+
+static void
+tcp_fastopen_autokey_callout(void *arg)
+{
+ struct tcp_fastopen_callout *ctx = arg;
+
+ CURVNET_SET(ctx->v);
+ tcp_fastopen_autokey_locked();
+ callout_reset(&ctx->c, V_tcp_fastopen_autokey * hz,
+ tcp_fastopen_autokey_callout, ctx);
+ CURVNET_RESTORE();
+}
+
+
+static uint64_t
+tcp_fastopen_make_cookie(uint8_t key[SIPHASH_KEY_LENGTH], struct in_conninfo *inc)
+{
+ SIPHASH_CTX ctx;
+ uint64_t siphash;
+
+ SipHash24_Init(&ctx);
+ SipHash_SetKey(&ctx, key);
+ switch (inc->inc_flags & INC_ISIPV6) {
+#ifdef INET
+ case 0:
+ SipHash_Update(&ctx, &inc->inc_faddr, sizeof(inc->inc_faddr));
+ break;
+#endif
+#ifdef INET6
+ case INC_ISIPV6:
+ SipHash_Update(&ctx, &inc->inc6_faddr, sizeof(inc->inc6_faddr));
+ break;
+#endif
+ }
+ SipHash_Final((u_int8_t *)&siphash, &ctx);
+
+ return (siphash);
+}
+
+
+/*
+ * Return values:
+ * -1 the cookie is invalid and no valid cookie is available
+ * 0 the cookie is invalid and the latest cookie has been returned
+ * 1 the cookie is valid and the latest cookie has been returned
+ */
+int
+tcp_fastopen_check_cookie(struct in_conninfo *inc, uint8_t *cookie,
+ unsigned int len, uint64_t *latest_cookie)
+{
+ struct rm_priotracker tracker;
+ unsigned int i, key_index;
+ uint64_t cur_cookie;
+
+ if (V_tcp_fastopen_acceptany) {
+ *latest_cookie = 0;
+ return (1);
+ }
+
+ if (len != TCP_FASTOPEN_COOKIE_LEN) {
+ if (V_tcp_fastopen_numkeys > 0) {
+ *latest_cookie =
+ tcp_fastopen_make_cookie(
+ V_tcp_fastopen_keys.key[V_tcp_fastopen_keys.newest],
+ inc);
+ return (0);
+ }
+ return (-1);
+ }
+
+ /*
+ * Check against each available key, from newest to oldest.
+ */
+ TCP_FASTOPEN_KEYS_RLOCK(&tracker);
+ key_index = V_tcp_fastopen_keys.newest;
+ for (i = 0; i < V_tcp_fastopen_numkeys; i++) {
+ cur_cookie =
+ tcp_fastopen_make_cookie(V_tcp_fastopen_keys.key[key_index],
+ inc);
+ if (i == 0)
+ *latest_cookie = cur_cookie;
+ if (memcmp(cookie, &cur_cookie, TCP_FASTOPEN_COOKIE_LEN) == 0) {
+ TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
+ return (1);
+ }
+ if (key_index == 0)
+ key_index = TCP_FASTOPEN_MAX_KEYS - 1;
+ else
+ key_index--;
+ }
+ TCP_FASTOPEN_KEYS_RUNLOCK(&tracker);
+
+ return (0);
+}
+
+static int
+sysctl_net_inet_tcp_fastopen_autokey(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ unsigned int new;
+
+ new = V_tcp_fastopen_autokey;
+ error = sysctl_handle_int(oidp, &new, 0, req);
+ if (error == 0 && req->newptr) {
+ if (new > (INT_MAX / hz))
+ return (EINVAL);
+
+ TCP_FASTOPEN_KEYS_WLOCK();
+ if (V_tcp_fastopen_enabled) {
+ if (V_tcp_fastopen_autokey && !new)
+ callout_stop(&V_tcp_fastopen_autokey_ctx.c);
+ else if (new)
+ callout_reset(&V_tcp_fastopen_autokey_ctx.c,
+ new * hz, tcp_fastopen_autokey_callout,
+ &V_tcp_fastopen_autokey_ctx);
+ }
+ V_tcp_fastopen_autokey = new;
+ TCP_FASTOPEN_KEYS_WUNLOCK();
+ }
+
+ return (error);
+}
+
+static int
+sysctl_net_inet_tcp_fastopen_enabled(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ unsigned int new;
+
+ new = V_tcp_fastopen_enabled;
+ error = sysctl_handle_int(oidp, &new, 0, req);
+ if (error == 0 && req->newptr) {
+ if (V_tcp_fastopen_enabled && !new) {
+ /* enabled -> disabled */
+ TCP_FASTOPEN_KEYS_WLOCK();
+ V_tcp_fastopen_numkeys = 0;
+ V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
+ if (V_tcp_fastopen_autokey)
+ callout_stop(&V_tcp_fastopen_autokey_ctx.c);
+ V_tcp_fastopen_enabled = 0;
+ TCP_FASTOPEN_KEYS_WUNLOCK();
+ } else if (!V_tcp_fastopen_enabled && new) {
+ /* disabled -> enabled */
+ TCP_FASTOPEN_KEYS_WLOCK();
+ if (V_tcp_fastopen_autokey &&
+ (V_tcp_fastopen_numkeys == 0)) {
+ tcp_fastopen_autokey_locked();
+ callout_reset(&V_tcp_fastopen_autokey_ctx.c,
+ V_tcp_fastopen_autokey * hz,
+ tcp_fastopen_autokey_callout,
+ &V_tcp_fastopen_autokey_ctx);
+ }
+ V_tcp_fastopen_enabled = 1;
+ TCP_FASTOPEN_KEYS_WUNLOCK();
+ }
+ }
+ return (error);
+}
+
+static int
+sysctl_net_inet_tcp_fastopen_setkey(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ uint8_t newkey[TCP_FASTOPEN_KEY_LEN];
+
+ if (req->oldptr != NULL || req->oldlen != 0)
+ return (EINVAL);
+ if (req->newptr == NULL)
+ return (EPERM);
+ if (req->newlen != sizeof(newkey))
+ return (EINVAL);
+ error = SYSCTL_IN(req, newkey, sizeof(newkey));
+ if (error)
+ return (error);
+
+ TCP_FASTOPEN_KEYS_WLOCK();
+ tcp_fastopen_addkey_locked(newkey);
+ TCP_FASTOPEN_KEYS_WUNLOCK();
+
+ return (0);
+}
diff --git a/sys/netinet/tcp_fastopen.h b/sys/netinet/tcp_fastopen.h
new file mode 100644
index 0000000..c64ba2c
--- /dev/null
+++ b/sys/netinet/tcp_fastopen.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2015 Patrick Kelsey
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TCP_FASTOPEN_H_
+#define _TCP_FASTOPEN_H_
+
+#ifdef _KERNEL
+
+#define TCP_FASTOPEN_COOKIE_LEN 8 /* tied to SipHash24 64-bit output */
+
+VNET_DECLARE(unsigned int, tcp_fastopen_enabled);
+#define V_tcp_fastopen_enabled VNET(tcp_fastopen_enabled)
+
+void tcp_fastopen_init(void);
+void tcp_fastopen_destroy(void);
+unsigned int *tcp_fastopen_alloc_counter(void);
+void tcp_fastopen_decrement_counter(unsigned int *counter);
+int tcp_fastopen_check_cookie(struct in_conninfo *inc, uint8_t *cookie,
+ unsigned int len, uint64_t *latest_cookie);
+#endif /* _KERNEL */
+
+#endif /* _TCP_FASTOPEN_H_ */
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 631cd2e..a59874e 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -98,6 +98,9 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_pcb.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
+#ifdef TCP_RFC7413
+#include <netinet/tcp_fastopen.h>
+#endif
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -1070,6 +1073,9 @@ relocked:
rstreason = BANDLIM_RST_OPENPORT;
goto dropwithreset;
}
+#ifdef TCP_RFC7413
+new_tfo_socket:
+#endif
if (so == NULL) {
/*
* We completed the 3-way handshake
@@ -1327,7 +1333,12 @@ relocked:
(void *)tcp_saveipgen, &tcp_savetcp, 0);
#endif
tcp_dooptions(&to, optp, optlen, TO_SYN);
+#ifdef TCP_RFC7413
+ if (syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL))
+ goto new_tfo_socket;
+#else
syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL);
+#endif
/*
* Entry added to syncache and mbuf consumed.
* Everything already unlocked by syncache_add().
@@ -1437,6 +1448,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
struct in_conninfo *inc;
struct mbuf *mfree;
struct tcpopt to;
+ int tfo_syn;
#ifdef TCPDEBUG
/*
@@ -1876,6 +1888,28 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
rstreason = BANDLIM_RST_OPENPORT;
goto dropwithreset;
}
+#ifdef TCP_RFC7413
+ if (tp->t_flags & TF_FASTOPEN) {
+ /*
+ * When a TFO connection is in SYN_RECEIVED, the
+ * only valid packets are the initial SYN, a
+ * retransmit/copy of the initial SYN (possibly with
+ * a subset of the original data), a valid ACK, a
+ * FIN, or a RST.
+ */
+ if ((thflags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
+ rstreason = BANDLIM_RST_OPENPORT;
+ goto dropwithreset;
+ } else if (thflags & TH_SYN) {
+ /* non-initial SYN is ignored */
+ if ((tcp_timer_active(tp, TT_DELACK) ||
+ tcp_timer_active(tp, TT_REXMT)))
+ goto drop;
+ } else if (!(thflags & (TH_ACK|TH_FIN|TH_RST))) {
+ goto drop;
+ }
+ }
+#endif
break;
/*
@@ -2316,9 +2350,16 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((thflags & TH_ACK) == 0) {
if (tp->t_state == TCPS_SYN_RECEIVED ||
- (tp->t_flags & TF_NEEDSYN))
+ (tp->t_flags & TF_NEEDSYN)) {
+#ifdef TCP_RFC7413
+ if (tp->t_state == TCPS_SYN_RECEIVED &&
+ tp->t_flags & TF_FASTOPEN) {
+ tp->snd_wnd = tiwin;
+ cc_conn_init(tp);
+ }
+#endif
goto step6;
- else if (tp->t_flags & TF_ACKNOW)
+ } else if (tp->t_flags & TF_ACKNOW)
goto dropafterack;
else
goto drop;
@@ -2357,7 +2398,27 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcp_state_change(tp, TCPS_ESTABLISHED);
TCP_PROBE5(accept__established, NULL, tp,
mtod(m, const char *), tp, th);
- cc_conn_init(tp);
+#ifdef TCP_RFC7413
+ if (tp->t_tfo_pending) {
+ tcp_fastopen_decrement_counter(tp->t_tfo_pending);
+ tp->t_tfo_pending = NULL;
+
+ /*
+ * Account for the ACK of our SYN prior to
+ * regular ACK processing below.
+ */
+ tp->snd_una++;
+ }
+ /*
+ * TFO connections call cc_conn_init() during SYN
+ * processing. Calling it again here for such
+ * connections is not harmless as it would undo the
+ * snd_cwnd reduction that occurs when a TFO SYN|ACK
+ * is retransmitted.
+ */
+ if (!(tp->t_flags & TF_FASTOPEN))
+#endif
+ cc_conn_init(tp);
tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
}
/*
@@ -2888,9 +2949,12 @@ dodata: /* XXX */
* case PRU_RCVD). If a FIN has already been received on this
* connection then we just ignore the text.
*/
- if ((tlen || (thflags & TH_FIN)) &&
+ tfo_syn = ((tp->t_state == TCPS_SYN_RECEIVED) &&
+ (tp->t_flags & TF_FASTOPEN));
+ if ((tlen || (thflags & TH_FIN) || tfo_syn) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
tcp_seq save_start = th->th_seq;
+
m_adj(m, drop_hdrlen); /* delayed header drop */
/*
* Insert segment which includes th into TCP reassembly queue
@@ -2906,8 +2970,9 @@ dodata: /* XXX */
*/
if (th->th_seq == tp->rcv_nxt &&
LIST_EMPTY(&tp->t_segq) &&
- TCPS_HAVEESTABLISHED(tp->t_state)) {
- if (DELAY_ACK(tp, tlen))
+ (TCPS_HAVEESTABLISHED(tp->t_state) ||
+ tfo_syn)) {
+ if (DELAY_ACK(tp, tlen) || tfo_syn)
tp->t_flags |= TF_DELACK;
else
tp->t_flags |= TF_ACKNOW;
@@ -3260,6 +3325,21 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags)
to->to_sacks = cp + 2;
TCPSTAT_INC(tcps_sack_rcv_blocks);
break;
+#ifdef TCP_RFC7413
+ case TCPOPT_FAST_OPEN:
+ if ((optlen != TCPOLEN_FAST_OPEN_EMPTY) &&
+ (optlen < TCPOLEN_FAST_OPEN_MIN) &&
+ (optlen > TCPOLEN_FAST_OPEN_MAX))
+ continue;
+ if (!(flags & TO_SYN))
+ continue;
+ if (!V_tcp_fastopen_enabled)
+ continue;
+ to->to_flags |= TOF_FASTOPEN;
+ to->to_tfo_len = optlen - 2;
+ to->to_tfo_cookie = to->to_tfo_len ? cp + 2 : NULL;
+ break;
+#endif
default:
continue;
}
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index f1196e1..c7dc547 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -69,6 +69,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#endif
+#ifdef TCP_RFC7413
+#include <netinet/tcp_fastopen.h>
+#endif
#define TCPOUTFLAGS
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
@@ -202,6 +205,17 @@ tcp_output(struct tcpcb *tp)
return (tcp_offload_output(tp));
#endif
+#ifdef TCP_RFC7413
+ /*
+ * For TFO connections in SYN_RECEIVED, only allow the initial
+ * SYN|ACK and those sent by the retransmit timer.
+ */
+ if ((tp->t_flags & TF_FASTOPEN) &&
+ (tp->t_state == TCPS_SYN_RECEIVED) &&
+ SEQ_GT(tp->snd_max, tp->snd_una) && /* inital SYN|ACK sent */
+ (tp->snd_nxt != tp->snd_una)) /* not a retransmit */
+ return (0);
+#endif
/*
* Determine length of data that should be transmitted,
* and flags that will be used.
@@ -387,6 +401,15 @@ after_sack_rexmit:
if ((flags & TH_SYN) && SEQ_GT(tp->snd_nxt, tp->snd_una)) {
if (tp->t_state != TCPS_SYN_RECEIVED)
flags &= ~TH_SYN;
+#ifdef TCP_RFC7413
+ /*
+ * When sending additional segments following a TFO SYN|ACK,
+ * do not include the SYN bit.
+ */
+ if ((tp->t_flags & TF_FASTOPEN) &&
+ (tp->t_state == TCPS_SYN_RECEIVED))
+ flags &= ~TH_SYN;
+#endif
off--, len++;
}
@@ -400,6 +423,17 @@ after_sack_rexmit:
flags &= ~TH_FIN;
}
+#ifdef TCP_RFC7413
+ /*
+ * When retransmitting SYN|ACK on a passively-created TFO socket,
+ * don't include data, as the presence of data may have caused the
+ * original SYN|ACK to have been dropped by a middlebox.
+ */
+ if ((tp->t_flags & TF_FASTOPEN) &&
+ (((tp->t_state == TCPS_SYN_RECEIVED) && (tp->t_rxtshift > 0)) ||
+ (flags & TH_RST)))
+ len = 0;
+#endif
if (len <= 0) {
/*
* If FIN has been sent but not acked,
@@ -718,6 +752,22 @@ send:
tp->snd_nxt = tp->iss;
to.to_mss = tcp_mssopt(&tp->t_inpcb->inp_inc);
to.to_flags |= TOF_MSS;
+#ifdef TCP_RFC7413
+ /*
+ * Only include the TFO option on the first
+ * transmission of the SYN|ACK on a
+ * passively-created TFO socket, as the presence of
+ * the TFO option may have caused the original
+ * SYN|ACK to have been dropped by a middlebox.
+ */
+ if ((tp->t_flags & TF_FASTOPEN) &&
+ (tp->t_state == TCPS_SYN_RECEIVED) &&
+ (tp->t_rxtshift == 0)) {
+ to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN;
+ to.to_tfo_cookie = (u_char *)&tp->t_tfo_cookie;
+ to.to_flags |= TOF_FASTOPEN;
+ }
+#endif
}
/* Window scaling. */
if ((flags & TH_SYN) && (tp->t_flags & TF_REQ_SCALE)) {
@@ -997,7 +1047,7 @@ send:
* give data to the user when a buffer fills or
* a PUSH comes in.)
*/
- if (off + len == so->so_snd.sb_cc)
+ if ((off + len == so->so_snd.sb_cc) && !(flags & TH_SYN))
flags |= TH_PUSH;
SOCKBUF_UNLOCK(&so->so_snd);
} else {
@@ -1694,6 +1744,25 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
TCPSTAT_INC(tcps_sack_send_blocks);
break;
}
+#ifdef TCP_RFC7413
+ case TOF_FASTOPEN:
+ {
+ int total_len;
+
+ /* XXX is there any point to aligning this option? */
+ total_len = TCPOLEN_FAST_OPEN_EMPTY + to->to_tfo_len;
+ if (TCP_MAXOLEN - optlen < total_len)
+ continue;
+ *optp++ = TCPOPT_FAST_OPEN;
+ *optp++ = total_len;
+ if (to->to_tfo_len > 0) {
+ bcopy(to->to_tfo_cookie, optp, to->to_tfo_len);
+ optp += to->to_tfo_len;
+ }
+ optlen += total_len;
+ break;
+ }
+#endif
default:
panic("%s: unknown TCP option type", __func__);
break;
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 7bdd573..3ce21a9 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -83,6 +83,9 @@ __FBSDID("$FreeBSD$");
#include <netinet6/nd6.h>
#endif
+#ifdef TCP_RFC7413
+#include <netinet/tcp_fastopen.h>
+#endif
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -427,6 +430,10 @@ tcp_init(void)
SHUTDOWN_PRI_DEFAULT);
EVENTHANDLER_REGISTER(maxsockets_change, tcp_zone_change, NULL,
EVENTHANDLER_PRI_ANY);
+
+#ifdef TCP_RFC7413
+ tcp_fastopen_init();
+#endif
}
#ifdef VIMAGE
@@ -434,6 +441,9 @@ void
tcp_destroy(void)
{
+#ifdef TCP_RFC7413
+ tcp_fastopen_destroy();
+#endif
tcp_hc_destroy();
syncache_destroy();
tcp_tw_destroy();
@@ -1102,6 +1112,17 @@ tcp_close(struct tcpcb *tp)
if (tp->t_state == TCPS_LISTEN)
tcp_offload_listen_stop(tp);
#endif
+#ifdef TCP_RFC7413
+ /*
+ * This releases the TFO pending counter resource for TFO listen
+ * sockets as well as passively-created TFO sockets that transition
+ * from SYN_RECEIVED to CLOSED.
+ */
+ if (tp->t_tfo_pending) {
+ tcp_fastopen_decrement_counter(tp->t_tfo_pending);
+ tp->t_tfo_pending = NULL;
+ }
+#endif
in_pcbdrop(inp);
TCPSTAT_INC(tcps_closed);
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 9896788..8d2cc98 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -78,6 +78,9 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_pcb.h>
#endif
#include <netinet/tcp.h>
+#ifdef TCP_RFC7413
+#include <netinet/tcp_fastopen.h>
+#endif
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -1089,6 +1092,39 @@ failed:
return (0);
}
+#ifdef TCP_RFC7413
+static void
+syncache_tfo_expand(struct syncache *sc, struct socket **lsop, struct mbuf *m,
+ uint64_t response_cookie)
+{
+ struct inpcb *inp;
+ struct tcpcb *tp;
+ unsigned int *pending_counter;
+
+ /*
+ * Global TCP locks are held because we manipulate the PCB lists
+ * and create a new socket.
+ */
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+
+ pending_counter = intotcpcb(sotoinpcb(*lsop))->t_tfo_pending;
+ *lsop = syncache_socket(sc, *lsop, m);
+ if (*lsop == NULL) {
+ TCPSTAT_INC(tcps_sc_aborted);
+ atomic_subtract_int(pending_counter, 1);
+ } else {
+ inp = sotoinpcb(*lsop);
+ tp = intotcpcb(inp);
+ tp->t_flags |= TF_FASTOPEN;
+ tp->t_tfo_cookie = response_cookie;
+ tp->snd_max = tp->iss;
+ tp->snd_nxt = tp->iss;
+ tp->t_tfo_pending = pending_counter;
+ TCPSTAT_INC(tcps_sc_completed);
+ }
+}
+#endif /* TCP_RFC7413 */
+
/*
* Given a LISTEN socket and an inbound SYN request, add
* this to the syn cache, and send back a segment:
@@ -1101,8 +1137,15 @@ failed:
* DoS attack, an attacker could send data which would eventually
* consume all available buffer space if it were ACKed. By not ACKing
* the data, we avoid this DoS scenario.
+ *
+ * The exception to the above is when a SYN with a valid TCP Fast Open (TFO)
+ * cookie is processed, V_tcp_fastopen_enabled set to true, and the
+ * TCP_FASTOPEN socket option is set. In this case, a new socket is created
+ * and returned via lsop, the mbuf is not freed so that tcp_input() can
+ * queue its data to the socket, and 1 is returned to indicate the
+ * TFO-socket-creation path was taken.
*/
-void
+int
syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
struct inpcb *inp, struct socket **lsop, struct mbuf *m, void *tod,
void *todctx)
@@ -1115,6 +1158,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
u_int ltflags;
int win, sb_hiwat, ip_ttl, ip_tos;
char *s;
+ int rv = 0;
#ifdef INET6
int autoflowlabel = 0;
#endif
@@ -1123,6 +1167,11 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
#endif
struct syncache scs;
struct ucred *cred;
+#ifdef TCP_RFC7413
+ uint64_t tfo_response_cookie;
+ int tfo_cookie_valid = 0;
+ int tfo_response_cookie_valid = 0;
+#endif
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp); /* listen socket */
@@ -1148,6 +1197,29 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sb_hiwat = so->so_rcv.sb_hiwat;
ltflags = (tp->t_flags & (TF_NOOPT | TF_SIGNATURE));
+#ifdef TCP_RFC7413
+ if (V_tcp_fastopen_enabled && (tp->t_flags & TF_FASTOPEN) &&
+ (tp->t_tfo_pending != NULL) && (to->to_flags & TOF_FASTOPEN)) {
+ /*
+ * Limit the number of pending TFO connections to
+ * approximately half of the queue limit. This prevents TFO
+ * SYN floods from starving the service by filling the
+ * listen queue with bogus TFO connections.
+ */
+ if (atomic_fetchadd_int(tp->t_tfo_pending, 1) <=
+ (so->so_qlimit / 2)) {
+ int result;
+
+ result = tcp_fastopen_check_cookie(inc,
+ to->to_tfo_cookie, to->to_tfo_len,
+ &tfo_response_cookie);
+ tfo_cookie_valid = (result > 0);
+ tfo_response_cookie_valid = (result >= 0);
+ } else
+ atomic_subtract_int(tp->t_tfo_pending, 1);
+ }
+#endif
+
/* By the time we drop the lock these should no longer be used. */
so = NULL;
tp = NULL;
@@ -1160,9 +1232,16 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
} else
mac_syncache_create(maclabel, inp);
#endif
+#ifdef TCP_RFC7413
+ if (!tfo_cookie_valid) {
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+ }
+#else
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
-
+#endif
+
/*
* Remember the IP options, if any.
*/
@@ -1190,6 +1269,12 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sc = syncache_lookup(inc, &sch); /* returns locked entry */
SCH_LOCK_ASSERT(sch);
if (sc != NULL) {
+#ifdef TCP_RFC7413
+ if (tfo_cookie_valid) {
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+ }
+#endif
TCPSTAT_INC(tcps_sc_dupsyn);
if (ipopts) {
/*
@@ -1232,6 +1317,14 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
goto done;
}
+#ifdef TCP_RFC7413
+ if (tfo_cookie_valid) {
+ bzero(&scs, sizeof(scs));
+ sc = &scs;
+ goto skip_alloc;
+ }
+#endif
+
sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO);
if (sc == NULL) {
/*
@@ -1255,7 +1348,13 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
}
}
-
+
+#ifdef TCP_RFC7413
+skip_alloc:
+ if (!tfo_cookie_valid && tfo_response_cookie_valid)
+ sc->sc_tfo_cookie = &tfo_response_cookie;
+#endif
+
/*
* Fill in the syncache values.
*/
@@ -1365,6 +1464,15 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
#endif
SCH_UNLOCK(sch);
+#ifdef TCP_RFC7413
+ if (tfo_cookie_valid) {
+ syncache_tfo_expand(sc, lsop, m, tfo_response_cookie);
+ /* INP_WUNLOCK(inp) will be performed by the called */
+ rv = 1;
+ goto tfo_done;
+ }
+#endif
+
/*
* Do a standard 3-way handshake.
*/
@@ -1382,17 +1490,20 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
done:
+ if (m) {
+ *lsop = NULL;
+ m_freem(m);
+ }
+#ifdef TCP_RFC7413
+tfo_done:
+#endif
if (cred != NULL)
crfree(cred);
#ifdef MAC
if (sc == &scs)
mac_syncache_destroy(&maclabel);
#endif
- if (m) {
-
- *lsop = NULL;
- m_freem(m);
- }
+ return (rv);
}
static int
@@ -1520,6 +1631,16 @@ syncache_respond(struct syncache *sc)
if (sc->sc_flags & SCF_SIGNATURE)
to.to_flags |= TOF_SIGNATURE;
#endif
+
+#ifdef TCP_RFC7413
+ if (sc->sc_tfo_cookie) {
+ to.to_flags |= TOF_FASTOPEN;
+ to.to_tfo_len = TCP_FASTOPEN_COOKIE_LEN;
+ to.to_tfo_cookie = sc->sc_tfo_cookie;
+ /* don't send cookie again when retransmitting response */
+ sc->sc_tfo_cookie = NULL;
+ }
+#endif
optlen = tcp_addoptions(&to, (u_char *)(th + 1));
/* Adjust headers by option size. */
diff --git a/sys/netinet/tcp_syncache.h b/sys/netinet/tcp_syncache.h
index fb9a6c6..d56afb6 100644
--- a/sys/netinet/tcp_syncache.h
+++ b/sys/netinet/tcp_syncache.h
@@ -41,7 +41,7 @@ void syncache_destroy(void);
void syncache_unreach(struct in_conninfo *, struct tcphdr *);
int syncache_expand(struct in_conninfo *, struct tcpopt *,
struct tcphdr *, struct socket **, struct mbuf *);
-void syncache_add(struct in_conninfo *, struct tcpopt *,
+int syncache_add(struct in_conninfo *, struct tcpopt *,
struct tcphdr *, struct inpcb *, struct socket **, struct mbuf *,
void *, void *);
void syncache_chkrst(struct in_conninfo *, struct tcphdr *);
@@ -74,7 +74,9 @@ struct syncache {
#endif
struct label *sc_label; /* MAC label reference */
struct ucred *sc_cred; /* cred cache for jail checks */
-
+#ifdef TCP_RFC7413
+ void *sc_tfo_cookie; /* for TCP Fast Open response */
+#endif
void *sc_pspare; /* TCP_SIGNATURE */
u_int32_t sc_spare[2]; /* UTO */
};
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 3dc3a81..c66cb76 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -596,7 +596,8 @@ tcp_timer_rexmt(void * xtp)
} else
tp->t_flags &= ~TF_PREVVALID;
TCPSTAT_INC(tcps_rexmttimeo);
- if (tp->t_state == TCPS_SYN_SENT)
+ if ((tp->t_state == TCPS_SYN_SENT) ||
+ (tp->t_state == TCPS_SYN_RECEIVED))
rexmt = TCPTV_RTOBASE * tcp_syn_backoff[tp->t_rxtshift];
else
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index c848306..1ccbf9a 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -79,6 +79,9 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6_var.h>
#include <netinet6/scope6_var.h>
#endif
+#ifdef TCP_RFC7413
+#include <netinet/tcp_fastopen.h>
+#endif
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
@@ -391,6 +394,10 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
}
SOCK_UNLOCK(so);
+#ifdef TCP_RFC7413
+ if (tp->t_flags & TF_FASTOPEN)
+ tp->t_tfo_pending = tcp_fastopen_alloc_counter();
+#endif
out:
TCPDEBUG2(PRU_LISTEN);
INP_WUNLOCK(inp);
@@ -436,6 +443,10 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
}
SOCK_UNLOCK(so);
+#ifdef TCP_RFC7413
+ if (tp->t_flags & TF_FASTOPEN)
+ tp->t_tfo_pending = tcp_fastopen_alloc_counter();
+#endif
out:
TCPDEBUG2(PRU_LISTEN);
INP_WUNLOCK(inp);
@@ -791,6 +802,18 @@ tcp_usr_rcvd(struct socket *so, int flags)
}
tp = intotcpcb(inp);
TCPDEBUG1();
+#ifdef TCP_RFC7413
+ /*
+ * For passively-created TFO connections, don't attempt a window
+ * update while still in SYN_RECEIVED as this may trigger an early
+ * SYN|ACK. It is preferable to have the SYN|ACK be sent along with
+ * application response data, or failing that, when the DELACK timer
+ * expires.
+ */
+ if ((tp->t_flags & TF_FASTOPEN) &&
+ (tp->t_state == TCPS_SYN_RECEIVED))
+ goto out;
+#endif
#ifdef TCP_OFFLOAD
if (tp->t_flags & TF_TOE)
tcp_offload_rcvd(tp);
@@ -1558,6 +1581,29 @@ unlock_and_done:
TP_MAXIDLE(tp));
goto unlock_and_done;
+#ifdef TCP_RFC7413
+ case TCP_FASTOPEN:
+ INP_WUNLOCK(inp);
+ if (!V_tcp_fastopen_enabled)
+ return (EPERM);
+
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ return (error);
+
+ INP_WLOCK_RECHECK(inp);
+ if (optval) {
+ tp->t_flags |= TF_FASTOPEN;
+ if ((tp->t_state == TCPS_LISTEN) &&
+ (tp->t_tfo_pending == NULL))
+ tp->t_tfo_pending =
+ tcp_fastopen_alloc_counter();
+ } else
+ tp->t_flags &= ~TF_FASTOPEN;
+ goto unlock_and_done;
+#endif
+
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -1628,6 +1674,13 @@ unlock_and_done:
INP_WUNLOCK(inp);
error = sooptcopyout(sopt, &ui, sizeof(ui));
break;
+#ifdef TCP_RFC7413
+ case TCP_FASTOPEN:
+ optval = tp->t_flags & TF_FASTOPEN;
+ INP_WUNLOCK(inp);
+ error = sooptcopyout(sopt, &optval, sizeof optval);
+ break;
+#endif
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
@@ -1951,6 +2004,10 @@ db_print_tflags(u_int t_flags)
db_printf("%sTF_ECN_PERMIT", comma ? ", " : "");
comma = 1;
}
+ if (t_flags & TF_FASTOPEN) {
+ db_printf("%sTF_FASTOPEN", comma ? ", " : "");
+ comma = 1;
+ }
}
static void
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 758f2c5..cff81c5 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -213,8 +213,18 @@ struct tcpcb {
u_int t_flags2; /* More tcpcb flags storage */
uint32_t t_ispare[6]; /* 5 UTO, 1 TBD */
+#if defined(_KERNEL) && defined(TCP_RFC7413)
+ void *t_pspare2[3]; /* 1 TCP_SIGNATURE, 2 TBD */
+ unsigned int *t_tfo_pending; /* TCP Fast Open pending counter */
+#else
void *t_pspare2[4]; /* 1 TCP_SIGNATURE, 3 TBD */
+#endif
+#if defined(_KERNEL) && defined(TCP_RFC7413)
+ uint64_t _pad[4]; /* 4 TBD (1-2 CC/RTT?) */
+ uint64_t t_tfo_cookie; /* TCP Fast Open cookie */
+#else
uint64_t _pad[5]; /* 5 TBD (1-2 CC/RTT?) */
+#endif
uint32_t t_tsomaxsegcount; /* TSO maximum segment count */
uint32_t t_tsomaxsegsize; /* TSO maximum segment size in bytes */
};
@@ -251,6 +261,7 @@ struct tcpcb {
#define TF_ECN_SND_ECE 0x10000000 /* ECN ECE in queue */
#define TF_CONGRECOVERY 0x20000000 /* congestion recovery mode */
#define TF_WASCRECOVERY 0x40000000 /* was in congestion recovery */
+#define TF_FASTOPEN 0x80000000 /* TCP Fast Open indication */
#define IN_FASTRECOVERY(t_flags) (t_flags & TF_FASTRECOVERY)
#define ENTER_FASTRECOVERY(t_flags) t_flags |= TF_FASTRECOVERY
@@ -310,14 +321,17 @@ struct tcpopt {
#define TOF_TS 0x0010 /* timestamp */
#define TOF_SIGNATURE 0x0040 /* TCP-MD5 signature option (RFC2385) */
#define TOF_SACK 0x0080 /* Peer sent SACK option */
-#define TOF_MAXOPT 0x0100
+#define TOF_FASTOPEN 0x0100 /* TCP Fast Open (TFO) cookie */
+#define TOF_MAXOPT 0x0200
u_int32_t to_tsval; /* new timestamp */
u_int32_t to_tsecr; /* reflected timestamp */
u_char *to_sacks; /* pointer to the first SACK blocks */
u_char *to_signature; /* pointer to the TCP-MD5 signature */
+ u_char *to_tfo_cookie; /* pointer to the TFO cookie */
u_int16_t to_mss; /* maximum segment size */
u_int8_t to_wscale; /* window scaling */
u_int8_t to_nsacks; /* number of SACK blocks */
+ u_int8_t to_tfo_len; /* TFO cookie length */
u_int32_t to_spare; /* UTO */
};
diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c
index 93ad342..0967c5d 100644
--- a/sys/sparc64/ebus/ebus.c
+++ b/sys/sparc64/ebus/ebus.c
@@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
-
#include <sys/rman.h>
#include <dev/ofw/ofw_bus.h>
@@ -294,7 +293,7 @@ ebus_nexus_attach(device_t dev)
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
sizeof(struct ebus_nexus_ranges), &sc->sc_range);
if (sc->sc_nrange == -1) {
- printf("%s: could not get ranges property\n", __func__);
+ device_printf(dev, "could not get ranges property\n");
return (ENXIO);
}
return (ebus_attach(dev, sc, node));
@@ -306,6 +305,7 @@ ebus_pci_attach(device_t dev)
struct ebus_softc *sc;
struct ebus_rinfo *eri;
struct resource *res;
+ struct isa_ranges *range;
phandle_t node;
int i, rnum, rid;
@@ -322,7 +322,7 @@ ebus_pci_attach(device_t dev)
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
sizeof(struct isa_ranges), &sc->sc_range);
if (sc->sc_nrange == -1) {
- printf("%s: could not get ranges property\n", __func__);
+ device_printf(dev, "could not get ranges property\n");
return (ENXIO);
}
@@ -332,21 +332,34 @@ ebus_pci_attach(device_t dev)
/* For every range, there must be a matching resource. */
for (rnum = 0; rnum < sc->sc_nrange; rnum++) {
eri = &sc->sc_rinfo[rnum];
- eri->eri_rtype = ofw_isa_range_restype(
- &((struct isa_ranges *)sc->sc_range)[rnum]);
+ range = &((struct isa_ranges *)sc->sc_range)[rnum];
+ eri->eri_rtype = ofw_isa_range_restype(range);
rid = PCIR_BAR(rnum);
res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid,
RF_ACTIVE);
if (res == NULL) {
- printf("%s: failed to allocate range resource!\n",
- __func__);
+ device_printf(dev,
+ "could not allocate range resource %d\n", rnum);
+ goto fail;
+ }
+ if (rman_get_start(res) != ISA_RANGE_PHYS(range)) {
+ device_printf(dev,
+ "mismatch in start of range %d (0x%lx/0x%lx)\n",
+ rnum, rman_get_start(res), ISA_RANGE_PHYS(range));
+ goto fail;
+ }
+ if (rman_get_size(res) != range->size) {
+ device_printf(dev,
+ "mismatch in size of range %d (0x%lx/0x%x)\n",
+ rnum, rman_get_size(res), range->size);
goto fail;
}
eri->eri_res = res;
eri->eri_rman.rm_type = RMAN_ARRAY;
eri->eri_rman.rm_descr = "EBus range";
if (rman_init_from_resource(&eri->eri_rman, res) != 0) {
- printf("%s: failed to initialize rman!", __func__);
+ device_printf(dev,
+ "could not initialize rman for range %d", rnum);
goto fail;
}
}
@@ -452,7 +465,7 @@ ebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
* Map EBus ranges to PCI ranges. This may include
* changing the allocation type.
*/
- (void)ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
+ type = ofw_isa_range_map(sc->sc_range, sc->sc_nrange,
&start, &end, &ridx);
eri = &sc->sc_rinfo[ridx];
res = rman_reserve_resource(&eri->eri_rman, start,
@@ -507,7 +520,7 @@ ebus_activate_resource(device_t bus, device_t child, int type, int rid,
int i, rv;
sc = device_get_softc(bus);
- if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
+ if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) {
for (i = 0; i < sc->sc_nrange; i++) {
eri = &sc->sc_rinfo[i];
if (rman_is_region_manager(res, &eri->eri_rman) != 0) {
@@ -550,7 +563,7 @@ ebus_release_resource(device_t bus, device_t child, int type, int rid,
passthrough = (device_get_parent(child) != bus);
rl = BUS_GET_RESOURCE_LIST(bus, child);
sc = device_get_softc(bus);
- if ((sc->sc_flags & EBUS_PCI) != 0 && type == SYS_RES_MEMORY) {
+ if ((sc->sc_flags & EBUS_PCI) != 0 && type != SYS_RES_IRQ) {
if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){
rv = bus_deactivate_resource(child, type, rid, res);
if (rv != 0)
diff --git a/sys/sparc64/include/md_var.h b/sys/sparc64/include/md_var.h
index 6a0a2f6..d3dbf99 100644
--- a/sys/sparc64/include/md_var.h
+++ b/sys/sparc64/include/md_var.h
@@ -47,9 +47,9 @@ extern vm_paddr_t kstack0_phys;
struct pcpu;
struct md_utrap;
-const char *cpu_cpuid_prop(u_int cpu_impl);
uint32_t cpu_get_mid(u_int cpu_impl);
void cpu_identify(u_long vers, u_int clock, u_int id);
+const char *cpu_portid_prop(u_int cpu_impl);
void cpu_setregs(struct pcpu *pc);
int is_physical_memory(vm_paddr_t addr);
struct md_utrap *utrap_alloc(void);
diff --git a/sys/sparc64/include/smp.h b/sys/sparc64/include/smp.h
index c46c4f8..266187e 100644
--- a/sys/sparc64/include/smp.h
+++ b/sys/sparc64/include/smp.h
@@ -47,6 +47,7 @@
#include <sys/sched.h>
#include <sys/smp.h>
+#include <machine/atomic.h>
#include <machine/intr_machdep.h>
#include <machine/tte.h>
@@ -143,7 +144,7 @@ ipi_all_but_self(u_int ipi)
{
cpuset_t cpus;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return;
cpus = all_cpus;
sched_pin();
@@ -158,7 +159,8 @@ static __inline void
ipi_selected(cpuset_t cpus, u_int ipi)
{
- if (__predict_false(smp_started == 0 || CPU_EMPTY(&cpus)))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0 ||
+ CPU_EMPTY(&cpus)))
return;
mtx_lock_spin(&ipi_mtx);
cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
@@ -169,7 +171,7 @@ static __inline void
ipi_cpu(int cpu, u_int ipi)
{
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return;
mtx_lock_spin(&ipi_mtx);
cpu_ipi_single(cpu, 0, (u_long)tl_ipi_level, ipi);
@@ -183,7 +185,7 @@ ipi_dcache_page_inval(void *func, vm_paddr_t pa)
{
struct ipi_cache_args *ica;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return (NULL);
sched_pin();
ica = &ipi_cache_args;
@@ -200,7 +202,7 @@ ipi_icache_page_inval(void *func, vm_paddr_t pa)
{
struct ipi_cache_args *ica;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return (NULL);
sched_pin();
ica = &ipi_cache_args;
@@ -217,7 +219,7 @@ ipi_rd(u_int cpu, void *func, u_long *val)
{
struct ipi_rd_args *ira;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return (NULL);
sched_pin();
ira = &ipi_rd_args;
@@ -234,7 +236,7 @@ ipi_tlb_context_demap(struct pmap *pm)
struct ipi_tlb_args *ita;
cpuset_t cpus;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return (NULL);
sched_pin();
cpus = pm->pm_active;
@@ -259,7 +261,7 @@ ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
struct ipi_tlb_args *ita;
cpuset_t cpus;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return (NULL);
sched_pin();
cpus = pm->pm_active;
@@ -284,7 +286,7 @@ ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
struct ipi_tlb_args *ita;
cpuset_t cpus;
- if (__predict_false(smp_started == 0))
+ if (__predict_false(atomic_load_acq_int(&smp_started) == 0))
return (NULL);
sched_pin();
cpus = pm->pm_active;
diff --git a/sys/sparc64/pci/fire.c b/sys/sparc64/pci/fire.c
index 84526f0..be0c64b 100644
--- a/sys/sparc64/pci/fire.c
+++ b/sys/sparc64/pci/fire.c
@@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/openfirm.h>
#include <vm/vm.h>
@@ -68,7 +67,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/bus_common.h>
#include <machine/bus_private.h>
-#include <machine/fsr.h>
#include <machine/iommureg.h>
#include <machine/iommuvar.h>
#include <machine/pmap.h>
@@ -111,19 +109,14 @@ static driver_filter_t fire_xcb;
/*
* Methods
*/
-static bus_activate_resource_t fire_activate_resource;
-static bus_adjust_resource_t fire_adjust_resource;
static pcib_alloc_msi_t fire_alloc_msi;
static pcib_alloc_msix_t fire_alloc_msix;
static bus_alloc_resource_t fire_alloc_resource;
static device_attach_t fire_attach;
-static bus_get_dma_tag_t fire_get_dma_tag;
-static ofw_bus_get_node_t fire_get_node;
static pcib_map_msi_t fire_map_msi;
static pcib_maxslots_t fire_maxslots;
static device_probe_t fire_probe;
static pcib_read_config_t fire_read_config;
-static bus_read_ivar_t fire_read_ivar;
static pcib_release_msi_t fire_release_msi;
static pcib_release_msix_t fire_release_msix;
static pcib_route_interrupt_t fire_route_interrupt;
@@ -140,15 +133,15 @@ static device_method_t fire_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_read_ivar, fire_read_ivar),
+ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar),
DEVMETHOD(bus_setup_intr, fire_setup_intr),
DEVMETHOD(bus_teardown_intr, fire_teardown_intr),
DEVMETHOD(bus_alloc_resource, fire_alloc_resource),
- DEVMETHOD(bus_activate_resource, fire_activate_resource),
+ DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_adjust_resource, fire_adjust_resource),
+ DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_get_dma_tag, fire_get_dma_tag),
+ DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag),
/* pcib interface */
DEVMETHOD(pcib_maxslots, fire_maxslots),
@@ -162,7 +155,7 @@ static device_method_t fire_methods[] = {
DEVMETHOD(pcib_map_msi, fire_map_msi),
/* ofw_bus interface */
- DEVMETHOD(ofw_bus_get_node, fire_get_node),
+ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node),
DEVMETHOD_END
};
@@ -296,7 +289,7 @@ fire_attach(device_t dev)
struct ofw_pci_msi_eq_to_devino msi_eq_to_devino;
struct fire_msiqarg *fmqa;
struct timecounter *tc;
- struct ofw_pci_ranges *range;
+ bus_dma_tag_t dmat;
uint64_t ino_bitmap, val;
phandle_t node;
uint32_t prop, prop_array[2];
@@ -310,7 +303,6 @@ fire_attach(device_t dev)
mode = desc->fd_mode;
sc->sc_dev = dev;
- sc->sc_node = node;
sc->sc_mode = mode;
sc->sc_flags = 0;
@@ -715,81 +707,21 @@ fire_attach(device_t dev)
sc->sc_is.is_bushandle = rman_get_bushandle(sc->sc_mem_res[FIRE_PCI]);
sc->sc_is.is_iommu = FO_PCI_MMU;
val = FIRE_PCI_READ_8(sc, FO_PCI_MMU + IMR_CTL);
- iommu_init(device_get_nameunit(sc->sc_dev), &sc->sc_is, 7, -1, 0);
+ iommu_init(device_get_nameunit(dev), &sc->sc_is, 7, -1, 0);
#ifdef FIRE_DEBUG
device_printf(dev, "FO_PCI_MMU + IMR_CTL 0x%016llx -> 0x%016llx\n",
(long long unsigned)val, (long long unsigned)sc->sc_is.is_cr);
#endif
-
- /* Initialize memory and I/O rmans. */
- sc->sc_pci_io_rman.rm_type = RMAN_ARRAY;
- sc->sc_pci_io_rman.rm_descr = "Fire PCI I/O Ports";
- if (rman_init(&sc->sc_pci_io_rman) != 0 ||
- rman_manage_region(&sc->sc_pci_io_rman, 0, FO_IO_SIZE) != 0)
- panic("%s: failed to set up I/O rman", __func__);
- sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_pci_mem_rman.rm_descr = "Fire PCI Memory";
- if (rman_init(&sc->sc_pci_mem_rman) != 0 ||
- rman_manage_region(&sc->sc_pci_mem_rman, 0, FO_MEM_SIZE) != 0)
- panic("%s: failed to set up memory rman", __func__);
-
- i = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
- /*
- * Make sure that the expected ranges are present. The
- * OFW_PCI_CS_MEM64 one is not currently used though.
- */
- if (i != FIRE_NRANGE)
- panic("%s: unsupported number of ranges", __func__);
- /*
- * Find the addresses of the various bus spaces.
- * There should not be multiple ones of one kind.
- * The physical start addresses of the ranges are the configuration,
- * memory and I/O handles.
- */
- for (i = 0; i < FIRE_NRANGE; i++) {
- j = OFW_PCI_RANGE_CS(&range[i]);
- if (sc->sc_pci_bh[j] != 0)
- panic("%s: duplicate range for space %d",
- __func__, j);
- sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]);
- }
- free(range, M_OFWPROP);
-
- /* Allocate our tags. */
- sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
- sc->sc_mem_res[FIRE_PCI]), PCI_IO_BUS_SPACE, NULL);
- if (sc->sc_pci_iot == NULL)
- panic("%s: could not allocate PCI I/O tag", __func__);
- sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
- sc->sc_mem_res[FIRE_PCI]), PCI_CONFIG_BUS_SPACE, NULL);
- if (sc->sc_pci_cfgt == NULL)
- panic("%s: could not allocate PCI configuration space tag",
- __func__);
+ /* Create our DMA tag. */
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0x100000000,
sc->sc_is.is_pmaxaddr, ~0, NULL, NULL, sc->sc_is.is_pmaxaddr,
- 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
+ 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0)
panic("%s: could not create PCI DMA tag", __func__);
- /* Customize the tag. */
- sc->sc_pci_dmat->dt_cookie = &sc->sc_is;
- sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods;
-
- /*
- * Get the bus range from the firmware.
- * NB: Neither Fire nor Oberon support PCI bus reenumeration.
- */
- i = OF_getprop(node, "bus-range", (void *)prop_array,
- sizeof(prop_array));
- if (i == -1)
- panic("%s: could not get bus-range", __func__);
- if (i != sizeof(prop_array))
- panic("%s: broken bus-range (%d)", __func__, i);
- sc->sc_pci_secbus = prop_array[0];
- sc->sc_pci_subbus = prop_array[1];
- if (bootverbose != 0)
- device_printf(dev, "bus range %u to %u; PCI bus %d\n",
- sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus);
+ dmat->dt_cookie = &sc->sc_is;
+ dmat->dt_mt = &sc->sc_dma_methods;
- ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t));
+ if (ofw_pci_attach_common(dev, dmat, FO_IO_SIZE, FO_MEM_SIZE) != 0)
+ panic("%s: ofw_pci_attach_common() failed", __func__);
#define FIRE_SYSCTL_ADD_UINT(name, arg, desc) \
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), \
@@ -1392,136 +1324,44 @@ static uint32_t
fire_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
int width)
{
- struct fire_softc *sc;
- bus_space_handle_t bh;
- u_long offset = 0;
- uint32_t r, wrd;
- int i;
- uint16_t shrt;
- uint8_t byte;
-
- sc = device_get_softc(dev);
- if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
- slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX)
- return (-1);
-
- offset = FO_CONF_OFF(bus, slot, func, reg);
- bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
- switch (width) {
- case 1:
- i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte);
- r = byte;
- break;
- case 2:
- i = bus_space_peek_2(sc->sc_pci_cfgt, bh, offset, &shrt);
- r = shrt;
- break;
- case 4:
- i = bus_space_peek_4(sc->sc_pci_cfgt, bh, offset, &wrd);
- r = wrd;
- break;
- default:
- panic("%s: bad width", __func__);
- /* NOTREACHED */
- }
- if (i) {
-#ifdef FIRE_DEBUG
- printf("%s: read data error reading: %d.%d.%d: 0x%x\n",
- __func__, bus, slot, func, reg);
-#endif
- r = -1;
- }
- return (r);
+ return (ofw_pci_read_config_common(dev, PCIE_REGMAX, FO_CONF_OFF(bus,
+ slot, func, reg), bus, slot, func, reg, width));
}
static void
fire_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
uint32_t val, int width)
{
- struct fire_softc *sc;
- bus_space_handle_t bh;
- u_long offset = 0;
-
- sc = device_get_softc(dev);
- if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
- slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCIE_REGMAX)
- return;
- offset = FO_CONF_OFF(bus, slot, func, reg);
- bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
- switch (width) {
- case 1:
- bus_space_write_1(sc->sc_pci_cfgt, bh, offset, val);
- break;
- case 2:
- bus_space_write_2(sc->sc_pci_cfgt, bh, offset, val);
- break;
- case 4:
- bus_space_write_4(sc->sc_pci_cfgt, bh, offset, val);
- break;
- default:
- panic("%s: bad width", __func__);
- /* NOTREACHED */
- }
+ ofw_pci_write_config_common(dev, PCIE_REGMAX, FO_CONF_OFF(bus, slot,
+ func, reg), bus, slot, func, reg, val, width);
}
static int
fire_route_interrupt(device_t bridge, device_t dev, int pin)
{
- struct fire_softc *sc;
- struct ofw_pci_register reg;
- ofw_pci_intr_t pintr, mintr;
-
- sc = device_get_softc(bridge);
- pintr = pin;
- if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
- &reg, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
- NULL) != 0)
- return (mintr);
-
- device_printf(bridge, "could not route pin %d for device %d.%d\n",
- pin, pci_get_slot(dev), pci_get_function(dev));
- return (PCI_INVALID_IRQ);
-}
-
-static int
-fire_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct fire_softc *sc;
-
- sc = device_get_softc(dev);
- switch (which) {
- case PCIB_IVAR_DOMAIN:
- *result = device_get_unit(dev);
- return (0);
- case PCIB_IVAR_BUS:
- *result = sc->sc_pci_secbus;
- return (0);
- }
- return (ENOENT);
+ ofw_pci_intr_t mintr;
+
+ mintr = ofw_pci_route_interrupt_common(bridge, dev, pin);
+ if (!PCI_INTERRUPT_VALID(mintr))
+ device_printf(bridge,
+ "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (mintr);
}
static void
fire_dmamap_sync(bus_dma_tag_t dt __unused, bus_dmamap_t map,
bus_dmasync_op_t op)
{
- static u_char buf[VIS_BLOCKSIZE] __aligned(VIS_BLOCKSIZE);
- register_t reg, s;
if ((map->dm_flags & DMF_LOADED) == 0)
return;
- if ((op & BUS_DMASYNC_POSTREAD) != 0) {
- s = intr_disable();
- reg = rd(fprs);
- wr(fprs, reg | FPRS_FEF, 0);
- __asm __volatile("stda %%f0, [%0] %1"
- : : "r" (buf), "n" (ASI_BLK_COMMIT_S));
- membar(Sync);
- wr(fprs, reg, 0);
- intr_restore(s);
- } else if ((op & BUS_DMASYNC_PREWRITE) != 0)
+ if ((op & BUS_DMASYNC_POSTREAD) != 0)
+ ofw_pci_dmamap_sync_stst_order_common();
+ else if ((op & BUS_DMASYNC_PREWRITE) != 0)
membar(Sync);
}
@@ -2015,122 +1855,13 @@ fire_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct fire_softc *sc;
- struct resource *rv;
- struct rman *rm;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- /*
- * XXX: Don't accept blank ranges for now, only single
- * interrupts. The other case should not happen with
- * the MI PCI code...
- * XXX: This may return a resource that is out of the
- * range that was specified. Is this correct...?
- */
- if (start != end)
- panic("%s: XXX: interrupt range", __func__);
- if (*rid == 0)
- start = end = INTMAP_VEC(sc->sc_ign, end);
- return (bus_generic_alloc_resource(bus, child, type, rid,
- start, end, count, flags));
- case SYS_RES_MEMORY:
- rm = &sc->sc_pci_mem_rman;
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_pci_io_rman;
- break;
- default:
- return (NULL);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
- child);
- if (rv == NULL)
- return (NULL);
- rman_set_rid(rv, *rid);
-
- if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
- *rid, rv) != 0) {
- rman_release_resource(rv);
- return (NULL);
- }
- return (rv);
-}
-
-static int
-fire_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
- struct fire_softc *sc;
- struct bus_space_tag *tag;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- return (bus_generic_activate_resource(bus, child, type, rid,
- r));
- case SYS_RES_MEMORY:
- tag = sparc64_alloc_bus_tag(r, rman_get_bustag(
- sc->sc_mem_res[FIRE_PCI]), PCI_MEMORY_BUS_SPACE, NULL);
- if (tag == NULL)
- return (ENOMEM);
- rman_set_bustag(r, tag);
- rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
- rman_get_start(r));
- break;
- case SYS_RES_IOPORT:
- rman_set_bustag(r, sc->sc_pci_iot);
- rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
- rman_get_start(r));
- break;
- }
- return (rman_activate_resource(r));
-}
-static int
-fire_adjust_resource(device_t bus, device_t child, int type,
- struct resource *r, u_long start, u_long end)
-{
- struct fire_softc *sc;
- struct rman *rm;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- return (bus_generic_adjust_resource(bus, child, type, r,
- start, end));
- case SYS_RES_MEMORY:
- rm = &sc->sc_pci_mem_rman;
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_pci_io_rman;
- break;
- default:
- return (EINVAL);
+ if (type == SYS_RES_IRQ && *rid == 0) {
+ sc = device_get_softc(bus);
+ start = end = INTMAP_VEC(sc->sc_ign, end);
}
- if (rman_is_region_manager(r, rm) == 0)
- return (EINVAL);
- return (rman_adjust_resource(r, start, end));
-}
-
-static bus_dma_tag_t
-fire_get_dma_tag(device_t bus, device_t child __unused)
-{
- struct fire_softc *sc;
-
- sc = device_get_softc(bus);
- return (sc->sc_pci_dmat);
-}
-
-static phandle_t
-fire_get_node(device_t bus, device_t child __unused)
-{
- struct fire_softc *sc;
-
- sc = device_get_softc(bus);
- /* We only have one child, the PCI bus, which needs our own node. */
- return (sc->sc_node);
+ return (ofw_pci_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
}
static u_int
diff --git a/sys/sparc64/pci/firereg.h b/sys/sparc64/pci/firereg.h
index 247a3f7..715d3b7 100644
--- a/sys/sparc64/pci/firereg.h
+++ b/sys/sparc64/pci/firereg.h
@@ -30,7 +30,6 @@
#define _SPARC64_PCI_FIREREG_H_
#define FIRE_NINTR 3 /* 2 OFW + 1 MSIq */
-#define FIRE_NRANGE 4
#define FIRE_NREG 2
#define FIRE_PCI 0
diff --git a/sys/sparc64/pci/firevar.h b/sys/sparc64/pci/firevar.h
index d414c1a..36fd8ea 100644
--- a/sys/sparc64/pci/firevar.h
+++ b/sys/sparc64/pci/firevar.h
@@ -32,6 +32,12 @@
#define _SPARC64_PCI_FIREVAR_H_
struct fire_softc {
+ /*
+ * This is here so that we can hook up the common bus interface
+ * methods in ofw_pci.c directly.
+ */
+ struct ofw_pci_softc sc_ops;
+
struct iommu_state sc_is;
struct bus_dma_methods sc_dma_methods;
@@ -42,13 +48,6 @@ struct fire_softc {
struct resource *sc_irq_res[FIRE_NINTR];
void *sc_ihand[FIRE_NINTR];
- struct rman sc_pci_mem_rman;
- struct rman sc_pci_io_rman;
- bus_space_handle_t sc_pci_bh[FIRE_NRANGE];
- bus_space_tag_t sc_pci_cfgt;
- bus_space_tag_t sc_pci_iot;
- bus_dma_tag_t sc_pci_dmat;
-
device_t sc_dev;
uint64_t *sc_msiq;
@@ -66,8 +65,6 @@ struct fire_softc {
uint32_t sc_msiq_first;
uint32_t sc_msiq_ino_first;
- phandle_t sc_node;
-
u_int sc_mode;
#define FIRE_MODE_FIRE 0
#define FIRE_MODE_OBERON 1
@@ -87,11 +84,6 @@ struct fire_softc {
uint32_t sc_stats_tlu_oe_rx_err;
uint32_t sc_stats_tlu_oe_tx_err;
uint32_t sc_stats_ubc_dmardue;
-
- uint8_t sc_pci_secbus;
- uint8_t sc_pci_subbus;
-
- struct ofw_bus_iinfo sc_pci_iinfo;
};
#endif /* !_SPARC64_PCI_FIREVAR_H_ */
diff --git a/sys/sparc64/pci/ofw_pci.c b/sys/sparc64/pci/ofw_pci.c
new file mode 100644
index 0000000..ae03ed3
--- /dev/null
+++ b/sys/sparc64/pci/ofw_pci.c
@@ -0,0 +1,412 @@
+/*-
+ * Copyright (c) 1999, 2000 Matthew R. Green
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>
+ * Copyright (c) 2005 - 2015 by Marius Strobl <marius@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: NetBSD: psycho.c,v 1.35 2001/09/10 16:17:06 eeh Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ofw_pci.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/openfirm.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <machine/asi.h>
+#include <machine/bus.h>
+#include <machine/bus_private.h>
+#include <machine/cpufunc.h>
+#include <machine/fsr.h>
+#include <machine/resource.h>
+
+#include <sparc64/pci/ofw_pci.h>
+
+/* XXX */
+extern struct bus_space_tag nexus_bustag;
+
+int
+ofw_pci_attach_common(device_t dev, bus_dma_tag_t dmat, u_long iosize,
+ u_long memsize)
+{
+ struct ofw_pci_softc *sc;
+ struct ofw_pci_ranges *range;
+ phandle_t node;
+ uint32_t prop_array[2];
+ u_int i, j, nrange;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+ sc->sc_node = node;
+ sc->sc_pci_dmat = dmat;
+
+ /* Initialize memory and I/O rmans. */
+ sc->sc_pci_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_pci_io_rman.rm_descr = "PCI I/O Ports";
+ if (rman_init(&sc->sc_pci_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_pci_io_rman, 0, iosize) != 0) {
+ device_printf(dev, "failed to set up I/O rman\n");
+ return (ENXIO);
+ }
+ sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_pci_mem_rman.rm_descr = "PCI Memory";
+ if (rman_init(&sc->sc_pci_mem_rman) != 0 ||
+ rman_manage_region(&sc->sc_pci_mem_rman, 0, memsize) != 0) {
+ device_printf(dev, "failed to set up memory rman\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Find the addresses of the various bus spaces. The physical
+ * start addresses of the ranges are the configuration, I/O and
+ * memory handles. There should not be multiple ones of one kind.
+ */
+ nrange = OF_getprop_alloc(node, "ranges", sizeof(*range),
+ (void **)&range);
+ for (i = 0; i < nrange; i++) {
+ j = OFW_PCI_RANGE_CS(&range[i]);
+ if (sc->sc_pci_bh[j] != 0) {
+ device_printf(dev, "duplicate range for space %d\n",
+ j);
+ free(range, M_OFWPROP);
+ return (EINVAL);
+ }
+ sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]);
+ }
+ free(range, M_OFWPROP);
+
+ /*
+ * Make sure that the expected ranges are actually present.
+ * The OFW_PCI_CS_MEM64 one is not currently used.
+ */
+ if (sc->sc_pci_bh[OFW_PCI_CS_CONFIG] == 0) {
+ device_printf(dev, "missing CONFIG range\n");
+ return (ENXIO);
+ }
+ if (sc->sc_pci_bh[OFW_PCI_CS_IO] == 0) {
+ device_printf(dev, "missing IO range\n");
+ return (ENXIO);
+ }
+ if (sc->sc_pci_bh[OFW_PCI_CS_MEM32] == 0) {
+ device_printf(dev, "missing MEM32 range\n");
+ return (ENXIO);
+ }
+
+ /* Allocate our tags. */
+ sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, &nexus_bustag,
+ PCI_IO_BUS_SPACE, NULL);
+ if (sc->sc_pci_iot == NULL) {
+ device_printf(dev, "could not allocate PCI I/O tag\n");
+ return (ENXIO);
+ }
+ sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, &nexus_bustag,
+ PCI_CONFIG_BUS_SPACE, NULL);
+ if (sc->sc_pci_cfgt == NULL) {
+ device_printf(dev,
+ "could not allocate PCI configuration space tag\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Get the bus range from the firmware.
+ */
+ i = OF_getprop(node, "bus-range", (void *)prop_array,
+ sizeof(prop_array));
+ if (i == -1) {
+ device_printf(dev, "could not get bus-range\n");
+ return (ENXIO);
+ }
+ if (i != sizeof(prop_array)) {
+ device_printf(dev, "broken bus-range (%d)", i);
+ return (EINVAL);
+ }
+ sc->sc_pci_secbus = prop_array[0];
+ sc->sc_pci_subbus = prop_array[1];
+ if (bootverbose != 0)
+ device_printf(dev, "bus range %u to %u; PCI bus %d\n",
+ sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus);
+
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t));
+
+ return (0);
+}
+
+uint32_t
+ofw_pci_read_config_common(device_t dev, u_int regmax, u_long offset,
+ u_int bus, u_int slot, u_int func, u_int reg, int width)
+{
+ struct ofw_pci_softc *sc;
+ bus_space_handle_t bh;
+ uint32_t r, wrd;
+ int i;
+ uint16_t shrt;
+ uint8_t byte;
+
+ sc = device_get_softc(dev);
+ if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
+ slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > regmax)
+ return (-1);
+
+ bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
+ switch (width) {
+ case 1:
+ i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte);
+ r = byte;
+ break;
+ case 2:
+ i = bus_space_peek_2(sc->sc_pci_cfgt, bh, offset, &shrt);
+ r = shrt;
+ break;
+ case 4:
+ i = bus_space_peek_4(sc->sc_pci_cfgt, bh, offset, &wrd);
+ r = wrd;
+ break;
+ default:
+ panic("%s: bad width %d", __func__, width);
+ /* NOTREACHED */
+ }
+
+ if (i) {
+#ifdef OFW_PCI_DEBUG
+ printf("%s: read data error reading: %d.%d.%d: 0x%x\n",
+ __func__, bus, slot, func, reg);
+#endif
+ r = -1;
+ }
+ return (r);
+}
+
+void
+ofw_pci_write_config_common(device_t dev, u_int regmax, u_long offset,
+ u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width)
+{
+ struct ofw_pci_softc *sc;
+ bus_space_handle_t bh;
+
+ sc = device_get_softc(dev);
+ if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
+ slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > regmax)
+ return;
+
+ bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
+ switch (width) {
+ case 1:
+ bus_space_write_1(sc->sc_pci_cfgt, bh, offset, val);
+ break;
+ case 2:
+ bus_space_write_2(sc->sc_pci_cfgt, bh, offset, val);
+ break;
+ case 4:
+ bus_space_write_4(sc->sc_pci_cfgt, bh, offset, val);
+ break;
+ default:
+ panic("%s: bad width %d", __func__, width);
+ /* NOTREACHED */
+ }
+}
+
+ofw_pci_intr_t
+ofw_pci_route_interrupt_common(device_t bridge, device_t dev, int pin)
+{
+ struct ofw_pci_softc *sc;
+ struct ofw_pci_register reg;
+ ofw_pci_intr_t pintr, mintr;
+
+ sc = device_get_softc(bridge);
+ pintr = pin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
+ &reg, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
+ NULL) != 0)
+ return (mintr);
+ return (PCI_INVALID_IRQ);
+}
+
+void
+ofw_pci_dmamap_sync_stst_order_common(void)
+{
+ static u_char buf[VIS_BLOCKSIZE] __aligned(VIS_BLOCKSIZE);
+ register_t reg, s;
+
+ s = intr_disable();
+ reg = rd(fprs);
+ wr(fprs, reg | FPRS_FEF, 0);
+ __asm __volatile("stda %%f0, [%0] %1"
+ : : "r" (buf), "n" (ASI_BLK_COMMIT_S));
+ membar(Sync);
+ wr(fprs, reg, 0);
+ intr_restore(s);
+}
+
+int
+ofw_pci_read_ivar(device_t dev, device_t child __unused, int which,
+ uintptr_t *result)
+{
+ struct ofw_pci_softc *sc;
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = device_get_unit(dev);
+ return (0);
+ case PCIB_IVAR_BUS:
+ sc = device_get_softc(dev);
+ *result = sc->sc_pci_secbus;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+struct resource *
+ofw_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct ofw_pci_softc *sc;
+ struct resource *rv;
+ struct rman *rm;
+
+ sc = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IRQ:
+ /*
+ * XXX: Don't accept blank ranges for now, only single
+ * interrupts. The other case should not happen with
+ * the MI PCI code ...
+ * XXX: This may return a resource that is out of the
+ * range that was specified. Is this correct ...?
+ */
+ if (start != end)
+ panic("%s: XXX: interrupt range", __func__);
+ return (bus_generic_alloc_resource(bus, child, type, rid,
+ start, end, count, flags));
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_pci_mem_rman;
+ break;
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_pci_io_rman;
+ break;
+ default:
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
+ child);
+ if (rv == NULL)
+ return (NULL);
+ rman_set_rid(rv, *rid);
+
+ if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
+ *rid, rv) != 0) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ return (rv);
+}
+
+int
+ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ struct ofw_pci_softc *sc;
+ struct bus_space_tag *tag;
+
+ sc = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IRQ:
+ return (bus_generic_activate_resource(bus, child, type, rid,
+ r));
+ case SYS_RES_MEMORY:
+ tag = sparc64_alloc_bus_tag(r, &nexus_bustag,
+ PCI_MEMORY_BUS_SPACE, NULL);
+ if (tag == NULL)
+ return (ENOMEM);
+ rman_set_bustag(r, tag);
+ rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
+ rman_get_start(r));
+ break;
+ case SYS_RES_IOPORT:
+ rman_set_bustag(r, sc->sc_pci_iot);
+ rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
+ rman_get_start(r));
+ break;
+ }
+ return (rman_activate_resource(r));
+}
+
+int
+ofw_pci_adjust_resource(device_t bus, device_t child, int type,
+ struct resource *r, u_long start, u_long end)
+{
+ struct ofw_pci_softc *sc;
+ struct rman *rm;
+
+ sc = device_get_softc(bus);
+ switch (type) {
+ case SYS_RES_IRQ:
+ return (bus_generic_adjust_resource(bus, child, type, r,
+ start, end));
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_pci_mem_rman;
+ break;
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_pci_io_rman;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (rman_is_region_manager(r, rm) == 0)
+ return (EINVAL);
+ return (rman_adjust_resource(r, start, end));
+}
+
+bus_dma_tag_t
+ofw_pci_get_dma_tag(device_t bus, device_t child __unused)
+{
+ struct ofw_pci_softc *sc;
+
+ sc = device_get_softc(bus);
+ return (sc->sc_pci_dmat);
+}
+
+phandle_t
+ofw_pci_get_node(device_t bus, device_t child __unused)
+{
+ struct ofw_pci_softc *sc;
+
+ sc = device_get_softc(bus);
+ /* We only have one child, the PCI bus, which needs our own node. */
+ return (sc->sc_node);
+}
diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h
index 3915fa7..6d1e5d9 100644
--- a/sys/sparc64/pci/ofw_pci.h
+++ b/sys/sparc64/pci/ofw_pci.h
@@ -62,6 +62,8 @@
#ifndef _SPARC64_PCI_OFW_PCI_H_
#define _SPARC64_PCI_OFW_PCI_H_
+#include <sys/rman.h>
+
#include <dev/ofw/ofw_bus_subr.h>
#include "ofw_pci_if.h"
@@ -73,6 +75,7 @@ typedef uint32_t ofw_pci_intr_t;
#define OFW_PCI_CS_IO 0x01
#define OFW_PCI_CS_MEM32 0x02
#define OFW_PCI_CS_MEM64 0x03
+#define OFW_PCI_NUM_CS 4
/* OFW device types */
#define OFW_TYPE_PCI "pci"
@@ -124,4 +127,44 @@ struct ofw_pci_ranges {
/* default values */
#define OFW_PCI_LATENCY 64
+/*
+ * Common and generic parts of host-PCI-bridge support
+ */
+
+struct ofw_pci_softc {
+ struct rman sc_pci_mem_rman;
+ struct rman sc_pci_io_rman;
+
+ bus_space_handle_t sc_pci_bh[OFW_PCI_NUM_CS];
+ bus_space_tag_t sc_pci_cfgt;
+ bus_space_tag_t sc_pci_iot;
+ bus_dma_tag_t sc_pci_dmat;
+
+ struct ofw_bus_iinfo sc_pci_iinfo;
+
+ phandle_t sc_node;
+
+ uint8_t sc_pci_secbus;
+ uint8_t sc_pci_subbus;
+};
+
+int ofw_pci_attach_common(device_t dev, bus_dma_tag_t dmat, u_long iosize,
+ u_long memsize);
+uint32_t ofw_pci_read_config_common(device_t dev, u_int regmax, u_long offset,
+ u_int bus, u_int slot, u_int func, u_int reg, int width);
+void ofw_pci_write_config_common(device_t dev, u_int regmax, u_long offset,
+ u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int width);
+ofw_pci_intr_t ofw_pci_route_interrupt_common(device_t bridge, device_t dev,
+ int pin);
+
+void ofw_pci_dmamap_sync_stst_order_common(void);
+
+bus_activate_resource_t ofw_pci_activate_resource;
+bus_adjust_resource_t ofw_pci_adjust_resource;
+bus_alloc_resource_t ofw_pci_alloc_resource;
+bus_get_dma_tag_t ofw_pci_get_dma_tag;
+bus_read_ivar_t ofw_pci_read_ivar;
+
+ofw_bus_get_node_t ofw_pci_get_node;
+
#endif /* ! _SPARC64_PCI_OFW_PCI_H_ */
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 4881d1f..f688df6 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
@@ -110,17 +109,12 @@ static void psycho_iommu_init(struct psycho_softc *, int, uint32_t);
*/
static device_probe_t psycho_probe;
static device_attach_t psycho_attach;
-static bus_read_ivar_t psycho_read_ivar;
static bus_setup_intr_t psycho_setup_intr;
static bus_alloc_resource_t psycho_alloc_resource;
-static bus_activate_resource_t psycho_activate_resource;
-static bus_adjust_resource_t psycho_adjust_resource;
-static bus_get_dma_tag_t psycho_get_dma_tag;
static pcib_maxslots_t psycho_maxslots;
static pcib_read_config_t psycho_read_config;
static pcib_write_config_t psycho_write_config;
static pcib_route_interrupt_t psycho_route_interrupt;
-static ofw_bus_get_node_t psycho_get_node;
static ofw_pci_setup_device_t psycho_setup_device;
static device_method_t psycho_methods[] = {
@@ -132,15 +126,15 @@ static device_method_t psycho_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_read_ivar, psycho_read_ivar),
+ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar),
DEVMETHOD(bus_setup_intr, psycho_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, psycho_alloc_resource),
- DEVMETHOD(bus_activate_resource, psycho_activate_resource),
+ DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_adjust_resource, psycho_adjust_resource),
+ DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_get_dma_tag, psycho_get_dma_tag),
+ DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag),
/* pcib interface */
DEVMETHOD(pcib_maxslots, psycho_maxslots),
@@ -149,7 +143,7 @@ static device_method_t psycho_methods[] = {
DEVMETHOD(pcib_route_interrupt, psycho_route_interrupt),
/* ofw_bus interface */
- DEVMETHOD(ofw_bus_get_node, psycho_get_node),
+ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node),
/* ofw_pci interface */
DEVMETHOD(ofw_pci_setup_device, psycho_setup_device),
@@ -288,12 +282,12 @@ psycho_attach(device_t dev)
{
struct psycho_icarg *pica;
struct psycho_softc *asc, *sc, *osc;
- struct ofw_pci_ranges *range;
const struct psycho_desc *desc;
bus_addr_t intrclr, intrmap;
+ bus_dma_tag_t dmat;
uint64_t csr, dr;
phandle_t node;
- uint32_t dvmabase, prop, prop_array[2];
+ uint32_t dvmabase, prop;
u_int rerun, ver;
int i, j;
@@ -301,7 +295,6 @@ psycho_attach(device_t dev)
sc = device_get_softc(dev);
desc = psycho_get_desc(dev);
- sc->sc_node = node;
sc->sc_dev = dev;
sc->sc_mode = desc->pd_mode;
@@ -367,6 +360,7 @@ psycho_attach(device_t dev)
panic("%s: mutex not initialized", __func__);
sc->sc_mtx = osc->sc_mtx;
}
+ SLIST_INSERT_HEAD(&psycho_softcs, sc, sc_link);
csr = PSYCHO_READ8(sc, PSR_CS);
ver = PSYCHO_GCSR_VERS(csr);
@@ -435,43 +429,6 @@ psycho_attach(device_t dev)
} else
dvmabase = -1;
- /* Initialize memory and I/O rmans. */
- sc->sc_pci_io_rman.rm_type = RMAN_ARRAY;
- sc->sc_pci_io_rman.rm_descr = "Psycho PCI I/O Ports";
- if (rman_init(&sc->sc_pci_io_rman) != 0 ||
- rman_manage_region(&sc->sc_pci_io_rman, 0, PSYCHO_IO_SIZE) != 0)
- panic("%s: failed to set up I/O rman", __func__);
- sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_pci_mem_rman.rm_descr = "Psycho PCI Memory";
- if (rman_init(&sc->sc_pci_mem_rman) != 0 ||
- rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0)
- panic("%s: failed to set up memory rman", __func__);
-
- i = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
- /*
- * Make sure that the expected ranges are present. The
- * OFW_PCI_CS_MEM64 one is not currently used though.
- */
- if (i != PSYCHO_NRANGE)
- panic("%s: unsupported number of ranges", __func__);
- /*
- * Find the addresses of the various bus spaces.
- * There should not be multiple ones of one kind.
- * The physical start addresses of the ranges are the configuration,
- * memory and I/O handles.
- */
- for (i = 0; i < PSYCHO_NRANGE; i++) {
- j = OFW_PCI_RANGE_CS(&range[i]);
- if (sc->sc_pci_bh[j] != 0)
- panic("%s: duplicate range for space %d",
- __func__, j);
- sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]);
- }
- free(range, M_OFWPROP);
-
- /* Register the softc, this is needed for paired Psychos. */
- SLIST_INSERT_HEAD(&psycho_softcs, sc, sc_link);
-
/*
* If we're a Hummingbird/Sabre or the first of a pair of Psychos
* to arrive here, do the interrupt setup and start up the IOMMU.
@@ -572,39 +529,21 @@ psycho_attach(device_t dev)
iommu_reset(sc->sc_is);
}
- /* Allocate our tags. */
- sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
- sc->sc_mem_res), PCI_IO_BUS_SPACE, NULL);
- if (sc->sc_pci_iot == NULL)
- panic("%s: could not allocate PCI I/O tag", __func__);
- sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
- sc->sc_mem_res), PCI_CONFIG_BUS_SPACE, NULL);
- if (sc->sc_pci_cfgt == NULL)
- panic("%s: could not allocate PCI configuration space tag",
- __func__);
+ /* Create our DMA tag. */
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
sc->sc_is->is_pmaxaddr, ~0, NULL, NULL, sc->sc_is->is_pmaxaddr,
- 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
+ 0xff, 0xffffffff, 0, NULL, NULL, &dmat) != 0)
panic("%s: could not create PCI DMA tag", __func__);
- /* Customize the tag. */
- sc->sc_pci_dmat->dt_cookie = sc->sc_is;
- sc->sc_pci_dmat->dt_mt = sc->sc_dma_methods;
-
- i = OF_getprop(node, "bus-range", (void *)prop_array,
- sizeof(prop_array));
- if (i == -1)
- panic("%s: could not get bus-range", __func__);
- if (i != sizeof(prop_array))
- panic("%s: broken bus-range (%d)", __func__, i);
- sc->sc_pci_secbus = prop_array[0];
- sc->sc_pci_subbus = prop_array[1];
- if (bootverbose)
- device_printf(dev, "bus range %u to %u; PCI bus %d\n",
- sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus);
+ dmat->dt_cookie = sc->sc_is;
+ dmat->dt_mt = sc->sc_dma_methods;
+
+ if (ofw_pci_attach_common(dev, dmat, PSYCHO_IO_SIZE,
+ PSYCHO_MEM_SIZE) != 0)
+ panic("%s: ofw_pci_attach_common() failed", __func__);
/* Clear any pending PCI error bits. */
- PCIB_WRITE_CONFIG(dev, sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC,
- PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_pci_secbus,
+ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC,
+ PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_ops.sc_pci_secbus,
PCS_DEVICE, PCS_FUNC, PCIR_STATUS, 2), 2);
PCICTL_WRITE8(sc, PCR_CS, PCICTL_READ8(sc, PCR_CS));
PCICTL_WRITE8(sc, PCR_AFS, PCICTL_READ8(sc, PCR_AFS));
@@ -667,20 +606,20 @@ psycho_attach(device_t dev)
* Set the latency timer register as this isn't always done by the
* firmware.
*/
- PCIB_WRITE_CONFIG(dev, sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC,
+ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC,
PCIR_LATTIMER, OFW_PCI_LATENCY, 1);
for (i = PCIR_VENDOR; i < PCIR_STATUS; i += sizeof(uint16_t))
- le16enc(&sc->sc_pci_hpbcfg[i], bus_space_read_2(
- sc->sc_pci_cfgt, sc->sc_pci_bh[OFW_PCI_CS_CONFIG],
- PSYCHO_CONF_OFF(sc->sc_pci_secbus, PCS_DEVICE,
+ le16enc(&sc->sc_pci_hpbcfg[i],
+ bus_space_read_2(sc->sc_ops.sc_pci_cfgt,
+ sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG],
+ PSYCHO_CONF_OFF(sc->sc_ops.sc_pci_secbus, PCS_DEVICE,
PCS_FUNC, i)));
for (i = PCIR_REVID; i <= PCIR_BIST; i += sizeof(uint8_t))
- sc->sc_pci_hpbcfg[i] = bus_space_read_1(sc->sc_pci_cfgt,
- sc->sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF(
- sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i));
+ sc->sc_pci_hpbcfg[i] = bus_space_read_1(sc->sc_ops.sc_pci_cfgt,
+ sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF(
+ sc->sc_ops.sc_pci_secbus, PCS_DEVICE, PCS_FUNC, i));
- ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t));
/*
* On E250 the interrupt map entry for the EBus bridge is wrong,
* causing incorrect interrupts to be assigned to some devices on
@@ -691,9 +630,9 @@ psycho_attach(device_t dev)
* EBus devices will be used directly instead.
*/
if (strcmp(sparc64_model, "SUNW,Ultra-250") == 0 &&
- sc->sc_pci_iinfo.opi_imapmsk != NULL)
- *(ofw_pci_intr_t *)(&sc->sc_pci_iinfo.opi_imapmsk[
- sc->sc_pci_iinfo.opi_addrc]) = INTMAP_INO_MASK;
+ sc->sc_ops.sc_pci_iinfo.opi_imapmsk != NULL)
+ *(ofw_pci_intr_t *)(&sc->sc_ops.sc_pci_iinfo.opi_imapmsk[
+ sc->sc_ops.sc_pci_iinfo.opi_addrc]) = INTMAP_INO_MASK;
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
@@ -927,20 +866,8 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
int width)
{
struct psycho_softc *sc;
- bus_space_handle_t bh;
- u_long offset = 0;
- uint8_t byte;
- uint16_t shrt;
- uint32_t r, wrd;
- int i;
sc = device_get_softc(dev);
- if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
- slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCI_REGMAX)
- return (-1);
-
- bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
-
/*
* The Hummingbird and Sabre bridges are picky in that they
* only allow their config space to be accessed using the
@@ -956,9 +883,9 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
* The Psycho bridges contain a dupe of their header at 0x80
* which we nullify that way also.
*/
- if (bus == sc->sc_pci_secbus && slot == PCS_DEVICE &&
+ if (bus == sc->sc_ops.sc_pci_secbus && slot == PCS_DEVICE &&
func == PCS_FUNC) {
- if (offset % width != 0)
+ if (reg % width != 0)
return (-1);
if (reg >= sizeof(sc->sc_pci_hpbcfg))
@@ -967,8 +894,9 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
if ((reg < PCIR_STATUS && reg + width > PCIR_STATUS) ||
reg == PCIR_STATUS || reg == PCIR_STATUS + 1)
le16enc(&sc->sc_pci_hpbcfg[PCIR_STATUS],
- bus_space_read_2(sc->sc_pci_cfgt, bh,
- PSYCHO_CONF_OFF(sc->sc_pci_secbus,
+ bus_space_read_2(sc->sc_ops.sc_pci_cfgt,
+ sc->sc_ops.sc_pci_bh[OFW_PCI_CS_CONFIG],
+ PSYCHO_CONF_OFF(sc->sc_ops.sc_pci_secbus,
PCS_DEVICE, PCS_FUNC, PCIR_STATUS)));
switch (width) {
@@ -981,79 +909,29 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
}
}
- offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
- switch (width) {
- case 1:
- i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte);
- r = byte;
- break;
- case 2:
- i = bus_space_peek_2(sc->sc_pci_cfgt, bh, offset, &shrt);
- r = shrt;
- break;
- case 4:
- i = bus_space_peek_4(sc->sc_pci_cfgt, bh, offset, &wrd);
- r = wrd;
- break;
- default:
- panic("%s: bad width", __func__);
- /* NOTREACHED */
- }
-
- if (i) {
-#ifdef PSYCHO_DEBUG
- printf("%s: read data error reading: %d.%d.%d: 0x%x\n",
- __func__, bus, slot, func, reg);
-#endif
- r = -1;
- }
- return (r);
+ return (ofw_pci_read_config_common(dev, PCI_REGMAX,
+ PSYCHO_CONF_OFF(bus, slot, func, reg), bus, slot, func, reg,
+ width));
}
static void
psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, uint32_t val, int width)
{
- struct psycho_softc *sc;
- bus_space_handle_t bh;
- u_long offset = 0;
- sc = device_get_softc(dev);
- if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
- slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCI_REGMAX)
- return;
-
- offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
- bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
- switch (width) {
- case 1:
- bus_space_write_1(sc->sc_pci_cfgt, bh, offset, val);
- break;
- case 2:
- bus_space_write_2(sc->sc_pci_cfgt, bh, offset, val);
- break;
- case 4:
- bus_space_write_4(sc->sc_pci_cfgt, bh, offset, val);
- break;
- default:
- panic("%s: bad width", __func__);
- /* NOTREACHED */
- }
+ ofw_pci_write_config_common(dev, PCI_REGMAX, PSYCHO_CONF_OFF(bus,
+ slot, func, reg), bus, slot, func, reg, val, width);
}
static int
psycho_route_interrupt(device_t bridge, device_t dev, int pin)
{
struct psycho_softc *sc;
- struct ofw_pci_register reg;
bus_addr_t intrmap;
- ofw_pci_intr_t pintr, mintr;
+ ofw_pci_intr_t mintr;
- sc = device_get_softc(bridge);
- pintr = pin;
- if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
- &reg, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
- NULL))
+ mintr = ofw_pci_route_interrupt_common(bridge, dev, pin);
+ if (PCI_INTERRUPT_VALID(mintr))
return (mintr);
/*
* If this is outside of the range for an intpin, it's likely a full
@@ -1072,6 +950,7 @@ psycho_route_interrupt(device_t bridge, device_t dev, int pin)
* for bus A are one-based, while those for bus B seemingly have an
* offset of 2 (hence the factor of 3 below).
*/
+ sc = device_get_softc(dev);
intrmap = PSR_PCIA0_INT_MAP +
8 * (pci_get_slot(dev) - 1 + 3 * sc->sc_half);
mintr = INTINO(PSYCHO_READ8(sc, intrmap)) + pin - 1;
@@ -1081,23 +960,6 @@ psycho_route_interrupt(device_t bridge, device_t dev, int pin)
return (mintr);
}
-static int
-psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct psycho_softc *sc;
-
- sc = device_get_softc(dev);
- switch (which) {
- case PCIB_IVAR_DOMAIN:
- *result = device_get_unit(dev);
- return (0);
- case PCIB_IVAR_BUS:
- *result = sc->sc_pci_secbus;
- return (0);
- }
- return (ENOENT);
-}
-
static void
sabre_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
{
@@ -1180,121 +1042,13 @@ psycho_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct psycho_softc *sc;
- struct resource *rv;
- struct rman *rm;
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- /*
- * XXX: Don't accept blank ranges for now, only single
- * interrupts. The other case should not happen with
- * the MI PCI code...
- * XXX: This may return a resource that is out of the
- * range that was specified. Is this correct...?
- */
- if (start != end)
- panic("%s: XXX: interrupt range", __func__);
+ if (type == SYS_RES_IRQ) {
+ sc = device_get_softc(bus);
start = end = INTMAP_VEC(sc->sc_ign, end);
- return (bus_generic_alloc_resource(bus, child, type, rid,
- start, end, count, flags));
- case SYS_RES_MEMORY:
- rm = &sc->sc_pci_mem_rman;
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_pci_io_rman;
- break;
- default:
- return (NULL);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
- child);
- if (rv == NULL)
- return (NULL);
- rman_set_rid(rv, *rid);
-
- if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
- *rid, rv) != 0) {
- rman_release_resource(rv);
- return (NULL);
- }
- return (rv);
-}
-
-static int
-psycho_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
- struct psycho_softc *sc;
- struct bus_space_tag *tag;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- return (bus_generic_activate_resource(bus, child, type, rid,
- r));
- case SYS_RES_MEMORY:
- tag = sparc64_alloc_bus_tag(r, rman_get_bustag(
- sc->sc_mem_res), PCI_MEMORY_BUS_SPACE, NULL);
- if (tag == NULL)
- return (ENOMEM);
- rman_set_bustag(r, tag);
- rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
- rman_get_start(r));
- break;
- case SYS_RES_IOPORT:
- rman_set_bustag(r, sc->sc_pci_iot);
- rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
- rman_get_start(r));
- break;
- }
- return (rman_activate_resource(r));
-}
-
-static int
-psycho_adjust_resource(device_t bus, device_t child, int type,
- struct resource *r, u_long start, u_long end)
-{
- struct psycho_softc *sc;
- struct rman *rm;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- return (bus_generic_adjust_resource(bus, child, type, r,
- start, end));
- case SYS_RES_MEMORY:
- rm = &sc->sc_pci_mem_rman;
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_pci_io_rman;
- break;
- default:
- return (EINVAL);
}
- if (rman_is_region_manager(r, rm) == 0)
- return (EINVAL);
- return (rman_adjust_resource(r, start, end));
-}
-
-static bus_dma_tag_t
-psycho_get_dma_tag(device_t bus, device_t child __unused)
-{
- struct psycho_softc *sc;
-
- sc = device_get_softc(bus);
- return (sc->sc_pci_dmat);
-}
-
-static phandle_t
-psycho_get_node(device_t bus, device_t child __unused)
-{
- struct psycho_softc *sc;
-
- sc = device_get_softc(bus);
- /* We only have one child, the PCI bus, which needs our own node. */
- return (sc->sc_node);
+ return (ofw_pci_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
}
static void
diff --git a/sys/sparc64/pci/psychoreg.h b/sys/sparc64/pci/psychoreg.h
index ede593a..6e4ea39 100644
--- a/sys/sparc64/pci/psychoreg.h
+++ b/sys/sparc64/pci/psychoreg.h
@@ -73,7 +73,6 @@
*/
#define PSYCHO_NINTR 6
-#define PSYCHO_NRANGE 4
/*
* Psycho register offsets
@@ -121,7 +120,7 @@
#define PSR_PWRMGT_INT_MAP 0x1090 /* power mgmt wake interrupt map reg */
#define PSR_FFB0_INT_MAP 0x1098 /* FFB0 graphics interrupt map reg */
#define PSR_FFB1_INT_MAP 0x10a0 /* FFB1 graphics interrupt map reg */
-/* Note: clear interrupt 0 registers are not really used */
+/* Note: Clear interrupt 0 registers are not really used. */
#define PSR_PCIA0_INT_CLR 0x1400 /* PCI a slot 0 clear int regs 0..3 */
#define PSR_PCIA1_INT_CLR 0x1420 /* PCI a slot 1 clear int regs 0..3 */
#define PSR_PCIA2_INT_CLR 0x1440 /* PCI a slot 2 clear int regs 0..3 */
@@ -165,6 +164,7 @@
#define PSR_PCI_INT_DIAG 0xa800 /* PCI int state diag reg */
#define PSR_OBIO_INT_DIAG 0xa808 /* OBIO and misc int state diag reg */
#define PSR_STRBUF_DIAG 0xb000 /* Streaming buffer diag regs */
+
/*
* Here is the rest of the map, which we're not specifying:
*
@@ -176,7 +176,7 @@
* 1ff.0000.0000 - 1ff.7fff.ffff PCI A memory space
* 1ff.8000.0000 - 1ff.ffff.ffff PCI B memory space
*
- * NB: config and I/O space can use 1-4 byte accesses, not 8 byte
+ * NB: Config and I/O space can use 1-4 byte accesses, not 8 byte
* accesses. Memory space can use any sized accesses.
*
* Note that the SUNW,sabre/SUNW,simba combinations found on the
diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h
index 5532d16..0f828ee 100644
--- a/sys/sparc64/pci/psychovar.h
+++ b/sys/sparc64/pci/psychovar.h
@@ -36,49 +36,38 @@
* per pair of psychos.
*/
struct psycho_softc {
- struct bus_dma_methods *sc_dma_methods;
+ /*
+ * This is here so that we can hook up the common bus interface
+ * methods in ofw_pci.c directly.
+ */
+ struct ofw_pci_softc sc_ops;
- device_t sc_dev;
+ struct iommu_state *sc_is;
+ struct bus_dma_methods *sc_dma_methods;
struct mtx *sc_mtx;
- /* Interrupt Group Number for this device */
- uint32_t sc_ign;
-
- bus_addr_t sc_pcictl;
-
- phandle_t sc_node; /* Firmware node */
- u_int sc_mode;
-#define PSYCHO_MODE_SABRE 0
-#define PSYCHO_MODE_PSYCHO 1
-
- /* Bus A or B of a psycho pair? */
- u_int sc_half;
-
- struct iommu_state *sc_is;
-
struct resource *sc_mem_res;
struct resource *sc_irq_res[PSYCHO_NINTR];
void *sc_ihand[PSYCHO_NINTR];
- struct ofw_bus_iinfo sc_pci_iinfo;
+ uint8_t sc_pci_hpbcfg[16];
- /* Tags for PCI access */
- bus_space_tag_t sc_pci_cfgt;
- bus_space_tag_t sc_pci_iot;
- bus_dma_tag_t sc_pci_dmat;
+ SLIST_ENTRY(psycho_softc) sc_link;
- bus_space_handle_t sc_pci_bh[PSYCHO_NRANGE];
+ device_t sc_dev;
- struct rman sc_pci_mem_rman;
- struct rman sc_pci_io_rman;
+ bus_addr_t sc_pcictl;
- uint8_t sc_pci_secbus;
- uint8_t sc_pci_subbus;
+ u_int sc_mode;
+#define PSYCHO_MODE_SABRE 0
+#define PSYCHO_MODE_PSYCHO 1
- uint8_t sc_pci_hpbcfg[16];
+ /* Bus A or B of a psycho pair? */
+ u_int sc_half;
- SLIST_ENTRY(psycho_softc) sc_link;
+ /* Interrupt Group Number for this device */
+ uint32_t sc_ign;
};
#endif /* !_SPARC64_PCI_PSYCHOVAR_H_ */
diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c
index b89c7c0..ed1cccd 100644
--- a/sys/sparc64/pci/schizo.c
+++ b/sys/sparc64/pci/schizo.c
@@ -57,13 +57,11 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
#include <machine/bus_common.h>
#include <machine/bus_private.h>
-#include <machine/fsr.h>
#include <machine/iommureg.h>
#include <machine/iommuvar.h>
#include <machine/resource.h>
@@ -108,17 +106,12 @@ static void schizo_iommu_init(struct schizo_softc *, int, uint32_t);
*/
static device_probe_t schizo_probe;
static device_attach_t schizo_attach;
-static bus_read_ivar_t schizo_read_ivar;
static bus_setup_intr_t schizo_setup_intr;
static bus_alloc_resource_t schizo_alloc_resource;
-static bus_activate_resource_t schizo_activate_resource;
-static bus_adjust_resource_t schizo_adjust_resource;
-static bus_get_dma_tag_t schizo_get_dma_tag;
static pcib_maxslots_t schizo_maxslots;
static pcib_read_config_t schizo_read_config;
static pcib_write_config_t schizo_write_config;
static pcib_route_interrupt_t schizo_route_interrupt;
-static ofw_bus_get_node_t schizo_get_node;
static ofw_pci_setup_device_t schizo_setup_device;
static device_method_t schizo_methods[] = {
@@ -130,15 +123,15 @@ static device_method_t schizo_methods[] = {
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
- DEVMETHOD(bus_read_ivar, schizo_read_ivar),
+ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar),
DEVMETHOD(bus_setup_intr, schizo_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, schizo_alloc_resource),
- DEVMETHOD(bus_activate_resource, schizo_activate_resource),
+ DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_adjust_resource, schizo_adjust_resource),
+ DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_get_dma_tag, schizo_get_dma_tag),
+ DEVMETHOD(bus_get_dma_tag, ofw_pci_get_dma_tag),
/* pcib interface */
DEVMETHOD(pcib_maxslots, schizo_maxslots),
@@ -147,7 +140,7 @@ static device_method_t schizo_methods[] = {
DEVMETHOD(pcib_route_interrupt, schizo_route_interrupt),
/* ofw_bus interface */
- DEVMETHOD(ofw_bus_get_node, schizo_get_node),
+ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node),
/* ofw_pci interface */
DEVMETHOD(ofw_pci_setup_device, schizo_setup_device),
@@ -270,10 +263,10 @@ schizo_probe(device_t dev)
static int
schizo_attach(device_t dev)
{
- struct ofw_pci_ranges *range;
const struct schizo_desc *desc;
struct schizo_softc *asc, *sc, *osc;
struct timecounter *tc;
+ bus_dma_tag_t dmat;
uint64_t ino_bitmap, reg;
phandle_t node;
uint32_t prop, prop_array[2];
@@ -285,7 +278,6 @@ schizo_attach(device_t dev)
mode = desc->sd_mode;
sc->sc_dev = dev;
- sc->sc_node = node;
sc->sc_mode = mode;
sc->sc_flags = 0;
@@ -347,6 +339,7 @@ schizo_attach(device_t dev)
panic("%s: mutex not initialized", __func__);
sc->sc_mtx = osc->sc_mtx;
}
+ SLIST_INSERT_HEAD(&schizo_softcs, sc, sc_link);
if (OF_getprop(node, "portid", &sc->sc_ign, sizeof(sc->sc_ign)) == -1)
panic("%s: could not determine IGN", __func__);
@@ -542,82 +535,23 @@ schizo_attach(device_t dev)
#undef TSBCASE
- /* Initialize memory and I/O rmans. */
- sc->sc_pci_io_rman.rm_type = RMAN_ARRAY;
- sc->sc_pci_io_rman.rm_descr = "Schizo PCI I/O Ports";
- if (rman_init(&sc->sc_pci_io_rman) != 0 ||
- rman_manage_region(&sc->sc_pci_io_rman, 0, STX_IO_SIZE) != 0)
- panic("%s: failed to set up I/O rman", __func__);
- sc->sc_pci_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_pci_mem_rman.rm_descr = "Schizo PCI Memory";
- if (rman_init(&sc->sc_pci_mem_rman) != 0 ||
- rman_manage_region(&sc->sc_pci_mem_rman, 0, STX_MEM_SIZE) != 0)
- panic("%s: failed to set up memory rman", __func__);
-
- i = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
- /*
- * Make sure that the expected ranges are present. The
- * OFW_PCI_CS_MEM64 one is not currently used though.
- */
- if (i != STX_NRANGE)
- panic("%s: unsupported number of ranges", __func__);
- /*
- * Find the addresses of the various bus spaces.
- * There should not be multiple ones of one kind.
- * The physical start addresses of the ranges are the configuration,
- * memory and I/O handles.
- */
- for (i = 0; i < STX_NRANGE; i++) {
- j = OFW_PCI_RANGE_CS(&range[i]);
- if (sc->sc_pci_bh[j] != 0)
- panic("%s: duplicate range for space %d",
- __func__, j);
- sc->sc_pci_bh[j] = OFW_PCI_RANGE_PHYS(&range[i]);
- }
- free(range, M_OFWPROP);
-
- /* Register the softc, this is needed for paired Schizos. */
- SLIST_INSERT_HEAD(&schizo_softcs, sc, sc_link);
-
- /* Allocate our tags. */
- sc->sc_pci_iot = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
- sc->sc_mem_res[STX_PCI]), PCI_IO_BUS_SPACE, NULL);
- if (sc->sc_pci_iot == NULL)
- panic("%s: could not allocate PCI I/O tag", __func__);
- sc->sc_pci_cfgt = sparc64_alloc_bus_tag(NULL, rman_get_bustag(
- sc->sc_mem_res[STX_PCI]), PCI_CONFIG_BUS_SPACE, NULL);
- if (sc->sc_pci_cfgt == NULL)
- panic("%s: could not allocate PCI configuration space tag",
- __func__);
+ /* Create our DMA tag. */
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0,
sc->sc_is.sis_is.is_pmaxaddr, ~0, NULL, NULL,
sc->sc_is.sis_is.is_pmaxaddr, 0xff, 0xffffffff, 0, NULL, NULL,
- &sc->sc_pci_dmat) != 0)
+ &dmat) != 0)
panic("%s: could not create PCI DMA tag", __func__);
- /* Customize the tag. */
- sc->sc_pci_dmat->dt_cookie = &sc->sc_is;
- sc->sc_pci_dmat->dt_mt = &sc->sc_dma_methods;
+ dmat->dt_cookie = &sc->sc_is;
+ dmat->dt_mt = &sc->sc_dma_methods;
- /*
- * Get the bus range from the firmware.
- * NB: Tomatillos don't support PCI bus reenumeration.
- */
- i = OF_getprop(node, "bus-range", (void *)prop_array,
- sizeof(prop_array));
- if (i == -1)
- panic("%s: could not get bus-range", __func__);
- if (i != sizeof(prop_array))
- panic("%s: broken bus-range (%d)", __func__, i);
- sc->sc_pci_secbus = prop_array[0];
- sc->sc_pci_subbus = prop_array[1];
- if (bootverbose)
- device_printf(dev, "bus range %u to %u; PCI bus %d\n",
- sc->sc_pci_secbus, sc->sc_pci_subbus, sc->sc_pci_secbus);
+ if (ofw_pci_attach_common(dev, dmat, STX_IO_SIZE, STX_MEM_SIZE) != 0)
+ panic("%s: ofw_pci_attach_common() failed", __func__);
/* Clear any pending PCI error bits. */
- PCIB_WRITE_CONFIG(dev, sc->sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC,
- PCIR_STATUS, PCIB_READ_CONFIG(dev, sc->sc_pci_secbus,
- STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS, 2), 2);
+ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE,
+ STX_CS_FUNC, PCIR_STATUS, PCIB_READ_CONFIG(dev,
+ sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS,
+ 2), 2);
SCHIZO_PCI_SET(sc, STX_PCI_CTRL, SCHIZO_PCI_READ_8(sc, STX_PCI_CTRL));
SCHIZO_PCI_SET(sc, STX_PCI_AFSR, SCHIZO_PCI_READ_8(sc, STX_PCI_AFSR));
@@ -745,10 +679,8 @@ schizo_attach(device_t dev)
* Set the latency timer register as this isn't always done by the
* firmware.
*/
- PCIB_WRITE_CONFIG(dev, sc->sc_pci_secbus, STX_CS_DEVICE, STX_CS_FUNC,
- PCIR_LATTIMER, OFW_PCI_LATENCY, 1);
-
- ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t));
+ PCIB_WRITE_CONFIG(dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE,
+ STX_CS_FUNC, PCIR_LATTIMER, OFW_PCI_LATENCY, 1);
#define SCHIZO_SYSCTL_ADD_UINT(name, arg, desc) \
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), \
@@ -872,7 +804,7 @@ schizo_pci_bus(void *arg)
xstat = SCHIZO_PCI_READ_8(sc, XMS_PCI_X_ERR_STAT);
else
xstat = 0;
- status = PCIB_READ_CONFIG(sc->sc_dev, sc->sc_pci_secbus,
+ status = PCIB_READ_CONFIG(sc->sc_dev, sc->sc_ops.sc_pci_secbus,
STX_CS_DEVICE, STX_CS_FUNC, PCIR_STATUS, 2);
/*
@@ -913,7 +845,7 @@ schizo_pci_bus(void *arg)
(unsigned long long)iommu, (unsigned long long)xstat, status);
/* Clear the error bits that we caught. */
- PCIB_WRITE_CONFIG(sc->sc_dev, sc->sc_pci_secbus, STX_CS_DEVICE,
+ PCIB_WRITE_CONFIG(sc->sc_dev, sc->sc_ops.sc_pci_secbus, STX_CS_DEVICE,
STX_CS_FUNC, PCIR_STATUS, status, 2);
SCHIZO_PCI_WRITE_8(sc, STX_PCI_CTRL, csr);
SCHIZO_PCI_WRITE_8(sc, STX_PCI_AFSR, afsr);
@@ -1034,121 +966,40 @@ schizo_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
int width)
{
struct schizo_softc *sc;
- bus_space_handle_t bh;
- u_long offset = 0;
- uint32_t r, wrd;
- int i;
- uint16_t shrt;
- uint8_t byte;
sc = device_get_softc(dev);
- if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
- slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCI_REGMAX)
- return (-1);
-
/*
* The Schizo bridges contain a dupe of their header at 0x80.
*/
- if (sc->sc_mode == SCHIZO_MODE_SCZ && bus == sc->sc_pci_secbus &&
- slot == STX_CS_DEVICE && func == STX_CS_FUNC &&
- reg + width > 0x80)
+ if (sc->sc_mode == SCHIZO_MODE_SCZ &&
+ bus == sc->sc_ops.sc_pci_secbus && slot == STX_CS_DEVICE &&
+ func == STX_CS_FUNC && reg + width > 0x80)
return (0);
- offset = STX_CONF_OFF(bus, slot, func, reg);
- bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
- switch (width) {
- case 1:
- i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte);
- r = byte;
- break;
- case 2:
- i = bus_space_peek_2(sc->sc_pci_cfgt, bh, offset, &shrt);
- r = shrt;
- break;
- case 4:
- i = bus_space_peek_4(sc->sc_pci_cfgt, bh, offset, &wrd);
- r = wrd;
- break;
- default:
- panic("%s: bad width", __func__);
- /* NOTREACHED */
- }
-
- if (i) {
-#ifdef SCHIZO_DEBUG
- printf("%s: read data error reading: %d.%d.%d: 0x%x\n",
- __func__, bus, slot, func, reg);
-#endif
- r = -1;
- }
- return (r);
+ return (ofw_pci_read_config_common(dev, PCI_REGMAX, STX_CONF_OFF(bus,
+ slot, func, reg), bus, slot, func, reg, width));
}
static void
schizo_write_config(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, uint32_t val, int width)
{
- struct schizo_softc *sc;
- bus_space_handle_t bh;
- u_long offset = 0;
-
- sc = device_get_softc(dev);
- if (bus < sc->sc_pci_secbus || bus > sc->sc_pci_subbus ||
- slot > PCI_SLOTMAX || func > PCI_FUNCMAX || reg > PCI_REGMAX)
- return;
- offset = STX_CONF_OFF(bus, slot, func, reg);
- bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
- switch (width) {
- case 1:
- bus_space_write_1(sc->sc_pci_cfgt, bh, offset, val);
- break;
- case 2:
- bus_space_write_2(sc->sc_pci_cfgt, bh, offset, val);
- break;
- case 4:
- bus_space_write_4(sc->sc_pci_cfgt, bh, offset, val);
- break;
- default:
- panic("%s: bad width", __func__);
- /* NOTREACHED */
- }
+ ofw_pci_write_config_common(dev, PCI_REGMAX, STX_CONF_OFF(bus, slot,
+ func, reg), bus, slot, func, reg, val, width);
}
static int
schizo_route_interrupt(device_t bridge, device_t dev, int pin)
{
- struct schizo_softc *sc;
- struct ofw_pci_register reg;
- ofw_pci_intr_t pintr, mintr;
-
- sc = device_get_softc(bridge);
- pintr = pin;
- if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo,
- &reg, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
- NULL))
- return (mintr);
-
- device_printf(bridge, "could not route pin %d for device %d.%d\n",
- pin, pci_get_slot(dev), pci_get_function(dev));
- return (PCI_INVALID_IRQ);
-}
-
-static int
-schizo_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct schizo_softc *sc;
-
- sc = device_get_softc(dev);
- switch (which) {
- case PCIB_IVAR_DOMAIN:
- *result = device_get_unit(dev);
- return (0);
- case PCIB_IVAR_BUS:
- *result = sc->sc_pci_secbus;
- return (0);
- }
- return (ENOENT);
+ ofw_pci_intr_t mintr;
+
+ mintr = ofw_pci_route_interrupt_common(bridge, dev, pin);
+ if (!PCI_INTERRUPT_VALID(mintr))
+ device_printf(bridge,
+ "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (mintr);
}
static void
@@ -1216,11 +1067,10 @@ schizo_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
static void
ichip_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
{
- static u_char buf[VIS_BLOCKSIZE] __aligned(VIS_BLOCKSIZE);
struct timeval cur, end;
struct schizo_iommu_state *sis = dt->dt_cookie;
struct schizo_softc *sc = sis->sis_sc;
- register_t reg, s;
+ uint64_t reg;
if ((map->dm_flags & DMF_STREAMED) != 0) {
iommu_dma_methods.dm_dmamap_sync(dt, map, op);
@@ -1248,14 +1098,7 @@ ichip_dmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
if (sc->sc_mode == SCHIZO_MODE_XMS)
mtx_unlock_spin(&sc->sc_sync_mtx);
else if ((sc->sc_flags & SCHIZO_FLAGS_BSWAR) != 0) {
- s = intr_disable();
- reg = rd(fprs);
- wr(fprs, reg | FPRS_FEF, 0);
- __asm __volatile("stda %%f0, [%0] %1"
- : : "r" (buf), "n" (ASI_BLK_COMMIT_S));
- membar(Sync);
- wr(fprs, reg, 0);
- intr_restore(s);
+ ofw_pci_dmamap_sync_stst_order_common();
return;
}
}
@@ -1356,121 +1199,13 @@ schizo_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct schizo_softc *sc;
- struct resource *rv;
- struct rman *rm;
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- /*
- * XXX: Don't accept blank ranges for now, only single
- * interrupts. The other case should not happen with
- * the MI PCI code...
- * XXX: This may return a resource that is out of the
- * range that was specified. Is this correct...?
- */
- if (start != end)
- panic("%s: XXX: interrupt range", __func__);
+ if (type == SYS_RES_IRQ) {
+ sc = device_get_softc(bus);
start = end = INTMAP_VEC(sc->sc_ign, end);
- return (bus_generic_alloc_resource(bus, child, type, rid,
- start, end, count, flags));
- case SYS_RES_MEMORY:
- rm = &sc->sc_pci_mem_rman;
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_pci_io_rman;
- break;
- default:
- return (NULL);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
- child);
- if (rv == NULL)
- return (NULL);
- rman_set_rid(rv, *rid);
-
- if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
- *rid, rv) != 0) {
- rman_release_resource(rv);
- return (NULL);
- }
- return (rv);
-}
-
-static int
-schizo_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
- struct schizo_softc *sc;
- struct bus_space_tag *tag;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- return (bus_generic_activate_resource(bus, child, type, rid,
- r));
- case SYS_RES_MEMORY:
- tag = sparc64_alloc_bus_tag(r, rman_get_bustag(
- sc->sc_mem_res[STX_PCI]), PCI_MEMORY_BUS_SPACE, NULL);
- if (tag == NULL)
- return (ENOMEM);
- rman_set_bustag(r, tag);
- rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_MEM32] +
- rman_get_start(r));
- break;
- case SYS_RES_IOPORT:
- rman_set_bustag(r, sc->sc_pci_iot);
- rman_set_bushandle(r, sc->sc_pci_bh[OFW_PCI_CS_IO] +
- rman_get_start(r));
- break;
- }
- return (rman_activate_resource(r));
-}
-
-static int
-schizo_adjust_resource(device_t bus, device_t child, int type,
- struct resource *r, u_long start, u_long end)
-{
- struct schizo_softc *sc;
- struct rman *rm;
-
- sc = device_get_softc(bus);
- switch (type) {
- case SYS_RES_IRQ:
- return (bus_generic_adjust_resource(bus, child, type, r,
- start, end));
- case SYS_RES_MEMORY:
- rm = &sc->sc_pci_mem_rman;
- break;
- case SYS_RES_IOPORT:
- rm = &sc->sc_pci_io_rman;
- break;
- default:
- return (EINVAL);
}
- if (rman_is_region_manager(r, rm) == 0)
- return (EINVAL);
- return (rman_adjust_resource(r, start, end));
-}
-
-static bus_dma_tag_t
-schizo_get_dma_tag(device_t bus, device_t child __unused)
-{
- struct schizo_softc *sc;
-
- sc = device_get_softc(bus);
- return (sc->sc_pci_dmat);
-}
-
-static phandle_t
-schizo_get_node(device_t bus, device_t child __unused)
-{
- struct schizo_softc *sc;
-
- sc = device_get_softc(bus);
- /* We only have one child, the PCI bus, which needs our own node. */
- return (sc->sc_node);
+ return (ofw_pci_alloc_resource(bus, child, type, rid, start, end,
+ count, flags));
}
static void
diff --git a/sys/sparc64/pci/schizoreg.h b/sys/sparc64/pci/schizoreg.h
index cd816b5..59c00b6 100644
--- a/sys/sparc64/pci/schizoreg.h
+++ b/sys/sparc64/pci/schizoreg.h
@@ -32,7 +32,6 @@
#define _SPARC64_PCI_SCHIZOREG_H_
#define STX_NINTR 5 /* 4 via OFW + 1 CDMA */
-#define STX_NRANGE 4
#define SCZ_NREG 3
#define TOM_NREG 4
@@ -279,7 +278,7 @@
/*
* Safari/JBus performance control register
- * NB: for Tomatillo only events 0x00 through 0x08 are documented as
+ * NB: For Tomatillo only events 0x00 through 0x08 are documented as
* implemented.
*/
#define SCZ_CTRL_PERF_ZDATA_OUT 0x0000000000000016ULL
@@ -345,7 +344,7 @@
/* Non-Standard registers in the configration space */
/*
- * NB: for Tomatillo the secondary and subordinate bus number registers
+ * NB: For Tomatillo the secondary and subordinate bus number registers
* apparently are read-only although documented otherwise; writing to
* them just triggers a PCI bus error interrupt or has no effect at best.
*/
diff --git a/sys/sparc64/pci/schizovar.h b/sys/sparc64/pci/schizovar.h
index ab339c8..1b58cf4 100644
--- a/sys/sparc64/pci/schizovar.h
+++ b/sys/sparc64/pci/schizovar.h
@@ -39,16 +39,27 @@ struct schizo_iommu_state {
};
struct schizo_softc {
- struct bus_dma_methods sc_dma_methods;
+ /*
+ * This is here so that we can hook up the common bus interface
+ * methods in ofw_pci.c directly.
+ */
+ struct ofw_pci_softc sc_ops;
- device_t sc_dev;
+ struct schizo_iommu_state sc_is;
+ struct bus_dma_methods sc_dma_methods;
struct mtx sc_sync_mtx;
uint64_t sc_sync_val;
struct mtx *sc_mtx;
- phandle_t sc_node;
+ struct resource *sc_mem_res[TOM_NREG];
+ struct resource *sc_irq_res[STX_NINTR];
+ void *sc_ihand[STX_NINTR];
+
+ SLIST_ENTRY(schizo_softc) sc_link;
+
+ device_t sc_dev;
u_int sc_mode;
#define SCHIZO_MODE_SCZ 0
@@ -72,28 +83,8 @@ struct schizo_softc {
uint32_t sc_ver;
uint32_t sc_mrev;
- struct resource *sc_mem_res[TOM_NREG];
- struct resource *sc_irq_res[STX_NINTR];
- void *sc_ihand[STX_NINTR];
-
- struct schizo_iommu_state sc_is;
-
- struct rman sc_pci_mem_rman;
- struct rman sc_pci_io_rman;
- bus_space_handle_t sc_pci_bh[STX_NRANGE];
- bus_space_tag_t sc_pci_cfgt;
- bus_space_tag_t sc_pci_iot;
- bus_dma_tag_t sc_pci_dmat;
-
uint32_t sc_stats_dma_ce;
uint32_t sc_stats_pci_non_fatal;
-
- uint8_t sc_pci_secbus;
- uint8_t sc_pci_subbus;
-
- struct ofw_bus_iinfo sc_pci_iinfo;
-
- SLIST_ENTRY(schizo_softc) sc_link;
};
#endif /* !_SPARC64_PCI_SCHIZOVAR_H_ */
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index f016eaa..07be1c8 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -249,7 +249,7 @@ find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl)
{
char type[sizeof("cpu")];
phandle_t child;
- uint32_t cpuid;
+ uint32_t portid;
for (; node != 0; node = OF_peer(node)) {
child = OF_child(node);
@@ -263,10 +263,10 @@ find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl)
continue;
if (strcmp(type, "cpu") != 0)
continue;
- if (OF_getprop(node, cpu_cpuid_prop(cpu_impl), &cpuid,
- sizeof(cpuid)) <= 0)
+ if (OF_getprop(node, cpu_portid_prop(cpu_impl),
+ &portid, sizeof(portid)) <= 0)
continue;
- if (cpuid == bspid)
+ if (portid == bspid)
return (node);
}
}
@@ -274,7 +274,7 @@ find_bsp(phandle_t node, uint32_t bspid, u_int cpu_impl)
}
const char *
-cpu_cpuid_prop(u_int cpu_impl)
+cpu_portid_prop(u_int cpu_impl)
{
switch (cpu_impl) {
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index c2c4e3e..52322a2 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -119,9 +119,11 @@ struct mtx ipi_mtx;
cpu_ipi_selected_t *cpu_ipi_selected;
cpu_ipi_single_t *cpu_ipi_single;
-static vm_offset_t mp_tramp;
static u_int cpuid_to_mid[MAXCPU];
+static u_int cpuids = 1;
static volatile cpuset_t shutdown_cpus;
+static char ipi_pbuf[CPUSETBUFSIZ];
+static vm_offset_t mp_tramp;
static void ap_count(phandle_t node, u_int mid, u_int cpu_impl);
static void ap_start(phandle_t node, u_int mid, u_int cpu_impl);
@@ -165,13 +167,12 @@ static void
foreach_ap(phandle_t node, void (*func)(phandle_t node, u_int mid,
u_int cpu_impl))
{
- char type[sizeof("cpu")];
+ static char type[sizeof("cpu")];
phandle_t child;
- u_int cpuid;
- uint32_t cpu_impl;
+ uint32_t cpu_impl, portid;
/* There's no need to traverse the whole OFW tree twice. */
- if (mp_maxid > 0 && mp_ncpus >= mp_maxid + 1)
+ if (mp_maxid > 0 && cpuids > mp_maxid)
return;
for (; node != 0; node = OF_peer(node)) {
@@ -188,13 +189,13 @@ foreach_ap(phandle_t node, void (*func)(phandle_t node, u_int mid,
sizeof(cpu_impl)) <= 0)
panic("%s: couldn't determine CPU "
"implementation", __func__);
- if (OF_getprop(node, cpu_cpuid_prop(cpu_impl), &cpuid,
- sizeof(cpuid)) <= 0)
- panic("%s: couldn't determine CPU module ID",
+ if (OF_getprop(node, cpu_portid_prop(cpu_impl),
+ &portid, sizeof(portid)) <= 0)
+ panic("%s: couldn't determine CPU port ID",
__func__);
- if (cpuid == PCPU_GET(mid))
+ if (portid == PCPU_GET(mid))
continue;
- (*func)(node, cpuid, cpu_impl);
+ (*func)(node, portid, cpu_impl);
}
}
}
@@ -208,16 +209,17 @@ cpu_mp_setmaxid(void)
CPU_SETOF(curcpu, &all_cpus);
mp_ncpus = 1;
- mp_maxid = 0;
foreach_ap(OF_child(OF_peer(0)), ap_count);
+ mp_ncpus = MIN(mp_ncpus, MAXCPU);
+ mp_maxid = mp_ncpus - 1;
}
static void
ap_count(phandle_t node __unused, u_int mid __unused, u_int cpu_impl __unused)
{
- mp_maxid++;
+ mp_ncpus++;
}
int
@@ -306,7 +308,7 @@ ap_start(phandle_t node, u_int mid, u_int cpu_impl)
u_int cpuid;
uint32_t clock;
- if (mp_ncpus > MAXCPU)
+ if (cpuids > mp_maxid)
return;
if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) <= 0)
@@ -334,7 +336,7 @@ ap_start(phandle_t node, u_int mid, u_int cpu_impl)
csa->csa_tick = csa->csa_stick = 0;
intr_restore(s);
- cpuid = mp_ncpus++;
+ cpuid = cpuids++;
cpuid_to_mid[cpuid] = mid;
cpu_identify(csa->csa_ver, clock, cpuid);
@@ -659,7 +661,6 @@ cheetah_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
static void
cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
{
- char pbuf[CPUSETBUFSIZ];
register_t s;
u_long ids;
u_int bnp;
@@ -675,14 +676,14 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
("%s: outstanding dispatch", __func__));
ids = 0;
- for (i = 0; i < IPI_RETRIES * mp_ncpus; i++) {
+ for (i = 0; i < IPI_RETRIES * smp_cpus; i++) {
s = intr_disable();
stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
membar(Sync);
bnp = 0;
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
+ for (cpu = 0; cpu < smp_cpus; cpu++) {
if (CPU_ISSET(cpu, &cpus)) {
stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] <<
IDC_ITID_SHIFT) | bnp << IDC_BN_SHIFT,
@@ -698,7 +699,7 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
;
intr_restore(s);
bnp = 0;
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
+ for (cpu = 0; cpu < smp_cpus; cpu++) {
if (CPU_ISSET(cpu, &cpus)) {
if ((ids & (IDR_NACK << (2 * bnp))) == 0)
CPU_CLR(cpu, &cpus);
@@ -710,10 +711,10 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
}
if (kdb_active != 0 || panicstr != NULL)
printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n",
- __func__, cpusetobj_strprint(pbuf, &cpus), ids);
+ __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
else
panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)",
- __func__, cpusetobj_strprint(pbuf, &cpus), ids);
+ __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
}
static void
@@ -760,7 +761,6 @@ jalapeno_ipi_single(u_int cpu, u_long d0, u_long d1, u_long d2)
static void
jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
{
- char pbuf[CPUSETBUFSIZ];
register_t s;
u_long ids;
u_int cpu;
@@ -775,13 +775,13 @@ jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
("%s: outstanding dispatch", __func__));
ids = 0;
- for (i = 0; i < IPI_RETRIES * mp_ncpus; i++) {
+ for (i = 0; i < IPI_RETRIES * smp_cpus; i++) {
s = intr_disable();
stxa(AA_SDB_INTR_D0, ASI_SDB_INTR_W, d0);
stxa(AA_SDB_INTR_D1, ASI_SDB_INTR_W, d1);
stxa(AA_SDB_INTR_D2, ASI_SDB_INTR_W, d2);
membar(Sync);
- for (cpu = 0; cpu < mp_ncpus; cpu++) {
+ for (cpu = 0; cpu < smp_cpus; cpu++) {
if (CPU_ISSET(cpu, &cpus)) {
stxa(AA_INTR_SEND | (cpuid_to_mid[cpu] <<
IDC_ITID_SHIFT), ASI_SDB_INTR_W, 0);
@@ -795,7 +795,7 @@ jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
if ((ids &
(IDR_CHEETAH_ALL_BUSY | IDR_CHEETAH_ALL_NACK)) == 0)
return;
- for (cpu = 0; cpu < mp_ncpus; cpu++)
+ for (cpu = 0; cpu < smp_cpus; cpu++)
if (CPU_ISSET(cpu, &cpus))
if ((ids & (IDR_NACK <<
(2 * cpuid_to_mid[cpu]))) == 0)
@@ -803,8 +803,8 @@ jalapeno_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
}
if (kdb_active != 0 || panicstr != NULL)
printf("%s: couldn't send IPI (cpus=%s ids=0x%lu)\n",
- __func__, cpusetobj_strprint(pbuf, &cpus), ids);
+ __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
else
panic("%s: couldn't send IPI (cpus=%s ids=0x%lu)",
- __func__, cpusetobj_strprint(pbuf, &cpus), ids);
+ __func__, cpusetobj_strprint(ipi_pbuf, &cpus), ids);
}
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 4e2c9ea..1b5ce2d 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -13300,43 +13300,43 @@ softdep_ast_cleanup_proc(void)
bool req;
td = curthread;
- mp = td->td_su;
- if (mp == NULL)
- return;
- td->td_su = NULL;
- error = vfs_busy(mp, MBF_NOWAIT);
- vfs_rel(mp);
- if (error != 0)
- return;
- if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) {
- ump = VFSTOUFS(mp);
- for (;;) {
- req = false;
- ACQUIRE_LOCK(ump);
- if (softdep_excess_items(ump, D_INODEDEP)) {
- req = true;
- request_cleanup(mp, FLUSH_INODES);
- }
- if (softdep_excess_items(ump, D_DIRREM)) {
- req = true;
- request_cleanup(mp, FLUSH_BLOCKS);
- }
- FREE_LOCK(ump);
- if (softdep_excess_items(ump, D_NEWBLK) ||
- softdep_excess_items(ump, D_ALLOCDIRECT) ||
- softdep_excess_items(ump, D_ALLOCINDIR)) {
- error = vn_start_write(NULL, &mp, V_WAIT);
- if (error == 0) {
+ while ((mp = td->td_su) != NULL) {
+ td->td_su = NULL;
+ error = vfs_busy(mp, MBF_NOWAIT);
+ vfs_rel(mp);
+ if (error != 0)
+ return;
+ if (ffs_own_mount(mp) && MOUNTEDSOFTDEP(mp)) {
+ ump = VFSTOUFS(mp);
+ for (;;) {
+ req = false;
+ ACQUIRE_LOCK(ump);
+ if (softdep_excess_items(ump, D_INODEDEP)) {
+ req = true;
+ request_cleanup(mp, FLUSH_INODES);
+ }
+ if (softdep_excess_items(ump, D_DIRREM)) {
req = true;
- VFS_SYNC(mp, MNT_WAIT);
- vn_finished_write(mp);
+ request_cleanup(mp, FLUSH_BLOCKS);
}
+ FREE_LOCK(ump);
+ if (softdep_excess_items(ump, D_NEWBLK) ||
+ softdep_excess_items(ump, D_ALLOCDIRECT) ||
+ softdep_excess_items(ump, D_ALLOCINDIR)) {
+ error = vn_start_write(NULL, &mp,
+ V_WAIT);
+ if (error == 0) {
+ req = true;
+ VFS_SYNC(mp, MNT_WAIT);
+ vn_finished_write(mp);
+ }
+ }
+ if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
+ break;
}
- if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
- break;
}
+ vfs_unbusy(mp);
}
- vfs_unbusy(mp);
}
/*
diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c
index f5c1b92..38c9f1e 100644
--- a/sys/x86/x86/busdma_bounce.c
+++ b/sys/x86/x86/busdma_bounce.c
@@ -751,6 +751,9 @@ bounce_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
{
struct bounce_page *bpage;
+ if (map == NULL)
+ return;
+
while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
STAILQ_REMOVE_HEAD(&map->bpages, links);
free_bounce_page(dmat, bpage);
@@ -763,47 +766,43 @@ bounce_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map,
{
struct bounce_page *bpage;
- if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
- /*
- * Handle data bouncing. We might also
- * want to add support for invalidating
- * the caches on broken hardware
- */
- CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
- "performing bounce", __func__, dmat,
- dmat->common.flags, op);
-
- if ((op & BUS_DMASYNC_PREWRITE) != 0) {
- while (bpage != NULL) {
- if (bpage->datavaddr != 0) {
- bcopy((void *)bpage->datavaddr,
- (void *)bpage->vaddr,
- bpage->datacount);
- } else {
- physcopyout(bpage->dataaddr,
- (void *)bpage->vaddr,
- bpage->datacount);
- }
- bpage = STAILQ_NEXT(bpage, links);
+ if (map == NULL || (bpage = STAILQ_FIRST(&map->bpages)) == NULL)
+ return;
+
+ /*
+ * Handle data bouncing. We might also want to add support for
+ * invalidating the caches on broken hardware.
+ */
+ CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
+ "performing bounce", __func__, dmat, dmat->common.flags, op);
+
+ if ((op & BUS_DMASYNC_PREWRITE) != 0) {
+ while (bpage != NULL) {
+ if (bpage->datavaddr != 0) {
+ bcopy((void *)bpage->datavaddr,
+ (void *)bpage->vaddr, bpage->datacount);
+ } else {
+ physcopyout(bpage->dataaddr,
+ (void *)bpage->vaddr, bpage->datacount);
}
- dmat->bounce_zone->total_bounced++;
+ bpage = STAILQ_NEXT(bpage, links);
}
+ dmat->bounce_zone->total_bounced++;
+ }
- if ((op & BUS_DMASYNC_POSTREAD) != 0) {
- while (bpage != NULL) {
- if (bpage->datavaddr != 0) {
- bcopy((void *)bpage->vaddr,
- (void *)bpage->datavaddr,
- bpage->datacount);
- } else {
- physcopyin((void *)bpage->vaddr,
- bpage->dataaddr,
- bpage->datacount);
- }
- bpage = STAILQ_NEXT(bpage, links);
+ if ((op & BUS_DMASYNC_POSTREAD) != 0) {
+ while (bpage != NULL) {
+ if (bpage->datavaddr != 0) {
+ bcopy((void *)bpage->vaddr,
+ (void *)bpage->datavaddr,
+ bpage->datacount);
+ } else {
+ physcopyin((void *)bpage->vaddr,
+ bpage->dataaddr, bpage->datacount);
}
- dmat->bounce_zone->total_bounced++;
+ bpage = STAILQ_NEXT(bpage, links);
}
+ dmat->bounce_zone->total_bounced++;
}
}
@@ -822,12 +821,14 @@ SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
static struct sysctl_ctx_list *
busdma_sysctl_tree(struct bounce_zone *bz)
{
+
return (&bz->sysctl_tree);
}
static struct sysctl_oid *
busdma_sysctl_tree_top(struct bounce_zone *bz)
{
+
return (bz->sysctl_tree_top);
}
OpenPOWER on IntegriCloud