From 748b87203d7219fd9fe2f73894359a6301ce5be1 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 11:49:29 +0000 Subject: Revert r298955 for the cxgbe firmware. These files have checksums that are none of my business. Requested by: np --- sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt | 4 ++-- sys/dev/cxgbe/firmware/t5fw_cfg_fpga.txt | 4 ++-- sys/dev/cxgbe/firmware/t5fw_cfg_uwire.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sys') diff --git a/sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt b/sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt index 43dc76e..cc8ad8b 100644 --- a/sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt +++ b/sys/dev/cxgbe/firmware/t4fw_cfg_uwire.txt @@ -17,7 +17,7 @@ # finite. This requires balancing the configuration/operation needs of # device drivers across OSes and a large number of customer application. # -# Some of the more important resources to allocate and their constraints are: +# Some of the more important resources to allocate and their constaints are: # 1. Virtual Interfaces: 128. # 2. Ingress Queues with Free Lists: 1024. PCI-E SR-IOV Virtual Functions # must use a power of 2 Ingress Queues. @@ -275,7 +275,7 @@ # to directly select the type of Physical Function to which they wish to be # attached. # -# Note that the actual values used for the PCI-E Intellectual Property will be +# Note that the actual values used for the PCI-E Intelectual Property will be # 1 less than those below since that's the way it "counts" things. For # readability, we use the number we actually mean ... # diff --git a/sys/dev/cxgbe/firmware/t5fw_cfg_fpga.txt b/sys/dev/cxgbe/firmware/t5fw_cfg_fpga.txt index 4c74fa1..e1c8b00 100644 --- a/sys/dev/cxgbe/firmware/t5fw_cfg_fpga.txt +++ b/sys/dev/cxgbe/firmware/t5fw_cfg_fpga.txt @@ -17,7 +17,7 @@ # finite. This requires balancing the configuration/operation needs of # device drivers across OSes and a large number of customer application. # -# Some of the more important resources to allocate and their constraints are: +# Some of the more important resources to allocate and their constaints are: # 1. Virtual Interfaces: 128. # 2. Ingress Queues with Free Lists: 1024. PCI-E SR-IOV Virtual Functions # must use a power of 2 Ingress Queues. @@ -292,7 +292,7 @@ # to directly select the type of Physical Function to which they wish to be # attached. # -# Note that the actual values used for the PCI-E Intellectual Property will be +# Note that the actual values used for the PCI-E Intelectual Property will be # 1 less than those below since that's the way it "counts" things. For # readability, we use the number we actually mean ... # diff --git a/sys/dev/cxgbe/firmware/t5fw_cfg_uwire.txt b/sys/dev/cxgbe/firmware/t5fw_cfg_uwire.txt index d6caf2c..6fcc934 100644 --- a/sys/dev/cxgbe/firmware/t5fw_cfg_uwire.txt +++ b/sys/dev/cxgbe/firmware/t5fw_cfg_uwire.txt @@ -18,7 +18,7 @@ # are finite. This requires balancing the configuration/operation needs of # device drivers across OSes and a large number of customer application. # -# Some of the more important resources to allocate and their constraints are: +# Some of the more important resources to allocate and their constaints are: # 1. Virtual Interfaces: 256. # 2. Ingress Queues with Free Lists: 1024. # 3. Egress Queues: 128K. @@ -309,7 +309,7 @@ # to directly select the type of Physical Function to which they wish to be # attached. # -# Note that the actual values used for the PCI-E Intellectual Property will be +# Note that the actual values used for the PCI-E Intelectual Property will be # 1 less than those below since that's the way it "counts" things. For # readability, we use the number we actually mean ... # -- cgit v1.1 From 5f9464965489d9535acea464c703064ac1788de0 Mon Sep 17 00:00:00 2001 From: scottl Date: Tue, 3 May 2016 14:30:26 +0000 Subject: Fix a memory leak in the devctl notify code. Submitted by: markj MFC after: asap --- sys/cam/cam_periph.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sys') diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index b1686bc..8f780fd 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -1876,6 +1876,7 @@ cam_periph_devctl_notify(union ccb *ccb) if (cgd->ccb_h.status == CAM_REQ_CMP) sbuf_bcat(&sb, cgd->serial_num, cgd->serial_num_len); + xpt_free_ccb((union ccb *)cgd); } sbuf_printf(&sb, "\" "); sbuf_printf(&sb, "cam_status=\"0x%x\" ", ccb->ccb_h.status); -- cgit v1.1 From 63376757cf97c97df302265cd6975b8daf66d631 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 14:49:49 +0000 Subject: dev/iscsi: minor spelling fixes. No functional change. Reviewed by: trasz --- sys/dev/iscsi/icl_soft.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c index c006c05..bf8bec7 100644 --- a/sys/dev/iscsi/icl_soft.c +++ b/sys/dev/iscsi/icl_soft.c @@ -782,7 +782,7 @@ icl_receive_thread(void *arg) /* * Set the low watermark, to be checked by * soreadable() in icl_soupcall_receive() - * to avoid unneccessary wakeups until there + * to avoid unnecessary wakeups until there * is enough data received to read the PDU. */ SOCKBUF_LOCK(&so->so_rcv); @@ -908,7 +908,7 @@ icl_conn_send_pdus(struct icl_conn *ic, struct icl_pdu_stailq *queue) /* * Set the low watermark, to be checked by * sowriteable() in icl_soupcall_send() - * to avoid unneccessary wakeups until there + * to avoid unnecessary wakeups until there * is enough space for the PDU to fit. */ SOCKBUF_LOCK(&so->so_snd); -- cgit v1.1 From cacb7c41e21bf8ff9e1e931a5a98bef75389a4e3 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 15:14:17 +0000 Subject: sys/sys: minor spelling fixes. While the changes are minor, these headers are very visible. MFC after: 2 weeks --- sys/sys/ata.h | 4 ++-- sys/sys/buf.h | 2 +- sys/sys/buf_ring.h | 4 ++-- sys/sys/iconv.h | 2 +- sys/sys/imgact_binmisc.h | 2 +- sys/sys/imgact_elf.h | 2 +- sys/sys/ipc.h | 2 +- sys/sys/ipmi.h | 2 +- sys/sys/linker.h | 2 +- sys/sys/memrange.h | 2 +- sys/sys/pmc.h | 4 ++-- sys/sys/priority.h | 2 +- sys/sys/priv.h | 2 +- sys/sys/proc.h | 2 +- sys/sys/procctl.h | 2 +- sys/sys/shm.h | 2 +- sys/sys/sockio.h | 2 +- sys/sys/soundcard.h | 4 ++-- sys/sys/sx.h | 2 +- sys/sys/sysctl.h | 4 ++-- sys/sys/timex.h | 2 +- sys/sys/user.h | 2 +- 22 files changed, 27 insertions(+), 27 deletions(-) (limited to 'sys') diff --git a/sys/sys/ata.h b/sys/sys/ata.h index 5df610e..672ee41 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -377,10 +377,10 @@ struct ata_params { #define ATA_NCQ_NON_DATA 0x63 /* NCQ non-data command */ #define ATA_SEND_FPDMA_QUEUED 0x64 /* send DMA NCQ */ #define ATA_SFPDMA_DSM 0x00 /* Data set management */ -#define ATA_SFPDMA_DSM_TRIM 0x01 /* Set trim bit in auxilary */ +#define ATA_SFPDMA_DSM_TRIM 0x01 /* Set trim bit in auxiliary */ #define ATA_SFPDMA_HYBRID_EVICT 0x01 /* Hybrid Evict */ #define ATA_SFPDMA_WLDMA 0x02 /* Write Log DMA EXT */ -#define ATA_RECV_FPDMA_QUEUED 0x65 /* recieve DMA NCQ */ +#define ATA_RECV_FPDMA_QUEUED 0x65 /* receive DMA NCQ */ #define ATA_SEP_ATTN 0x67 /* SEP request */ #define ATA_SEEK 0x70 /* seek */ #define ATA_PACKET_CMD 0xa0 /* packet command */ diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 77343e7..cec28f4 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -206,7 +206,7 @@ struct buf { #define B_NOREUSE 0x00000800 /* Contents not reused once released. */ #define B_00001000 0x00001000 /* Available flag. */ #define B_INVAL 0x00002000 /* Does not contain valid info. */ -#define B_BARRIER 0x00004000 /* Write this and all preceeding first. */ +#define B_BARRIER 0x00004000 /* Write this and all preceding first. */ #define B_NOCACHE 0x00008000 /* Do not cache block after use. */ #define B_MALLOC 0x00010000 /* malloced b_data */ #define B_CLUSTEROK 0x00020000 /* Pagein op, so swap() can count it. */ diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h index 6a6bfc4..c771fe0 100644 --- a/sys/sys/buf_ring.h +++ b/sys/sys/buf_ring.h @@ -98,7 +98,7 @@ buf_ring_enqueue(struct buf_ring *br, void *buf) /* * If there are other enqueues in progress - * that preceeded us, we need to wait for them + * that preceded us, we need to wait for them * to complete */ while (br->br_prod_tail != prod_head) @@ -135,7 +135,7 @@ buf_ring_dequeue_mc(struct buf_ring *br) #endif /* * If there are other dequeues in progress - * that preceeded us, we need to wait for them + * that preceded us, we need to wait for them * to complete */ while (br->br_cons_tail != cons_head) diff --git a/sys/sys/iconv.h b/sys/sys/iconv.h index 5e59795..44a03e961 100644 --- a/sys/sys/iconv.h +++ b/sys/sys/iconv.h @@ -65,7 +65,7 @@ struct iconv_cspair_info { }; /* - * Paramters for 'add' sysctl + * Parameters for 'add' sysctl */ #define ICONV_ADD_VER 1 diff --git a/sys/sys/imgact_binmisc.h b/sys/sys/imgact_binmisc.h index f1ed1d8..ea1b601 100644 --- a/sys/sys/imgact_binmisc.h +++ b/sys/sys/imgact_binmisc.h @@ -41,7 +41,7 @@ #define IBE_NAME_MAX 32 /* Max size for entry name. */ #define IBE_MAGIC_MAX 256 /* Max size for header magic and mask. */ #define IBE_ARG_LEN_MAX 256 /* Max space for optional interpreter command- - line argruments seperated by white space */ + line argruments separated by white space */ #define IBE_INTERP_LEN_MAX (MAXPATHLEN + IBE_ARG_LEN_MAX) #define IBE_MAX_ENTRIES 64 /* Max number of interpreter entries. */ diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h index 9b47042..beb5f96 100644 --- a/sys/sys/imgact_elf.h +++ b/sys/sys/imgact_elf.h @@ -41,7 +41,7 @@ struct image_params; struct thread; /* - * Structure used to pass infomation from the loader to the + * Structure used to pass information from the loader to the * stack fixup routine. */ typedef struct { diff --git a/sys/sys/ipc.h b/sys/sys/ipc.h index e643d48..19f1d39 100644 --- a/sys/sys/ipc.h +++ b/sys/sys/ipc.h @@ -112,7 +112,7 @@ struct ipc_perm { #define IPC_STAT 2 /* get options */ #if __BSD_VISIBLE /* - * For Linux compatability. + * For Linux compatibility. */ #define IPC_INFO 3 /* get info */ #endif diff --git a/sys/sys/ipmi.h b/sys/sys/ipmi.h index 578d78c..b8e318a 100644 --- a/sys/sys/ipmi.h +++ b/sys/sys/ipmi.h @@ -122,7 +122,7 @@ struct ipmi_ipmb_addr { }; #if defined(__amd64__) -/* Compatiblity with 32-bit binaries. */ +/* Compatibility with 32-bit binaries. */ #define IPMICTL_RECEIVE_MSG_TRUNC_32 _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv32) #define IPMICTL_RECEIVE_MSG_32 _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv32) diff --git a/sys/sys/linker.h b/sys/sys/linker.h index 5248bfb..42253a7 100644 --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -160,7 +160,7 @@ int linker_file_function_listall(linker_file_t, linker_function_nameval_callback_t, void *); /* - * Functions soley for use by the linker class handlers. + * Functions solely for use by the linker class handlers. */ int linker_add_class(linker_class_t _cls); int linker_file_unload(linker_file_t _file, int flags); diff --git a/sys/sys/memrange.h b/sys/sys/memrange.h index 32ae238..6d6ff0e 100644 --- a/sys/sys/memrange.h +++ b/sys/sys/memrange.h @@ -1,5 +1,5 @@ /* - * Memory range attribute operations, peformed on /dev/mem + * Memory range attribute operations, performed on /dev/mem * * $FreeBSD$ */ diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index e559b76..a03e507 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -283,7 +283,7 @@ enum pmc_disp { __PMC_CAP(THRESHOLD, 4, "ignore events below a threshold") \ __PMC_CAP(READ, 5, "read PMC counter") \ __PMC_CAP(WRITE, 6, "reprogram PMC counter") \ - __PMC_CAP(INVERT, 7, "invert comparision sense") \ + __PMC_CAP(INVERT, 7, "invert comparison sense") \ __PMC_CAP(QUALIFIER, 8, "further qualify monitored events") \ __PMC_CAP(PRECISE, 9, "perform precise sampling") \ __PMC_CAP(TAGGING, 10, "tag upstream events") \ @@ -587,7 +587,7 @@ struct pmc_op_writelog { /* * OP GETMSR * - * Retrieve the machine specific address assoicated with the allocated + * Retrieve the machine specific address associated with the allocated * PMC. This number can be used subsequently with a read-performance-counter * instruction. */ diff --git a/sys/sys/priority.h b/sys/sys/priority.h index 6548a35..a2cd3b7 100644 --- a/sys/sys/priority.h +++ b/sys/sys/priority.h @@ -126,7 +126,7 @@ struct priority { u_char pri_class; /* Scheduling class. */ u_char pri_level; /* Normal priority level. */ - u_char pri_native; /* Priority before propogation. */ + u_char pri_native; /* Priority before propagation. */ u_char pri_user; /* User priority based on p_cpu and p_nice. */ }; diff --git a/sys/sys/priv.h b/sys/sys/priv.h index 981538b..b1eaece 100644 --- a/sys/sys/priv.h +++ b/sys/sys/priv.h @@ -134,7 +134,7 @@ #define PRIV_JAIL_REMOVE 112 /* Remove a jail. */ /* - * Kernel environment priveleges. + * Kernel environment privileges. */ #define PRIV_KENV_SET 120 /* Set kernel env. variables. */ #define PRIV_KENV_UNSET 121 /* Unset kernel env. variables. */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 16c739e..35303fc 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -426,7 +426,7 @@ do { \ #define TDP_BUFNEED 0x00000008 /* Do not recurse into the buf flush */ #define TDP_COWINPROGRESS 0x00000010 /* Snapshot copy-on-write in progress. */ #define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */ -#define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */ +#define TDP_DEADLKTREAT 0x00000040 /* Lock acquisition - deadlock treatment. */ #define TDP_NOFAULTING 0x00000080 /* Do not handle page faults. */ #define TDP_UNUSED9 0x00000100 /* --available-- */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ diff --git a/sys/sys/procctl.h b/sys/sys/procctl.h index 75dbf53..c6f1e94 100644 --- a/sys/sys/procctl.h +++ b/sys/sys/procctl.h @@ -88,7 +88,7 @@ struct procctl_reaper_kill { int rk_sig; /* in - signal to send */ u_int rk_flags; /* in - REAPER_KILL flags */ pid_t rk_subtree; /* in - subtree, if REAPER_KILL_SUBTREE */ - u_int rk_killed; /* out - count of processes sucessfully + u_int rk_killed; /* out - count of processes successfully killed */ pid_t rk_fpid; /* out - first failed pid for which error is returned */ diff --git a/sys/sys/shm.h b/sys/sys/shm.h index f685df3..455e858 100644 --- a/sys/sys/shm.h +++ b/sys/sys/shm.h @@ -56,7 +56,7 @@ #define SHM_LOCK 11 #define SHM_UNLOCK 12 -/* ipcs shmctl commands for Linux compatability */ +/* ipcs shmctl commands for Linux compatibility */ #define SHM_STAT 13 #define SHM_INFO 14 diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h index 73ebf5f..abdf1c3 100644 --- a/sys/sys/sockio.h +++ b/sys/sys/sockio.h @@ -98,7 +98,7 @@ #define SIOCSIFLLADDR _IOW('i', 60, struct ifreq) /* set linklevel addr */ #define SIOCGI2C _IOWR('i', 61, struct ifreq) /* get I2C data */ -#define SIOCSIFPHYADDR _IOW('i', 70, struct ifaliasreq) /* set gif addres */ +#define SIOCSIFPHYADDR _IOW('i', 70, struct ifaliasreq) /* set gif address */ #define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq) /* get gif psrc addr */ #define SIOCGIFPDSTADDR _IOWR('i', 72, struct ifreq) /* get gif pdst addr */ #define SIOCDIFPHYADDR _IOW('i', 73, struct ifreq) /* delete gif addrs */ diff --git a/sys/sys/soundcard.h b/sys/sys/soundcard.h index 2916287..4867f6c 100644 --- a/sys/sys/soundcard.h +++ b/sys/sys/soundcard.h @@ -185,7 +185,7 @@ struct snd_size { #define AFMT_U24_LE 0x00040000 /* Little endian unsigned 24-bit */ #define AFMT_U24_BE 0x00080000 /* Big endian unsigned 24-bit */ -/* Machine dependant AFMT_* definitions. */ +/* Machine dependent AFMT_* definitions. */ #if BYTE_ORDER == LITTLE_ENDIAN #define AFMT_S16_NE AFMT_S16_LE #define AFMT_S24_NE AFMT_S24_LE @@ -1447,7 +1447,7 @@ void seqbuf_dump(void); /* This function must be provided by programs */ SEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2) /* - * Timing and syncronization macros + * Timing and synchronization macros */ #define _TIMER_EVENT(ev, parm) { \ diff --git a/sys/sys/sx.h b/sys/sys/sx.h index 96a664f..03b51d3 100644 --- a/sys/sys/sx.h +++ b/sys/sys/sx.h @@ -308,7 +308,7 @@ __sx_sunlock(struct sx *sx, const char *file, int line) #define SA_RECURSED LA_RECURSED #define SA_NOTRECURSED LA_NOTRECURSED -/* Backwards compatability. */ +/* Backwards compatibility. */ #define SX_LOCKED LA_LOCKED #define SX_SLOCKED LA_SLOCKED #define SX_XLOCKED LA_XLOCKED diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index eb5eef0..4590ef9 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -608,7 +608,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); __ptr, 0, sysctl_handle_64, "QU", __DESCR(descr)); \ }) -/* Oid for a CPU dependant variable */ +/* Oid for a CPU dependent variable */ #define SYSCTL_ADD_UAUTO(ctx, parent, nbr, name, access, ptr, descr) \ ({ \ struct sysctl_oid *__ret; \ @@ -753,7 +753,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); }) /* - * A macro to generate a read-only sysctl to indicate the presense of optional + * A macro to generate a read-only sysctl to indicate the presence of optional * kernel features. */ #define FEATURE(name, desc) \ diff --git a/sys/sys/timex.h b/sys/sys/timex.h index 4b75fcc..4fa5735 100644 --- a/sys/sys/timex.h +++ b/sys/sys/timex.h @@ -105,7 +105,7 @@ #define TIME_INS 1 /* insert leap second warning */ #define TIME_DEL 2 /* delete leap second warning */ #define TIME_OOP 3 /* leap second in progress */ -#define TIME_WAIT 4 /* leap second has occured */ +#define TIME_WAIT 4 /* leap second has occurred */ #define TIME_ERROR 5 /* error (see status word) */ /* diff --git a/sys/sys/user.h b/sys/sys/user.h index fd362c2..6049e80 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -296,7 +296,7 @@ struct user { /* * Old format. Has variable hidden padding due to alignment. - * This is a compatability hack for pre-build 7.1 packages. + * This is a compatibility hack for pre-build 7.1 packages. */ #if defined(__amd64__) #define KINFO_OFILE_SIZE 1328 -- cgit v1.1 From 838f7d1304c723206899cd4965a1a8ba0761d68f Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 3 May 2016 15:17:43 +0000 Subject: Add EVFILT_VNODE open, read and close notifications. While there, order EVFILT_VNODE notes descriptions alphabetically. Based on submission, and tested by: Vladimir Kondratyev MFC after: 2 weeks --- sys/kern/vfs_subr.c | 39 +++++++++++++++++++++++++++++++++++++++ sys/kern/vnode_if.src | 4 ++++ sys/sys/event.h | 6 ++++++ sys/sys/vnode.h | 4 ++++ 4 files changed, 53 insertions(+) (limited to 'sys') diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 795eac5..97ab886 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -4722,6 +4722,45 @@ vop_symlink_post(void *ap, int rc) VFS_KNOTE_LOCKED(a->a_dvp, NOTE_WRITE); } +void +vop_open_post(void *ap, int rc) +{ + struct vop_open_args *a = ap; + + if (!rc) + VFS_KNOTE_LOCKED(a->a_vp, NOTE_OPEN); +} + +void +vop_close_post(void *ap, int rc) +{ + struct vop_close_args *a = ap; + + if (!rc && (a->a_cred != NOCRED || /* filter out revokes */ + (a->a_vp->v_iflag & VI_DOOMED) == 0)) { + VFS_KNOTE_LOCKED(a->a_vp, (a->a_fflag & FWRITE) != 0 ? + NOTE_CLOSE_WRITE : NOTE_CLOSE); + } +} + +void +vop_read_post(void *ap, int rc) +{ + struct vop_read_args *a = ap; + + if (!rc) + VFS_KNOTE_LOCKED(a->a_vp, NOTE_READ); +} + +void +vop_readdir_post(void *ap, int rc) +{ + struct vop_readdir_args *a = ap; + + if (!rc) + VFS_KNOTE_LOCKED(a->a_vp, NOTE_READ); +} + static struct knlist fs_knlist; static void diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 1b07a36..0350e0e 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -121,6 +121,7 @@ vop_mknod { %% open vp L L L +%! open post vop_open_post vop_open { IN struct vnode *vp; @@ -132,6 +133,7 @@ vop_open { %% close vp L L L +%! close post vop_close_post vop_close { IN struct vnode *vp; @@ -186,6 +188,7 @@ vop_markatime { }; %% read vp L L L +%! read post vop_read_post vop_read { IN struct vnode *vp; @@ -326,6 +329,7 @@ vop_symlink { %% readdir vp L L L +%! readdir post vop_readdir_post vop_readdir { IN struct vnode *vp; diff --git a/sys/sys/event.h b/sys/sys/event.h index 7897c81..5b54150 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -121,6 +121,12 @@ struct kevent { #define NOTE_LINK 0x0010 /* link count changed */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ #define NOTE_REVOKE 0x0040 /* vnode access was revoked */ +#define NOTE_OPEN 0x0080 /* vnode was opened */ +#define NOTE_CLOSE 0x0100 /* file closed, fd did not + allowed write */ +#define NOTE_CLOSE_WRITE 0x0200 /* file closed, fd did allowed + write */ +#define NOTE_READ 0x0400 /* file was read */ /* * data/hint flags for EVFILT_PROC and EVFILT_PROCDESC, shared with userspace diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index f3ae773..df43134 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -774,6 +774,7 @@ int dead_read(struct vop_read_args *ap); int dead_write(struct vop_write_args *ap); /* These are called from within the actual VOPS. */ +void vop_close_post(void *a, int rc); void vop_create_post(void *a, int rc); void vop_deleteextattr_post(void *a, int rc); void vop_link_post(void *a, int rc); @@ -783,6 +784,9 @@ void vop_lookup_post(void *a, int rc); void vop_lookup_pre(void *a); void vop_mkdir_post(void *a, int rc); void vop_mknod_post(void *a, int rc); +void vop_open_post(void *a, int rc); +void vop_read_post(void *a, int rc); +void vop_readdir_post(void *a, int rc); void vop_reclaim_post(void *a, int rc); void vop_remove_post(void *a, int rc); void vop_rename_post(void *a, int rc); -- cgit v1.1 From c3175c64dafd12e981a01665a9422459847df20a Mon Sep 17 00:00:00 2001 From: mav Date: Tue, 3 May 2016 15:27:47 +0000 Subject: Add some device IDs from Intel Sunrise Point chipsets. MFC after: 2 weeks --- sys/dev/ahci/ahci_pci.c | 9 +++++++++ sys/dev/sound/pci/hda/hdac.c | 2 ++ sys/dev/sound/pci/hda/hdac.h | 2 ++ sys/dev/usb/controller/xhci_pci.c | 2 ++ 4 files changed, 15 insertions(+) (limited to 'sys') diff --git a/sys/dev/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c index 11e89c5..6b6a1a6 100644 --- a/sys/dev/ahci/ahci_pci.c +++ b/sys/dev/ahci/ahci_pci.c @@ -176,6 +176,15 @@ static const struct { {0x9c078086, 0x00, "Intel Lynx Point-LP (RAID)", 0}, {0x9c0e8086, 0x00, "Intel Lynx Point-LP (RAID)", 0}, {0x9c0f8086, 0x00, "Intel Lynx Point-LP (RAID)", 0}, + {0x9d038086, 0x00, "Intel Sunrise Point-LP", 0}, + {0x9d058086, 0x00, "Intel Sunrise Point-LP (RAID)", 0}, + {0x9d078086, 0x00, "Intel Sunrise Point-LP (RAID)", 0}, + {0xa1028086, 0x00, "Intel Sunrise Point", 0}, + {0xa1038086, 0x00, "Intel Sunrise Point", 0}, + {0xa1058086, 0x00, "Intel Sunrise Point (RAID)", 0}, + {0xa1068086, 0x00, "Intel Sunrise Point (RAID)", 0}, + {0xa1078086, 0x00, "Intel Sunrise Point (RAID)", 0}, + {0xa10f8086, 0x00, "Intel Sunrise Point (RAID)", 0}, {0x23238086, 0x00, "Intel DH89xxCC", 0}, {0x2360197b, 0x00, "JMicron JMB360", 0}, {0x2361197b, 0x00, "JMicron JMB361", AHCI_Q_NOFORCE}, diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index c761acb..a63c730 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -93,6 +93,8 @@ static const struct { { HDA_INTEL_WELLS2, "Intel Wellsburg", 0, 0 }, { HDA_INTEL_LPTLP1, "Intel Lynx Point-LP", 0, 0 }, { HDA_INTEL_LPTLP2, "Intel Lynx Point-LP", 0, 0 }, + { HDA_INTEL_SRPTLP, "Intel Sunrise Point-LP", 0, 0 }, + { HDA_INTEL_SRPT, "Intel Sunrise Point", 0, 0 }, { HDA_INTEL_82801F, "Intel 82801F", 0, 0 }, { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0, 0 }, { HDA_INTEL_82801G, "Intel 82801G", 0, 0 }, diff --git a/sys/dev/sound/pci/hda/hdac.h b/sys/dev/sound/pci/hda/hdac.h index 1fc265a..71c9e08 100644 --- a/sys/dev/sound/pci/hda/hdac.h +++ b/sys/dev/sound/pci/hda/hdac.h @@ -69,6 +69,8 @@ #define HDA_INTEL_LPTLP1 HDA_MODEL_CONSTRUCT(INTEL, 0x9c20) #define HDA_INTEL_LPTLP2 HDA_MODEL_CONSTRUCT(INTEL, 0x9c21) #define HDA_INTEL_BDW2 HDA_MODEL_CONSTRUCT(INTEL, 0x9ca0) +#define HDA_INTEL_SRPTLP HDA_MODEL_CONSTRUCT(INTEL, 0x9d70) +#define HDA_INTEL_SRPT HDA_MODEL_CONSTRUCT(INTEL, 0xa170) #define HDA_INTEL_ALL HDA_MODEL_CONSTRUCT(INTEL, 0xffff) /* Nvidia */ diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c index d4355e9..09fab21 100644 --- a/sys/dev/usb/controller/xhci_pci.c +++ b/sys/dev/usb/controller/xhci_pci.c @@ -122,6 +122,8 @@ xhci_pci_match(device_t self) return ("Intel Wellsburg USB 3.0 controller"); case 0x9cb18086: return ("Broadwell Integrated PCH-LP chipset USB 3.0 controller"); + case 0xa12f8086: + return ("Intel Sunrise Point USB 3.0 controller"); case 0xa01b177d: return ("Cavium ThunderX USB 3.0 controller"); -- cgit v1.1 From a0e5ea962e5b88a8d2d5573314bd38d106186be7 Mon Sep 17 00:00:00 2001 From: bz Date: Tue, 3 May 2016 16:01:53 +0000 Subject: Remove the most useful INET || INET6 check leftover from whenever, doing nothing. MFC after: 1 week Sponsored by: The FreeBSD Foundation --- sys/net/if_ethersubr.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sys') diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 8698647..6f0e6e3 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -426,9 +426,6 @@ ether_output_frame(struct ifnet *ifp, struct mbuf *m) return ((ifp->if_transmit)(ifp, m)); } -#if defined(INET) || defined(INET6) -#endif - /* * Process a received Ethernet packet; the packet is in the * mbuf chain m with the ethernet header at the front. -- cgit v1.1 From 1602ce85acb3a5eaa0ac7cbd9c090201bfd3ccea Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 16:37:09 +0000 Subject: sys/sys: missed in r298981. I am sure I've missed others as well, but at least it should be more readable now. No functional change. --- sys/sys/imgact_binmisc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/sys/imgact_binmisc.h b/sys/sys/imgact_binmisc.h index ea1b601..7d58fa0 100644 --- a/sys/sys/imgact_binmisc.h +++ b/sys/sys/imgact_binmisc.h @@ -41,7 +41,7 @@ #define IBE_NAME_MAX 32 /* Max size for entry name. */ #define IBE_MAGIC_MAX 256 /* Max size for header magic and mask. */ #define IBE_ARG_LEN_MAX 256 /* Max space for optional interpreter command- - line argruments separated by white space */ + line arguments separated by white space */ #define IBE_INTERP_LEN_MAX (MAXPATHLEN + IBE_ARG_LEN_MAX) #define IBE_MAX_ENTRIES 64 /* Max number of interpreter entries. */ -- cgit v1.1 From a5d1a4f2a502a64fc5ce094c06962fff0efd3f6b Mon Sep 17 00:00:00 2001 From: cem Date: Tue, 3 May 2016 17:05:58 +0000 Subject: ioat(4): Limit descriptor allocation to low 40 bits The IOAT engine can only address the low 40 bits (1 TB) of physmem via the 'next descriptor' pointer. Restrict acceptable range given to bus_dma_tag_create to match. Sponsored by: EMC / Isilon Storage Division --- sys/dev/ioat/ioat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index 85ceacb..1131f48 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -52,6 +52,9 @@ __FBSDID("$FreeBSD$"); #include "ioat_hw.h" #include "ioat_internal.h" +#ifndef BUS_SPACE_MAXADDR_40BIT +#define BUS_SPACE_MAXADDR_40BIT 0xFFFFFFFFFFULL +#endif #define IOAT_INTR_TIMO (hz / 10) #define IOAT_REFLK (&ioat->submit_lock) @@ -454,7 +457,7 @@ ioat3_attach(device_t device) num_descriptors = 1 << ioat->ring_size_order; bus_dma_tag_create(bus_get_dma_tag(ioat->device), 0x40, 0x0, - BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, + BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR, NULL, NULL, sizeof(struct ioat_dma_hw_descriptor), 1, sizeof(struct ioat_dma_hw_descriptor), 0, NULL, NULL, &ioat->hw_desc_tag); -- cgit v1.1 From 3c77465acc4124ea77779461f7d8f48f90fb8198 Mon Sep 17 00:00:00 2001 From: cem Date: Tue, 3 May 2016 17:06:33 +0000 Subject: ioat(4): Add CRC descriptor structure Add CRC/MOVECRC operations, as well as the TEST and STORE variants. With these operations, a CRC32C can be computed over one or more descriptors' source data. When the STORE operation is encountered, the accumulated CRC32C is emitted to memory. A TEST operations triggers an IOAT channel error if the accumulated CRC32C does not match one in memory. These operations are not exposed through any API yet. Sponsored by: EMC / Isilon Storage Division --- sys/dev/ioat/ioat_internal.h | 88 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 7 deletions(-) (limited to 'sys') diff --git a/sys/dev/ioat/ioat_internal.h b/sys/dev/ioat/ioat_internal.h index 85b7316..322671c 100644 --- a/sys/dev/ioat/ioat_internal.h +++ b/sys/dev/ioat/ioat_internal.h @@ -211,6 +211,85 @@ struct ioat_fill_hw_descriptor { uint64_t user2; }; +struct ioat_crc32_hw_descriptor { + uint32_t size; + union { + uint32_t control_raw; + struct generic_dma_control control_generic; + struct { + uint32_t int_enable:1; + uint32_t src_snoop_disable:1; + uint32_t dest_snoop_disable:1; + uint32_t completion_update:1; + uint32_t fence:1; + uint32_t reserved1:3; + uint32_t bundle:1; + uint32_t dest_dca:1; + uint32_t hint:1; + uint32_t use_seed:1; + /* + * crc_location: + * For IOAT_OP_MOVECRC_TEST and IOAT_OP_CRC_TEST: + * 0: comparison value is pointed to by CRC Address + * field. + * 1: comparison value follows data in wire format + * ("inverted reflected bit order") in the 4 bytes + * following the source data. + * + * For IOAT_OP_CRC_STORE: + * 0: Result will be stored at location pointed to by + * CRC Address field (in wire format). + * 1: Result will be stored directly following the + * source data. + * + * For IOAT_OP_MOVECRC_STORE: + * 0: Result will be stored at location pointed to by + * CRC Address field (in wire format). + * 1: Result will be stored directly following the + * *destination* data. + */ + uint32_t crc_location:1; + uint32_t reserved2:11; + /* + * MOVECRC - Move data in the same way as standard copy + * operation, but also compute CRC32. + * + * CRC - Only compute CRC on source data. + * + * There is a CRC accumulator register in the hardware. + * If 'initial' is set, it is initialized to the value + * in 'seed.' + * + * In all modes, these operators accumulate size bytes + * at src_addr into the running CRC32C. + * + * Store mode emits the accumulated CRC, in wire + * format, as specified by the crc_location bit above. + * + * Test mode compares the accumulated CRC against the + * reference CRC, as described in crc_location above. + * On failure, halts the DMA engine with a CRC error + * status. + */ + #define IOAT_OP_MOVECRC 0x41 + #define IOAT_OP_MOVECRC_TEST 0x42 + #define IOAT_OP_MOVECRC_STORE 0x43 + #define IOAT_OP_CRC 0x81 + #define IOAT_OP_CRC_TEST 0x82 + #define IOAT_OP_CRC_STORE 0x83 + uint32_t op:8; + } control; + } u; + uint64_t src_addr; + uint64_t dest_addr; + uint64_t next; + uint64_t next_src_addr; + uint64_t next_dest_addr; + uint32_t seed; + uint32_t reserved; + uint64_t crc_address; +}; + struct ioat_xor_hw_descriptor { uint32_t size; union { @@ -338,6 +417,7 @@ struct ioat_descriptor { struct ioat_generic_hw_descriptor *generic; struct ioat_dma_hw_descriptor *dma; struct ioat_fill_hw_descriptor *fill; + struct ioat_crc32_hw_descriptor *crc32; struct ioat_xor_hw_descriptor *xor; struct ioat_xor_ext_hw_descriptor *xor_ext; struct ioat_pq_hw_descriptor *pq; @@ -348,13 +428,7 @@ struct ioat_descriptor { bus_addr_t hw_desc_bus_addr; }; -/* Unsupported by this driver at this time. */ -#define IOAT_OP_MOVECRC 0x41 -#define IOAT_OP_MOVECRC_TEST 0x42 -#define IOAT_OP_MOVECRC_STORE 0x43 -#define IOAT_OP_CRC 0x81 -#define IOAT_OP_CRC_TEST 0x82 -#define IOAT_OP_CRC_STORE 0x83 +/* Unused by this driver at this time. */ #define IOAT_OP_MARKER 0x84 /* -- cgit v1.1 From e2d34cc69ec0ee70d9140b329dce96dafe228176 Mon Sep 17 00:00:00 2001 From: cem Date: Tue, 3 May 2016 17:07:18 +0000 Subject: ioat(4): Implement CRC and MOVECRC APIs And document them in ioat.4. Sponsored by: EMC / Isilon Storage Division --- sys/dev/ioat/ioat.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++- sys/dev/ioat/ioat.h | 57 +++++++++++++++++- 2 files changed, 216 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index 1131f48..faf6cb4 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -882,8 +882,8 @@ ioat_op_generic(struct ioat_softc *ioat, uint8_t op, mtx_assert(&ioat->submit_lock, MA_OWNED); - KASSERT((flags & ~DMA_ALL_FLAGS) == 0, ("Unrecognized flag(s): %#x", - flags & ~DMA_ALL_FLAGS)); + KASSERT((flags & ~_DMA_GENERIC_FLAGS) == 0, + ("Unrecognized flag(s): %#x", flags & ~_DMA_GENERIC_FLAGS)); if ((flags & DMA_NO_WAIT) != 0) mflags = M_NOWAIT; else @@ -1018,6 +1018,164 @@ ioat_copy_8k_aligned(bus_dmaengine_t dmaengine, bus_addr_t dst1, } struct bus_dmadesc * +ioat_copy_crc(bus_dmaengine_t dmaengine, bus_addr_t dst, bus_addr_t src, + bus_size_t len, uint32_t *initialseed, bus_addr_t crcptr, + bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) +{ + struct ioat_crc32_hw_descriptor *hw_desc; + struct ioat_descriptor *desc; + struct ioat_softc *ioat; + uint32_t teststore; + uint8_t op; + + CTR0(KTR_IOAT, __func__); + ioat = to_ioat_softc(dmaengine); + + if ((ioat->capabilities & IOAT_DMACAP_MOVECRC) == 0) { + ioat_log_message(0, "%s: Device lacks MOVECRC capability\n", + __func__); + return (NULL); + } + if (((src | dst) & (0xffffffull << 40)) != 0) { + ioat_log_message(0, "%s: High 24 bits of src/dst invalid\n", + __func__); + return (NULL); + } + teststore = (flags & _DMA_CRC_TESTSTORE); + if (teststore == _DMA_CRC_TESTSTORE) { + ioat_log_message(0, "%s: TEST and STORE invalid\n", __func__); + return (NULL); + } + if (teststore == 0 && (flags & DMA_CRC_INLINE) != 0) { + ioat_log_message(0, "%s: INLINE invalid without TEST or STORE\n", + __func__); + return (NULL); + } + + switch (teststore) { + case DMA_CRC_STORE: + op = IOAT_OP_MOVECRC_STORE; + break; + case DMA_CRC_TEST: + op = IOAT_OP_MOVECRC_TEST; + break; + default: + KASSERT(teststore == 0, ("bogus")); + op = IOAT_OP_MOVECRC; + break; + } + + if ((flags & DMA_CRC_INLINE) == 0 && + (crcptr & (0xffffffull << 40)) != 0) { + ioat_log_message(0, + "%s: High 24 bits of crcptr invalid\n", __func__); + return (NULL); + } + + desc = ioat_op_generic(ioat, op, len, src, dst, callback_fn, + callback_arg, flags & ~_DMA_CRC_FLAGS); + if (desc == NULL) + return (NULL); + + hw_desc = desc->u.crc32; + + if ((flags & DMA_CRC_INLINE) == 0) + hw_desc->crc_address = crcptr; + else + hw_desc->u.control.crc_location = 1; + + if (initialseed != NULL) { + hw_desc->u.control.use_seed = 1; + hw_desc->seed = *initialseed; + } + + if (g_ioat_debug_level >= 3) + dump_descriptor(hw_desc); + + ioat_submit_single(ioat); + return (&desc->bus_dmadesc); +} + +struct bus_dmadesc * +ioat_crc(bus_dmaengine_t dmaengine, bus_addr_t src, bus_size_t len, + uint32_t *initialseed, bus_addr_t crcptr, + bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) +{ + struct ioat_crc32_hw_descriptor *hw_desc; + struct ioat_descriptor *desc; + struct ioat_softc *ioat; + uint32_t teststore; + uint8_t op; + + CTR0(KTR_IOAT, __func__); + ioat = to_ioat_softc(dmaengine); + + if ((ioat->capabilities & IOAT_DMACAP_CRC) == 0) { + ioat_log_message(0, "%s: Device lacks CRC capability\n", + __func__); + return (NULL); + } + if ((src & (0xffffffull << 40)) != 0) { + ioat_log_message(0, "%s: High 24 bits of src invalid\n", + __func__); + return (NULL); + } + teststore = (flags & _DMA_CRC_TESTSTORE); + if (teststore == _DMA_CRC_TESTSTORE) { + ioat_log_message(0, "%s: TEST and STORE invalid\n", __func__); + return (NULL); + } + if (teststore == 0 && (flags & DMA_CRC_INLINE) != 0) { + ioat_log_message(0, "%s: INLINE invalid without TEST or STORE\n", + __func__); + return (NULL); + } + + switch (teststore) { + case DMA_CRC_STORE: + op = IOAT_OP_CRC_STORE; + break; + case DMA_CRC_TEST: + op = IOAT_OP_CRC_TEST; + break; + default: + KASSERT(teststore == 0, ("bogus")); + op = IOAT_OP_CRC; + break; + } + + if ((flags & DMA_CRC_INLINE) == 0 && + (crcptr & (0xffffffull << 40)) != 0) { + ioat_log_message(0, + "%s: High 24 bits of crcptr invalid\n", __func__); + return (NULL); + } + + desc = ioat_op_generic(ioat, op, len, src, 0, callback_fn, + callback_arg, flags & ~_DMA_CRC_FLAGS); + if (desc == NULL) + return (NULL); + + hw_desc = desc->u.crc32; + + if ((flags & DMA_CRC_INLINE) == 0) + hw_desc->crc_address = crcptr; + else + hw_desc->u.control.crc_location = 1; + + if (initialseed != NULL) { + hw_desc->u.control.use_seed = 1; + hw_desc->seed = *initialseed; + } + + if (g_ioat_debug_level >= 3) + dump_descriptor(hw_desc); + + ioat_submit_single(ioat); + return (&desc->bus_dmadesc); +} + +struct bus_dmadesc * ioat_blockfill(bus_dmaengine_t dmaengine, bus_addr_t dst, uint64_t fillpattern, bus_size_t len, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags) diff --git a/sys/dev/ioat/ioat.h b/sys/dev/ioat/ioat.h index ff05602..2e10124 100644 --- a/sys/dev/ioat/ioat.h +++ b/sys/dev/ioat/ioat.h @@ -52,7 +52,26 @@ __FBSDID("$FreeBSD$"); * may be prefetched before operation 1 completes. */ #define DMA_FENCE 0x4 -#define DMA_ALL_FLAGS (DMA_INT_EN | DMA_NO_WAIT | DMA_FENCE) +#define _DMA_GENERIC_FLAGS (DMA_INT_EN | DMA_NO_WAIT | DMA_FENCE) + +/* + * Emit a CRC32C as the result of a ioat_copy_crc() or ioat_crc(). + */ +#define DMA_CRC_STORE 0x8 + +/* + * Compare the CRC32C of a ioat_copy_crc() or ioat_crc() against an expeceted + * value. It is invalid to specify both TEST and STORE. + */ +#define DMA_CRC_TEST 0x10 +#define _DMA_CRC_TESTSTORE (DMA_CRC_STORE | DMA_CRC_TEST) + +/* + * Use an inline comparison CRC32C or emit an inline CRC32C result. Invalid + * without one of STORE or TEST. + */ +#define DMA_CRC_INLINE 0x20 +#define _DMA_CRC_FLAGS (DMA_CRC_STORE | DMA_CRC_TEST | DMA_CRC_INLINE) /* * Hardware revision number. Different hardware revisions support different @@ -152,6 +171,42 @@ struct bus_dmadesc *ioat_copy_8k_aligned(bus_dmaengine_t dmaengine, bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); /* + * Copy len bytes from dst to src, like ioat_copy(). + * + * Additionally, accumulate a CRC32C of the data. + * + * If initialseed is not NULL, the value it points to is used to seed the + * initial value of the CRC32C. + * + * If flags include DMA_CRC_STORE and not DMA_CRC_INLINE, crcptr is written + * with the 32-bit CRC32C result (in wire format). + * + * If flags include DMA_CRC_TEST and not DMA_CRC_INLINE, the computed CRC32C is + * compared with the 32-bit CRC32C pointed to by crcptr. If they do not match, + * a channel error is raised. + * + * If the DMA_CRC_INLINE flag is set, crcptr is ignored and the DMA engine uses + * the 4 bytes trailing the source data (TEST) or the destination data (STORE). + */ +struct bus_dmadesc *ioat_copy_crc(bus_dmaengine_t dmaengine, bus_addr_t dst, + bus_addr_t src, bus_size_t len, uint32_t *initialseed, bus_addr_t crcptr, + bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); + +/* + * ioat_crc() is nearly identical to ioat_copy_crc(), but does not actually + * move data around. + * + * Like ioat_copy_crc, ioat_crc computes a CRC32C over len bytes pointed to by + * src. The flags affect its operation in the same way, with one exception: + * + * If flags includes both DMA_CRC_STORE and DMA_CRC_INLINE, the computed CRC32C + * is written to the 4 bytes trailing the *source* data. + */ +struct bus_dmadesc *ioat_crc(bus_dmaengine_t dmaengine, bus_addr_t src, + bus_size_t len, uint32_t *initialseed, bus_addr_t crcptr, + bus_dmaengine_callback_t callback_fn, void *callback_arg, uint32_t flags); + +/* * Issues a null operation. This issues the operation to the hardware, but the * hardware doesn't do anything with it. */ -- cgit v1.1 From 28c014925a3f81792d7e34d604dec6030f5c5121 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 3 May 2016 17:11:33 +0000 Subject: [asmc] Add support for MacBookPro5,1 Tested by: Johannes Lundberg PR: kern/209179 Submitted by: Thomas Brierley --- sys/dev/asmc/asmc.c | 6 ++++++ sys/dev/asmc/asmcvar.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'sys') diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c index bbe8bfd..384e733 100644 --- a/sys/dev/asmc/asmc.c +++ b/sys/dev/asmc/asmc.c @@ -216,6 +216,12 @@ struct asmc_model asmc_models[] = { }, { + "MacBookPro5,1", "Apple SMC MacBook Pro Core 2 Duo (2008/2009)", + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, + ASMC_MBP5_TEMPS, ASMC_MBP5_TEMPNAMES, ASMC_MBP5_TEMPDESCS + }, + + { "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)", ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, ASMC_MBP8_TEMPS, ASMC_MBP8_TEMPNAMES, ASMC_MBP8_TEMPDESCS diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h index f67ee16..26c6203 100644 --- a/sys/dev/asmc/asmcvar.h +++ b/sys/dev/asmc/asmcvar.h @@ -188,6 +188,34 @@ struct asmc_softc { "Unknown", "Unknown", \ "Wireless Module", } +#define ASMC_MBP5_TEMPS { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", \ + "TC0F", "TC0P", "TG0D", "TG0F", "TG0H", \ + "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", \ + "TTF0", "Th2H", "Tm0P", "Ts0P", "Ts0S", \ + NULL } + +#define ASMC_MBP5_TEMPNAMES { "enclosure_bottom_0", "enclosure_bottom_1", \ + "enclosure_bottom_2", "enclosure_bottom_3", \ + "cpu_diode", "cpu", \ + "cpu_pin", "gpu_diode", \ + "gpu", "gpu_heatsink", \ + "gpu_pin", "gpu_transistor", \ + "gpu_2_heatsink", "northbridge_diode", \ + "northbridge_pin", "unknown", \ + "heatsink_2", "memory_controller", \ + "pci_express_slot_pin", "pci_express_slot_unk" } + +#define ASMC_MBP5_TEMPDESCS { "Enclosure Bottom 0", "Enclosure Bottom 1", \ + "Enclosure Bottom 2", "Enclosure Bottom 3", \ + "CPU Diode", "CPU ???", \ + "CPU Pin", "GPU Diode", \ + "GPU ???", "GPU Heatsink", \ + "GPU Pin", "GPU Transistor", \ + "GPU 2 Heatsink", "Northbridge Diode", \ + "Northbridge Pin", "Unknown", \ + "Heatsink 2", "Memory Controller", \ + "PCI Express Slot Pin", "PCI Express Slot (unk)" } + #define ASMC_MBP8_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", \ "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \ "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \ -- cgit v1.1 From d9c9113377a2f19d01848ae8dcc470e9306ce932 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 18:05:43 +0000 Subject: sys/net*: minor spelling fixes. No functional change. --- sys/net/altq/altq_cbq.c | 2 +- sys/net/altq/altq_red.c | 4 ++-- sys/net/altq/altq_rio.c | 2 +- sys/net/altq/altq_rmclass.h | 2 +- sys/net/bpf.h | 2 +- sys/net/bridgestp.c | 2 +- sys/net/if.c | 2 +- sys/net/if_arcsubr.c | 2 +- sys/net/if_atm.h | 2 +- sys/net/if_bridge.c | 2 +- sys/net/if_clone.c | 2 +- sys/net/if_epair.c | 2 +- sys/net/if_lagg.c | 2 +- sys/net/if_llatbl.c | 2 +- sys/net/if_sppp.h | 2 +- sys/net/if_spppsubr.c | 4 ++-- sys/net/if_vlan.c | 4 ++-- sys/net/rss_config.c | 2 +- sys/net/rtsock.c | 2 +- sys/net/sff8472.h | 2 +- sys/net80211/ieee80211.c | 2 +- sys/net80211/ieee80211_adhoc.c | 2 +- sys/net80211/ieee80211_hostap.c | 2 +- sys/net80211/ieee80211_ht.c | 2 +- sys/net80211/ieee80211_ioctl.c | 4 ++-- sys/net80211/ieee80211_mesh.c | 2 +- sys/net80211/ieee80211_node.c | 2 +- sys/net80211/ieee80211_output.c | 6 +++--- sys/net80211/ieee80211_proto.c | 6 +++--- sys/net80211/ieee80211_proto.h | 6 +++--- sys/net80211/ieee80211_regdomain.c | 2 +- sys/net80211/ieee80211_scan_sw.c | 6 +++--- sys/netinet/cc/cc_cubic.c | 2 +- sys/netinet/cc/cc_dctcp.c | 2 +- sys/netinet/cc/cc_htcp.c | 2 +- sys/netinet/igmp.c | 4 ++-- sys/netinet/in_mcast.c | 2 +- sys/netinet/in_pcb.h | 2 +- sys/netinet/ip.h | 2 +- sys/netinet/ip_fastfwd.c | 2 +- sys/netinet/ip_fw.h | 6 +++--- sys/netinet/ip_icmp.c | 2 +- sys/netinet/ip_options.c | 2 +- sys/netinet/libalias/alias_irc.c | 4 ++-- sys/netinet/libalias/alias_local.h | 2 +- sys/netinet/libalias/alias_smedia.c | 2 +- sys/netinet/libalias/libalias.3 | 2 +- sys/netinet/tcp_input.c | 4 ++-- sys/netinet/tcp_output.c | 8 ++++---- sys/netinet/tcp_sack.c | 4 ++-- sys/netinet/tcp_stacks/fastpath.c | 4 ++-- sys/netinet/tcp_subr.c | 2 +- sys/netinet/tcp_syncache.c | 4 ++-- sys/netinet/tcp_timer.c | 2 +- sys/netinet6/frag6.c | 2 +- sys/netinet6/in6.c | 2 +- sys/netinet6/in6_mcast.c | 2 +- sys/netinet6/ip6_forward.c | 2 +- sys/netinet6/ip6_id.c | 6 +++--- sys/netinet6/ip6protosw.h | 2 +- sys/netinet6/mld6.c | 4 ++-- sys/netinet6/nd6.c | 4 ++-- sys/netinet6/nd6_rtr.c | 2 +- sys/netipsec/ipsec.c | 6 +++--- sys/netipsec/ipsec_output.c | 2 +- sys/netipsec/key.c | 12 ++++++------ sys/netpfil/ipfw/dn_heap.h | 4 ++-- sys/netpfil/ipfw/dummynet.txt | 12 ++++++------ sys/netpfil/ipfw/ip_dn_glue.c | 2 +- sys/netpfil/ipfw/ip_dummynet.c | 2 +- sys/netpfil/ipfw/ip_fw2.c | 4 ++-- sys/netpfil/ipfw/ip_fw_dynamic.c | 4 ++-- sys/netpfil/ipfw/ip_fw_nat.c | 2 +- sys/netpfil/ipfw/ip_fw_sockopt.c | 10 +++++----- sys/netpfil/ipfw/ip_fw_table.c | 10 +++++----- sys/netpfil/ipfw/ip_fw_table_algo.c | 4 ++-- sys/netpfil/ipfw/ip_fw_table_value.c | 4 ++-- sys/netpfil/pf/pf.c | 2 +- sys/netpfil/pf/pf_ioctl.c | 2 +- sys/netpfil/pf/pf_norm.c | 2 +- sys/netsmb/smb_usr.c | 2 +- 81 files changed, 133 insertions(+), 133 deletions(-) (limited to 'sys') diff --git a/sys/net/altq/altq_cbq.c b/sys/net/altq/altq_cbq.c index a51a21f..56c14d3 100644 --- a/sys/net/altq/altq_cbq.c +++ b/sys/net/altq/altq_cbq.c @@ -701,7 +701,7 @@ cbq_modify_class(acp) * struct rm_class *parent, struct rm_class *borrow) * * This function create a new traffic class in the CBQ class hierarchy of - * given paramters. The class that created is either the root, default, + * given parameters. The class that created is either the root, default, * or a new dynamic class. If CBQ is not initilaized, the the root class * will be created. */ diff --git a/sys/net/altq/altq_red.c b/sys/net/altq/altq_red.c index 1347851..9d75460 100644 --- a/sys/net/altq/altq_red.c +++ b/sys/net/altq/altq_red.c @@ -158,7 +158,7 @@ #define TH_MIN 5 /* min threshold */ #define TH_MAX 15 /* max threshold */ -#define RED_LIMIT 60 /* default max queue lenght */ +#define RED_LIMIT 60 /* default max queue length */ #define RED_STATS /* collect statistics */ /* @@ -171,7 +171,7 @@ #ifdef ALTQ3_COMPAT #ifdef ALTQ_FLOWVALVE /* - * flow-valve is an extention to protect red from unresponsive flows + * flow-valve is an extension to protect red from unresponsive flows * and to promote end-to-end congestion control. * flow-valve observes the average drop rates of the flows that have * experienced packet drops in the recent past. diff --git a/sys/net/altq/altq_rio.c b/sys/net/altq/altq_rio.c index 0f19735e..7687701 100644 --- a/sys/net/altq/altq_rio.c +++ b/sys/net/altq/altq_rio.c @@ -146,7 +146,7 @@ #define TH_MIN 5 /* min threshold */ #define TH_MAX 15 /* max threshold */ -#define RIO_LIMIT 60 /* default max queue lenght */ +#define RIO_LIMIT 60 /* default max queue length */ #define RIO_STATS /* collect statistics */ #define TV_DELTA(a, b, delta) { \ diff --git a/sys/net/altq/altq_rmclass.h b/sys/net/altq/altq_rmclass.h index d511714..6130c4f 100644 --- a/sys/net/altq/altq_rmclass.h +++ b/sys/net/altq/altq_rmclass.h @@ -188,7 +188,7 @@ struct rm_class { */ struct rm_ifdat { int queued_; /* # pkts queued downstream */ - int efficient_; /* Link Efficency bit */ + int efficient_; /* Link Efficiency bit */ int wrr_; /* Enable Weighted Round-Robin */ u_long ns_per_byte_; /* Link byte speed. */ int maxqueued_; /* Max packets to queue */ diff --git a/sys/net/bpf.h b/sys/net/bpf.h index 0ffc15ac..058f3c0 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -579,7 +579,7 @@ struct bpf_zbuf_header { * input packets such as port scans, packets from old lost connections, * etc. to force the connection to stay up). * - * The first byte of the PPP header (0xff03) is modified to accomodate + * The first byte of the PPP header (0xff03) is modified to accommodate * the direction - 0x00 = IN, 0x01 = OUT. */ #define DLT_PPP_PPPD 166 diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c index d6e118c..c308542 100644 --- a/sys/net/bridgestp.c +++ b/sys/net/bridgestp.c @@ -789,7 +789,7 @@ bstp_assign_roles(struct bstp_state *bs) bs->bs_root_htime = bs->bs_bridge_htime; bs->bs_root_port = NULL; - /* check if any recieved info supersedes us */ + /* check if any received info supersedes us */ LIST_FOREACH(bp, &bs->bs_bplist, bp_next) { if (bp->bp_infois != BSTP_INFO_RECEIVED) continue; diff --git a/sys/net/if.c b/sys/net/if.c index 1a11093..7a0bcec 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -558,7 +558,7 @@ ifq_delete(struct ifaltq *ifq) } /* - * Perform generic interface initalization tasks and attach the interface + * Perform generic interface initialization tasks and attach the interface * to the list of "active" interfaces. If vmove flag is set on entry * to if_attach_internal(), perform only a limited subset of initialization * tasks, given that we are moving from one vnet to another an ifnet which diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index 271e652..ff38b68 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -345,7 +345,7 @@ arc_frag_next(struct ifnet *ifp) /* * Defragmenter. Returns mbuf if last packet found, else - * NULL. frees imcoming mbuf as necessary. + * NULL. frees incoming mbuf as necessary. */ static __inline struct mbuf * diff --git a/sys/net/if_atm.h b/sys/net/if_atm.h index c669c3d..a0900ee 100644 --- a/sys/net/if_atm.h +++ b/sys/net/if_atm.h @@ -96,7 +96,7 @@ struct ifatm_mib { /* * Traffic parameters for ATM connections. This contains all parameters - * to accomodate UBR, UBR+MCR, CBR, VBR and ABR connections. + * to accommodate UBR, UBR+MCR, CBR, VBR and ABR connections. * * Keep in sync with ng_atm.h */ diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 6b03711..4fe5e67 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -71,7 +71,7 @@ * - Currently only supports Ethernet-like interfaces (Ethernet, * 802.11, VLANs on Ethernet, etc.) Figure out a nice way * to bridge other types of interfaces (FDDI-FDDI, and maybe - * consider heterogenous bridges). + * consider heterogeneous bridges). */ #include diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index dc71bfc..41516b6 100644 --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -484,7 +484,7 @@ if_clone_list(struct if_clonereq *ifcr) * below, but that's not a major problem. Not caping our * allocation to the number of cloners actually in the system * could be because that would let arbitrary users cause us to - * allocate abritrary amounts of kernel memory. + * allocate arbitrary amounts of kernel memory. */ buf_count = (V_if_cloners_count < ifcr->ifcr_count) ? V_if_cloners_count : ifcr->ifcr_count; diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c index 6c14037..943776c 100644 --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -514,7 +514,7 @@ epair_transmit_locked(struct ifnet *ifp, struct mbuf *m) DPRINTF("packet %s -> %s\n", ifp->if_xname, oifp->if_xname); #ifdef ALTQ - /* Support ALTQ via the clasic if_start() path. */ + /* Support ALTQ via the classic if_start() path. */ IF_LOCK(&ifp->if_snd); if (ALTQ_IS_ENABLED(&ifp->if_snd)) { ALTQ_ENQUEUE(&ifp->if_snd, m, NULL, error); diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 0477122..8b81abf 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -2031,7 +2031,7 @@ lagg_fail_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) if (!LAGG_PORTACTIVE(sc->sc_primary)) { tmp_tp = lagg_link_active(sc, sc->sc_primary); /* - * If tmp_tp is null, we've recieved a packet when all + * If tmp_tp is null, we've received a packet when all * our links are down. Weird, but process it anyways. */ if ((tmp_tp == NULL || tmp_tp == lp)) { diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index beef6b4..7183cff 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -409,7 +409,7 @@ lltable_update_ifaddr(struct lltable *llt) /* * - * Performes generic cleanup routines and frees lle. + * Performs generic cleanup routines and frees lle. * * Called for non-linked entries, with callouts and * other AF-specific cleanups performed. diff --git a/sys/net/if_sppp.h b/sys/net/if_sppp.h index 97f94b3..23a08e7 100644 --- a/sys/net/if_sppp.h +++ b/sys/net/if_sppp.h @@ -78,7 +78,7 @@ struct sauth { /* * Don't change the order of this. Ordering the phases this way allows - * for a comparision of ``pp_phase >= PHASE_AUTHENTICATE'' in order to + * for a comparison of ``pp_phase >= PHASE_AUTHENTICATE'' in order to * know whether LCP is up. */ enum ppp_phase { diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index 092106e..c448061 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -2962,7 +2962,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) * since our algorithm always uses the * original option to NAK it with new values, * things would become more complicated. In - * pratice, the only commonly implemented IP + * practice, the only commonly implemented IP * compression option is VJ anyway, so the * difference is negligible. */ @@ -4295,7 +4295,7 @@ sppp_chap_tlu(struct sppp *sp) if ((sp->hisauth.flags & AUTHFLAG_NORECHALLENGE) == 0) log(-1, "next re-challenge in %d seconds\n", i); else - log(-1, "re-challenging supressed\n"); + log(-1, "re-challenging suppressed\n"); } SPPP_LOCK(sp); diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 462c907..ffa5349 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -700,7 +700,7 @@ vlan_devat(struct ifnet *ifp, uint16_t vid) * VLAN support can be loaded as a module. The only place in the * system that's intimately aware of this is ether_input. We hook * into this code through vlan_input_p which is defined there and - * set here. Noone else in the system should be aware of this so + * set here. No one else in the system should be aware of this so * we use an explicit reference here. */ extern void (*vlan_input_p)(struct ifnet *, struct mbuf *); @@ -873,7 +873,7 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) * o specify no parameters and get an unattached device that * must be configured separately. * The first technique is preferred; the latter two are - * supported for backwards compatibilty. + * supported for backwards compatibility. * * XXXRW: Note historic use of the word "tag" here. New ioctls may be * called for. diff --git a/sys/net/rss_config.c b/sys/net/rss_config.c index e7e8eb4..9597614 100644 --- a/sys/net/rss_config.c +++ b/sys/net/rss_config.c @@ -168,7 +168,7 @@ static uint8_t rss_key[RSS_KEYSIZE] = { /* * RSS hash->CPU table, which maps hashed packet headers to particular CPUs. - * Drivers may supplement this table with a seperate CPU<->queue table when + * Drivers may supplement this table with a separate CPU<->queue table when * programming devices. */ struct rss_table_entry { diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 4a22913..c074603 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1199,7 +1199,7 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * /* * This routine is called to generate a message from the routing - * socket indicating that a redirect has occured, a routing lookup + * socket indicating that a redirect has occurred, a routing lookup * has failed, or that a protocol has detected timeouts to a particular * destination. */ diff --git a/sys/net/sff8472.h b/sys/net/sff8472.h index fdeb2e9..5c50ea4 100644 --- a/sys/net/sff8472.h +++ b/sys/net/sff8472.h @@ -431,7 +431,7 @@ static const char *sff_8024_id[SFF_8024_ID_LAST + 1] = {"Unknown", "SMM8", "CDFP3"}; -/* Keep compability with old definitions */ +/* Keep compatibility with old definitions */ #define SFF_8472_ID_UNKNOWN SFF_8024_ID_UNKNOWN #define SFF_8472_ID_GBIC SFF_8024_ID_GBIC #define SFF_8472_ID_SFF SFF_8024_ID_SFF diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 86f4d81..d2b254a 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -1833,7 +1833,7 @@ ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode m { 6 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM3 }, { 9 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM4 }, { 54 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM27 }, - /* NB: OFDM72 doesn't realy exist so we don't handle it */ + /* NB: OFDM72 doesn't really exist so we don't handle it */ }; static const struct ratemedia htrates[] = { { 0, IFM_IEEE80211_MCS }, diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index deb329f..b7f4bbd 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -775,7 +775,7 @@ adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, * * Since there's no (current) way to inform * the driver that a channel width change has - * occured for a single node, just stub this + * occurred for a single node, just stub this * out. */ #if 0 diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index 3b2670c..1f32c7e 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -1452,7 +1452,7 @@ ieee80211_parse_rsn(struct ieee80211vap *vap, const uint8_t *frm, } /* - * WPA/802.11i assocation request processing. + * WPA/802.11i association request processing. */ static int wpa_assocreq(struct ieee80211_node *ni, struct ieee80211_rsnparms *rsnparms, diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index d33b5c4..9bcd573 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -2298,7 +2298,7 @@ bar_timeout(void *arg) * to make sure we notify the driver that a BAR * TX did occur and fail. This gives the driver * a chance to undo any queue pause that may - * have occured. + * have occurred. */ ic->ic_bar_response(ni, tap, 1); ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT); diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 823906b..3d93278 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -3428,10 +3428,10 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFADDR: /* - * XXX Handle this directly so we can supress if_init calls. + * XXX Handle this directly so we can suppress if_init calls. * XXX This should be done in ether_ioctl but for the moment * XXX there are too many other parts of the system that - * XXX set IFF_UP and so supress if_init being called when + * XXX set IFF_UP and so suppress if_init being called when * XXX it should be. */ ifa = (struct ifaddr *) data; diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 58ec8c1..17adda0 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1155,7 +1155,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m, IEEE80211_TX_UNLOCK_ASSERT(ic); /* - * mesh ttl of 1 means we are the last one receving it, + * mesh ttl of 1 means we are the last one receiving it, * according to amendment we decrement and then check if * 0, if so we dont forward. */ diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 0986145..c1135af 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -2217,7 +2217,7 @@ ieee80211_node_timeout(void *arg) * Defer timeout processing if a channel switch is pending. * We typically need to be mute so not doing things that * might generate frames is good to handle in one place. - * Supressing the station timeout processing may extend the + * Suppressing the station timeout processing may extend the * lifetime of inactive stations (by not decrementing their * idle counters) but this should be ok unless the CSA is * active for an unusually long time. diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 857b042..68e46eb 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -2894,7 +2894,7 @@ ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status) /* * Frame transmit completed; arrange timer callback. If - * transmit was successfuly we wait for response. Otherwise + * transmit was successfully we wait for response. Otherwise * we arrange an immediate callback instead of doing the * callback directly since we don't know what state the driver * is in (e.g. what locks it is holding). This work should @@ -3231,10 +3231,10 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) struct ieee80211_wme_state *wme = &ic->ic_wme; /* - * Check for agressive mode change. When there is + * Check for aggressive mode change. When there is * significant high priority traffic in the BSS * throttle back BE traffic by using conservative - * parameters. Otherwise BE uses agressive params + * parameters. Otherwise BE uses aggressive params * to optimize performance of legacy/non-QoS traffic. */ if (wme->wme_flags & WME_F_AGGRMODE) { diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 6704fea..c85aebf 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -1082,7 +1082,7 @@ ieee80211_wme_initparams_locked(struct ieee80211vap *vap) /* NB: check ic_bss to avoid NULL deref on initial attach */ if (vap->iv_bss != NULL) { /* - * Calculate agressive mode switching threshold based + * Calculate aggressive mode switching threshold based * on beacon interval. This doesn't need locking since * we're only called before entering the RUN state at * which point we start sending beacon frames. @@ -1164,11 +1164,11 @@ ieee80211_wme_updateparams_locked(struct ieee80211vap *vap) mode = IEEE80211_MODE_AUTO; /* - * This implements agressive mode as found in certain + * This implements aggressive mode as found in certain * vendors' AP's. When there is significant high * priority (VI/VO) traffic in the BSS throttle back BE * traffic by using conservative parameters. Otherwise - * BE uses agressive params to optimize performance of + * BE uses aggressive params to optimize performance of * legacy/non-QoS traffic. */ diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 74f8ebcd..f2b231c 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -276,10 +276,10 @@ struct chanAccParams { struct ieee80211_wme_state { u_int wme_flags; -#define WME_F_AGGRMODE 0x00000001 /* STATUS: WME agressive mode */ +#define WME_F_AGGRMODE 0x00000001 /* STATUS: WME aggressive mode */ u_int wme_hipri_traffic; /* VI/VO frames in beacon interval */ - u_int wme_hipri_switch_thresh;/* agressive mode switch thresh */ - u_int wme_hipri_switch_hysteresis;/* agressive mode switch hysteresis */ + u_int wme_hipri_switch_thresh;/* aggressive mode switch thresh */ + u_int wme_hipri_switch_hysteresis;/* aggressive mode switch hysteresis */ struct wmeParams wme_params[4]; /* from assoc resp for each AC*/ struct chanAccParams wme_wmeChanParams; /* WME params applied to self */ diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c index 4db08fd..f565a65 100644 --- a/sys/net80211/ieee80211_regdomain.c +++ b/sys/net80211/ieee80211_regdomain.c @@ -266,7 +266,7 @@ ieee80211_alloc_countryie(struct ieee80211com *ic) * Indoor/Outdoor portion of country string: * 'I' indoor only * 'O' outdoor only - * ' ' all enviroments + * ' ' all environments */ ie->cc[2] = (rd->location == 'I' ? 'I' : rd->location == 'O' ? 'O' : ' '); diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c index 323bf93..9899200 100644 --- a/sys/net80211/ieee80211_scan_sw.c +++ b/sys/net80211/ieee80211_scan_sw.c @@ -771,7 +771,7 @@ scan_end(struct ieee80211_scan_state *ss, int scandone) /* XXX scan state can change! Re-validate scan state! */ /* - * Since a cancellation may have occured during one of the + * Since a cancellation may have occurred during one of the * driver calls (whilst unlocked), update scandone. */ if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_CANCEL) != 0) { @@ -818,7 +818,7 @@ scan_end(struct ieee80211_scan_state *ss, int scandone) "[ticks %u, dwell min %lu scanend %lu]\n", __func__, ticks, ss->ss_mindwell, ss_priv->ss_scanend); - ss->ss_next = 0; /* reset to begining */ + ss->ss_next = 0; /* reset to beginning */ if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) vap->iv_stats.is_scan_active++; else @@ -840,7 +840,7 @@ scan_end(struct ieee80211_scan_state *ss, int scandone) ticks, ss->ss_mindwell, ss_priv->ss_scanend); /* - * Since a cancellation may have occured during one of the + * Since a cancellation may have occurred during one of the * driver calls (whilst unlocked), update scandone. */ if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_CANCEL) != 0) { diff --git a/sys/netinet/cc/cc_cubic.c b/sys/netinet/cc/cc_cubic.c index 9fdb99e..a447345 100644 --- a/sys/netinet/cc/cc_cubic.c +++ b/sys/netinet/cc/cc_cubic.c @@ -143,7 +143,7 @@ cubic_ack_received(struct cc_var *ccv, uint16_t type) * the I-D. Using min_rtt in the tf_cwnd calculation * causes w_tf to grow much faster than it should if the * RTT is dominated by network buffering rather than - * propogation delay. + * propagation delay. */ w_tf = tf_cwnd(ticks_since_cong, cubic_data->mean_rtt_ticks, cubic_data->max_cwnd, diff --git a/sys/netinet/cc/cc_dctcp.c b/sys/netinet/cc/cc_dctcp.c index fd36d1c..ce75750 100644 --- a/sys/netinet/cc/cc_dctcp.c +++ b/sys/netinet/cc/cc_dctcp.c @@ -202,7 +202,7 @@ dctcp_cb_init(struct cc_var *ccv) dctcp_data->bytes_ecn = 0; dctcp_data->bytes_total = 0; /* - * When alpha is set to 0 in the beggining, DCTCP sender transfers as + * When alpha is set to 0 in the beginning, DCTCP sender transfers as * much data as possible until the value converges which may expand the * queueing delay at the switch. When alpha is set to 1, queueing delay * is kept small. diff --git a/sys/netinet/cc/cc_htcp.c b/sys/netinet/cc/cc_htcp.c index 97012f5..5cd84f3 100644 --- a/sys/netinet/cc/cc_htcp.c +++ b/sys/netinet/cc/cc_htcp.c @@ -440,7 +440,7 @@ htcp_recalc_beta(struct cc_var *ccv) /* * TCPTV_SRTTBASE is the initialised value of each connection's SRTT, so * we only calc beta if the connection's SRTT has been changed from its - * inital value. beta is bounded to ensure it is always between + * initial value. beta is bounded to ensure it is always between * HTCP_MINBETA and HTCP_MAXBETA. */ if (V_htcp_adaptive_backoff && htcp_data->minrtt != TCPTV_SRTTBASE && diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index dcadec5..90c00c62 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1103,9 +1103,9 @@ out_locked: } /* - * Process a recieved IGMPv3 group-specific or group-and-source-specific + * Process a received IGMPv3 group-specific or group-and-source-specific * query. - * Return <0 if any error occured. Currently this is ignored. + * Return <0 if any error occurred. Currently this is ignored. */ static int igmp_input_v3_group_query(struct in_multi *inm, struct igmp_ifsoftc *igi, diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index 4037dbf..07b5bba 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -619,7 +619,7 @@ inm_clear_recorded(struct in_multi *inm) * * Return 0 if the source didn't exist or was already marked as recorded. * Return 1 if the source was marked as recorded by this function. - * Return <0 if any error occured (negated errno code). + * Return <0 if any error occurred (negated errno code). */ int inm_record_source(struct in_multi *inm, const in_addr_t naddr) diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 9c77a51..17f7c3d 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -121,7 +121,7 @@ struct in_conninfo { */ #define INC_ISIPV6 0x01 -#define inc_isipv6 inc_flags /* temp compatability */ +#define inc_isipv6 inc_flags /* temp compatibility */ #define inc_fport inc_ie.ie_fport #define inc_lport inc_ie.ie_lport #define inc_faddr inc_ie.ie_faddr diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h index 9269396..98bd1e9 100644 --- a/sys/netinet/ip.h +++ b/sys/netinet/ip.h @@ -147,7 +147,7 @@ struct ip { #define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ #define IPOPT_LSRR 131 /* loose source route */ #define IPOPT_ESO 133 /* extended security */ -#define IPOPT_CIPSO 134 /* commerical security */ +#define IPOPT_CIPSO 134 /* commercial security */ #define IPOPT_SATID 136 /* satnet id */ #define IPOPT_SSRR 137 /* strict source route */ #define IPOPT_RA 148 /* router alert */ diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 22eb727..3fc7c74 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -205,7 +205,7 @@ ip_tryforward(struct mbuf *m) * * XXX: Probably some of these checks could be direct drop * conditions. However it is not clear whether there are some - * hacks or obscure behaviours which make it neccessary to + * hacks or obscure behaviours which make it necessary to * let ip_input handle it. We play safe here and let ip_input * deal with it until it is proven that we can directly drop it. */ diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 7250527..e46abf8 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -861,9 +861,9 @@ typedef struct _ipfw_obj_tentry { #define IPFW_CTF_ATOMIC 0x01 /* Perform atomic operation */ /* Operation results */ #define IPFW_TR_IGNORED 0 /* Entry was ignored (rollback) */ -#define IPFW_TR_ADDED 1 /* Entry was succesfully added */ -#define IPFW_TR_UPDATED 2 /* Entry was succesfully updated*/ -#define IPFW_TR_DELETED 3 /* Entry was succesfully deleted*/ +#define IPFW_TR_ADDED 1 /* Entry was successfully added */ +#define IPFW_TR_UPDATED 2 /* Entry was successfully updated*/ +#define IPFW_TR_DELETED 3 /* Entry was successfully deleted*/ #define IPFW_TR_LIMIT 4 /* Entry was ignored (limit) */ #define IPFW_TR_NOTFOUND 5 /* Entry was not found */ #define IPFW_TR_EXISTS 6 /* Entry already exists */ diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index fee980f..a87daf7 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -223,7 +223,7 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu) /* * Calculate length to quote from original packet and * prevent the ICMP mbuf from overflowing. - * Unfortunatly this is non-trivial since ip_forward() + * Unfortunately this is non-trivial since ip_forward() * sends us truncated packets. */ nlen = m_length(n, NULL); diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c index b050423..3e44ffb 100644 --- a/sys/netinet/ip_options.c +++ b/sys/netinet/ip_options.c @@ -706,7 +706,7 @@ bad: * may change in future. * Router alert options SHOULD be passed if running in IPSTEALTH mode and * we are not the endpoint. - * Length checks on individual options should already have been peformed + * Length checks on individual options should already have been performed * by ip_dooptions() therefore they are folded under INVARIANTS here. * * Return zero if not present or options are invalid, non-zero if present. diff --git a/sys/netinet/libalias/alias_irc.c b/sys/netinet/libalias/alias_irc.c index 552fab8..cb2d67d 100644 --- a/sys/netinet/libalias/alias_irc.c +++ b/sys/netinet/libalias/alias_irc.c @@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$"); Version 2.1: May, 1997 (cjm) Very minor changes to conform with local/global/function naming conventions - withing the packet alising module. + within the packet alising module. */ /* Includes */ @@ -482,7 +482,7 @@ lPACKET_DONE: which will generate a type-error on all but 32-bit machines. [Note 2] This routine really ought to be replaced with one that - creates a transparent proxy on the aliasing host, to allow arbitary + creates a transparent proxy on the aliasing host, to allow arbitrary changes in the TCP stream. This should not be too difficult given this base; I (ee) will try to do this some time later. */ diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h index c291a37..506193c 100644 --- a/sys/netinet/libalias/alias_local.h +++ b/sys/netinet/libalias/alias_local.h @@ -357,7 +357,7 @@ void PunchFWHole(struct alias_link *_lnk); /* Housekeeping function */ void HouseKeeping(struct libalias *); -/* Tcp specfic routines */ +/* Tcp specific routines */ /* lint -save -library Suppress flexelint warnings */ /* Transparent proxy routines */ diff --git a/sys/netinet/libalias/alias_smedia.c b/sys/netinet/libalias/alias_smedia.c index 0e44207..6ab490b 100644 --- a/sys/netinet/libalias/alias_smedia.c +++ b/sys/netinet/libalias/alias_smedia.c @@ -518,7 +518,7 @@ AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, /* * When aliasing a server, check for the 200 reply - * Accomodate varying number of blanks between 200 & OK + * Accommodate varying number of blanks between 200 & OK */ if (dlen >= (int)strlen(str200)) { diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3 index 543420b..e496168 100644 --- a/sys/netinet/libalias/libalias.3 +++ b/sys/netinet/libalias/libalias.3 @@ -1067,7 +1067,7 @@ In case the application provides a .Dv SIGHUP signal handler, add a call to .Fn LibAliasRefreshModules -inside the handler, and everytime you want to refresh the loaded modules, +inside the handler, and every time you want to refresh the loaded modules, send it the .Dv SIGHUP signal: diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 324b0da..cd400f5 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -365,7 +365,7 @@ cc_conn_init(struct tcpcb *tp) /* * There's some sort of gateway or interface * buffer limit on the path. Use this to set - * the slow start threshhold, but set the + * the slow start threshold, but set the * threshold to no less than 2*mss. */ tp->snd_ssthresh = max(2 * maxseg, metrics.rmx_ssthresh); @@ -2533,7 +2533,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * change and FIN isn't set), * the ack is the biggest we've * seen and we've seen exactly our rexmt - * threshhold of them, assume a packet + * threshold of them, assume a packet * has been dropped and retransmit it. * Kludge snd_nxt & the congestion * window so we send only this one diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 2043fc9..e2490ac 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -215,7 +215,7 @@ tcp_output(struct tcpcb *tp) */ if ((tp->t_flags & TF_FASTOPEN) && (tp->t_state == TCPS_SYN_RECEIVED) && - SEQ_GT(tp->snd_max, tp->snd_una) && /* inital SYN|ACK sent */ + SEQ_GT(tp->snd_max, tp->snd_una) && /* initial SYN|ACK sent */ (tp->snd_nxt != tp->snd_una)) /* not a retransmit */ return (0); #endif @@ -495,9 +495,9 @@ after_sack_rexmit: * and does at most one step per received ACK. This fast * scaling has the drawback of growing the send buffer beyond * what is strictly necessary to make full use of a given - * delay*bandwith product. However testing has shown this not + * delay*bandwidth product. However testing has shown this not * to be much of an problem. At worst we are trading wasting - * of available bandwith (the non-use of it) for wasting some + * of available bandwidth (the non-use of it) for wasting some * socket buffer memory. * * TODO: Shrink send buffer during idle periods together @@ -1619,7 +1619,7 @@ tcp_setpersist(struct tcpcb *tp) if (tcp_timer_active(tp, TT_REXMT)) panic("tcp_setpersist: retransmit pending"); /* - * Start/restart persistance timer. + * Start/restart persistence timer. */ TCPT_RANGESET(tt, t * tcp_backoff[tp->t_rxtshift], tcp_persmin, tcp_persmax); diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index 1e31871..a153f6c 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -401,8 +401,8 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) /* * Sort the SACK blocks so we can update the scoreboard with just one - * pass. The overhead of sorting upto 4+1 elements is less than - * making upto 4+1 passes over the scoreboard. + * pass. The overhead of sorting up to 4+1 elements is less than + * making up to 4+1 passes over the scoreboard. */ for (i = 0; i < num_sack_blks; i++) { for (j = i + 1; j < num_sack_blks; j++) { diff --git a/sys/netinet/tcp_stacks/fastpath.c b/sys/netinet/tcp_stacks/fastpath.c index 5529fd8..83547eb 100644 --- a/sys/netinet/tcp_stacks/fastpath.c +++ b/sys/netinet/tcp_stacks/fastpath.c @@ -185,7 +185,7 @@ tcp_do_fastack(struct mbuf *m, struct tcphdr *th, struct socket *so, short ostate = 0; #endif /* - * The following if statment will be true if + * The following if statement will be true if * we are doing the win_up_in_fp * - We have more new data (SEQ_LT(tp->snd_wl1, th->th_seq)) * - No more new data, but we have an ack for new data @@ -1061,7 +1061,7 @@ tcp_do_slowpath(struct mbuf *m, struct tcphdr *th, struct socket *so, * change and FIN isn't set), * the ack is the biggest we've * seen and we've seen exactly our rexmt - * threshhold of them, assume a packet + * threshold of them, assume a packet * has been dropped and retransmit it. * Kludge snd_nxt & the congestion * window so we send only this one diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 178ea77..64d7124 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1376,7 +1376,7 @@ tcp_discardcb(struct tcpcb *tp) * Update the ssthresh always when the conditions below * are satisfied. This gives us better new start value * for the congestion avoidance for new connections. - * ssthresh is only set if packet loss occured on a session. + * ssthresh is only set if packet loss occurred on a session. * * XXXRW: 'so' may be NULL here, and/or socket buffer may be * being torn down. Ideally this code would not use 'so'. diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 2c568da..adb4cab 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1419,7 +1419,7 @@ skip_alloc: * With the default maxsockbuf of 256K, a scale factor * of 3 will be chosen by this algorithm. Those who * choose a larger maxsockbuf should watch out - * for the compatiblity problems mentioned above. + * for the compatibility problems mentioned above. * * RFC1323: The Window field in a SYN (i.e., a * or ) segment itself is never scaled. @@ -1746,7 +1746,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked, * with the latter taking over when the former is exhausted. When matching * syncache entry is found the syncookie is ignored. * - * The only reliable information persisting the 3WHS is our inital sequence + * The only reliable information persisting the 3WHS is our initial sequence * number ISS of 32 bits. Syncookies embed a cryptographically sufficient * strong hash (MAC) value and a few bits of TCP SYN options in the ISS * of our SYN|ACK. The MAC can be recomputed when the ACK to our SYN|ACK diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 5d6865c..5925f42 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -522,7 +522,7 @@ tcp_timer_persist(void *xtp) KASSERT((tp->t_timers->tt_flags & TT_PERSIST) != 0, ("%s: tp %p persist callout should be running", __func__, tp)); /* - * Persistance timer into zero window. + * Persistence timer into zero window. * Force a byte to be output, if possible. */ TCPSTAT_INC(tcps_persisttimeo); diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c index a2f6635..b0aa5fe 100644 --- a/sys/netinet6/frag6.c +++ b/sys/netinet6/frag6.c @@ -135,7 +135,7 @@ frag6_init(void) * fragment's Fragment header. * -> should grab it from the first fragment only * - * The following note also contradicts with fragment rule - noone is going to + * The following note also contradicts with fragment rule - no one is going to * send different fragment with different next header field. * * additional note (p22): diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 0dfaf04..b6817da 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1955,7 +1955,7 @@ in6if_do_dad(struct ifnet *ifp) /* * Our DAD routine requires the interface up and running. * However, some interfaces can be up before the RUNNING - * status. Additionaly, users may try to assign addresses + * status. Additionally, users may try to assign addresses * before the interface becomes up (or running). * This function returns EAGAIN in that case. * The caller should mark "tentative" on the address instead of diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c index 9d96cf5..4effb57 100644 --- a/sys/netinet6/in6_mcast.c +++ b/sys/netinet6/in6_mcast.c @@ -574,7 +574,7 @@ in6m_clear_recorded(struct in6_multi *inm) * * Return 0 if the source didn't exist or was already marked as recorded. * Return 1 if the source was marked as recorded by this function. - * Return <0 if any error occured (negated errno code). + * Return <0 if any error occurred (negated errno code). */ int in6m_record_source(struct in6_multi *inm, const struct in6_addr *addr) diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index e8810d6..3b3058b 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -282,7 +282,7 @@ ip6_forward(struct mbuf *m, int srcrt) * ipsec6_proces_packet will send the packet using ip6_output */ error = ipsec6_process_packet(m, sp->req); - /* Release SP if an error occured */ + /* Release SP if an error occurred */ if (error != 0) KEY_FREESP(&sp); if (error == EJUSTRETURN) { diff --git a/sys/netinet6/ip6_id.c b/sys/netinet6/ip6_id.c index 3f40fa5..9a8086f 100644 --- a/sys/netinet6/ip6_id.c +++ b/sys/netinet6/ip6_id.c @@ -108,7 +108,7 @@ __FBSDID("$FreeBSD$"); struct randomtab { const int ru_bits; /* resulting bits */ - const long ru_out; /* Time after wich will be reseeded */ + const long ru_out; /* Time after which will be reseeded */ const u_int32_t ru_max; /* Uniq cycle, avoid blackjack prediction */ const u_int32_t ru_gen; /* Starting generator */ const u_int32_t ru_n; /* ru_n: prime, ru_n - 1: product of pfacts[] */ @@ -128,7 +128,7 @@ struct randomtab { static struct randomtab randomtab_32 = { 32, /* resulting bits */ - 180, /* Time after wich will be reseeded */ + 180, /* Time after which will be reseeded */ 1000000000, /* Uniq cycle, avoid blackjack prediction */ 2, /* Starting generator */ 2147483629, /* RU_N-1 = 2^2*3^2*59652323 */ @@ -139,7 +139,7 @@ static struct randomtab randomtab_32 = { static struct randomtab randomtab_20 = { 20, /* resulting bits */ - 180, /* Time after wich will be reseeded */ + 180, /* Time after which will be reseeded */ 200000, /* Uniq cycle, avoid blackjack prediction */ 2, /* Starting generator */ 524269, /* RU_N-1 = 2^2*3^2*14563 */ diff --git a/sys/netinet6/ip6protosw.h b/sys/netinet6/ip6protosw.h index e8d4bad..9e80a69 100644 --- a/sys/netinet6/ip6protosw.h +++ b/sys/netinet6/ip6protosw.h @@ -92,7 +92,7 @@ struct pr_usrreqs; * * ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original * (internal) packet carries a routing header, it may point the final - * dstination address in the routing header. + * destination address in the routing header. * * ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6 * (beware of flowlabel, if you try to compare it against others) diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c index 3c4cc99..a2f2d7e 100644 --- a/sys/netinet6/mld6.c +++ b/sys/netinet6/mld6.c @@ -971,9 +971,9 @@ out_locked: } /* - * Process a recieved MLDv2 group-specific or group-and-source-specific + * Process a received MLDv2 group-specific or group-and-source-specific * query. - * Return <0 if any error occured. Currently this is ignored. + * Return <0 if any error occurred. Currently this is ignored. */ static int mld_v2_process_group_query(struct in6_multi *inm, struct mld_ifsoftc *mli, diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 3921e32..2aaa10d 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -479,7 +479,7 @@ nd6_options(union nd_opts *ndopts) default: /* * Unknown options must be silently ignored, - * to accomodate future extension to the protocol. + * to accommodate future extension to the protocol. */ nd6log((LOG_DEBUG, "nd6_options: unsupported option %d - " @@ -1604,7 +1604,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) case SIOCSIFINFO_IN6: /* * used to change host variables from userland. - * intented for a use on router to reflect RA configurations. + * intended for a use on router to reflect RA configurations. */ /* 0 means 'unspecified' */ if (ND.linkmtu != 0) { diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index aa7baad..f679c3f 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -482,7 +482,7 @@ nd6_rtmsg(int cmd, struct rtentry *rt) } /* - * default router list proccessing sub routines + * default router list processing sub routines */ static void diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index e03fc02..fbe4b1a 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -290,7 +290,7 @@ key_allocsp_default(const char* where, int tag) * 0 : bypass * EACCES : discard packet. * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. + * others : error occurred. * others: a pointer to SP * * NOTE: IPv6 mapped adddress concern is implemented here. @@ -318,7 +318,7 @@ ipsec_getpolicy(struct tdb_ident *tdbi, u_int dir) * 0 : bypass * EACCES : discard packet. * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. + * others : error occurred. * others: a pointer to SP * * NOTE: IPv6 mapped adddress concern is implemented here. @@ -425,7 +425,7 @@ ipsec_getpolicybysock(const struct mbuf *m, u_int dir, struct inpcb *inp, * 0 : bypass * EACCES : discard packet. * ENOENT : ipsec_acquire() in progress, maybe. - * others : error occured. + * others : error occurred. */ struct secpolicy * ipsec_getpolicybyaddr(const struct mbuf *m, u_int dir, int *error) diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c index e0523d4..24d8f4e 100644 --- a/sys/netipsec/ipsec_output.c +++ b/sys/netipsec/ipsec_output.c @@ -589,7 +589,7 @@ ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr) * packet will be returned for transmission after crypto * processing, etc. are completed. * - * NB: m & sav are ``passed to caller'' who's reponsible for + * NB: m & sav are ``passed to caller'' who's responsible for * for reclaiming their resources. */ switch(dst->sa.sa_family) { diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 7d58d84..db7defd 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -933,7 +933,7 @@ key_do_allocsa_policy(struct secashead *sah, u_int state) { struct secasvar *sav, *nextsav, *candidate, *d; - /* initilize */ + /* initialize */ candidate = NULL; SAHTREE_LOCK(); @@ -1058,7 +1058,7 @@ key_do_allocsa_policy(struct secashead *sah, u_int state) * allocating a usable SA entry for a *INBOUND* packet. * Must call key_freesav() later. * OUT: positive: pointer to a usable sav (i.e. MATURE or DYING state). - * NULL: not found, or error occured. + * NULL: not found, or error occurred. * * In the comparison, no source address is used--for RFC2401 conformance. * To quote, from section 4.1: @@ -2335,7 +2335,7 @@ key_spdget(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) * send * * to KMD, and expect to receive - * with SADB_X_SPDACQUIRE if error occured, + * with SADB_X_SPDACQUIRE if error occurred, * or * * with SADB_X_SPDUPDATE from KMD by PF_KEY. @@ -6153,7 +6153,7 @@ key_getprop(const struct secasindex *saidx) * * to KMD, and expect to receive - * with SADB_ACQUIRE if error occured, + * with SADB_ACQUIRE if error occurred, * or * with SADB_GETSPI * from KMD by PF_KEY. @@ -6517,9 +6517,9 @@ key_acquire2(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) /* * Error message from KMd. - * We assume that if error was occured in IKEd, the length of PFKEY + * We assume that if error was occurred in IKEd, the length of PFKEY * message is equal to the size of sadb_msg structure. - * We do not raise error even if error occured in this function. + * We do not raise error even if error occurred in this function. */ if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) { struct secacq *acq; diff --git a/sys/netpfil/ipfw/dn_heap.h b/sys/netpfil/ipfw/dn_heap.h index c95473a..cb6e03e 100644 --- a/sys/netpfil/ipfw/dn_heap.h +++ b/sys/netpfil/ipfw/dn_heap.h @@ -83,7 +83,7 @@ enum { * heap_insert() adds a key-pointer pair to the heap * * HEAP_TOP() returns a pointer to the top element of the heap, - * but makes no checks on its existance (XXX should we change ?) + * but makes no checks on its existence (XXX should we change ?) * * heap_extract() removes the entry at the top, returing the pointer. * (the key should have been read before). @@ -146,7 +146,7 @@ int heap_scan(struct dn_heap *, int (*)(void *, uintptr_t), uintptr_t); * of the dn_ht_find(), and of the callbacks: * * DNHT_KEY_IS_OBJ means the key is the object pointer. - * It is usally of interest for the hash and match functions. + * It is usually of interest for the hash and match functions. * * DNHT_MATCH_PTR during a lookup, match pointers instead * of calling match(). Normally used when removing specific diff --git a/sys/netpfil/ipfw/dummynet.txt b/sys/netpfil/ipfw/dummynet.txt index b3b2ee9..68cce1a 100644 --- a/sys/netpfil/ipfw/dummynet.txt +++ b/sys/netpfil/ipfw/dummynet.txt @@ -86,7 +86,7 @@ USERLAND-KERNEL API (ip_dummynet.h) struct dn_link: contains data about the physical link such as - bandwith, delay, burst size; + bandwidth, delay, burst size; struct dn_fs: describes a flowset, i.e. a template for queues. @@ -444,7 +444,7 @@ of the object to remove Delete of pipe x ---------------- -A pipe can be deleted by the user throught the command 'ipfw pipe x delete'. +A pipe can be deleted by the user through the command 'ipfw pipe x delete'. To delete a pipe, the pipe is removed from the pipe list, and then deleted. Also the scheduler associated with this pipe should be deleted. For compatibility with old dummynet syntax, the associated FIFO scheduler and @@ -452,7 +452,7 @@ FIFO flowset must be deleted. Delete of flowset x ------------------- -To remove a flowset, we must be sure that is no loger referenced by any object. +To remove a flowset, we must be sure that is no longer referenced by any object. If the flowset to remove is in the unlinked flowset list, there is not any issue, the flowset can be safely removed calling a free() (the flowset extension is not yet created if the flowset is in this list). @@ -492,7 +492,7 @@ If the counter was not 0, we wait for it. Every time the dummynet_task() function extract a scheduler from the system_heap, the counter is decremented. If the scheduler has the delete flag enabled the dequeue() is not called and delete_scheduler_instance() is called to delete the instance. -Obviously this scheduler instance is no loger inserted in the system_heap. +Obviously this scheduler instance is no longer inserted in the system_heap. If the counter reaches 0, the delete_scheduler_template() function is called all memory is released. NOTE: Flowsets that belong to this scheduler are not deleted, so if a new @@ -559,7 +559,7 @@ There are four request for old dummynet: depending of its version. There are two function that build the corrected buffer, ip_dummynet_get7() and ip_dummynet_get8(). These functions reproduce the buffer exactly as 'ipfw' expect. The only difference - is that the weight parameter for a queue is no loger sent by dummynet and so + is that the weight parameter for a queue is no longer sent by dummynet and so it is set to 0. Moreover, because of the internal structure has changed, the bucket size of a queue could not be correct, because now all flowset share the hash @@ -581,7 +581,7 @@ I have to modify the ip_fw2.c file to manage these two case, and added a variable (is7) to store the ipfw version used, using an approach like the previous file: - when a new rule is added (option IP_FW_ADD) the is7 variable is set if the - size of the rule received corrispond to FreeBSD 7.2 ipfw version. If so, the + size of the rule received correspond to FreeBSD 7.2 ipfw version. If so, the rule is converted to version 8 calling the function convert_rule_to_8(). Moreover, after the insertion of the rule, the rule is now reconverted to version 7 because the ipfw binary will print it. diff --git a/sys/netpfil/ipfw/ip_dn_glue.c b/sys/netpfil/ipfw/ip_dn_glue.c index 7d7e695..02fbf3e 100644 --- a/sys/netpfil/ipfw/ip_dn_glue.c +++ b/sys/netpfil/ipfw/ip_dn_glue.c @@ -778,7 +778,7 @@ ip_dummynet_compat(struct sockopt *sopt) void *v = NULL; struct dn_id oid; - /* Lenght of data, used to found ipfw version... */ + /* Length of data, used to found ipfw version... */ int len = sopt->sopt_valsize; /* len can be 0 if command was dummynet_flush */ diff --git a/sys/netpfil/ipfw/ip_dummynet.c b/sys/netpfil/ipfw/ip_dummynet.c index 120f30f..941e0a3 100644 --- a/sys/netpfil/ipfw/ip_dummynet.c +++ b/sys/netpfil/ipfw/ip_dummynet.c @@ -1629,7 +1629,7 @@ dummynet_flush(void) * with an oid which is at least a dn_id. * - the first object is the command (config, delete, flush, ...) * - config_link must be issued after the corresponding config_sched - * - parameters (DN_TXT) for an object must preceed the object + * - parameters (DN_TXT) for an object must precede the object * processed on a config_sched. */ int diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index b0a7474..45da69d 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -936,7 +936,7 @@ ipfw_chk(struct ip_fw_args *args) * offset == 0 means that (if this is an IPv4 packet) * this is the first or only fragment. * For IPv6 offset|ip6f_mf == 0 means there is no Fragment Header - * or there is a single packet fragement (fragement header added + * or there is a single packet fragment (fragment header added * without needed). We will treat a single packet fragment as if * there was no fragment header (or log/block depending on the * V_fw_permit_single_frag6 sysctl setting). @@ -1999,7 +1999,7 @@ do { \ * certainly be inp_user_cookie? */ - /* For incomming packet, lookup up the + /* For incoming packet, lookup up the inpcb using the src/dest ip/port tuple */ if (inp == NULL) { inp = in_pcblookup(pi, diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c index 96f38e4..991de22 100644 --- a/sys/netpfil/ipfw/ip_fw_dynamic.c +++ b/sys/netpfil/ipfw/ip_fw_dynamic.c @@ -989,7 +989,7 @@ ipfw_dyn_send_ka(struct mbuf **mtailp, ipfw_dyn_rule *q) } /* - * This procedure is used to perform various maintance + * This procedure is used to perform various maintenance * on dynamic hash list. Currently it is called every second. */ static void @@ -1021,7 +1021,7 @@ ipfw_dyn_tick(void * vnetx) /* - * Walk thru all dynamic states doing generic maintance: + * Walk through all dynamic states doing generic maintenance: * 1) free expired states * 2) free all states based on deleted rule / set * 3) send keepalives for states if needed diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c index df40398..a32d32f 100644 --- a/sys/netpfil/ipfw/ip_fw_nat.c +++ b/sys/netpfil/ipfw/ip_fw_nat.c @@ -932,7 +932,7 @@ ipfw_nat_cfg(struct sockopt *sopt) /* * Allocate 2x buffer to store converted structures. - * new redir_cfg has shrinked, so we're sure that + * new redir_cfg has shrunk, so we're sure that * new buffer size is enough. */ buf = malloc(roundup2(len, 8) + len2, M_TEMP, M_WAITOK | M_ZERO); diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 5eecf97..c2b9a79 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -2467,7 +2467,7 @@ ref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule, if (error != 0) break; /* - * Compability stuff for old clients: + * Compatibility stuff for old clients: * prepare to automaitcally create non-existing objects. */ if (unresolved != 0) { @@ -2579,7 +2579,7 @@ free: * Rules in reply are modified to store their actual ruleset number. * * (*1) TLVs inside IPFW_TLV_TBL_LIST needs to be sorted ascending - * accoring to their idx field and there has to be no duplicates. + * according to their idx field and there has to be no duplicates. * (*2) Numbered rules inside IPFW_TLV_RULE_LIST needs to be sorted ascending. * (*3) Each ip_fw structure needs to be aligned to u64 boundary. * @@ -3279,7 +3279,7 @@ ipfw_flush_sopt_data(struct sockopt_data *sd) } /* - * Ensures that @sd buffer has contigious @neeeded number of + * Ensures that @sd buffer has contiguous @neeeded number of * bytes. * * Returns pointer to requested space or NULL. @@ -3307,7 +3307,7 @@ ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed) } /* - * Requests @needed contigious bytes from @sd buffer. + * Requests @needed contiguous bytes from @sd buffer. * Function is used to notify subsystem that we are * interesed in first @needed bytes (request header) * and the rest buffer can be safely zeroed. @@ -3396,7 +3396,7 @@ ipfw_ctl3(struct sockopt *sopt) /* * Determine opcode type/buffer size: * allocate sliding-window buf for data export or - * contigious buffer for special ops. + * contiguous buffer for special ops. */ if ((h.dir & HDIR_SET) != 0) { /* Set request. Allocate contigous buffer. */ diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 175202a..2bb70d6 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -319,7 +319,7 @@ find_ref_table(struct ip_fw_chain *ch, struct tid_info *ti, if (op == OP_DEL) return (ESRCH); - /* Compability mode: create new table for old clients */ + /* Compatibility mode: create new table for old clients */ if ((tei->flags & TEI_FLAGS_COMPAT) == 0) return (ESRCH); @@ -927,7 +927,7 @@ manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3, tei.masklen = xent->masklen; ipfw_import_table_value_legacy(xent->value, &v); tei.pvalue = &v; - /* Old requests compability */ + /* Old requests compatibility */ tei.flags = TEI_FLAGS_COMPAT; if (xent->type == IPFW_TABLE_ADDR) { if (xent->len - hdrlen == sizeof(in_addr_t)) @@ -1207,7 +1207,7 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti) uint8_t tflags; /* - * Stage 1: save table algoritm. + * Stage 1: save table algorithm. * Reference found table to ensure it won't disappear. */ IPFW_UH_WLOCK(ch); @@ -2582,7 +2582,7 @@ ipfw_foreach_table_tentry(struct ip_fw_chain *ch, uint16_t kidx, */ /* - * Finds algoritm by index, table type or supplied name. + * Finds algorithm by index, table type or supplied name. * * Returns pointer to algo or NULL. */ @@ -3224,7 +3224,7 @@ ipfw_swap_tables_sets(struct ip_fw_chain *ch, uint32_t set, * Move all tables which are reference by rules in @rr to set @new_set. * Makes sure that all relevant tables are referenced ONLLY by given rules. * - * Retuns 0 on success, + * Returns 0 on success, */ int ipfw_move_tables_sets(struct ip_fw_chain *ch, ipfw_range_tlv *rt, diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c index c04ee86..b0ad73d 100644 --- a/sys/netpfil/ipfw/ip_fw_table_algo.c +++ b/sys/netpfil/ipfw/ip_fw_table_algo.c @@ -181,7 +181,7 @@ __FBSDID("$FreeBSD$"); * OPTIONAL, locked (UH). (M_NOWAIT). Returns 0 on success. * * Finds entry specified by given key. - * * Caller is requred to do the following: + * * Caller is required to do the following: * entry found: returns 0, export entry to @tent * entry not found: returns ENOENT * @@ -263,7 +263,7 @@ __FBSDID("$FreeBSD$"); * Dumps entry @e to @tent. * * - * -print_config: prints custom algoritm options into buffer. + * -print_config: prints custom algorithm options into buffer. * typedef void (ta_print_config)(void *ta_state, struct table_info *ti, * char *buf, size_t bufsize); * OPTIONAL. locked(UH). (M_NOWAIT). diff --git a/sys/netpfil/ipfw/ip_fw_table_value.c b/sys/netpfil/ipfw/ip_fw_table_value.c index 7e2f5cb..7ca316d 100644 --- a/sys/netpfil/ipfw/ip_fw_table_value.c +++ b/sys/netpfil/ipfw/ip_fw_table_value.c @@ -500,7 +500,7 @@ ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts) count = ts->count; for (i = 0; i < count; i++) { ptei = &tei[i]; - ptei->value = 0; /* Ensure value is always 0 in the beginnig */ + ptei->value = 0; /* Ensure value is always 0 in the beginning */ mask_table_value(ptei->pvalue, &tval, ts->vmask); ptv = (struct table_val_link *)ipfw_objhash_lookup_name(vi, 0, (char *)&tval); @@ -603,7 +603,7 @@ ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts) } /* - * Compability function used to import data from old + * Compatibility function used to import data from old * IP_FW_TABLE_ADD / IP_FW_TABLE_XADD opcodes. */ void diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 0220286..9799780 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -3957,7 +3957,7 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst, * (Selective ACK). We could optionally validate the SACK values * against the current ACK window, either forwards or backwards, but * I'm not confident that SACK has been implemented properly - * everywhere. It wouldn't surprise me if several stacks accidently + * everywhere. It wouldn't surprise me if several stacks accidentally * SACK too far backwards of previously ACKed data. There really aren't * any security implications of bad SACKing unless the target stack * doesn't validate the option length correctly. Someone trying to diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index c98846a..83eabcd 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -3539,7 +3539,7 @@ shutdown_pf(void) pf_clear_srcnodes(NULL); /* status does not use malloced mem so no need to cleanup */ - /* fingerprints and interfaces have thier own cleanup code */ + /* fingerprints and interfaces have their own cleanup code */ } while(0); return (error); diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c index 99cca63..a2841a2 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$"); struct pf_frent { TAILQ_ENTRY(pf_frent) fr_next; struct mbuf *fe_m; - uint16_t fe_hdrlen; /* ipv4 header lenght with ip options + uint16_t fe_hdrlen; /* ipv4 header length with ip options ipv6, extension, fragment header */ uint16_t fe_extoff; /* last extension header offset or 0 */ uint16_t fe_len; /* fragment length */ diff --git a/sys/netsmb/smb_usr.c b/sys/netsmb/smb_usr.c index 6c3e6b1..1b1d1f8 100644 --- a/sys/netsmb/smb_usr.c +++ b/sys/netsmb/smb_usr.c @@ -158,7 +158,7 @@ out: /* * Connect to the resource specified by smbioc_ossn structure. * It may either find an existing connection or try to establish a new one. - * If no errors occured smb_vc returned locked and referenced. + * If no errors occurred smb_vc returned locked and referenced. */ int smb_usr_opensession(struct smbioc_ossn *dp, struct smb_cred *scred, -- cgit v1.1 From 804dbb21fcfa6e9565452f746b24e4f9f5fa84ec Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 3 May 2016 19:37:25 +0000 Subject: Use the correct location of the SRIOV capability when enabling ARI. While here, check if ARI was enabled by re-reading the config register after writing it and return an error if the write fails. Reviewed by: rstone, vangyzen --- sys/dev/pci/pci_iov.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index 287f5a2..337441d 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -442,6 +442,7 @@ pci_iov_set_ari(device_t bus) } } } + free(devlist, M_TEMP); /* * If we called this function some device must have the SR-IOV @@ -451,10 +452,14 @@ pci_iov_set_ari(device_t bus) ("Could not find child of %s with SR-IOV capability", device_get_nameunit(bus))); - iov_ctl = pci_read_config(lowest, iov_pos + PCIR_SRIOV_CTL, 2); + iov_ctl = pci_read_config(lowest, lowest_pos + PCIR_SRIOV_CTL, 2); iov_ctl |= PCIM_SRIOV_ARI_EN; - pci_write_config(lowest, iov_pos + PCIR_SRIOV_CTL, iov_ctl, 2); - free(devlist, M_TEMP); + pci_write_config(lowest, lowest_pos + PCIR_SRIOV_CTL, iov_ctl, 2); + if ((pci_read_config(lowest, lowest_pos + PCIR_SRIOV_CTL, 2) & + PCIM_SRIOV_ARI_EN) == 0) { + device_printf(lowest, "failed to enable ARI\n"); + return (ENXIO); + } return (0); } -- cgit v1.1 From aa744856810115af0244cfb9887d1e1667fcf415 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 3 May 2016 19:45:24 +0000 Subject: Save and restore SRIOV-related config registers. Save the value of the IOV control and page size registers and restore them (along with the VF count) in pci_cfg_save/pci_cfg_restore. This ensures ARI remains enabled if a PF driver resets itself during the PCI_IOV_INIT callback. This might also properly restore SRIOV state across suspend/resume. Reviewed by: rstone, vangyzen Differential Revision: https://reviews.freebsd.org/D6192 --- sys/dev/pci/pci.c | 7 +++++++ sys/dev/pci/pci_iov.c | 23 +++++++++++++++++++++++ sys/dev/pci/pci_iov_private.h | 6 ++++++ 3 files changed, 36 insertions(+) (limited to 'sys') diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 630aaa9..ae01f24 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -5643,6 +5643,10 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo) pci_resume_msi(dev); if (dinfo->cfg.msix.msix_location != 0) pci_resume_msix(dev); + + if (dinfo->cfg.iov != NULL) + pci_iov_cfg_restore(dev, dinfo); + } static void @@ -5755,6 +5759,9 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) if (dinfo->cfg.pcix.pcix_location != 0) pci_cfg_save_pcix(dev, dinfo); + if (dinfo->cfg.iov != NULL) + pci_iov_cfg_save(dev, dinfo); + /* * don't set the state for display devices, base peripherals and * memory devices since bad things happen when they are powered down. diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index 337441d..bba99f6 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -770,6 +770,29 @@ out: return (error); } +void +pci_iov_cfg_restore(device_t dev, struct pci_devinfo *dinfo) +{ + struct pcicfg_iov *iov; + + iov = dinfo->cfg.iov; + + IOV_WRITE(dinfo, PCIR_SRIOV_PAGE_SIZE, iov->iov_page_size, 4); + IOV_WRITE(dinfo, PCIR_SRIOV_NUM_VFS, iov->iov_num_vfs, 2); + IOV_WRITE(dinfo, PCIR_SRIOV_CTL, iov->iov_ctl, 2); +} + +void +pci_iov_cfg_save(device_t dev, struct pci_devinfo *dinfo) +{ + struct pcicfg_iov *iov; + + iov = dinfo->cfg.iov; + + iov->iov_page_size = IOV_READ(dinfo, PCIR_SRIOV_PAGE_SIZE, 4); + iov->iov_ctl = IOV_READ(dinfo, PCIR_SRIOV_CTL, 2); +} + /* Return true if child is a VF of the given PF. */ static int pci_iov_is_child_vf(struct pcicfg_iov *pf, device_t child) diff --git a/sys/dev/pci/pci_iov_private.h b/sys/dev/pci/pci_iov_private.h index 6938e2e..2d15353 100644 --- a/sys/dev/pci/pci_iov_private.h +++ b/sys/dev/pci/pci_iov_private.h @@ -47,10 +47,16 @@ struct pcicfg_iov { int iov_pos; int iov_num_vfs; uint32_t iov_flags; + + uint16_t iov_ctl; + uint32_t iov_page_size; }; #define IOV_RMAN_INITED 0x0001 #define IOV_BUSY 0x0002 +void pci_iov_cfg_restore(device_t dev, struct pci_devinfo *dinfo); +void pci_iov_cfg_save(device_t dev, struct pci_devinfo *dinfo); + #endif -- cgit v1.1 From 9474ad68a7d52eeba605ca2cc9a9a17584c649f5 Mon Sep 17 00:00:00 2001 From: vangyzen Date: Tue, 3 May 2016 20:14:04 +0000 Subject: Work around (ignore) broken SRAT tables Instead of panicking when parsing an invalid ACPI SRAT table, just ignore it, effectively disabling NUMA. https://lists.freebsd.org/pipermail/freebsd-current/2016-May/060984.html Reported and tested by: Bill O'Hanlon (bill.ohanlon at gmail.com) Reviewed by: jhb MFC after: 1 week Relnotes: If dmesg shows "SRAT: Duplicate local APIC ID", try updating your BIOS to fix NUMA support. Sponsored by: Dell Inc. --- sys/x86/acpica/srat.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/x86/acpica/srat.c b/sys/x86/acpica/srat.c index 85f1922..1d0f73d 100644 --- a/sys/x86/acpica/srat.c +++ b/sys/x86/acpica/srat.c @@ -201,8 +201,12 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg) "enabled" : "disabled"); if (!(cpu->Flags & ACPI_SRAT_CPU_ENABLED)) break; - KASSERT(!cpus[cpu->ApicId].enabled, - ("Duplicate local APIC ID %u", cpu->ApicId)); + if (cpus[cpu->ApicId].enabled) { + printf("SRAT: Duplicate local APIC ID %u\n", + cpu->ApicId); + *(int *)arg = ENXIO; + break; + } cpus[cpu->ApicId].domain = domain; cpus[cpu->ApicId].enabled = 1; break; -- cgit v1.1 From ffb7443159e30477f3edc3382e3312675025e80b Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 21:51:52 +0000 Subject: sys/isa: minor spelling fixes. No functional change. --- sys/isa/isa_common.h | 2 +- sys/isa/pnp.c | 2 +- sys/isa/pnpparse.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/isa/isa_common.h b/sys/isa/isa_common.h index 977e222..18975cb 100644 --- a/sys/isa/isa_common.h +++ b/sys/isa/isa_common.h @@ -65,7 +65,7 @@ struct isa_device { #define DEVTOISA(dev) ((struct isa_device *) device_get_ivars(dev)) /* - * These functions are architecture dependant. + * These functions are architecture dependent. */ extern void isa_init(device_t dev); extern struct resource *isa_alloc_resource(device_t bus, device_t child, diff --git a/sys/isa/pnp.c b/sys/isa/pnp.c index 599af84..db37fa6 100644 --- a/sys/isa/pnp.c +++ b/sys/isa/pnp.c @@ -450,7 +450,7 @@ pnp_create_devices(device_t parent, pnp_id *p, int csn, if (dev) { /* * This is an optional device - * indentifier string. Skipt it + * identifier string. Skip it * for now. */ continue; diff --git a/sys/isa/pnpparse.c b/sys/isa/pnpparse.c index 7f051d6..2f0a1fe 100644 --- a/sys/isa/pnpparse.c +++ b/sys/isa/pnpparse.c @@ -499,7 +499,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len, int ldn) /* * Back to the common part; clear it * as its contents has already been copied - * to each dependant. + * to each dependent. */ config = &configs[0]; bzero(config, sizeof(*config)); -- cgit v1.1 From 871e47bb43ad9f672c1f123bd94ba4e6ebc8749d Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 22:01:48 +0000 Subject: Misc. build: minor spelling fixes. No functional change. --- sys/conf/options | 2 +- sys/modules/igb/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/conf/options b/sys/conf/options index 11e778f..4d6ee66 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -822,7 +822,7 @@ ATH_KTR_INTR_DEBUG opt_ath.h # options for the Atheros hal AH_SUPPORT_AR5416 opt_ah.h # XXX For now, this breaks non-AR9130 chipsets, so only use it -# XXX when actually targetting AR9130. +# XXX when actually targeting AR9130. AH_SUPPORT_AR9130 opt_ah.h # This is required for AR933x SoC support diff --git a/sys/modules/igb/Makefile b/sys/modules/igb/Makefile index 57a74fa..4db9608 100644 --- a/sys/modules/igb/Makefile +++ b/sys/modules/igb/Makefile @@ -17,7 +17,7 @@ CFLAGS += -I${.CURDIR}/../../dev/e1000 -DSMP # IGB_LEGACY_TX will override the stack if_transmit path and # instead use the older if_start non-multiqueue capable interface. -# This might be desireable for testing, or to enable the use of +# This might be desirable for testing, or to enable the use of # ALTQ. #CFLAGS += -DIGB_LEGACY_TX -- cgit v1.1 From 4c0eff3af1d173b40acb0588ec1575b3ae9abfae Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 22:05:03 +0000 Subject: kgssapi: insignificant spelling fix. No functional change. --- sys/kgssapi/krb5/krb5_mech.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/kgssapi/krb5/krb5_mech.c b/sys/kgssapi/krb5/krb5_mech.c index 4cfea58..38db0d2 100644 --- a/sys/kgssapi/krb5/krb5_mech.c +++ b/sys/kgssapi/krb5/krb5_mech.c @@ -1339,7 +1339,7 @@ krb5_wrap_old(struct krb5_context *kc, int conf_req_flag, * SND_SEQ: * * Take the four bytes of the sequence number least - * significant first (most signficant first for ARCFOUR) + * significant first (most significant first for ARCFOUR) * followed by four bytes of direction marker (zero for * initiator and 0xff for acceptor). Encrypt that data using * the SGN_CKSUM as IV. -- cgit v1.1 From 826c10b2f366c8c6ecf0ceec0d97d59d642e87fc Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 22:07:18 +0000 Subject: vmm(4): Small spelling fixes. Reviewed by: grehan --- sys/amd64/vmm/amd/vmcb.h | 2 +- sys/amd64/vmm/intel/vtd.c | 2 +- sys/amd64/vmm/io/vlapic.c | 2 +- sys/amd64/vmm/vmm_instruction_emul.c | 2 +- sys/amd64/vmm/vmm_stat.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/amd64/vmm/amd/vmcb.h b/sys/amd64/vmm/amd/vmcb.h index 496f880..9c4f582 100644 --- a/sys/amd64/vmm/amd/vmcb.h +++ b/sys/amd64/vmm/amd/vmcb.h @@ -313,7 +313,7 @@ struct vmcb_state { uint64_t br_to; uint64_t int_from; uint64_t int_to; - uint8_t pad7[0x968]; /* Reserved upto end of VMCB */ + uint8_t pad7[0x968]; /* Reserved up to end of VMCB */ } __attribute__ ((__packed__)); CTASSERT(sizeof(struct vmcb_state) == 0xC00); diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c index be57aff..f3b7a98 100644 --- a/sys/amd64/vmm/intel/vtd.c +++ b/sys/amd64/vmm/intel/vtd.c @@ -463,7 +463,7 @@ vtd_update_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len, panic("vtd_create_mapping: unaligned len 0x%0lx", len); /* - * Compute the size of the mapping that we can accomodate. + * Compute the size of the mapping that we can accommodate. * * This is based on three factors: * - supported super page size diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index 3451e1e..cdf411b 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -841,7 +841,7 @@ vlapic_calcdest(struct vm *vm, cpuset_t *dmask, uint32_t dest, bool phys, } else { /* * In the "Flat Model" the MDA is interpreted as an 8-bit wide - * bitmask. This model is only avilable in the xAPIC mode. + * bitmask. This model is only available in the xAPIC mode. */ mda_flat_ldest = dest & 0xff; diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index ae5330f..852f1d7 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -1232,7 +1232,7 @@ emulate_stack_op(void *vm, int vcpuid, uint64_t mmio_gpa, struct vie *vie, size = vie->opsize_override ? 2 : 8; } else { /* - * In protected or compability mode the 'B' flag in the + * In protected or compatibility mode the 'B' flag in the * stack-segment descriptor determines the size of the * stack pointer. */ diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c index 7e2f64d..62002d6 100644 --- a/sys/amd64/vmm/vmm_stat.c +++ b/sys/amd64/vmm/vmm_stat.c @@ -69,7 +69,7 @@ vmm_stat_register(void *arg) return; if (vst_num_elems + vst->nelems >= MAX_VMM_STAT_ELEMS) { - printf("Cannot accomodate vmm stat type \"%s\"!\n", vst->desc); + printf("Cannot accommodate vmm stat type \"%s\"!\n", vst->desc); return; } -- cgit v1.1 From 7f85f79ccef5a83bf3f01e7d3b70260c5d007e96 Mon Sep 17 00:00:00 2001 From: pfg Date: Tue, 3 May 2016 22:13:04 +0000 Subject: sys/amd64: Small spelling fixes. No functional change. --- sys/amd64/acpica/acpi_wakecode.S | 4 ++-- sys/amd64/amd64/atomic.c | 2 +- sys/amd64/amd64/exception.S | 2 +- sys/amd64/amd64/mpboot.S | 4 ++-- sys/amd64/conf/GENERIC | 2 +- sys/amd64/conf/NOTES | 2 +- sys/amd64/include/vmm.h | 2 +- sys/amd64/linux/linux_machdep.c | 2 +- sys/amd64/linux32/linux32_machdep.c | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) (limited to 'sys') diff --git a/sys/amd64/acpica/acpi_wakecode.S b/sys/amd64/acpica/acpi_wakecode.S index a4c559f..6b36d55 100644 --- a/sys/amd64/acpica/acpi_wakecode.S +++ b/sys/amd64/acpica/acpi_wakecode.S @@ -179,7 +179,7 @@ wakeup_32: * Finally, switch to long bit mode by enabling paging. We have * to be very careful here because all the segmentation disappears * out from underneath us. The spec says we can depend on the - * subsequent pipelined branch to execute, but *only if* everthing + * subsequent pipelined branch to execute, but *only if* everything * is still identity mapped. If any mappings change, the pipeline * will flush. */ @@ -188,7 +188,7 @@ wakeup_32: mov %eax, %cr0 /* - * At this point paging is enabled, and we are in "compatability" mode. + * At this point paging is enabled, and we are in "compatibility" mode. * We do another far jump to reload %cs with the 64 bit selector. * %cr3 points to a 4-level page table page. * We cannot yet jump all the way to the kernel because we can only diff --git a/sys/amd64/amd64/atomic.c b/sys/amd64/amd64/atomic.c index 063201f..9dc3e8d 100644 --- a/sys/amd64/amd64/atomic.c +++ b/sys/amd64/amd64/atomic.c @@ -27,7 +27,7 @@ #include __FBSDID("$FreeBSD$"); -/* This file creates publically callable functions to perform various +/* This file creates publicly callable functions to perform various * simple arithmetic on memory which is atomic in the presence of * interrupts and multiple processors. */ diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index fd8cdac..2c2b99b 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -427,7 +427,7 @@ IDTVEC(fast_syscall) /* * Here for CYA insurance, in case a "syscall" instruction gets - * issued from 32 bit compatability mode. MSR_CSTAR has to point + * issued from 32 bit compatibility mode. MSR_CSTAR has to point * to *something* if EFER_SCE is enabled. */ IDTVEC(fast_syscall32) diff --git a/sys/amd64/amd64/mpboot.S b/sys/amd64/amd64/mpboot.S index c4b6537..5576aff 100644 --- a/sys/amd64/amd64/mpboot.S +++ b/sys/amd64/amd64/mpboot.S @@ -121,7 +121,7 @@ protmode: * Finally, switch to long bit mode by enabling paging. We have * to be very careful here because all the segmentation disappears * out from underneath us. The spec says we can depend on the - * subsequent pipelined branch to execute, but *only if* everthing + * subsequent pipelined branch to execute, but *only if* everything * is still identity mapped. If any mappings change, the pipeline * will flush. */ @@ -130,7 +130,7 @@ protmode: mov %eax, %cr0 /* - * At this point paging is enabled, and we are in "compatability" mode. + * At this point paging is enabled, and we are in "compatibility" mode. * We do another far jump to reload %cs with the 64 bit selector. * %cr3 points to a 4-level page table page. * We cannot yet jump all the way to the kernel because we can only diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 272da43..747acc5 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -349,7 +349,7 @@ device virtio_blk # VirtIO Block device device virtio_scsi # VirtIO SCSI device device virtio_balloon # VirtIO Memory Balloon device -# HyperV drivers and enchancement support +# HyperV drivers and enhancement support device hyperv # HyperV drivers # Xen HVM Guest Optimizations diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index 604a1a3..4107ca6 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -509,7 +509,7 @@ device virtio_balloon # VirtIO Memory Balloon device device virtio_random # VirtIO Entropy device device virtio_console # VirtIO Console device -# Microsoft Hyper-V enchancement support +# Microsoft Hyper-V enhancement support device hyperv # HyperV drivers # Xen HVM Guest Optimizations diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index f2de960..bdfff1f 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -377,7 +377,7 @@ struct vm_copyinfo { * at 'gla' and 'len' bytes long. The 'prot' should be set to PROT_READ for * a copyin or PROT_WRITE for a copyout. * - * retval is_fault Intepretation + * retval is_fault Interpretation * 0 0 Success * 0 1 An exception was injected into the guest * EFAULT N/A Unrecoverable error diff --git a/sys/amd64/linux/linux_machdep.c b/sys/amd64/linux/linux_machdep.c index 376cce7..0459ba7 100644 --- a/sys/amd64/linux/linux_machdep.c +++ b/sys/amd64/linux/linux_machdep.c @@ -212,7 +212,7 @@ linux_mmap2(struct thread *td, struct linux_mmap2_args *args) /* * The Linux MAP_GROWSDOWN option does not limit auto * growth of the region. Linux mmap with this option - * takes as addr the inital BOS, and as len, the initial + * takes as addr the initial BOS, and as len, the initial * region size. It can then grow down from addr without * limit. However, Linux threads has an implicit internal * limit to stack size of STACK_SIZE. Its just not diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index 8f4e350..25f023c 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -576,7 +576,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, /* * The Linux MAP_GROWSDOWN option does not limit auto * growth of the region. Linux mmap with this option - * takes as addr the inital BOS, and as len, the initial + * takes as addr the initial BOS, and as len, the initial * region size. It can then grow down from addr without * limit. However, Linux threads has an implicit internal * limit to stack size of STACK_SIZE. Its just not -- cgit v1.1 From 54f0c229669dbb2fca1b40291ae0430918b2ab41 Mon Sep 17 00:00:00 2001 From: ngie Date: Tue, 3 May 2016 23:56:52 +0000 Subject: Use DEVMETHOD_END ({ NULL, NULL }) instead of hardcoding { 0, 0 } Sponsored by: EMC / Isilon Storage Division --- sys/dev/ioat/ioat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c index faf6cb4..2a68e6e 100644 --- a/sys/dev/ioat/ioat.c +++ b/sys/dev/ioat/ioat.c @@ -135,7 +135,7 @@ static device_method_t ioat_pci_methods[] = { DEVMETHOD(device_probe, ioat_probe), DEVMETHOD(device_attach, ioat_attach), DEVMETHOD(device_detach, ioat_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ioat_pci_driver = { -- cgit v1.1 From 7b45b27d56c05896dd87216d93397da417b7c971 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 01:29:00 +0000 Subject: [bwn] ensure the fallback rate stays in the same PHY mode. Falling back from 6MB OFDM to 5MB CCK (a) may not work well in the 11bg PHYs, (b) won't work at all if you're 11g only, and (c) plainly won't work for the 11a PHY. So, don't do that! Tested: * BCM4312 802.11b/g Wireless, STA mode WLAN (chipid 0x4312 rev 15) PHY (analog 6 type 5 rev 1) RADIO (manuf 0x17f ver 0x2062 rev 2) --- sys/dev/bwn/if_bwn.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index de1bf71..8766ffa 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -5958,10 +5958,16 @@ bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n) return (n); } +/* + * Return a fallback rate for the given rate. + * + * Note: Don't fall back from OFDM to CCK. + */ static uint8_t bwn_get_fbrate(uint8_t bitrate) { switch (bitrate) { + /* CCK */ case BWN_CCK_RATE_1MB: return (BWN_CCK_RATE_1MB); case BWN_CCK_RATE_2MB: @@ -5970,8 +5976,10 @@ bwn_get_fbrate(uint8_t bitrate) return (BWN_CCK_RATE_2MB); case BWN_CCK_RATE_11MB: return (BWN_CCK_RATE_5MB); + + /* OFDM */ case BWN_OFDM_RATE_6MB: - return (BWN_CCK_RATE_5MB); + return (BWN_OFDM_RATE_6MB); case BWN_OFDM_RATE_9MB: return (BWN_OFDM_RATE_6MB); case BWN_OFDM_RATE_12MB: -- cgit v1.1 From d9ae2d9d8ff238da8b860ea88d8c8dce9ce0df89 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 01:36:19 +0000 Subject: [bwn] accurately(ish) account transmit/recieve failures for rate control. I noticed that it'd associate fine, but it'd quickly stop exchanging traffic. Receive was okay, but transmit just failed. Then I went "wlandebug +rate". I discovered it started at 36M OFDM, and then quickly rose to 54M, which then showed 0% transmit success. Then, I dug into how the completion path works. We are reading 'ack=0' in the TX status side, so .. then I discovered we were only processing the TX completion status /if/ ack=1. So, we'd only ever count successes; we'd never count failures, and thus the rate control code thought everything was a-ok. We also have to set retrycnt to something non-zero so it indeed does bring the rate down upon failure. So: * Delete the rate control completion code from the tx completion routine, it's just duplicate and never worked. Putting it behind 'if (status->ack) was pointless. * Move it to the PIO and DMA completion routines which actually do free the node reference and mbuf. We know at that point what the status is, so do it there. * Fake a retrycnt of 1 for now, so we at least count failures. Also: * Start adding comments about weird stuff I find with rate selection. In this instance, we shouldn't be selecting a fallback rate that doesn't match the currently configured mode (11a, 11b, 11g, etc.) This isn't perfect - AMRR does try 54mbit and takes a few packets before it figures out it's a bad idea - but it's better than nothing. This makes the bwn(4) driver actually useful for the first time since I've tried using it - and that dates back to 2011. I've resisted successfully until now. Tested: * Broadcom BCM4312 802.11b/g Wireless, STA mode WLAN (chipid 0x4312 rev 15) PHY (analog 6 type 5 rev 1) RADIO (manuf 0x17f ver 0x2062 rev 2) TODO: * See if the fallback rate actually /is/ working * Question my own sanity over touching this driver in the first place. --- sys/dev/bwn/if_bwn.c | 77 +++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 46 deletions(-) (limited to 'sys') diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 8766ffa..f7dc50c 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -5132,16 +5132,8 @@ bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot) static void bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) { - struct bwn_dma_ring *dr; - struct bwn_dmadesc_generic *desc; - struct bwn_dmadesc_meta *meta; - struct bwn_pio_txqueue *tq; - struct bwn_pio_txpkt *tp = NULL; struct bwn_softc *sc = mac->mac_sc; struct bwn_stats *stats = &mac->mac_stats; - struct ieee80211_node *ni; - struct ieee80211vap *vap; - int retrycnt = 0, slot; BWN_ASSERT_LOCKED(mac->mac_sc); @@ -5157,46 +5149,8 @@ bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) } if (mac->mac_flags & BWN_MAC_FLAG_DMA) { - if (status->ack) { - dr = bwn_dma_parse_cookie(mac, status, - status->cookie, &slot); - if (dr == NULL) { - device_printf(sc->sc_dev, - "failed to parse cookie\n"); - return; - } - while (1) { - dr->getdesc(dr, slot, &desc, &meta); - if (meta->mt_islast) { - ni = meta->mt_ni; - vap = ni->ni_vap; - ieee80211_ratectl_tx_complete(vap, ni, - status->ack ? - IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, 0); - break; - } - slot = bwn_dma_nextslot(dr, slot); - } - } bwn_dma_handle_txeof(mac, status); } else { - if (status->ack) { - tq = bwn_pio_parse_cookie(mac, status->cookie, &tp); - if (tq == NULL) { - device_printf(sc->sc_dev, - "failed to parse cookie\n"); - return; - } - ni = tp->tp_ni; - vap = ni->ni_vap; - ieee80211_ratectl_tx_complete(vap, ni, - status->ack ? - IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, 0); - } bwn_pio_handle_txeof(mac, status); } @@ -5538,6 +5492,7 @@ bwn_dma_handle_txeof(struct bwn_mac *mac, struct bwn_dmadesc_meta *meta; struct bwn_softc *sc = mac->mac_sc; int slot; + int retrycnt = 0; BWN_ASSERT_LOCKED(sc); @@ -5562,6 +5517,16 @@ bwn_dma_handle_txeof(struct bwn_mac *mac, KASSERT(meta->mt_m != NULL, ("%s:%d: fail", __func__, __LINE__)); + /* XXX */ + if (status->ack == 0) + retrycnt = 1; + else + retrycnt = 0; + ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni, + status->ack ? + IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, 0); ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0); meta->mt_ni = NULL; meta->mt_m = NULL; @@ -5589,6 +5554,7 @@ bwn_pio_handle_txeof(struct bwn_mac *mac, struct bwn_pio_txqueue *tq; struct bwn_pio_txpkt *tp = NULL; struct bwn_softc *sc = mac->mac_sc; + int retrycnt = 0; BWN_ASSERT_LOCKED(sc); @@ -5604,6 +5570,18 @@ bwn_pio_handle_txeof(struct bwn_mac *mac, * Do any tx complete callback. Note this must * be done before releasing the node reference. */ + + /* XXX */ + if (status->ack == 0) + retrycnt = 1; + else + retrycnt = 0; + ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni, + status->ack ? + IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, 0); + if (tp->tp_m->m_flags & M_TXCB) ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0); ieee80211_free_node(tp->tp_ni); @@ -5751,6 +5729,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = rate_fb = tp->ucastrate; else { + /* XXX TODO: don't fall back to CCK rates for OFDM */ rix = ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; @@ -5763,6 +5742,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, sc->sc_tx_rate = rate; + /* Note: this maps the select ieee80211 rate to hardware rate */ rate = bwn_ieeerate2hwrate(sc, rate); rate_fb = bwn_ieeerate2hwrate(sc, rate_fb); @@ -5771,6 +5751,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc)); bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN); + /* XXX rate/rate_fb is the hardware rate */ if ((rate_fb == rate) || (*(u_int16_t *)wh->i_dur & htole16(0x8000)) || (*(u_int16_t *)wh->i_dur == htole16(0))) @@ -5792,6 +5773,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, txhdr->chan = phy->chan; phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM : BWN_TX_PHY_ENC_CCK; + /* XXX preamble? obey net80211 */ if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB || rate == BWN_CCK_RATE_11MB)) phyctl |= BWN_TX_PHY_SHORTPRMBL; @@ -5828,9 +5810,11 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, if (ic->ic_flags & IEEE80211_F_USEPROT) { /* XXX RTS rate is always 1MB??? */ + /* XXX TODO: don't fall back to CCK rates for OFDM */ rts_rate = BWN_CCK_RATE_1MB; rts_rate_fb = bwn_get_fbrate(rts_rate); + /* XXX 'rate' here is hardware rate now, not the net80211 rate */ protdur = ieee80211_compute_duration(ic->ic_rt, m->m_pkthdr.len, rate, isshort) + + ieee80211_ack_duration(ic->ic_rt, rate, isshort); @@ -5851,6 +5835,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ? (txhdr->body.old.rts_frame) : (txhdr->body.new.rts_frame)); + /* XXX rate/rate_fb is the hardware rate */ protdur += ieee80211_ack_duration(ic->ic_rt, rate, isshort); mprot = ieee80211_alloc_rts(ic, wh->i_addr1, -- cgit v1.1 From 1169f4f78010d9725e24de54091e32f7ac0d05f1 Mon Sep 17 00:00:00 2001 From: araujo Date: Wed, 4 May 2016 01:43:07 +0000 Subject: Use imin() macro from sys/libkern.h. MFC after: 2 weeks. --- sys/dev/hptiop/hptiop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c index b9c7211..ea05f4b 100644 --- a/sys/dev/hptiop/hptiop.c +++ b/sys/dev/hptiop/hptiop.c @@ -1241,7 +1241,7 @@ static int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, req->header.result = IOP_RESULT_PENDING; req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; size = req->header.size >> 8; - size = size > 3 ? 3 : size; + size = imin(3, size); req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size; hptiop_mv_inbound_write(req_phy, hba); @@ -2561,7 +2561,7 @@ static void hptiop_post_req_mv(struct hpt_iop_hba *hba, size = req->header.size >> 8; hptiop_mv_inbound_write(req_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT - | (size > 3 ? 3 : size), hba); + | imin(3, size), hba); } static void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba, -- cgit v1.1 From 732c37e6cb7a5394016baf0b4f40e0d646f23225 Mon Sep 17 00:00:00 2001 From: kan Date: Wed, 4 May 2016 01:56:37 +0000 Subject: Fix nvram2env after bus_space_fdt removal. The generic bus space does the mapping now, no need to pre-translate phys addresses to KSEG1 anymore. Submitted by: Hiroki Mori --- sys/dev/nvram2env/nvram2env.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/nvram2env/nvram2env.c b/sys/dev/nvram2env/nvram2env.c index 608fac6..4c0ce1e 100644 --- a/sys/dev/nvram2env/nvram2env.c +++ b/sys/dev/nvram2env/nvram2env.c @@ -127,7 +127,7 @@ nvram2env_probe(device_t dev) ivar == 0) continue; - sc->addr = MIPS_PHYS_TO_KSEG1(ivar); + sc->addr = ivar; if (bootverbose) device_printf(dev, "base=0x%08x sig=0x%08x " -- cgit v1.1 From 31c3749d026d43c3b2556b49b23622053bb7e0ba Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 02:11:45 +0000 Subject: [bwn] fix rate control feedback. * Add a debug print for the xmit completion status fields. Yes, I like staring at a stream of DWORDS. * Set the retrycnt to the number of full frame retries for now; I'll figure out how to factor rts/cts failures into it when I figure out what the difference is. It's -1 because it's not "retries", it's "tries". It now passes the youtube test. Tested: * BCM4312, STA mode --- sys/dev/bwn/if_bwn.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'sys') diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index f7dc50c..60d408eb 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -4942,6 +4942,12 @@ bwn_intr_txeof(struct bwn_mac *mac) break; stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1); + DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT, + "%s: stat0=0x%08x, stat1=0x%08x\n", + __func__, + stat0, + stat1); + stat.cookie = (stat0 >> 16); stat.seq = (stat1 & 0x0000ffff); stat.phy_stat = ((stat1 & 0x00ff0000) >> 16); @@ -5517,11 +5523,8 @@ bwn_dma_handle_txeof(struct bwn_mac *mac, KASSERT(meta->mt_m != NULL, ("%s:%d: fail", __func__, __LINE__)); - /* XXX */ - if (status->ack == 0) - retrycnt = 1; - else - retrycnt = 0; + /* Just count full frame retries for now */ + retrycnt = status->framecnt - 1; ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni, status->ack ? IEEE80211_RATECTL_TX_SUCCESS : @@ -5571,11 +5574,8 @@ bwn_pio_handle_txeof(struct bwn_mac *mac, * be done before releasing the node reference. */ - /* XXX */ - if (status->ack == 0) - retrycnt = 1; - else - retrycnt = 0; + /* Just count full frame retries for now */ + retrycnt = status->framecnt - 1; ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni, status->ack ? IEEE80211_RATECTL_TX_SUCCESS : -- cgit v1.1 From 24e41b4fb56fa7e5ce9d2e3b68c52ea561b3ed77 Mon Sep 17 00:00:00 2001 From: sephe Date: Wed, 4 May 2016 03:07:52 +0000 Subject: kern: Factor out function to convert hash flags to malloc(9) flags Suggested by: jhb Reviewed by: jhb, kib Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6184 --- sys/kern/subr_hash.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'sys') diff --git a/sys/kern/subr_hash.c b/sys/kern/subr_hash.c index 4d9249f..2aae043 100644 --- a/sys/kern/subr_hash.c +++ b/sys/kern/subr_hash.c @@ -41,6 +41,13 @@ __FBSDID("$FreeBSD$"); #include #include +static __inline int +hash_mflags(int flags) +{ + + return ((flags & HASH_NOWAIT) ? M_NOWAIT : M_WAITOK); +} + /* * General routine to allocate a hash table with control of memory flags. */ @@ -61,13 +68,8 @@ hashinit_flags(int elements, struct malloc_type *type, u_long *hashmask, continue; hashsize >>= 1; - if (flags & HASH_NOWAIT) - hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), - type, M_NOWAIT); - else - hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), - type, M_WAITOK); - + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, + hash_mflags(flags)); if (hashtbl != NULL) { for (i = 0; i < hashsize; i++) LIST_INIT(&hashtbl[i]); @@ -112,7 +114,7 @@ phashinit_flags(int elements, struct malloc_type *type, u_long *nentries, int fl { long hashsize; LIST_HEAD(generic, generic) *hashtbl; - int i, m_flags; + int i; KASSERT(elements > 0, ("%s: bad elements", __func__)); /* Exactly one of HASH_WAITOK and HASH_NOWAIT must be set. */ @@ -127,8 +129,8 @@ phashinit_flags(int elements, struct malloc_type *type, u_long *nentries, int fl } hashsize = primes[i - 1]; - m_flags = (flags & HASH_NOWAIT) ? M_NOWAIT : M_WAITOK; - hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, m_flags); + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, + hash_mflags(flags)); if (hashtbl == NULL) return (NULL); -- cgit v1.1 From 06432ef1273aca67315bdedca252ad83535c313f Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 4 May 2016 06:22:41 +0000 Subject: Fix build without "options PCI_IOV". --- sys/dev/pci/pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index ae01f24..d668bd7 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -5644,9 +5644,10 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo) if (dinfo->cfg.msix.msix_location != 0) pci_resume_msix(dev); +#ifdef PCI_IOV if (dinfo->cfg.iov != NULL) pci_iov_cfg_restore(dev, dinfo); - +#endif } static void @@ -5759,8 +5760,10 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate) if (dinfo->cfg.pcix.pcix_location != 0) pci_cfg_save_pcix(dev, dinfo); +#ifdef PCI_IOV if (dinfo->cfg.iov != NULL) pci_iov_cfg_save(dev, dinfo); +#endif /* * don't set the state for display devices, base peripherals and -- cgit v1.1 From 890363435903cb2a240f8b71f842bb26632bc4ed Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 06:23:49 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/dev/lmc/if_lmc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/lmc/if_lmc.h b/sys/dev/lmc/if_lmc.h index 0121375..357fd88 100644 --- a/sys/dev/lmc/if_lmc.h +++ b/sys/dev/lmc/if_lmc.h @@ -1092,7 +1092,7 @@ struct softc #endif struct callout callout; /* watchdog needs this */ - struct device *dev; /* base device pointer */ + device_t dev; /* base device pointer */ bus_space_tag_t csr_tag; /* bus_space needs this */ bus_space_handle_t csr_handle;/* bus_space_needs this */ void *irq_cookie; /* bus_teardown_intr needs this */ -- cgit v1.1 From f1b9557d448ef6f501595f28390595a2bed4e464 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 06:24:10 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/dev/buslogic/btreg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/buslogic/btreg.h b/sys/dev/buslogic/btreg.h index 1475fd5..a22c5aa 100644 --- a/sys/dev/buslogic/btreg.h +++ b/sys/dev/buslogic/btreg.h @@ -595,7 +595,7 @@ struct sg_map_node { }; struct bt_softc { - struct device *dev; + device_t dev; struct resource *port; struct resource *irq; struct resource *drq; -- cgit v1.1 From 011e5d53f3663b8037fb1b1719d32d0eb93e2d37 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 06:24:51 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/dev/esp/esp_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/esp/esp_pci.c b/sys/dev/esp/esp_pci.c index bd85d8e..fc3af2b 100644 --- a/sys/dev/esp/esp_pci.c +++ b/sys/dev/esp/esp_pci.c @@ -97,7 +97,7 @@ __FBSDID("$FreeBSD$"); struct esp_pci_softc { struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */ - struct device *sc_dev; + device_t sc_dev; struct resource *sc_res[2]; #define ESP_PCI_RES_INTR 0 -- cgit v1.1 From 24c5174a49587781ed0bbe57cb195c16ea398053 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 06:25:12 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/dev/fdc/fdcvar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/fdc/fdcvar.h b/sys/dev/fdc/fdcvar.h index be4b638..edaef79 100644 --- a/sys/dev/fdc/fdcvar.h +++ b/sys/dev/fdc/fdcvar.h @@ -66,7 +66,7 @@ struct fdc_data { bus_space_handle_t ioh[FDC_MAXREG]; int ioff[FDC_MAXREG]; void *fdc_intr; - struct device *fdc_dev; + device_t fdc_dev; struct mtx fdc_mtx; struct proc *fdc_thread; }; -- cgit v1.1 From 5ecb149f523557a3f795c118cb59edbaef530844 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 06:26:27 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/dev/acpi_support/atk0110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/acpi_support/atk0110.c b/sys/dev/acpi_support/atk0110.c index 7d30d5f..3a49988 100644 --- a/sys/dev/acpi_support/atk0110.c +++ b/sys/dev/acpi_support/atk0110.c @@ -66,7 +66,7 @@ struct aibs_sensor { }; struct aibs_softc { - struct device *sc_dev; + device_t sc_dev; ACPI_HANDLE sc_ah; struct aibs_sensor *sc_asens_volt; -- cgit v1.1 From 9297126a777e3a74f004d85874fea4fd4ae5d38c Mon Sep 17 00:00:00 2001 From: hselasky Date: Wed, 4 May 2016 08:57:40 +0000 Subject: Extend the UQ_NO_STRINGS quirk to also cover the USB language string descriptor. This fixes enumeration of some older Samsung Galaxy S3 phones. MFC after: 1 week --- sys/dev/usb/usb_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index df9fea6..30336a1 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1774,7 +1774,9 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, scratch_ptr = udev->scratch.data; - if (udev->ddesc.iManufacturer || + if (udev->flags.no_strings) { + err = USB_ERR_INVAL; + } else if (udev->ddesc.iManufacturer || udev->ddesc.iProduct || udev->ddesc.iSerialNumber) { /* read out the language ID string */ -- cgit v1.1 From 2419ffe0931643f0534ce66621db40f331bcede4 Mon Sep 17 00:00:00 2001 From: avos Date: Wed, 4 May 2016 12:51:27 +0000 Subject: iwn: fix device reset after watchdog timeout. Simple device reset (stop/start) is not enough here; post-init state changes must be applied too. --- sys/dev/iwn/if_iwn.c | 18 +----------------- sys/dev/iwn/if_iwnvar.h | 1 - 2 files changed, 1 insertion(+), 18 deletions(-) (limited to 'sys') diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index 6a740d3..5d7a1d1 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -344,7 +344,6 @@ static void iwn_scan_end(struct ieee80211com *); static void iwn_set_channel(struct ieee80211com *); static void iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long); static void iwn_scan_mindwell(struct ieee80211_scan_state *); -static void iwn_hw_reset(void *, int); #ifdef IWN_DEBUG static char *iwn_get_csr_string(int); static void iwn_debug_register(struct iwn_softc *); @@ -677,7 +676,6 @@ iwn_attach(device_t dev) callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0); callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0); - TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc); TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc); TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc); TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc); @@ -1400,7 +1398,6 @@ iwn_detach(device_t dev) iwn_xmit_queue_drain(sc); IWN_UNLOCK(sc); - ieee80211_draintask(&sc->sc_ic, &sc->sc_reinit_task); ieee80211_draintask(&sc->sc_ic, &sc->sc_radioon_task); ieee80211_draintask(&sc->sc_ic, &sc->sc_radiooff_task); iwn_stop(sc); @@ -4972,7 +4969,7 @@ iwn_watchdog(void *arg) if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { ic_printf(ic, "device timeout\n"); - ieee80211_runtask(ic, &sc->sc_reinit_task); + ieee80211_restart_all(ic); return; } } @@ -8907,19 +8904,6 @@ iwn_scan_mindwell(struct ieee80211_scan_state *ss) { /* NB: don't try to abort scan; wait for firmware to finish */ } - -static void -iwn_hw_reset(void *arg0, int pending) -{ - struct iwn_softc *sc = arg0; - struct ieee80211com *ic = &sc->sc_ic; - - DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); - - iwn_stop(sc); - iwn_init(sc); - ieee80211_notify_radio(ic, 1); -} #ifdef IWN_DEBUG #define IWN_DESC(x) case x: return #x diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h index a271304..ad9b948 100644 --- a/sys/dev/iwn/if_iwnvar.h +++ b/sys/dev/iwn/if_iwnvar.h @@ -304,7 +304,6 @@ struct iwn_softc { int sc_cap_off; /* PCIe Capabilities. */ /* Tasks used by the driver */ - struct task sc_reinit_task; struct task sc_radioon_task; struct task sc_radiooff_task; struct task sc_panic_task; -- cgit v1.1 From 9610d15b516e3ce2c945ea59ca9bb13e9f50bad0 Mon Sep 17 00:00:00 2001 From: royger Date: Wed, 4 May 2016 13:48:59 +0000 Subject: rtc: fix inverted resolution check The current code in clock_register checks if the newly added clock has a resolution value higher than the current one in order to make it the default, which is wrong. Clocks with a lower resolution value should be better than ones with a higher resolution value, in fact with the current code FreeBSD is always selecting the worse clock. Reviewed by: kib jhb jkim Sponsored by: Citrix Systems R&D MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D6185 --- sys/kern/subr_rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c index ed2befc..5d4167d 100644 --- a/sys/kern/subr_rtc.c +++ b/sys/kern/subr_rtc.c @@ -84,7 +84,7 @@ clock_register(device_t dev, long res) /* res has units of microseconds */ { if (clock_dev != NULL) { - if (clock_res > res) { + if (clock_res <= res) { if (bootverbose) device_printf(dev, "not installed as " "time-of-day clock: clock %s has higher " -- cgit v1.1 From 0352224997041e08916791cf1ee4defef3e9cfb7 Mon Sep 17 00:00:00 2001 From: royger Date: Wed, 4 May 2016 13:49:59 +0000 Subject: xen/pvclock: set the correct resolution for the Xen PV clock The Xen PV clock has a resolution of 1ns, so set the resolution to the highest one that FreeBSD supports, which is 1us. MFC after: 2 weeks Sponsored by: Citrix Systems R&D --- sys/dev/xen/timer/timer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/xen/timer/timer.c b/sys/dev/xen/timer/timer.c index 083898c..996399b 100644 --- a/sys/dev/xen/timer/timer.c +++ b/sys/dev/xen/timer/timer.c @@ -77,7 +77,12 @@ static devclass_t xentimer_devclass; /* Xen timers may fire up to 100us off */ #define XENTIMER_MIN_PERIOD_IN_NSEC 100*NSEC_IN_USEC -#define XENCLOCK_RESOLUTION 1000001 /* ATRTC resolution + 1 */ + +/* + * The real resolution of the PV clock is 1ns, but the highest + * resolution that FreeBSD supports is 1us, so just use that. + */ +#define XENCLOCK_RESOLUTION 1 #define XENTIMER_QUALITY 950 -- cgit v1.1 From eac6031c8a32dc2ae70ab8d42ec35194ab53e2ad Mon Sep 17 00:00:00 2001 From: pfg Date: Wed, 4 May 2016 15:48:59 +0000 Subject: sys/arm: Minor spelling fixes. Only affects comments: no functional change. --- sys/arm/amlogic/aml8726/aml8726_mmc.c | 2 +- sys/arm/amlogic/aml8726/aml8726_mmc.h | 2 +- sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c | 2 +- sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h | 2 +- sys/arm/arm/cpufunc_asm_arm11.S | 2 +- sys/arm/arm/exception.S | 2 +- sys/arm/arm/gic.c | 2 +- sys/arm/arm/machdep.c | 2 +- sys/arm/arm/mpcore_timer.c | 4 ++-- sys/arm/arm/pmap-v4.c | 6 +++--- sys/arm/arm/pmap-v6.c | 4 ++-- sys/arm/arm/swtch-v4.S | 2 +- sys/arm/at91/at91_cfata.c | 2 +- sys/arm/at91/at91_machdep.c | 2 +- sys/arm/at91/at91_mci.c | 4 ++-- sys/arm/at91/at91_reset.S | 2 +- sys/arm/at91/at91reg.h | 4 ++-- sys/arm/at91/at91sam9260.c | 2 +- sys/arm/at91/if_ate.c | 12 ++++++------ sys/arm/at91/if_atereg.h | 4 ++-- sys/arm/broadcom/bcm2835/bcm2835_audio.c | 2 +- sys/arm/broadcom/bcm2835/bcm2835_dma.c | 4 ++-- sys/arm/cavium/cns11xx/if_ece.c | 2 +- sys/arm/freescale/imx/imx6_ipu.c | 2 +- sys/arm/freescale/imx/imx6_ssi.c | 4 ++-- sys/arm/freescale/vybrid/vf_uart.c | 2 +- sys/arm/mv/mpic.c | 2 +- sys/arm/mv/mv_common.c | 2 +- sys/arm/samsung/exynos/exynos5_usb_phy.c | 2 +- sys/arm/ti/omap4/omap4_prcm_clks.c | 2 +- sys/arm/ti/ti_i2c.c | 4 ++-- sys/arm/ti/ti_pinmux.c | 2 +- sys/arm/ti/ti_prcm.c | 2 +- sys/arm/ti/ti_scm.c | 2 +- sys/arm/ti/ti_sdma.c | 24 ++++++++++++------------ sys/arm/xilinx/zy7_slcr.c | 2 +- sys/arm/xscale/i8134x/crb_machdep.c | 2 +- sys/arm/xscale/i8134x/i81342reg.h | 2 +- sys/arm/xscale/ixp425/avila_machdep.c | 2 +- sys/arm/xscale/ixp425/cambria_gpio.c | 2 +- sys/arm/xscale/ixp425/ixp425_npe.c | 6 +++--- sys/arm/xscale/ixp425/ixp425_npereg.h | 2 +- sys/arm/xscale/ixp425/ixp425_qmgr.c | 2 +- sys/arm/xscale/pxa/pxa_machdep.c | 2 +- 44 files changed, 72 insertions(+), 72 deletions(-) (limited to 'sys') diff --git a/sys/arm/amlogic/aml8726/aml8726_mmc.c b/sys/arm/amlogic/aml8726/aml8726_mmc.c index 0e24975..5205507 100644 --- a/sys/arm/amlogic/aml8726/aml8726_mmc.c +++ b/sys/arm/amlogic/aml8726/aml8726_mmc.c @@ -240,7 +240,7 @@ aml8726_mmc_start_command(struct aml8726_mmc_softc *sc, struct mmc_command *cmd) * Start and transmission bits are per section 4.7.2 of the: * * SD Specifications Part 1 - * Physicaly Layer Simplified Specification + * Physical Layer Simplified Specification * Version 4.10 */ cmdr = AML_MMC_CMD_START_BIT | AML_MMC_CMD_TRANS_BIT_HOST | cmd->opcode; diff --git a/sys/arm/amlogic/aml8726/aml8726_mmc.h b/sys/arm/amlogic/aml8726/aml8726_mmc.h index 64e3bae..a2dde21 100644 --- a/sys/arm/amlogic/aml8726/aml8726_mmc.h +++ b/sys/arm/amlogic/aml8726/aml8726_mmc.h @@ -39,7 +39,7 @@ * Read and write are per section 4.6.2 of the: * * SD Specifications Part 1 - * Physicaly Layer Simplified Specification + * Physical Layer Simplified Specification * Version 4.10 */ #define AML_MMC_CMD_TIMEOUT 50 diff --git a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c index 75825fb..a5be5e4 100644 --- a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c +++ b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c @@ -484,7 +484,7 @@ aml8726_sdxc_finish_command(struct aml8726_sdxc_softc *sc, int mmc_error) if (stop_cmd != NULL) { /* - * If the original command executed successfuly, then + * If the original command executed successfully, then * the hardware will also have automatically executed * a stop command so don't bother with the one supplied * with the original request. diff --git a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h index 013a86e..1d0dc14 100644 --- a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h +++ b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.h @@ -38,7 +38,7 @@ * Read and write are per section 4.6.2 of the: * * SD Specifications Part 1 - * Physicaly Layer Simplified Specification + * Physical Layer Simplified Specification * Version 4.10 */ #define AML_SDXC_CMD_TIMEOUT 50 diff --git a/sys/arm/arm/cpufunc_asm_arm11.S b/sys/arm/arm/cpufunc_asm_arm11.S index f83f819..d6538c6 100644 --- a/sys/arm/arm/cpufunc_asm_arm11.S +++ b/sys/arm/arm/cpufunc_asm_arm11.S @@ -30,7 +30,7 @@ * * ARM11 assembly functions for CPU / MMU / TLB specific operations * - * XXX We make no attempt at present to take advantage of the v6 memroy + * XXX We make no attempt at present to take advantage of the v6 memory * architecture or physically tagged cache. */ diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S index 9f186a5..9466cf6 100644 --- a/sys/arm/arm/exception.S +++ b/sys/arm/arm/exception.S @@ -175,7 +175,7 @@ _C_LABEL(dtrace_invop_jump_addr): ldr r4, [r5, #4]; /* reset it to point at the */ \ cmp r4, #0xffffffff; /* end of memory if necessary; */ \ movne r1, #0xffffffff; /* leave value in r4 for later */ \ - strne r1, [r5, #4]; /* comparision against PC. */ \ + strne r1, [r5, #4]; /* comparison against PC. */ \ ldr r3, [r5]; /* Retrieve global RAS_START */ \ cmp r3, #0; /* and reset it if non-zero. */ \ movne r1, #0; /* If non-zero RAS_START and */ \ diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index 08693d9..a898532 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -1231,7 +1231,7 @@ arm_gic_next_irq(struct arm_gic_softc *sc, int last_irq) active_irq = gic_c_read_4(sc, GICC_IAR); /* - * Immediatly EOIR the SGIs, because doing so requires the other + * Immediately EOIR the SGIs, because doing so requires the other * bits (ie CPU number), not just the IRQ number, and we do not * have this information later. */ diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c index 453c197..49d5986 100644 --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -36,7 +36,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Machine dependant functions for kernel setup + * Machine dependent functions for kernel setup * * Created : 17/09/94 * Updated : 18/04/01 updated for new wscons diff --git a/sys/arm/arm/mpcore_timer.c b/sys/arm/arm/mpcore_timer.c index fb30d38..03f8e4b 100644 --- a/sys/arm/arm/mpcore_timer.c +++ b/sys/arm/arm/mpcore_timer.c @@ -367,7 +367,7 @@ attach_et(struct arm_tmr_softc *sc) * globally and registers both the timecount and eventtimer objects. * * RETURNS - * Zero on sucess or ENXIO if an error occuried. + * Zero on success or ENXIO if an error occuried. */ static int arm_tmr_attach(device_t dev) @@ -457,7 +457,7 @@ EARLY_DRIVER_MODULE(mp_tmr, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0, /* * Handle a change in clock frequency. The mpcore timer runs at half the CPU * frequency. When the CPU frequency changes due to power-saving or thermal - * managment, the platform-specific code that causes the frequency change calls + * management, the platform-specific code that causes the frequency change calls * this routine to inform the clock driver, and we in turn inform the event * timer system, which actually updates the value in et->frequency for us and * reschedules the current event(s) in a way that's atomic with respect to diff --git a/sys/arm/arm/pmap-v4.c b/sys/arm/arm/pmap-v4.c index 733ccf2..3bdc9e4 100644 --- a/sys/arm/arm/pmap-v4.c +++ b/sys/arm/arm/pmap-v4.c @@ -126,7 +126,7 @@ * * pmap.c * - * Machine dependant vm stuff + * Machine dependent vm stuff * * Created : 20/09/94 */ @@ -1386,9 +1386,9 @@ pmap_clearbit(struct vm_page *pg, u_int maskbits) * * Don't turn caching on again if this is a * modified emulation. This would be - * inconsitent with the settings created by + * inconsistent with the settings created by * pmap_fix_cache(). Otherwise, it's safe - * to re-enable cacheing. + * to re-enable caching. * * There's no need to call pmap_fix_cache() * here: all pages are losing their write diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c index f5a6fa8..703f39d 100644 --- a/sys/arm/arm/pmap-v6.c +++ b/sys/arm/arm/pmap-v6.c @@ -705,7 +705,7 @@ pmap_preboot_get_pages(u_int num) } /* - * The fundamental initalization of PMAP stuff. + * The fundamental initialization of PMAP stuff. * * Some things already happened in locore.S and some things could happen * before pmap_bootstrap_prepare() is called, so let's recall what is done: @@ -1210,7 +1210,7 @@ pmap_bootstrap(vm_offset_t firstaddr) /* * Note that in very short time in initarm(), we are going to - * initialize phys_avail[] array and no futher page allocation + * initialize phys_avail[] array and no further page allocation * can happen after that until vm subsystem will be initialized. */ kernel_vm_end_new = kernel_vm_end; diff --git a/sys/arm/arm/swtch-v4.S b/sys/arm/arm/swtch-v4.S index 6fdbeed..21924dc 100644 --- a/sys/arm/arm/swtch-v4.S +++ b/sys/arm/arm/swtch-v4.S @@ -296,7 +296,7 @@ ENTRY(cpu_switch) beq .Lcs_context_switched /* yes! */ /* - * Definately need to flush the cache. + * Definitely need to flush the cache. */ ldr r1, .Lcpufuncs diff --git a/sys/arm/at91/at91_cfata.c b/sys/arm/at91/at91_cfata.c index 37ce434..d4848ff 100644 --- a/sys/arm/at91/at91_cfata.c +++ b/sys/arm/at91/at91_cfata.c @@ -26,7 +26,7 @@ * common memory mode. Interrupts are driven by polling. The driver * implements an ATA bridge and attached ATA channel driver on top * of it. - * NOTE WELL: this driver uses polling mode. To achive an acceptable + * NOTE WELL: this driver uses polling mode. To achieve an acceptable * operating speed you will probably want to use HZ=2000 in kernel * config. */ diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index b6ff9ca..6be7f72 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -36,7 +36,7 @@ * * machdep.c * - * Machine dependant functions for kernel setup + * Machine dependent functions for kernel setup * * This file needs a lot of work. * diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c index cf884b9..bb5b7d5 100644 --- a/sys/arm/at91/at91_mci.c +++ b/sys/arm/at91/at91_mci.c @@ -92,7 +92,7 @@ __FBSDID("$FreeBSD$"); * speed is 25MHz and the next highest speed is 15MHz or less. This appears * to work on virtually all SD cards, since it is what this driver has been * doing prior to the introduction of this option, where the overclocking vs - * underclocking decision was automaticly "overclock". Modern SD cards can + * underclocking decision was automatically "overclock". Modern SD cards can * run at 45mhz/1-bit in standard mode (high speed mode enable commands not * sent) without problems. * @@ -212,7 +212,7 @@ at91_bswap_buf(struct at91_mci_softc *sc, void * dptr, void * sptr, uint32_t mem /* * If the hardware doesn't need byte-swapping, let bcopy() do the * work. Use bounce buffer even if we don't need byteswap, since - * buffer may straddle a page boundry, and we don't handle + * buffer may straddle a page boundary, and we don't handle * multi-segment transfers in hardware. Seen from 'bsdlabel -w' which * uses raw geom access to the volume. Greg Ansley (gja (at) * ansley.com) diff --git a/sys/arm/at91/at91_reset.S b/sys/arm/at91/at91_reset.S index 28703cc..36d72e4 100644 --- a/sys/arm/at91/at91_reset.S +++ b/sys/arm/at91/at91_reset.S @@ -14,7 +14,7 @@ __FBSDID("$FreeBSD$"); /* * From AT91SAM9G20 Datasheet errata 44:3.5: * - * When User Reset occurs durring SDRAM read acces, eh SDRAM clock is turned + * When User Reset occurs during SDRAM read access, the SDRAM clock is turned * off while data are ready to be read on the data bus. The SDRAM maintains * the data until the clock restarts. * diff --git a/sys/arm/at91/at91reg.h b/sys/arm/at91/at91reg.h index e0aaa81..35e14f5 100644 --- a/sys/arm/at91/at91reg.h +++ b/sys/arm/at91/at91reg.h @@ -39,9 +39,9 @@ #define AT91_PA_BASE 0xf0000000 /* A few things that we count on being the same - * throught the whole family of SOCs */ + * throughout the whole family of SOCs */ -/* SYSC System Controler */ +/* SYSC System Controller */ /* System Registers */ #define AT91_SYS_BASE 0xffff000 #define AT91_SYS_SIZE 0x1000 diff --git a/sys/arm/at91/at91sam9260.c b/sys/arm/at91/at91sam9260.c index 5b0f537..4514d87 100644 --- a/sys/arm/at91/at91sam9260.c +++ b/sys/arm/at91/at91sam9260.c @@ -188,7 +188,7 @@ at91_clock_init(void) * PMC alogrithm choose the divisor that causes the input clock * to be near the optimal 2 MHz per datasheet. We know * we are going to be using this for the USB clock at 96 MHz. - * Causes no extra frequency deviation for all recomended crystal + * Causes no extra frequency deviation for all recommended crystal * values. See Note 1, table 40-16 SAM9260 doc. */ clk = at91_pmc_clock_ref("pllb"); diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c index 082b24f..fdca46b 100644 --- a/sys/arm/at91/if_ate.c +++ b/sys/arm/at91/if_ate.c @@ -651,7 +651,7 @@ ate_activate(device_t dev) ate_getaddr, &sc->tx_desc_phys, 0) != 0) goto errout; - /* Initilize descriptors; mark all empty */ + /* Initialize descriptors; mark all empty */ for (i = 0; i < ATE_MAX_TX_BUFFERS; i++) { sc->tx_descs[i].addr =0; sc->tx_descs[i].status = ETHB_TX_USED; @@ -919,7 +919,7 @@ ate_intr(void *xsc) /* * Simulate SAM9 FIRST/LAST bits for RM9200. * RM9200 EMAC has only on Rx buffer per packet. - * But sometime we are handed a zero lenght packet. + * But sometime we are handed a zero length packet. */ if ((rxdhead->status & ETH_LEN_MASK) == 0) rxdhead->status = 0; /* Mark error */ @@ -980,7 +980,7 @@ ate_intr(void *xsc) do { /* Last buffer may just be 1-4 bytes of FCS so remain - * may be zero for last decriptor. */ + * may be zero for last descriptor. */ if (remain > 0) { /* Make sure we get the current bytes */ bus_dmamap_sync(sc->rx_tag, sc->rx_map[sc->rxhead], @@ -989,7 +989,7 @@ ate_intr(void *xsc) count = MIN(remain, sc->rx_buf_size); /* XXX Performance robbing copy. Could - * recieve directly to mbufs if not an + * receive directly to mbufs if not an * RM9200. And even then we could likely * copy just the protocol headers. XXX */ m_append(mb, count, sc->rx_buf[sc->rxhead]); @@ -1468,7 +1468,7 @@ ate_miibus_readreg(device_t dev, int phy, int reg) int val; /* - * XXX if we implement agressive power savings, then we need + * XXX if we implement aggressive power savings, then we need * XXX to make sure that the clock to the emac is on here */ @@ -1488,7 +1488,7 @@ ate_miibus_writereg(device_t dev, int phy, int reg, int data) struct ate_softc *sc; /* - * XXX if we implement agressive power savings, then we need + * XXX if we implement aggressive power savings, then we need * XXX to make sure that the clock to the emac is on here */ diff --git a/sys/arm/at91/if_atereg.h b/sys/arm/at91/if_atereg.h index fc7e4de..c6cbbcf 100644 --- a/sys/arm/at91/if_atereg.h +++ b/sys/arm/at91/if_atereg.h @@ -28,7 +28,7 @@ #ifndef ARM_AT91_IF_ATEREG_H #define ARM_AT91_IF_ATEREG_H -/* deines begining ETHB_ are EMACB (newer SAM9 hardware) versions only */ +/* Defines beginning ETHB_ are EMACB (newer SAM9 hardware) versions only. */ #define ETH_CTL 0x00 /* EMAC Control Register */ #define ETH_CFG 0x04 /* EMAC Configuration Register */ @@ -191,7 +191,7 @@ typedef struct { #define ETH_MAC_LOCAL_3 (1U << 24) /* Packet matched addr 3 */ #define ETH_MAC_LOCAL_2 (1U << 25) /* Packet matched addr 2 */ #define ETH_MAC_LOCAL_1 (1U << 26) /* Packet matched addr 1 */ -#define ETH_MAC_UNK (1U << 27) /* Unkown source address RFU */ +#define ETH_MAC_UNK (1U << 27) /* Unknown source address RFU */ #define ETH_MAC_EXT (1U << 28) /* External Address */ #define ETH_MAC_UCAST (1U << 29) /* Unicast hash match */ #define ETH_MAC_MCAST (1U << 30) /* Multicast hash match */ diff --git a/sys/arm/broadcom/bcm2835/bcm2835_audio.c b/sys/arm/broadcom/bcm2835/bcm2835_audio.c index bfed287..8658c26 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_audio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_audio.c @@ -828,7 +828,7 @@ bcm2835_audio_attach(device_t dev) /* * We need interrupts enabled for VCHI to work properly, - * so delay intialization until it happens + * so delay initialization until it happens. */ sc->intr_hook.ich_func = bcm2835_audio_delayed_init; sc->intr_hook.ich_arg = sc; diff --git a/sys/arm/broadcom/bcm2835/bcm2835_dma.c b/sys/arm/broadcom/bcm2835/bcm2835_dma.c index 347be2b..f174701 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_dma.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_dma.c @@ -278,7 +278,7 @@ bcm_dma_init(device_t dev) /* * Least alignment for busdma-allocated stuff is cache - * line size, so just make sure nothing stupid happend + * line size, so just make sure nothing stupid happened * and we got properly aligned address */ if ((uintptr_t)cb_virt & 0x1f) { @@ -539,7 +539,7 @@ bcm_dma_reg_dump(int ch) * ch - channel number * src, dst - source and destination address in * ARM physical memory address space. - * len - amount of bytes to be transfered + * len - amount of bytes to be transferred * * Returns 0 on success, -1 otherwise */ diff --git a/sys/arm/cavium/cns11xx/if_ece.c b/sys/arm/cavium/cns11xx/if_ece.c index 2ae3d22..9ed5cbd 100644 --- a/sys/arm/cavium/cns11xx/if_ece.c +++ b/sys/arm/cavium/cns11xx/if_ece.c @@ -1685,7 +1685,7 @@ ece_encap(struct ece_softc *sc, struct mbuf *m0) /* * After all descriptors are set, we set the flags to start the - * sending proces. + * sending process. */ for (seg = 0; seg < nsegs; seg++) { desc->cown = 0; diff --git a/sys/arm/freescale/imx/imx6_ipu.c b/sys/arm/freescale/imx/imx6_ipu.c index d1efbff..f561fa7 100644 --- a/sys/arm/freescale/imx/imx6_ipu.c +++ b/sys/arm/freescale/imx/imx6_ipu.c @@ -872,7 +872,7 @@ ipu_init_buffer(struct ipu_softc *sc) stride = sc->sc_mode->hdisplay * MODE_BPP / 8; - /* init channel paramters */ + /* init channel parameters */ CH_PARAM_RESET(¶m); /* XXX: interlaced modes are not supported yet */ CH_PARAM_SET_FW(¶m, sc->sc_mode->hdisplay - 1); diff --git a/sys/arm/freescale/imx/imx6_ssi.c b/sys/arm/freescale/imx/imx6_ssi.c index 9387aa3..9000ae3 100644 --- a/sys/arm/freescale/imx/imx6_ssi.c +++ b/sys/arm/freescale/imx/imx6_ssi.c @@ -738,7 +738,7 @@ ssi_attach(device_t dev) sc->lock = snd_mtxcreate(device_get_nameunit(dev), "ssi softc"); if (sc->lock == NULL) { - device_printf(dev, "Cant create mtx\n"); + device_printf(dev, "Can't create mtx\n"); return (ENXIO); } @@ -764,7 +764,7 @@ ssi_attach(device_t dev) /* * Maximum possible DMA buffer. - * Will be used partialy to match 24 bit word. + * Will be used partially to match 24 bit word. */ sc->dma_size = 131072; diff --git a/sys/arm/freescale/vybrid/vf_uart.c b/sys/arm/freescale/vybrid/vf_uart.c index 312f18c..61a08fb 100644 --- a/sys/arm/freescale/vybrid/vf_uart.c +++ b/sys/arm/freescale/vybrid/vf_uart.c @@ -205,7 +205,7 @@ uart_reinit(struct uart_softc *sc, int clkspeed, int baud) bas = &sc->sc_bas; if (!bas) { - printf("Error: cant reconfigure bas\n"); + printf("Error: can't reconfigure bas\n"); return; } diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c index 4c5856a..7be61fc 100644 --- a/sys/arm/mv/mpic.c +++ b/sys/arm/mv/mpic.c @@ -564,7 +564,7 @@ mv_msi_data(int irq, uint64_t *addr, uint32_t *data) node = ofw_bus_get_node(mv_mpic_sc->sc_dev); - /* Get physical addres of register space */ + /* Get physical address of register space */ error = fdt_get_range(OF_parent(node), 0, &phys, &size); if (error) { printf("%s: Cannot get register physical address, err:%d", diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c index 2bd13f6..55e3cd1 100644 --- a/sys/arm/mv/mv_common.c +++ b/sys/arm/mv/mv_common.c @@ -1398,7 +1398,7 @@ decode_win_pcie_setup(u_long base) /* * Upper 16 bits in BAR register is interpreted as BAR size - * (in 64 kB units) plus 64kB, so substract 0x10000 + * (in 64 kB units) plus 64kB, so subtract 0x10000 * form value passed to register to get correct value. */ size -= 0x10000; diff --git a/sys/arm/samsung/exynos/exynos5_usb_phy.c b/sys/arm/samsung/exynos/exynos5_usb_phy.c index 2756efb..430c8f8 100644 --- a/sys/arm/samsung/exynos/exynos5_usb_phy.c +++ b/sys/arm/samsung/exynos/exynos5_usb_phy.c @@ -161,7 +161,7 @@ vbus_on(struct usb_phy_softc *sc) gpio_dev = devclass_get_device(devclass_find("gpio"), 0); if (gpio_dev == NULL) { - device_printf(sc->dev, "cant find gpio_dev\n"); + device_printf(sc->dev, "can't find gpio_dev\n"); return (1); } diff --git a/sys/arm/ti/omap4/omap4_prcm_clks.c b/sys/arm/ti/omap4/omap4_prcm_clks.c index e83e6ee..e17fe3d 100644 --- a/sys/arm/ti/omap4/omap4_prcm_clks.c +++ b/sys/arm/ti/omap4/omap4_prcm_clks.c @@ -1329,7 +1329,7 @@ omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev) * Inherits the locks from the omap_prcm driver, no internal locking. * * RETURNS: - * Returns 0 if sucessful otherwise a negative error code on failure. + * Returns 0 if successful otherwise a negative error code on failure. */ static int omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev, diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c index 92a44a7..55336ff 100644 --- a/sys/arm/ti/ti_i2c.c +++ b/sys/arm/ti/ti_i2c.c @@ -236,7 +236,7 @@ ti_i2c_transfer_intr(struct ti_i2c_softc* sc, uint16_t status) if (status & I2C_STAT_RDR) { /* * Receive draining interrupt - last data received. - * The set FIFO threshold wont be reached to trigger + * The set FIFO threshold won't be reached to trigger * RRDY. */ ti_i2c_dbg(sc, "Receive draining interrupt\n"); @@ -272,7 +272,7 @@ ti_i2c_transfer_intr(struct ti_i2c_softc* sc, uint16_t status) /* * Transmit draining interrupt - FIFO level is below * the set threshold and the amount of data still to - * be transferred wont reach the set FIFO threshold. + * be transferred won't reach the set FIFO threshold. */ ti_i2c_dbg(sc, "Transmit draining interrupt\n"); diff --git a/sys/arm/ti/ti_pinmux.c b/sys/arm/ti/ti_pinmux.c index ff4743d..ffeaf75 100644 --- a/sys/arm/ti/ti_pinmux.c +++ b/sys/arm/ti/ti_pinmux.c @@ -394,7 +394,7 @@ ti_pinmux_probe(device_t dev) * @dev: new device * * RETURNS - * Zero on sucess or ENXIO if an error occuried. + * Zero on success or ENXIO if an error occuried. */ static int ti_pinmux_attach(device_t dev) diff --git a/sys/arm/ti/ti_prcm.c b/sys/arm/ti/ti_prcm.c index c5ab9c7..d742d07 100644 --- a/sys/arm/ti/ti_prcm.c +++ b/sys/arm/ti/ti_prcm.c @@ -31,7 +31,7 @@ */ /** - * Power, Reset and Clock Managment Module + * Power, Reset and Clock Management Module * * This is a very simple driver wrapper around the PRCM set of registers in * the OMAP3 chip. It allows you to turn on and off things like the functional diff --git a/sys/arm/ti/ti_scm.c b/sys/arm/ti/ti_scm.c index 14e9200..5608265 100644 --- a/sys/arm/ti/ti_scm.c +++ b/sys/arm/ti/ti_scm.c @@ -111,7 +111,7 @@ ti_scm_probe(device_t dev) * globally and registers both the timecount and eventtimer objects. * * RETURNS - * Zero on sucess or ENXIO if an error occuried. + * Zero on success or ENXIO if an error occuried. */ static int ti_scm_attach(device_t dev) diff --git a/sys/arm/ti/ti_sdma.c b/sys/arm/ti/ti_sdma.c index a8faba8..7e5e957 100644 --- a/sys/arm/ti/ti_sdma.c +++ b/sys/arm/ti/ti_sdma.c @@ -446,7 +446,7 @@ ti_sdma_deactivate_channel(unsigned int ch) * ti_sdma_disable_channel_irq - disables IRQ's on the given channel * @ch: the channel to disable IRQ's on * - * Disable interupt generation for the given channel. + * Disable interrupt generation for the given channel. * * LOCKING: * DMA registers protected by internal mutex @@ -608,7 +608,7 @@ ti_sdma_get_channel_status(unsigned int ch, uint32_t *status) /** * ti_sdma_start_xfer - starts a DMA transfer - * @ch: the channel number to set the endianess of + * @ch: the channel number to set the endianness of * @src_paddr: the source phsyical address * @dst_paddr: the destination phsyical address * @frmcnt: the number of frames per block @@ -707,7 +707,7 @@ ti_sdma_start_xfer(unsigned int ch, unsigned int src_paddr, * frmcnt = 1, elmcnt = 512, pktsize = 128 * * Total transfer bytes = 1 * 512 = 512 elements or 2048 bytes - * Packets transfered = 128 / 512 = 4 + * Packets transferred = 128 / 512 = 4 * * * LOCKING: @@ -787,7 +787,7 @@ ti_sdma_start_xfer_packet(unsigned int ch, unsigned int src_paddr, /** * ti_sdma_stop_xfer - stops any currently active transfers - * @ch: the channel number to set the endianess of + * @ch: the channel number to set the endianness of * * This function call is effectively a NOP if no transaction is in progress. * @@ -835,10 +835,10 @@ ti_sdma_stop_xfer(unsigned int ch) } /** - * ti_sdma_set_xfer_endianess - sets the endianess of subsequent transfers - * @ch: the channel number to set the endianess of - * @src: the source endianess (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) - * @dst: the destination endianess (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) + * ti_sdma_set_xfer_endianess - sets the endianness of subsequent transfers + * @ch: the channel number to set the endianness of + * @src: the source endianness (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) + * @dst: the destination endianness (either DMA_ENDIAN_LITTLE or DMA_ENDIAN_BIG) * * * LOCKING: @@ -879,9 +879,9 @@ ti_sdma_set_xfer_endianess(unsigned int ch, unsigned int src, unsigned int dst) /** * ti_sdma_set_xfer_burst - sets the source and destination element size * @ch: the channel number to set the burst settings of - * @src: the source endianess (either DMA_BURST_NONE, DMA_BURST_16, DMA_BURST_32 + * @src: the source endianness (either DMA_BURST_NONE, DMA_BURST_16, DMA_BURST_32 * or DMA_BURST_64) - * @dst: the destination endianess (either DMA_BURST_NONE, DMA_BURST_16, + * @dst: the destination endianness (either DMA_BURST_NONE, DMA_BURST_16, * DMA_BURST_32 or DMA_BURST_64) * * This function sets the size of the elements for all subsequent transfers. @@ -923,7 +923,7 @@ ti_sdma_set_xfer_burst(unsigned int ch, unsigned int src, unsigned int dst) /** * ti_sdma_set_xfer_data_type - driver attach function - * @ch: the channel number to set the endianess of + * @ch: the channel number to set the endianness of * @type: the xfer data type (either DMA_DATA_8BITS_SCALAR, DMA_DATA_16BITS_SCALAR * or DMA_DATA_32BITS_SCALAR) * @@ -1065,7 +1065,7 @@ ti_sdma_sync_params(unsigned int ch, unsigned int trigger, unsigned int mode) /** * ti_sdma_set_addr_mode - driver attach function - * @ch: the channel number to set the endianess of + * @ch: the channel number to set the endianness of * @rd_mode: the xfer source addressing mode (either DMA_ADDR_CONSTANT, * DMA_ADDR_POST_INCREMENT, DMA_ADDR_SINGLE_INDEX or * DMA_ADDR_DOUBLE_INDEX) diff --git a/sys/arm/xilinx/zy7_slcr.c b/sys/arm/xilinx/zy7_slcr.c index e243ff6..c99d5b0 100644 --- a/sys/arm/xilinx/zy7_slcr.c +++ b/sys/arm/xilinx/zy7_slcr.c @@ -177,7 +177,7 @@ zy7_slcr_preload_pl(void) /* After PL configuration, enable level shifters and deassert top-level * PL resets. Called from zy7_devcfg.c. Optionally, the level shifters * can be left disabled but that's rare of an FPGA application. That option - * is controled by a sysctl in the devcfg driver. + * is controlled by a sysctl in the devcfg driver. */ void zy7_slcr_postload_pl(int en_level_shifters) diff --git a/sys/arm/xscale/i8134x/crb_machdep.c b/sys/arm/xscale/i8134x/crb_machdep.c index 5268ca9..898bbaa 100644 --- a/sys/arm/xscale/i8134x/crb_machdep.c +++ b/sys/arm/xscale/i8134x/crb_machdep.c @@ -38,7 +38,7 @@ * * machdep.c * - * Machine dependant functions for kernel setup + * Machine dependent functions for kernel setup * * This file needs a lot of work. * diff --git a/sys/arm/xscale/i8134x/i81342reg.h b/sys/arm/xscale/i8134x/i81342reg.h index fd087ce..2402194 100644 --- a/sys/arm/xscale/i8134x/i81342reg.h +++ b/sys/arm/xscale/i8134x/i81342reg.h @@ -184,7 +184,7 @@ #define ATU_IATVR2 0x005c /* Inbound ATU Translate Value Register 2 */ #define ATU_IAUTVR2 0x0060 /* Inbound ATU Upper Translate Value Register 2*/ #define ATU_ERLR 0x0064 /* Expansion ROM Limit Register */ -#define ATU_ERTVR 0x0068 /* Expansion ROM Translater Value Register */ +#define ATU_ERTVR 0x0068 /* Expansion ROM Translator Value Register */ #define ATU_ERUTVR 0x006c /* Expansion ROM Upper Translate Value Register*/ #define ATU_CR 0x0070 /* ATU Configuration Register */ #define ATU_CR_OUT_EN (1 << 1) diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c index 46e4b10..f26d3ca 100644 --- a/sys/arm/xscale/ixp425/avila_machdep.c +++ b/sys/arm/xscale/ixp425/avila_machdep.c @@ -38,7 +38,7 @@ * * machdep.c * - * Machine dependant functions for kernel setup + * Machine dependent functions for kernel setup * * This file needs a lot of work. * diff --git a/sys/arm/xscale/ixp425/cambria_gpio.c b/sys/arm/xscale/ixp425/cambria_gpio.c index aa3947b..c871418 100644 --- a/sys/arm/xscale/ixp425/cambria_gpio.c +++ b/sys/arm/xscale/ixp425/cambria_gpio.c @@ -32,7 +32,7 @@ * The Cambria PLD does not set the i2c ack bit after each write, if we used the * regular iicbus interface it would abort the xfer after the address byte * times out and not write our latch. To get around this we grab the iicbus and - * then do our own bit banging. This is a comprimise to changing all the iicbb + * then do our own bit banging. This is a compromise to changing all the iicbb * device methods to allow a flag to be passed down and is similir to how Linux * does it. * diff --git a/sys/arm/xscale/ixp425/ixp425_npe.c b/sys/arm/xscale/ixp425/ixp425_npe.c index 6dbce4c..95facb4 100644 --- a/sys/arm/xscale/ixp425/ixp425_npe.c +++ b/sys/arm/xscale/ixp425/ixp425_npe.c @@ -507,7 +507,7 @@ ixpnpe_load_firmware(struct ixpnpe_softc *sc, const char *imageName, /* * If download was successful, store image Id in list of - * currently loaded images. If a critical error occured + * currently loaded images. If a critical error occurred * during download, record that the NPE has an invalid image */ mtx_lock(&sc->sc_mtx); @@ -864,7 +864,7 @@ npe_cpu_reset(struct ixpnpe_softc *sc) while (npe_checkbits(sc, IX_NPEDL_REG_OFFSET_STAT, IX_NPEDL_MASK_STAT_IFNE)) { /* - * Step execution of the NPE intruction to read inFIFO using + * Step execution of the NPE instruction to read inFIFO using * the Debug Executing Context stack. */ error = npe_cpu_step(sc, IX_NPEDL_INSTR_RD_FIFO, 0, 0); @@ -1307,7 +1307,7 @@ npe_logical_reg_write(struct ixpnpe_softc *sc, uint32_t regAddr, uint32_t regVal ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) << IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA); - /* step execution of NPE intruction using Debug ECS */ + /* step execution of NPE instruction using Debug ECS */ error = npe_cpu_step(sc, npeInstruction, ctxtNum, IX_NPEDL_WR_INSTR_LDUR); } diff --git a/sys/arm/xscale/ixp425/ixp425_npereg.h b/sys/arm/xscale/ixp425/ixp425_npereg.h index 069e9d7..94aff85 100644 --- a/sys/arm/xscale/ixp425/ixp425_npereg.h +++ b/sys/arm/xscale/ixp425/ixp425_npereg.h @@ -125,7 +125,7 @@ /* * Reset value for Mailbox (MBST) register - * NOTE that if used, it should be complemented with an NPE intruction + * NOTE that if used, it should be complemented with an NPE instruction * to clear the Mailbox at the NPE side as well */ #define IX_NPEDL_REG_RESET_MBST 0x0000F0F0 diff --git a/sys/arm/xscale/ixp425/ixp425_qmgr.c b/sys/arm/xscale/ixp425/ixp425_qmgr.c index 822623c..d6db260 100644 --- a/sys/arm/xscale/ixp425/ixp425_qmgr.c +++ b/sys/arm/xscale/ixp425/ixp425_qmgr.c @@ -421,7 +421,7 @@ ixpqmgr_qwrite(int qId, uint32_t entry) return ENOSPC; } /* - * No overflow occured : someone is draining the queue + * No overflow occurred : someone is draining the queue * and the current counter needs to be * updated from the current number of entries in the queue */ diff --git a/sys/arm/xscale/pxa/pxa_machdep.c b/sys/arm/xscale/pxa/pxa_machdep.c index 32cbcd8..bc3ab6f 100644 --- a/sys/arm/xscale/pxa/pxa_machdep.c +++ b/sys/arm/xscale/pxa/pxa_machdep.c @@ -38,7 +38,7 @@ * * machdep.c * - * Machine dependant functions for kernel setup + * Machine dependent functions for kernel setup * * This file needs a lot of work. * -- cgit v1.1 From abb5bc5dabb2949981b48fbcf53a083d9f8b5047 Mon Sep 17 00:00:00 2001 From: pfg Date: Wed, 4 May 2016 15:52:40 +0000 Subject: sys/sparc64: minor spelling fixes. Only affects comments: no functional change. --- sys/sparc64/sbus/sbus.c | 2 +- sys/sparc64/sparc64/intr_machdep.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c index 65e44ff..6d448f9 100644 --- a/sys/sparc64/sbus/sbus.c +++ b/sys/sparc64/sbus/sbus.c @@ -341,7 +341,7 @@ sbus_attach(device_t dev) sc->sc_burst = (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF; - /* initalise the IOMMU */ + /* initialise the IOMMU */ /* punch in our copies */ sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(SBUS_IOMMU_BITS); diff --git a/sys/sparc64/sparc64/intr_machdep.c b/sys/sparc64/sparc64/intr_machdep.c index fe467f0..2c0c538 100644 --- a/sys/sparc64/sparc64/intr_machdep.c +++ b/sys/sparc64/sparc64/intr_machdep.c @@ -367,7 +367,7 @@ inthand_add(const char *name, int vec, driver_filter_t *filt, /* * Check if we need to upgrade from PIL_ITHREAD to PIL_FILTER. * Given that apart from the on-board SCCs and UARTs shared - * interrupts are rather uncommon on sparc64 this sould be + * interrupts are rather uncommon on sparc64 this should be * pretty rare in practice. */ filter = 0; -- cgit v1.1 From a3bf622b6a79aed42ea15ff970771a99c251027b Mon Sep 17 00:00:00 2001 From: bz Date: Wed, 4 May 2016 16:09:51 +0000 Subject: The ARM generic timer keeps ticking even if disabled or it expired. In case of updating it with a very low value it might expire again after writing the tval but before updating ctrl. In that case we do lose the status bit saying that the timer expired and we will consequently not get an interrupt for it, leaving the timer in a "dead" state. In order to solve this increase the minimum period with what the timer can be loaded to something higher. Found & analysed with: gem5 Debugged with: andrew Sponsored by: DARPA/AFRL Reviewed by: andrew MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D6202 --- sys/arm/arm/generic_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index 6e6fcea..ba612dc 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -417,7 +417,7 @@ arm_tmr_attach(device_t dev) sc->et.et_quality = 1000; sc->et.et_frequency = sc->clkfreq; - sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency; + sc->et.et_min_period = (0x00000010LLU << 32) / sc->et.et_frequency; sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency; sc->et.et_start = arm_tmr_start; sc->et.et_stop = arm_tmr_stop; -- cgit v1.1 From 64ae5d371f0ee7f0b0d74b0784b299d3bd90c1b7 Mon Sep 17 00:00:00 2001 From: bz Date: Wed, 4 May 2016 16:15:39 +0000 Subject: The virtual timer is optional on ARM64. Properly handle that condition. [1] In case we do not have an interrupt assignment for the virtual timer, force the physical timer. Also skip resource allocation for any timer we do not have an interrupt assignment for. In collaboration with: andrew Submitted by: br ([1] from his gem5 arm64 work) Sponsored by: DARPA/AFRL Reviewed by: andrew MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D6203 --- sys/arm/arm/generic_timer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index ba612dc..dcf48bc 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -100,7 +100,7 @@ static struct arm_tmr_softc *arm_tmr_sc = NULL; static struct resource_spec timer_spec[] = { { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Secure */ { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Non-secure */ - { SYS_RES_IRQ, 2, RF_ACTIVE }, /* Virt */ + { SYS_RES_IRQ, 2, RF_ACTIVE | RF_OPTIONAL }, /* Virt */ { SYS_RES_IRQ, 3, RF_ACTIVE | RF_OPTIONAL }, /* Hyp */ { -1, 0 } }; @@ -392,13 +392,17 @@ arm_tmr_attach(device_t dev) #ifdef __arm__ sc->physical = true; #else /* __aarch64__ */ - sc->physical = false; + /* If we do not have a virtual timer use the physical. */ + sc->physical = (sc->res[2] == NULL) ? true : false; #endif arm_tmr_sc = sc; /* Setup secure, non-secure and virtual IRQs handler */ for (i = 0; i < 3; i++) { + /* If we do not have the interrupt, skip it. */ + if (sc->res[i] == NULL) + continue; error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK, arm_tmr_intr, NULL, sc, &sc->ihl[i]); if (error) { -- cgit v1.1 From ba335e3838d1bf62c741921f83dc804c87441293 Mon Sep 17 00:00:00 2001 From: bz Date: Wed, 4 May 2016 16:24:12 +0000 Subject: While gem5 is not qemu, we treat it as "simulators" or "virtual environments". Add the needed hardcoded gem5 attachments for the UART there, re-using all the other bits. In collaboration with: andrew Sponsored by: DARPA/AFRL Reviewed by: andrew MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D6204 --- sys/arm/qemu/virt_machdep.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sys') diff --git a/sys/arm/qemu/virt_machdep.c b/sys/arm/qemu/virt_machdep.c index 95cc225..d15b97c 100644 --- a/sys/arm/qemu/virt_machdep.c +++ b/sys/arm/qemu/virt_machdep.c @@ -97,3 +97,20 @@ static platform_method_t virt_methods[] = { }; FDT_PLATFORM_DEF(virt, "virt", 0, "linux,dummy-virt", 1); + +static int +gem5_devmap_init(platform_t plat) +{ + + devmap_add_entry(0x1c090000, 0x100000); /* Uart */ + return (0); +} + +static platform_method_t gem5_methods[] = { + PLATFORMMETHOD(platform_devmap_init, gem5_devmap_init), + PLATFORMMETHOD(platform_lastaddr, virt_lastaddr), + + PLATFORMMETHOD_END, +}; + +FDT_PLATFORM_DEF(gem5, "gem5", 0, "arm,vexpress", 1); -- cgit v1.1 From 604866ab1831d90852376097e662a5469f57c66c Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 16:42:53 +0000 Subject: [net80211] add extra debugging around negotiated A-MPDU parameters. --- sys/net80211/ieee80211_ht.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sys') diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index 9bcd573..0320c2d 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -2742,6 +2742,14 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni) rxmax = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU); density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); + IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, + "%s: advertised rxmax=%d, density=%d, vap rxmax=%d, density=%d\n", + __func__, + rxmax, + density, + vap->iv_ampdu_rxmax, + vap->iv_ampdu_density); + /* Cap at VAP rxmax */ if (rxmax > vap->iv_ampdu_rxmax) rxmax = vap->iv_ampdu_rxmax; -- cgit v1.1 From 94154f279dff7c13d162139e09b83d995634f1dc Mon Sep 17 00:00:00 2001 From: avos Date: Wed, 4 May 2016 17:22:35 +0000 Subject: net80211: do not hardcode size of ic_modecaps field. --- sys/net80211/ieee80211_var.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 8c0f6fb..f94a15a 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -148,7 +148,8 @@ struct ieee80211com { uint32_t ic_htcaps; /* HT capabilities */ uint32_t ic_htextcaps; /* HT extended capabilities */ uint32_t ic_cryptocaps; /* crypto capabilities */ - uint8_t ic_modecaps[2]; /* set of mode capabilities */ + /* set of mode capabilities */ + uint8_t ic_modecaps[IEEE80211_MODE_BYTES]; uint8_t ic_promisc; /* vap's needing promisc mode */ uint8_t ic_allmulti; /* vap's needing all multicast*/ uint8_t ic_nrunning; /* vap's marked running */ -- cgit v1.1 From dfa987f8a029da774c0a3f9ab580b0202bdfa018 Mon Sep 17 00:00:00 2001 From: pfg Date: Wed, 4 May 2016 17:52:53 +0000 Subject: dev/pms: minor spelling fixes for the FreeBSD-specific part. --- sys/dev/pms/freebsd/driver/common/lxcommon.h | 4 ++-- sys/dev/pms/freebsd/driver/common/osenv.h | 10 +++++----- sys/dev/pms/freebsd/driver/ini/src/agtiapi.c | 4 ++-- sys/dev/pms/freebsd/driver/ini/src/osapi.c | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'sys') diff --git a/sys/dev/pms/freebsd/driver/common/lxcommon.h b/sys/dev/pms/freebsd/driver/common/lxcommon.h index 0df2702..71ce230 100644 --- a/sys/dev/pms/freebsd/driver/common/lxcommon.h +++ b/sys/dev/pms/freebsd/driver/common/lxcommon.h @@ -452,7 +452,7 @@ typedef struct _ag_card_info { /* ** Optional Adjustable Parameters Structures. -** Not using pointer stucture for easy read and access tree structure. +** Not using pointer structure for easy read and access tree structure. ** In the future if more layer of key tree involved, it might be a good ** idea to change the structure and program. */ @@ -637,7 +637,7 @@ typedef struct _LINK_LIST { PLINK_NODE pHead; bit32 Count; - LINK_NODE Head __cacheline_aligned; // allways one link to speed up insert&rm + LINK_NODE Head __cacheline_aligned; // always one link to speed up insert&rm } LINK_LIST, * PLINK_LIST __cacheline_aligned; diff --git a/sys/dev/pms/freebsd/driver/common/osenv.h b/sys/dev/pms/freebsd/driver/common/osenv.h index 16b8aa9..491c29e 100644 --- a/sys/dev/pms/freebsd/driver/common/osenv.h +++ b/sys/dev/pms/freebsd/driver/common/osenv.h @@ -28,7 +28,7 @@ Version Control Information: $RCSfile: osenv.h,v $ $Revision: 114125 $ -Note: This file defines the working enviornment of the system. All +Note: This file defines the working environment of the system. All defines listed in this file could also be compiler flags. I am listing all the defines (even if used as a compiler flag) so that they can be seen and documented. @@ -41,7 +41,7 @@ Note: This file defines the working enviornment of the system. All /* ** Define the protocols to compile with. Currently, these defines are ** only for this header file and are used further down to define the protocol -** specific enviornment: +** specific environment: ** ** #define AG_PROTOCOL_ISCSI ** #define AG_PROTOCOL_FC @@ -87,12 +87,12 @@ Note: This file defines the working enviornment of the system. All #endif /*************************************************************************** -iSCSI enviornment - The following is used for compiling the iSCSI +iSCSI environment - The following is used for compiling the iSCSI protocol. **************************************************************************/ /* -** Define the existance of an external bus swapper using on of the +** Define the existence of an external bus swapper using on of the ** following: ** ** #define AG_SWAPPING_BUS @@ -109,7 +109,7 @@ iSCSI enviornment - The following is used for compiling the iSCSI /* #define AG_CACHED_MSG_SYSTEM */ /*************************************************************************** -FC enviornment - The following is used for compiling the FC protocol. +FC environment - The following is used for compiling the FC protocol. **************************************************************************/ /* diff --git a/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c b/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c index 640d341..f0646dd 100644 --- a/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c +++ b/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c @@ -3749,7 +3749,7 @@ static void agtiapi_PrepareSMPSGListCB( void *arg, return; } /* TODO: add indirect handling */ - /* set the flag correctly based on Indiret SMP request and responce */ + /* set the flag correctly based on Indiret SMP request and response */ AGTIAPI_PRINTK( "agtiapi_PrepareSMPSGListCB: send ccb pccb->devHandle %p, " "pccb->targetId %d TID %d pmcsc->devDiscover %d card %p\n", @@ -5811,7 +5811,7 @@ agtiapi_ReleaseCCBs() Purpose: Free all allocated CCB memories for the Host Adapter. Parameters: - struct agtiapi_softc *pCard (IN) Pointer to HBA data stucture + struct agtiapi_softc *pCard (IN) Pointer to HBA data structure Return: Note: ******************************************************************************/ diff --git a/sys/dev/pms/freebsd/driver/ini/src/osapi.c b/sys/dev/pms/freebsd/driver/ini/src/osapi.c index f461923..2faaff8 100644 --- a/sys/dev/pms/freebsd/driver/ini/src/osapi.c +++ b/sys/dev/pms/freebsd/driver/ini/src/osapi.c @@ -172,7 +172,7 @@ void ostiInitiatorEvent( tiRoot_t *ptiRoot, ccbIO = pccb->pccbIO; if (ccbIO->startTime == 0) /* IO has been completed. */ { - AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: TM failed becasue IO has been completed! pTMccb %p flag %x \n", + AGTIAPI_PRINTK("tiIntrEventTypeTaskManagement: TM failed because IO has been completed! pTMccb %p flag %x \n", pccb, pccb->flags); } else @@ -443,7 +443,7 @@ ostiInitiatorSMPCompleted(tiRoot_t *ptiRoot, struct ccb_smpio *csmpio = &ccb->smpio; memcpy(csmpio->smp_response, tiFrameHandle, tiSMPInfoLen); csmpio->smp_response_len = tiSMPInfoLen; - agtiapi_hexdump("ostiInitiatorSMPCompleted: Responce Payload in CAM", (bit8 *)csmpio->smp_response, csmpio->smp_response_len); + agtiapi_hexdump("ostiInitiatorSMPCompleted: Response Payload in CAM", (bit8 *)csmpio->smp_response, csmpio->smp_response_len); } pccb->flags |= REQ_DONE; agtiapi_QueueCCB(pCard, &pCard->smpDoneHead, &pCard->smpDoneTail -- cgit v1.1 From 52f3fcfa90cf9bf2b975562688c13718237be636 Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 4 May 2016 17:54:13 +0000 Subject: Explain why pmap_copy(), pmap_enter_pde(), and pmap_enter_quick_locked() call pmap_invalidate_page() even though they are not destroying a leaf- level page table entry. Eliminate some bogus white-space characters in a comment. Reviewed by: kib --- sys/amd64/amd64/pmap.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 22a6c31..a7c879c 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -4407,6 +4407,12 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, lockp)) { SLIST_INIT(&free); if (pmap_unwire_ptp(pmap, va, mpde, &free)) { + /* + * Although "va" is not mapped, paging- + * structure caches could nonetheless have + * entries that refer to the freed page table + * pages. Invalidate those entries. + */ pmap_invalidate_page(pmap, va); pmap_free_zero_pages(&free); } @@ -4584,6 +4590,12 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, if (mpte != NULL) { SLIST_INIT(&free); if (pmap_unwire_ptp(pmap, va, mpte, &free)) { + /* + * Although "va" is not mapped, paging- + * structure caches could nonetheless have + * entries that refer to the freed page table + * pages. Invalidate those entries. + */ pmap_invalidate_page(pmap, va); pmap_free_zero_pages(&free); } @@ -4967,6 +4979,14 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len, SLIST_INIT(&free); if (pmap_unwire_ptp(dst_pmap, addr, dstmpte, &free)) { + /* + * Although "addr" is not + * mapped, paging-structure + * caches could nonetheless + * have entries that refer to + * the freed page table pages. + * Invalidate those entries. + */ pmap_invalidate_page(dst_pmap, addr); pmap_free_zero_pages(&free); @@ -5219,7 +5239,7 @@ pmap_page_is_mapped(vm_page_t m) * Destroy all managed, non-wired mappings in the given user-space * pmap. This pmap cannot be active on any processor besides the * caller. - * + * * This function cannot be applied to the kernel pmap. Moreover, it * is not intended for general use. It is only to be used during * process termination. Consequently, it can be implemented in ways -- cgit v1.1 From bca262833780bbe4fe39f45486cb53ad1a5a2315 Mon Sep 17 00:00:00 2001 From: avos Date: Wed, 4 May 2016 18:08:38 +0000 Subject: wi: fix a comment (0x1fff has 13 bits set). --- sys/dev/wi/if_wi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 19876e1..e2ea3c9 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -337,7 +337,7 @@ wi_attach(device_t dev) */ buflen = sizeof(val); if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0) - val = htole16(0x1fff); /* assume 1-11 */ + val = htole16(0x1fff); /* assume 1-13 */ KASSERT(val != 0, ("wi_attach: no available channels listed!")); val <<= 1; /* shift for base 1 indices */ -- cgit v1.1 From 4be5f4b925430624ba065927300a52301bc06f18 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Wed, 4 May 2016 20:06:20 +0000 Subject: Add driver for Allwinner A83T/H3/A64 Gigabit Ethernet. The datasheets refer to this controller as EMAC, not to be confused with the fast ethernet controller (also named EMAC) found in A10/A20 SoCs. Tested on a BananaPi M3 (A83T), which uses an external RGMII PHY (RTL8211E). Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D6169 --- sys/arm/allwinner/files.allwinner | 1 + sys/arm/allwinner/if_awg.c | 1418 +++++++++++++++++++++++++++++++++++++ sys/arm/allwinner/if_awgreg.h | 181 +++++ 3 files changed, 1600 insertions(+) create mode 100644 sys/arm/allwinner/if_awg.c create mode 100644 sys/arm/allwinner/if_awgreg.h (limited to 'sys') diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner index d02a868..84453a6 100644 --- a/sys/arm/allwinner/files.allwinner +++ b/sys/arm/allwinner/files.allwinner @@ -18,6 +18,7 @@ arm/allwinner/a20/a20_cpu_cfg.c standard arm/allwinner/allwinner_machdep.c standard arm/allwinner/aw_mp.c optional smp arm/allwinner/axp209.c optional axp209 +arm/allwinner/if_awg.c optional awg arm/allwinner/if_emac.c optional emac arm/allwinner/sunxi_dma_if.m standard dev/iicbus/twsi/a10_twsi.c optional twsi diff --git a/sys/arm/allwinner/if_awg.c b/sys/arm/allwinner/if_awg.c new file mode 100644 index 0000000..87606c3 --- /dev/null +++ b/sys/arm/allwinner/if_awg.c @@ -0,0 +1,1418 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 ``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. + * + * $FreeBSD$ + */ + +/* + * Allwinner Gigabit Ethernet MAC (EMAC) controller + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "miibus_if.h" + +#define RD4(sc, reg) bus_read_4((sc)->res[0], (reg)) +#define WR4(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val)) + +#define AWG_LOCK(sc) mtx_lock(&(sc)->mtx) +#define AWG_UNLOCK(sc) mtx_unlock(&(sc)->mtx); +#define AWG_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED) +#define AWG_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED) + +#define DESC_ALIGN 4 +#define TX_DESC_COUNT 256 +#define TX_DESC_SIZE (sizeof(struct emac_desc) * TX_DESC_COUNT) +#define RX_DESC_COUNT 256 +#define RX_DESC_SIZE (sizeof(struct emac_desc) * RX_DESC_COUNT) + +#define DESC_OFF(n) ((n) * sizeof(struct emac_desc)) +#define TX_NEXT(n) (((n) + 1) & (TX_DESC_COUNT - 1)) +#define TX_SKIP(n, o) (((n) + (o)) & (TX_DESC_COUNT - 1)) +#define RX_NEXT(n) (((n) + 1) & (RX_DESC_COUNT - 1)) + +#define TX_MAX_SEGS 10 + +#define SOFT_RST_RETRY 1000 +#define MII_BUSY_RETRY 1000 +#define MDIO_FREQ 2500000 + +#define BURST_LEN_DEFAULT 8 +#define RX_TX_PRI_DEFAULT 0 +#define PAUSE_TIME_DEFAULT 0x400 +#define TX_INTERVAL_DEFAULT 64 + +/* Burst length of RX and TX DMA transfers */ +static int awg_burst_len = BURST_LEN_DEFAULT; +TUNABLE_INT("hw.awg.burst_len", &awg_burst_len); + +/* RX / TX DMA priority. If 1, RX DMA has priority over TX DMA. */ +static int awg_rx_tx_pri = RX_TX_PRI_DEFAULT; +TUNABLE_INT("hw.awg.rx_tx_pri", &awg_rx_tx_pri); + +/* Pause time field in the transmitted control frame */ +static int awg_pause_time = PAUSE_TIME_DEFAULT; +TUNABLE_INT("hw.awg.pause_time", &awg_pause_time); + +/* Request a TX interrupt every descriptors */ +static int awg_tx_interval = TX_INTERVAL_DEFAULT; +TUNABLE_INT("hw.awg.tx_interval", &awg_tx_interval); + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun8i-a83t-emac", 1 }, + { NULL, 0 } +}; + +struct awg_bufmap { + bus_dmamap_t map; + struct mbuf *mbuf; +}; + +struct awg_txring { + bus_dma_tag_t desc_tag; + bus_dmamap_t desc_map; + struct emac_desc *desc_ring; + bus_addr_t desc_ring_paddr; + bus_dma_tag_t buf_tag; + struct awg_bufmap buf_map[TX_DESC_COUNT]; + u_int cur, next, queued; +}; + +struct awg_rxring { + bus_dma_tag_t desc_tag; + bus_dmamap_t desc_map; + struct emac_desc *desc_ring; + bus_addr_t desc_ring_paddr; + bus_dma_tag_t buf_tag; + struct awg_bufmap buf_map[RX_DESC_COUNT]; + u_int cur; +}; + +struct awg_softc { + struct resource *res[2]; + struct mtx mtx; + if_t ifp; + device_t miibus; + struct callout stat_ch; + struct task link_task; + void *ih; + u_int mdc_div_ratio_m; + int link; + int if_flags; + + struct awg_txring tx; + struct awg_rxring rx; +}; + +static struct resource_spec awg_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +awg_miibus_readreg(device_t dev, int phy, int reg) +{ + struct awg_softc *sc; + int retry, val; + + sc = device_get_softc(dev); + val = 0; + + WR4(sc, EMAC_MII_CMD, + (sc->mdc_div_ratio_m << MDC_DIV_RATIO_M_SHIFT) | + (phy << PHY_ADDR_SHIFT) | + (reg << PHY_REG_ADDR_SHIFT) | + MII_BUSY); + for (retry = MII_BUSY_RETRY; retry > 0; retry--) { + if ((RD4(sc, EMAC_MII_CMD) & MII_BUSY) == 0) { + val = RD4(sc, EMAC_MII_DATA); + break; + } + DELAY(10); + } + + if (retry == 0) + device_printf(dev, "phy read timeout, phy=%d reg=%d\n", + phy, reg); + + return (val); +} + +static int +awg_miibus_writereg(device_t dev, int phy, int reg, int val) +{ + struct awg_softc *sc; + int retry; + + sc = device_get_softc(dev); + + WR4(sc, EMAC_MII_DATA, val); + WR4(sc, EMAC_MII_CMD, + (sc->mdc_div_ratio_m << MDC_DIV_RATIO_M_SHIFT) | + (phy << PHY_ADDR_SHIFT) | + (reg << PHY_REG_ADDR_SHIFT) | + MII_WR | MII_BUSY); + for (retry = MII_BUSY_RETRY; retry > 0; retry--) { + if ((RD4(sc, EMAC_MII_CMD) & MII_BUSY) == 0) + break; + DELAY(10); + } + + if (retry == 0) + device_printf(dev, "phy write timeout, phy=%d reg=%d\n", + phy, reg); + + return (0); +} + +static void +awg_update_link_locked(struct awg_softc *sc) +{ + struct mii_data *mii; + uint32_t val; + + AWG_ASSERT_LOCKED(sc); + + if ((if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) == 0) + return; + mii = device_get_softc(sc->miibus); + + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_1000_T: + case IFM_1000_SX: + case IFM_100_TX: + case IFM_10_T: + sc->link = 1; + break; + default: + sc->link = 0; + break; + } + } else + sc->link = 0; + + if (sc->link == 0) + return; + + val = RD4(sc, EMAC_BASIC_CTL_0); + val &= ~(BASIC_CTL_SPEED | BASIC_CTL_DUPLEX); + + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || + IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) + val |= BASIC_CTL_SPEED_1000 << BASIC_CTL_SPEED_SHIFT; + else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) + val |= BASIC_CTL_SPEED_100 << BASIC_CTL_SPEED_SHIFT; + else + val |= BASIC_CTL_SPEED_10 << BASIC_CTL_SPEED_SHIFT; + + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) + val |= BASIC_CTL_DUPLEX; + + WR4(sc, EMAC_BASIC_CTL_0, val); + + val = RD4(sc, EMAC_RX_CTL_0); + val &= ~RX_FLOW_CTL_EN; + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) + val |= RX_FLOW_CTL_EN; + WR4(sc, EMAC_RX_CTL_0, val); + + val = RD4(sc, EMAC_TX_FLOW_CTL); + val &= ~(PAUSE_TIME|TX_FLOW_CTL_EN); + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) + val |= TX_FLOW_CTL_EN; + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) + val |= awg_pause_time << PAUSE_TIME_SHIFT; + WR4(sc, EMAC_TX_FLOW_CTL, val); +} + +static void +awg_link_task(void *arg, int pending) +{ + struct awg_softc *sc; + + sc = arg; + + AWG_LOCK(sc); + awg_update_link_locked(sc); + AWG_UNLOCK(sc); +} + +static void +awg_miibus_statchg(device_t dev) +{ + struct awg_softc *sc; + + sc = device_get_softc(dev); + + taskqueue_enqueue(taskqueue_swi, &sc->link_task); +} + +static void +awg_media_status(if_t ifp, struct ifmediareq *ifmr) +{ + struct awg_softc *sc; + struct mii_data *mii; + + sc = if_getsoftc(ifp); + mii = device_get_softc(sc->miibus); + + AWG_LOCK(sc); + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; + AWG_UNLOCK(sc); +} + +static int +awg_media_change(if_t ifp) +{ + struct awg_softc *sc; + struct mii_data *mii; + int error; + + sc = if_getsoftc(ifp); + mii = device_get_softc(sc->miibus); + + AWG_LOCK(sc); + error = mii_mediachg(mii); + AWG_UNLOCK(sc); + + return (error); +} + +static void +awg_setup_txdesc(struct awg_softc *sc, int index, int flags, bus_addr_t paddr, + u_int len) +{ + uint32_t status, size; + + if (paddr == 0 || len == 0) { + status = 0; + size = 0; + --sc->tx.queued; + } else { + status = TX_DESC_CTL; + size = flags | len; + if ((index & (awg_tx_interval - 1)) == 0) + size |= htole32(TX_INT_CTL); + ++sc->tx.queued; + } + + sc->tx.desc_ring[index].addr = htole32((uint32_t)paddr); + sc->tx.desc_ring[index].size = htole32(size); + sc->tx.desc_ring[index].status = htole32(status); +} + +static int +awg_setup_txbuf(struct awg_softc *sc, int index, struct mbuf **mp) +{ + bus_dma_segment_t segs[TX_MAX_SEGS]; + int error, nsegs, cur, i, flags; + u_int csum_flags; + struct mbuf *m; + + m = *mp; + error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, + sc->tx.buf_map[index].map, m, segs, &nsegs, BUS_DMA_NOWAIT); + if (error == EFBIG) { + m = m_collapse(m, M_NOWAIT, TX_MAX_SEGS); + if (m == NULL) + return (0); + *mp = m; + error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, + sc->tx.buf_map[index].map, m, segs, &nsegs, BUS_DMA_NOWAIT); + } + if (error != 0) + return (0); + + bus_dmamap_sync(sc->tx.buf_tag, sc->tx.buf_map[index].map, + BUS_DMASYNC_PREWRITE); + + flags = TX_FIR_DESC; + if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) { + if ((m->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) != 0) + csum_flags = TX_CHECKSUM_CTL_FULL; + else + csum_flags = TX_CHECKSUM_CTL_IP; + flags |= (csum_flags << TX_CHECKSUM_CTL_SHIFT); + } + + for (cur = index, i = 0; i < nsegs; i++) { + sc->tx.buf_map[cur].mbuf = (i == 0 ? m : NULL); + if (i == nsegs - 1) + flags |= TX_LAST_DESC; + awg_setup_txdesc(sc, cur, flags, segs[i].ds_addr, + segs[i].ds_len); + flags &= ~TX_FIR_DESC; + cur = TX_NEXT(cur); + } + + return (nsegs); +} + +static void +awg_setup_rxdesc(struct awg_softc *sc, int index, bus_addr_t paddr) +{ + uint32_t status, size; + + status = RX_DESC_CTL; + size = MCLBYTES - 1; + + sc->rx.desc_ring[index].addr = htole32((uint32_t)paddr); + sc->rx.desc_ring[index].size = htole32(size); + sc->rx.desc_ring[index].next = + htole32(sc->rx.desc_ring_paddr + DESC_OFF(RX_NEXT(index))); + sc->rx.desc_ring[index].status = htole32(status); +} + +static int +awg_setup_rxbuf(struct awg_softc *sc, int index, struct mbuf *m) +{ + bus_dma_segment_t seg; + int error, nsegs; + + m_adj(m, ETHER_ALIGN); + + error = bus_dmamap_load_mbuf_sg(sc->rx.buf_tag, + sc->rx.buf_map[index].map, m, &seg, &nsegs, 0); + if (error != 0) + return (error); + + bus_dmamap_sync(sc->rx.buf_tag, sc->rx.buf_map[index].map, + BUS_DMASYNC_PREREAD); + + sc->rx.buf_map[index].mbuf = m; + awg_setup_rxdesc(sc, index, seg.ds_addr); + + return (0); +} + +static struct mbuf * +awg_alloc_mbufcl(struct awg_softc *sc) +{ + struct mbuf *m; + + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + if (m != NULL) + m->m_pkthdr.len = m->m_len = m->m_ext.ext_size; + + return (m); +} + +static void +awg_start_locked(struct awg_softc *sc) +{ + struct mbuf *m; + uint32_t val; + if_t ifp; + int cnt, nsegs; + + AWG_ASSERT_LOCKED(sc); + + if (!sc->link) + return; + + ifp = sc->ifp; + + if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return; + + for (cnt = 0; ; cnt++) { + if (sc->tx.queued >= TX_DESC_COUNT - TX_MAX_SEGS) { + if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); + break; + } + + m = if_dequeue(ifp); + if (m == NULL) + break; + + nsegs = awg_setup_txbuf(sc, sc->tx.cur, &m); + if (nsegs == 0) { + if_sendq_prepend(ifp, m); + break; + } + if_bpfmtap(ifp, m); + sc->tx.cur = TX_SKIP(sc->tx.cur, nsegs); + } + + if (cnt != 0) { + bus_dmamap_sync(sc->tx.desc_tag, sc->tx.desc_map, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + /* Start and run TX DMA */ + val = RD4(sc, EMAC_TX_CTL_1); + WR4(sc, EMAC_TX_CTL_1, val | TX_DMA_START); + } +} + +static void +awg_start(if_t ifp) +{ + struct awg_softc *sc; + + sc = if_getsoftc(ifp); + + AWG_LOCK(sc); + awg_start_locked(sc); + AWG_UNLOCK(sc); +} + +static void +awg_tick(void *softc) +{ + struct awg_softc *sc; + struct mii_data *mii; + if_t ifp; + int link; + + sc = softc; + ifp = sc->ifp; + mii = device_get_softc(sc->miibus); + + AWG_ASSERT_LOCKED(sc); + + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) + return; + + link = sc->link; + mii_tick(mii); + if (sc->link && !link) + awg_start_locked(sc); + + callout_reset(&sc->stat_ch, hz, awg_tick, sc); +} + +/* Bit Reversal - http://aggregate.org/MAGIC/#Bit%20Reversal */ +static uint32_t +bitrev32(uint32_t x) +{ + x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1)); + x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2)); + x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4)); + x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8)); + + return (x >> 16) | (x << 16); +} + +static void +awg_setup_rxfilter(struct awg_softc *sc) +{ + uint32_t val, crc, hashreg, hashbit, hash[2], machi, maclo; + int mc_count, mcnt, i; + uint8_t *eaddr, *mta; + if_t ifp; + + AWG_ASSERT_LOCKED(sc); + + ifp = sc->ifp; + val = 0; + hash[0] = hash[1] = 0; + + mc_count = if_multiaddr_count(ifp, -1); + + if (if_getflags(ifp) & IFF_PROMISC) + val |= DIS_ADDR_FILTER; + else if (if_getflags(ifp) & IFF_ALLMULTI) { + val |= RX_ALL_MULTICAST; + hash[0] = hash[1] = ~0; + } else if (mc_count > 0) { + val |= HASH_MULTICAST; + + mta = malloc(sizeof(unsigned char) * ETHER_ADDR_LEN * mc_count, + M_DEVBUF, M_NOWAIT); + if (mta == NULL) { + if_printf(ifp, + "failed to allocate temporary multicast list\n"); + return; + } + + if_multiaddr_array(ifp, mta, &mcnt, mc_count); + for (i = 0; i < mcnt; i++) { + crc = ether_crc32_le(mta + (i * ETHER_ADDR_LEN), + ETHER_ADDR_LEN) & 0x7f; + crc = bitrev32(~crc) >> 26; + hashreg = (crc >> 5); + hashbit = (crc & 0x1f); + hash[hashreg] |= (1 << hashbit); + } + + free(mta, M_DEVBUF); + } + + /* Write our unicast address */ + eaddr = IF_LLADDR(ifp); + machi = (eaddr[5] << 8) | eaddr[4]; + maclo = (eaddr[3] << 24) | (eaddr[2] << 16) | (eaddr[1] << 8) | + (eaddr[0] << 0); + WR4(sc, EMAC_ADDR_HIGH(0), machi); + WR4(sc, EMAC_ADDR_LOW(0), maclo); + + /* Multicast hash filters */ + WR4(sc, EMAC_RX_HASH_0, hash[1]); + WR4(sc, EMAC_RX_HASH_1, hash[0]); + + /* RX frame filter config */ + WR4(sc, EMAC_RX_FRM_FLT, val); +} + +static void +awg_init_locked(struct awg_softc *sc) +{ + struct mii_data *mii; + uint32_t val; + if_t ifp; + + mii = device_get_softc(sc->miibus); + ifp = sc->ifp; + + AWG_ASSERT_LOCKED(sc); + + if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) + return; + + awg_setup_rxfilter(sc); + + /* Configure DMA burst length and priorities */ + val = awg_burst_len << BASIC_CTL_BURST_LEN_SHIFT; + if (awg_rx_tx_pri) + val |= BASIC_CTL_RX_TX_PRI; + WR4(sc, EMAC_BASIC_CTL_1, val); + + /* Enable interrupts */ + WR4(sc, EMAC_INT_EN, RX_INT_EN | TX_INT_EN | TX_BUF_UA_INT_EN); + + /* Enable transmit DMA */ + val = RD4(sc, EMAC_TX_CTL_1); + WR4(sc, EMAC_TX_CTL_1, val | TX_DMA_EN | TX_MD); + + /* Enable receive DMA */ + val = RD4(sc, EMAC_RX_CTL_1); + WR4(sc, EMAC_RX_CTL_1, val | RX_DMA_EN | RX_MD); + + /* Enable transmitter */ + val = RD4(sc, EMAC_TX_CTL_0); + WR4(sc, EMAC_TX_CTL_0, val | TX_EN); + + /* Enable receiver */ + val = RD4(sc, EMAC_RX_CTL_0); + WR4(sc, EMAC_RX_CTL_0, val | RX_EN | CHECK_CRC); + + if_setdrvflagbits(ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE); + + mii_mediachg(mii); + callout_reset(&sc->stat_ch, hz, awg_tick, sc); +} + +static void +awg_init(void *softc) +{ + struct awg_softc *sc; + + sc = softc; + + AWG_LOCK(sc); + awg_init_locked(sc); + AWG_UNLOCK(sc); +} + +static void +awg_stop(struct awg_softc *sc) +{ + if_t ifp; + uint32_t val; + + AWG_ASSERT_LOCKED(sc); + + ifp = sc->ifp; + + callout_stop(&sc->stat_ch); + + /* Stop transmit DMA and flush data in the TX FIFO */ + val = RD4(sc, EMAC_TX_CTL_1); + val &= ~TX_DMA_EN; + val |= FLUSH_TX_FIFO; + WR4(sc, EMAC_TX_CTL_1, val); + + /* Disable transmitter */ + val = RD4(sc, EMAC_TX_CTL_0); + WR4(sc, EMAC_TX_CTL_0, val & ~TX_EN); + + /* Disable receiver */ + val = RD4(sc, EMAC_RX_CTL_0); + WR4(sc, EMAC_RX_CTL_0, val & ~RX_EN); + + /* Disable interrupts */ + WR4(sc, EMAC_INT_EN, 0); + + /* Disable transmit DMA */ + val = RD4(sc, EMAC_TX_CTL_1); + WR4(sc, EMAC_TX_CTL_1, val & ~TX_DMA_EN); + + /* Disable receive DMA */ + val = RD4(sc, EMAC_RX_CTL_1); + WR4(sc, EMAC_RX_CTL_1, val & ~RX_DMA_EN); + + sc->link = 0; + + if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING | IFF_DRV_OACTIVE); +} + +static void +awg_rxintr(struct awg_softc *sc) +{ + if_t ifp; + struct mbuf *m, *m0; + int error, index, len; + uint32_t status; + + ifp = sc->ifp; + + bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + for (index = sc->rx.cur; ; index = RX_NEXT(index)) { + status = le32toh(sc->rx.desc_ring[index].status); + if ((status & RX_DESC_CTL) != 0) + break; + + bus_dmamap_sync(sc->rx.buf_tag, sc->rx.buf_map[index].map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->rx.buf_tag, sc->rx.buf_map[index].map); + + len = (status & RX_FRM_LEN) >> RX_FRM_LEN_SHIFT; + if (len != 0) { + m = sc->rx.buf_map[index].mbuf; + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = len; + m->m_len = len; + if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + + if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0 && + (status & RX_FRM_TYPE) != 0) { + m->m_pkthdr.csum_flags = CSUM_IP_CHECKED; + if ((status & RX_HEADER_ERR) == 0) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; + if ((status & RX_PAYLOAD_ERR) == 0) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID | CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } + + AWG_UNLOCK(sc); + if_input(ifp, m); + AWG_LOCK(sc); + } + + if ((m0 = awg_alloc_mbufcl(sc)) != NULL) { + error = awg_setup_rxbuf(sc, index, m0); + if (error != 0) { + /* XXX hole in RX ring */ + } + } else + if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); + } + + if (index != sc->rx.cur) { + bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, + BUS_DMASYNC_PREWRITE); + } + + sc->rx.cur = index; +} + +static void +awg_txintr(struct awg_softc *sc) +{ + struct awg_bufmap *bmap; + struct emac_desc *desc; + uint32_t status; + if_t ifp; + int i; + + AWG_ASSERT_LOCKED(sc); + + bus_dmamap_sync(sc->tx.desc_tag, sc->tx.desc_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + + ifp = sc->ifp; + for (i = sc->tx.next; sc->tx.queued > 0; i = TX_NEXT(i)) { + desc = &sc->tx.desc_ring[i]; + status = le32toh(desc->status); + if ((status & TX_DESC_CTL) != 0) + break; + bmap = &sc->tx.buf_map[i]; + if (bmap->mbuf != NULL) { + bus_dmamap_sync(sc->tx.buf_tag, bmap->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->tx.buf_tag, bmap->map); + m_freem(bmap->mbuf); + bmap->mbuf = NULL; + } + awg_setup_txdesc(sc, i, 0, 0, 0); + if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); + if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + } + + sc->tx.next = i; + + bus_dmamap_sync(sc->tx.desc_tag, sc->tx.desc_map, + BUS_DMASYNC_PREWRITE); +} + +static void +awg_intr(void *arg) +{ + struct awg_softc *sc; + uint32_t val; + + sc = arg; + + AWG_LOCK(sc); + val = RD4(sc, EMAC_INT_STA); + WR4(sc, EMAC_INT_STA, val); + + if (val & RX_INT) + awg_rxintr(sc); + + if (val & (TX_INT|TX_BUF_UA_INT)) { + awg_txintr(sc); + if (!if_sendq_empty(sc->ifp)) + awg_start_locked(sc); + } + + AWG_UNLOCK(sc); +} + +static int +awg_ioctl(if_t ifp, u_long cmd, caddr_t data) +{ + struct awg_softc *sc; + struct mii_data *mii; + struct ifreq *ifr; + int flags, mask, error; + + sc = if_getsoftc(ifp); + mii = device_get_softc(sc->miibus); + ifr = (struct ifreq *)data; + error = 0; + + switch (cmd) { + case SIOCSIFFLAGS: + AWG_LOCK(sc); + if (if_getflags(ifp) & IFF_UP) { + if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { + flags = if_getflags(ifp) ^ sc->if_flags; + if ((flags & (IFF_PROMISC|IFF_ALLMULTI)) != 0) + awg_setup_rxfilter(sc); + } else + awg_init_locked(sc); + } else { + if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) + awg_stop(sc); + } + sc->if_flags = if_getflags(ifp); + AWG_UNLOCK(sc); + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { + AWG_LOCK(sc); + awg_setup_rxfilter(sc); + AWG_UNLOCK(sc); + } + break; + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); + break; + case SIOCSIFCAP: + mask = ifr->ifr_reqcap ^ if_getcapenable(ifp); + if (mask & IFCAP_VLAN_MTU) + if_togglecapenable(ifp, IFCAP_VLAN_MTU); + if (mask & IFCAP_RXCSUM) + if_togglecapenable(ifp, IFCAP_RXCSUM); + if (mask & IFCAP_TXCSUM) + if_togglecapenable(ifp, IFCAP_TXCSUM); + if ((if_getcapenable(ifp) & (IFCAP_RXCSUM|IFCAP_TXCSUM)) != 0) + if_sethwassistbits(ifp, CSUM_IP, 0); + else + if_sethwassistbits(ifp, 0, CSUM_IP); + break; + default: + error = ether_ioctl(ifp, cmd, data); + break; + } + + return (error); +} + +static int +awg_setup_extres(device_t dev) +{ + struct awg_softc *sc; + hwreset_t rst_ahb; + clk_t clk_ahb, clk_tx, clk_tx_parent; + regulator_t reg; + const char *tx_parent_name; + char *phy_type; + phandle_t node; + uint64_t freq; + int error, div; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(dev); + rst_ahb = NULL; + clk_ahb = NULL; + clk_tx = NULL; + clk_tx_parent = NULL; + reg = NULL; + phy_type = NULL; + + /* Get AHB clock and reset resources */ + error = hwreset_get_by_ofw_name(dev, "ahb", &rst_ahb); + if (error != 0) { + device_printf(dev, "cannot get ahb reset\n"); + goto fail; + } + error = clk_get_by_ofw_name(dev, "ahb", &clk_ahb); + if (error != 0) { + device_printf(dev, "cannot get ahb clock\n"); + goto fail; + } + + /* Configure PHY for MII or RGMII mode */ + if (OF_getprop_alloc(node, "phy-mode", 1, (void **)&phy_type)) { + if (bootverbose) + device_printf(dev, "PHY type: %s\n", phy_type); + + if (strcmp(phy_type, "rgmii") == 0) + tx_parent_name = "emac_int_tx"; + else + tx_parent_name = "mii_phy_tx"; + free(phy_type, M_OFWPROP); + + /* Get the TX clock */ + error = clk_get_by_ofw_name(dev, "tx", &clk_tx); + if (error != 0) { + device_printf(dev, "cannot get tx clock\n"); + goto fail; + } + + /* Find the desired parent clock based on phy-mode property */ + error = clk_get_by_name(dev, tx_parent_name, &clk_tx_parent); + if (error != 0) { + device_printf(dev, "cannot get clock '%s'\n", + tx_parent_name); + goto fail; + } + + /* Set TX clock parent */ + error = clk_set_parent_by_clk(clk_tx, clk_tx_parent); + if (error != 0) { + device_printf(dev, "cannot set tx clock parent\n"); + goto fail; + } + + /* Enable TX clock */ + error = clk_enable(clk_tx); + if (error != 0) { + device_printf(dev, "cannot enable tx clock\n"); + goto fail; + } + } + + /* Enable AHB clock */ + error = clk_enable(clk_ahb); + if (error != 0) { + device_printf(dev, "cannot enable ahb clock\n"); + goto fail; + } + + /* De-assert reset */ + error = hwreset_deassert(rst_ahb); + if (error != 0) { + device_printf(dev, "cannot de-assert ahb reset\n"); + goto fail; + } + + /* Enable PHY regulator if applicable */ + if (regulator_get_by_ofw_property(dev, "phy-supply", ®) == 0) { + error = regulator_enable(reg); + if (error != 0) { + device_printf(dev, "cannot enable PHY regulator\n"); + goto fail; + } + } + + /* Determine MDC clock divide ratio based on AHB clock */ + error = clk_get_freq(clk_ahb, &freq); + if (error != 0) { + device_printf(dev, "cannot get AHB clock frequency\n"); + goto fail; + } + div = freq / MDIO_FREQ; + if (div <= 16) + sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_16; + else if (div <= 32) + sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_32; + else if (div <= 64) + sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_64; + else if (div <= 128) + sc->mdc_div_ratio_m = MDC_DIV_RATIO_M_128; + else { + device_printf(dev, "cannot determine MDC clock divide ratio\n"); + error = ENXIO; + goto fail; + } + + if (bootverbose) + device_printf(dev, "AHB frequency %llu Hz, MDC div: 0x%x\n", + freq, sc->mdc_div_ratio_m); + + return (0); + +fail: + free(phy_type, M_OFWPROP); + + if (reg != NULL) + regulator_release(reg); + if (clk_tx_parent != NULL) + clk_release(clk_tx_parent); + if (clk_tx != NULL) + clk_release(clk_tx); + if (clk_ahb != NULL) + clk_release(clk_ahb); + if (rst_ahb != NULL) + hwreset_release(rst_ahb); + return (error); +} + +static void +awg_get_eaddr(device_t dev, uint8_t *eaddr) +{ + struct awg_softc *sc; + uint32_t maclo, machi, rnd; + + sc = device_get_softc(dev); + + machi = RD4(sc, EMAC_ADDR_HIGH(0)) & 0xffff; + maclo = RD4(sc, EMAC_ADDR_LOW(0)); + + if (maclo == 0xffffffff && machi == 0xffff) { + /* MAC address in hardware is invalid, create one */ + rnd = arc4random(); + maclo = 0x00f2 | (rnd & 0xffff0000); + machi = rnd & 0xffff; + } + + eaddr[0] = maclo & 0xff; + eaddr[1] = (maclo >> 8) & 0xff; + eaddr[2] = (maclo >> 16) & 0xff; + eaddr[3] = (maclo >> 24) & 0xff; + eaddr[4] = machi & 0xff; + eaddr[5] = (machi >> 8) & 0xff; +} + +#ifdef AWG_DEBUG +static void +awg_dump_regs(device_t dev) +{ + static const struct { + const char *name; + u_int reg; + } regs[] = { + { "BASIC_CTL_0", EMAC_BASIC_CTL_0 }, + { "BASIC_CTL_1", EMAC_BASIC_CTL_1 }, + { "INT_STA", EMAC_INT_STA }, + { "INT_EN", EMAC_INT_EN }, + { "TX_CTL_0", EMAC_TX_CTL_0 }, + { "TX_CTL_1", EMAC_TX_CTL_1 }, + { "TX_FLOW_CTL", EMAC_TX_FLOW_CTL }, + { "TX_DMA_LIST", EMAC_TX_DMA_LIST }, + { "RX_CTL_0", EMAC_RX_CTL_0 }, + { "RX_CTL_1", EMAC_RX_CTL_1 }, + { "RX_DMA_LIST", EMAC_RX_DMA_LIST }, + { "RX_FRM_FLT", EMAC_RX_FRM_FLT }, + { "RX_HASH_0", EMAC_RX_HASH_0 }, + { "RX_HASH_1", EMAC_RX_HASH_1 }, + { "MII_CMD", EMAC_MII_CMD }, + { "ADDR_HIGH0", EMAC_ADDR_HIGH(0) }, + { "ADDR_LOW0", EMAC_ADDR_LOW(0) }, + { "TX_DMA_STA", EMAC_TX_DMA_STA }, + { "TX_DMA_CUR_DESC", EMAC_TX_DMA_CUR_DESC }, + { "TX_DMA_CUR_BUF", EMAC_TX_DMA_CUR_BUF }, + { "RX_DMA_STA", EMAC_RX_DMA_STA }, + { "RX_DMA_CUR_DESC", EMAC_RX_DMA_CUR_DESC }, + { "RX_DMA_CUR_BUF", EMAC_RX_DMA_CUR_BUF }, + { "RGMII_STA", EMAC_RGMII_STA }, + }; + struct awg_softc *sc; + unsigned int n; + + sc = device_get_softc(dev); + + for (n = 0; n < nitems(regs); n++) + device_printf(dev, " %-20s %08x\n", regs[n].name, + RD4(sc, regs[n].reg)); +} +#endif + +static int +awg_reset(device_t dev) +{ + struct awg_softc *sc; + int retry; + + sc = device_get_softc(dev); + + /* Soft reset all registers and logic */ + WR4(sc, EMAC_BASIC_CTL_1, BASIC_CTL_SOFT_RST); + + /* Wait for soft reset bit to self-clear */ + for (retry = SOFT_RST_RETRY; retry > 0; retry--) { + if ((RD4(sc, EMAC_BASIC_CTL_1) & BASIC_CTL_SOFT_RST) == 0) + break; + DELAY(10); + } + if (retry == 0) { + device_printf(dev, "soft reset timed out\n"); +#ifdef AWG_DEBUG + awg_dump_regs(dev); +#endif + return (ETIMEDOUT); + } + + return (0); +} + +static void +awg_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + if (error != 0) + return; + *(bus_addr_t *)arg = segs[0].ds_addr; +} + +static int +awg_setup_dma(device_t dev) +{ + struct awg_softc *sc; + struct mbuf *m; + int error, i; + + sc = device_get_softc(dev); + + /* Setup TX ring */ + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent tag */ + DESC_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + TX_DESC_SIZE, 1, /* maxsize, nsegs */ + TX_DESC_SIZE, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->tx.desc_tag); + if (error != 0) { + device_printf(dev, "cannot create TX descriptor ring tag\n"); + return (error); + } + + error = bus_dmamem_alloc(sc->tx.desc_tag, (void **)&sc->tx.desc_ring, + BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->tx.desc_map); + if (error != 0) { + device_printf(dev, "cannot allocate TX descriptor ring\n"); + return (error); + } + + error = bus_dmamap_load(sc->tx.desc_tag, sc->tx.desc_map, + sc->tx.desc_ring, TX_DESC_SIZE, awg_dmamap_cb, + &sc->tx.desc_ring_paddr, 0); + if (error != 0) { + device_printf(dev, "cannot load TX descriptor ring\n"); + return (error); + } + + for (i = 0; i < TX_DESC_COUNT; i++) + sc->tx.desc_ring[i].next = + htole32(sc->tx.desc_ring_paddr + DESC_OFF(TX_NEXT(i))); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent tag */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MCLBYTES, TX_MAX_SEGS, /* maxsize, nsegs */ + MCLBYTES, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->tx.buf_tag); + if (error != 0) { + device_printf(dev, "cannot create TX buffer tag\n"); + return (error); + } + + sc->tx.queued = TX_DESC_COUNT; + for (i = 0; i < TX_DESC_COUNT; i++) { + error = bus_dmamap_create(sc->tx.buf_tag, 0, + &sc->tx.buf_map[i].map); + if (error != 0) { + device_printf(dev, "cannot create TX buffer map\n"); + return (error); + } + awg_setup_txdesc(sc, i, 0, 0, 0); + } + + /* Setup RX ring */ + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent tag */ + DESC_ALIGN, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + RX_DESC_SIZE, 1, /* maxsize, nsegs */ + RX_DESC_SIZE, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->rx.desc_tag); + if (error != 0) { + device_printf(dev, "cannot create RX descriptor ring tag\n"); + return (error); + } + + error = bus_dmamem_alloc(sc->rx.desc_tag, (void **)&sc->rx.desc_ring, + BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx.desc_map); + if (error != 0) { + device_printf(dev, "cannot allocate RX descriptor ring\n"); + return (error); + } + + error = bus_dmamap_load(sc->rx.desc_tag, sc->rx.desc_map, + sc->rx.desc_ring, RX_DESC_SIZE, awg_dmamap_cb, + &sc->rx.desc_ring_paddr, 0); + if (error != 0) { + device_printf(dev, "cannot load RX descriptor ring\n"); + return (error); + } + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* Parent tag */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MCLBYTES, 1, /* maxsize, nsegs */ + MCLBYTES, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->rx.buf_tag); + if (error != 0) { + device_printf(dev, "cannot create RX buffer tag\n"); + return (error); + } + + for (i = 0; i < RX_DESC_COUNT; i++) { + error = bus_dmamap_create(sc->rx.buf_tag, 0, + &sc->rx.buf_map[i].map); + if (error != 0) { + device_printf(dev, "cannot create RX buffer map\n"); + return (error); + } + if ((m = awg_alloc_mbufcl(sc)) == NULL) { + device_printf(dev, "cannot allocate RX mbuf\n"); + return (ENOMEM); + } + error = awg_setup_rxbuf(sc, i, m); + if (error != 0) { + device_printf(dev, "cannot create RX buffer\n"); + return (error); + } + } + bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, + BUS_DMASYNC_PREWRITE); + + /* Write transmit and receive descriptor base address registers */ + WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr); + WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr); + + return (0); +} + +static int +awg_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Allwinner Gigabit Ethernet"); + return (BUS_PROBE_DEFAULT); +} + +static int +awg_attach(device_t dev) +{ + uint8_t eaddr[ETHER_ADDR_LEN]; + struct awg_softc *sc; + phandle_t node; + int error; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(dev); + + if (bus_alloc_resources(dev, awg_spec, sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + mtx_init(&sc->mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); + callout_init_mtx(&sc->stat_ch, &sc->mtx, 0); + TASK_INIT(&sc->link_task, 0, awg_link_task, sc); + + /* Setup clocks and regulators */ + error = awg_setup_extres(dev); + if (error != 0) + return (error); + + /* Read MAC address before resetting the chip */ + awg_get_eaddr(dev, eaddr); + + /* Soft reset EMAC core */ + error = awg_reset(dev); + if (error != 0) + return (error); + + /* Setup DMA descriptors */ + error = awg_setup_dma(dev); + if (error != 0) + return (error); + + /* Install interrupt handler */ + error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE, + NULL, awg_intr, sc, &sc->ih); + if (error != 0) { + device_printf(dev, "cannot setup interrupt handler\n"); + return (error); + } + + /* Setup ethernet interface */ + sc->ifp = if_alloc(IFT_ETHER); + if_setsoftc(sc->ifp, sc); + if_initname(sc->ifp, device_get_name(dev), device_get_unit(dev)); + if_setflags(sc->ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); + if_setstartfn(sc->ifp, awg_start); + if_setioctlfn(sc->ifp, awg_ioctl); + if_setinitfn(sc->ifp, awg_init); + if_setsendqlen(sc->ifp, TX_DESC_COUNT - 1); + if_setsendqready(sc->ifp); + if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP); + if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM); + if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp)); + + /* Attach MII driver */ + error = mii_attach(dev, &sc->miibus, sc->ifp, awg_media_change, + awg_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, + MIIF_DOPAUSE); + if (error != 0) { + device_printf(dev, "cannot attach PHY\n"); + return (error); + } + + /* Attach ethernet interface */ + ether_ifattach(sc->ifp, eaddr); + + return (0); +} + +static device_method_t awg_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, awg_probe), + DEVMETHOD(device_attach, awg_attach), + + /* MII interface */ + DEVMETHOD(miibus_readreg, awg_miibus_readreg), + DEVMETHOD(miibus_writereg, awg_miibus_writereg), + DEVMETHOD(miibus_statchg, awg_miibus_statchg), + + DEVMETHOD_END +}; + +static driver_t awg_driver = { + "awg", + awg_methods, + sizeof(struct awg_softc), +}; + +static devclass_t awg_devclass; + +DRIVER_MODULE(awg, simplebus, awg_driver, awg_devclass, 0, 0); +DRIVER_MODULE(miibus, awg, miibus_driver, miibus_devclass, 0, 0); + +MODULE_DEPEND(awg, ether, 1, 1, 1); +MODULE_DEPEND(awg, miibus, 1, 1, 1); diff --git a/sys/arm/allwinner/if_awgreg.h b/sys/arm/allwinner/if_awgreg.h new file mode 100644 index 0000000..53a15c1 --- /dev/null +++ b/sys/arm/allwinner/if_awgreg.h @@ -0,0 +1,181 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 ``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. + * + * $FreeBSD$ + */ + +/* + * Allwinner Gigabit Ethernet + */ + +#ifndef __IF_AWGREG_H__ +#define __IF_AWGREG_H__ + +#define EMAC_BASIC_CTL_0 0x00 +#define BASIC_CTL_SPEED (0x3 << 2) +#define BASIC_CTL_SPEED_SHIFT 2 +#define BASIC_CTL_SPEED_1000 0 +#define BASIC_CTL_SPEED_10 2 +#define BASIC_CTL_SPEED_100 3 +#define BASIC_CTL_LOOPBACK (1 << 1) +#define BASIC_CTL_DUPLEX (1 << 0) +#define EMAC_BASIC_CTL_1 0x04 +#define BASIC_CTL_BURST_LEN (0x3f << 24) +#define BASIC_CTL_BURST_LEN_SHIFT 24 +#define BASIC_CTL_RX_TX_PRI (1 << 1) +#define BASIC_CTL_SOFT_RST (1 << 0) +#define EMAC_INT_STA 0x08 +#define RX_BUF_UA_INT (1 << 10) +#define RX_INT (1 << 8) +#define TX_UNDERFLOW_INT (1 << 4) +#define TX_BUF_UA_INT (1 << 2) +#define TX_DMA_STOPPED_INT (1 << 1) +#define TX_INT (1 << 0) +#define EMAC_INT_EN 0x0c +#define RX_BUF_UA_INT_EN (1 << 10) +#define RX_INT_EN (1 << 8) +#define TX_UNDERFLOW_INT_EN (1 << 4) +#define TX_BUF_UA_INT_EN (1 << 2) +#define TX_DMA_STOPPED_INT_EN (1 << 1) +#define TX_INT_EN (1 << 0) +#define EMAC_TX_CTL_0 0x10 +#define TX_EN (1 << 31) +#define EMAC_TX_CTL_1 0x14 +#define TX_DMA_START (1 << 31) +#define TX_DMA_EN (1 << 30) +#define TX_MD (1 << 1) +#define FLUSH_TX_FIFO (1 << 0) +#define EMAC_TX_FLOW_CTL 0x1c +#define PAUSE_TIME (0xffff << 4) +#define PAUSE_TIME_SHIFT 4 +#define TX_FLOW_CTL_EN (1 << 0) +#define EMAC_TX_DMA_LIST 0x20 +#define EMAC_RX_CTL_0 0x24 +#define RX_EN (1 << 31) +#define JUMBO_FRM_EN (1 << 29) +#define STRIP_FCS (1 << 28) +#define CHECK_CRC (1 << 27) +#define RX_FLOW_CTL_EN (1 << 16) +#define EMAC_RX_CTL_1 0x28 +#define RX_DMA_START (1 << 31) +#define RX_DMA_EN (1 << 30) +#define RX_MD (1 << 1) +#define EMAC_RX_DMA_LIST 0x34 +#define EMAC_RX_FRM_FLT 0x38 +#define DIS_ADDR_FILTER (1 << 31) +#define DIS_BROADCAST (1 << 17) +#define RX_ALL_MULTICAST (1 << 16) +#define CTL_FRM_FILTER (0x3 << 12) +#define CTL_FRM_FILTER_SHIFT 12 +#define HASH_MULTICAST (1 << 9) +#define HASH_UNICAST (1 << 8) +#define SA_FILTER_EN (1 << 6) +#define SA_INV_FILTER (1 << 5) +#define DA_INV_FILTER (1 << 4) +#define FLT_MD (1 << 1) +#define RX_ALL (1 << 0) +#define EMAC_RX_HASH_0 0x40 +#define EMAC_RX_HASH_1 0x44 +#define EMAC_MII_CMD 0x48 +#define MDC_DIV_RATIO_M (0x7 << 20) +#define MDC_DIV_RATIO_M_16 0 +#define MDC_DIV_RATIO_M_32 1 +#define MDC_DIV_RATIO_M_64 2 +#define MDC_DIV_RATIO_M_128 3 +#define MDC_DIV_RATIO_M_SHIFT 20 +#define PHY_ADDR (0x1f << 12) +#define PHY_ADDR_SHIFT 12 +#define PHY_REG_ADDR (0x1f << 4) +#define PHY_REG_ADDR_SHIFT 4 +#define MII_WR (1 << 1) +#define MII_BUSY (1 << 0) +#define EMAC_MII_DATA 0x4c +#define EMAC_ADDR_HIGH(n) (0x50 + (n) * 8) +#define EMAC_ADDR_LOW(n) (0x54 + (n) * 8) +#define EMAC_TX_DMA_STA 0x80 +#define EMAC_TX_DMA_CUR_DESC 0x84 +#define EMAC_TX_DMA_CUR_BUF 0x88 +#define EMAC_RX_DMA_STA 0xc0 +#define EMAC_RX_DMA_CUR_DESC 0xc4 +#define EMAC_RX_DMA_CUR_BUF 0xc8 +#define EMAC_RGMII_STA 0xd0 + +struct emac_desc { + uint32_t status; +/* Transmit */ +#define TX_DESC_CTL (1 << 31) +#define TX_HEADER_ERR (1 << 16) +#define TX_LENGTH_ERR (1 << 14) +#define TX_PAYLOAD_ERR (1 << 12) +#define TX_CRS_ERR (1 << 10) +#define TX_COL_ERR_0 (1 << 9) +#define TX_COL_ERR_1 (1 << 8) +#define TX_COL_CNT (0xf << 3) +#define TX_COL_CNT_SHIFT 3 +#define TX_DEFER_ERR (1 << 2) +#define TX_UNDERFLOW_ERR (1 << 1) +#define TX_DEFER (1 << 0) +/* Receive */ +#define RX_DESC_CTL (1 << 31) +#define RX_DAF_FAIL (1 << 30) +#define RX_FRM_LEN (0x3fff << 16) +#define RX_FRM_LEN_SHIFT 16 +#define RX_NO_ENOUGH_BUF_ERR (1 << 14) +#define RX_SAF_FAIL (1 << 13) +#define RX_OVERFLOW_ERR (1 << 11) +#define RX_FIR_DESC (1 << 9) +#define RX_LAST_DESC (1 << 8) +#define RX_HEADER_ERR (1 << 7) +#define RX_COL_ERR (1 << 6) +#define RX_FRM_TYPE (1 << 5) +#define RX_LENGTH_ERR (1 << 4) +#define RX_PHY_ERR (1 << 3) +#define RX_CRC_ERR (1 << 1) +#define RX_PAYLOAD_ERR (1 << 0) + + uint32_t size; +/* Transmit */ +#define TX_INT_CTL (1 << 31) +#define TX_LAST_DESC (1 << 30) +#define TX_FIR_DESC (1 << 29) +#define TX_CHECKSUM_CTL (0x3 << 27) +#define TX_CHECKSUM_CTL_IP 1 +#define TX_CHECKSUM_CTL_NO_PSE 2 +#define TX_CHECKSUM_CTL_FULL 3 +#define TX_CHECKSUM_CTL_SHIFT 27 +#define TX_CRC_CTL (1 << 26) +#define TX_BUF_SIZE (0xfff << 0) +#define TX_BUF_SIZE_SHIFT 0 +/* Receive */ +#define RX_INT_CTL (1 << 31) +#define RX_BUF_SIZE (0xfff << 0) +#define RX_BUF_SIZE_SHIFT 0 + + uint32_t addr; + + uint32_t next; +} __packed; + +#endif /* !__IF_AWGREG_H__ */ -- cgit v1.1 From 09b44517caee8dcc60f36ba481d3f9f47c6c17ec Mon Sep 17 00:00:00 2001 From: asomers Date: Wed, 4 May 2016 22:34:11 +0000 Subject: Improve performance and functionality of the bitstring(3) api Two new functions are provided, bit_ffs_at() and bit_ffc_at(), which allow for efficient searching of set or cleared bits starting from any bit offset within the bit string. Performance is improved by operating on longs instead of bytes and using ffsl() for searches within a long. ffsl() is a compiler builtin in both clang and gcc for most architectures, converting what was a brute force while loop search into a couple of instructions. All of the bitstring(3) API continues to be contained in the header file. Some of the functions are large enough that perhaps they should be uninlined and moved to a library, but that is beyond the scope of this commit. sys/sys/bitstring.h: Convert the majority of the existing bit string implementation from macros to inline functions. Properly protect the implementation from inadvertant macro expansion when included in a user's program by prefixing all private macros/functions and local variables with '_'. Add bit_ffs_at() and bit_ffc_at(). Implement bit_ffs() and bit_ffc() in terms of their "at" counterparts. Provide a kernel implementation of bit_alloc(), making the full API usable in the kernel. Improve code documenation. share/man/man3/bitstring.3: Add pre-exisiting API bit_ffc() to the synopsis. Document new APIs. Document the initialization state of the bit strings allocated/declared by bit_alloc() and bit_decl(). Correct documentation for bitstr_size(). The original code comments indicate the size is in bytes, not "elements of bitstr_t". The new implementation follows this lead. Only hastd assumed "elements" rather than bytes and it has been corrected. etc/mtree/BSD.tests.dist: tests/sys/Makefile: tests/sys/sys/Makefile: tests/sys/sys/bitstring.c: Add tests for all existing and new functionality. include/bitstring.h Include all headers needed by sys/bitstring.h lib/libbluetooth/bluetooth.h: usr.sbin/bluetooth/hccontrol/le.c: Include bitstring.h instead of sys/bitstring.h. sbin/hastd/activemap.c: Correct usage of bitstr_size(). sys/dev/xen/blkback/blkback.c Use new bit_alloc. sys/kern/subr_unit.c: Remove hard-coded assumption that sizeof(bitstr_t) is 1. Get rid of unrb.busy, which caches the number of bits set in unrb.map. When INVARIANTS are disabled, nothing needs to know that information. callapse_unr can be adapted to use bit_ffs and bit_ffc instead. Eliminating unrb.busy saves memory, simplifies the code, and provides a slight speedup when INVARIANTS are disabled. sys/net/flowtable.c: Use the new kernel implementation of bit-alloc, instead of hacking the old libc-dependent macro. sys/sys/param.h Update __FreeBSD_version to indicate availability of new API Submitted by: gibbs, asomers Reviewed by: gibbs, ngie MFC after: 4 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D6004 --- sys/dev/xen/blkback/blkback.c | 12 +- sys/kern/subr_unit.c | 79 ++++++----- sys/net/flowtable.c | 9 +- sys/sys/bitstring.h | 321 ++++++++++++++++++++++++++++-------------- sys/sys/param.h | 2 +- 5 files changed, 264 insertions(+), 159 deletions(-) (limited to 'sys') diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index 97068a1..8729b45 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -977,8 +977,8 @@ xbb_get_gntaddr(struct xbb_xen_reqlist *reqlist, int pagenr, int sector) static uint8_t * xbb_get_kva(struct xbb_softc *xbb, int nr_pages) { - intptr_t first_clear; - intptr_t num_clear; + int first_clear; + int num_clear; uint8_t *free_kva; int i; @@ -1027,7 +1027,7 @@ xbb_get_kva(struct xbb_softc *xbb, int nr_pages) first_clear + nr_pages - 1); free_kva = xbb->kva + - (uint8_t *)(first_clear * PAGE_SIZE); + (uint8_t *)((intptr_t)first_clear * PAGE_SIZE); KASSERT(free_kva >= (uint8_t *)xbb->kva && free_kva + (nr_pages * PAGE_SIZE) <= @@ -2967,10 +2967,6 @@ xbb_connect_ring(struct xbb_softc *xbb) return 0; } -/* Needed to make bit_alloc() macro work */ -#define calloc(count, size) malloc((count)*(size), M_XENBLOCKBACK, \ - M_NOWAIT|M_ZERO); - /** * Size KVA and pseudo-physical address allocations based on negotiated * values for the size and number of I/O requests, and the size of our @@ -2989,7 +2985,7 @@ xbb_alloc_communication_mem(struct xbb_softc *xbb) xbb->kva_size = xbb->reqlist_kva_size + (xbb->ring_config.ring_pages * PAGE_SIZE); - xbb->kva_free = bit_alloc(xbb->reqlist_kva_pages); + xbb->kva_free = bit_alloc(xbb->reqlist_kva_pages, M_XENBLOCKBACK, M_NOWAIT); if (xbb->kva_free == NULL) return (ENOMEM); diff --git a/sys/kern/subr_unit.c b/sys/kern/subr_unit.c index 8283550..f39f001 100644 --- a/sys/kern/subr_unit.c +++ b/sys/kern/subr_unit.c @@ -67,13 +67,13 @@ * N is the number of the highest unit allocated. */ +#include #include #include #ifdef _KERNEL #include -#include #include #include #include @@ -169,7 +169,7 @@ mtx_assert(struct mtx *mp, int flag) * element: * If ptr is NULL, it represents a run of free items. * If ptr points to the unrhdr it represents a run of allocated items. - * Otherwise it points to an bitstring of allocated items. + * Otherwise it points to a bitstring of allocated items. * * For runs the len field is the length of the run. * For bitmaps the len field represents the number of allocated items. @@ -183,14 +183,33 @@ struct unr { }; struct unrb { - u_char busy; - bitstr_t map[sizeof(struct unr) - 1]; + bitstr_t map[sizeof(struct unr) / sizeof(bitstr_t)]; }; -CTASSERT(sizeof(struct unr) == sizeof(struct unrb)); +CTASSERT((sizeof(struct unr) % sizeof(bitstr_t)) == 0); + +/* Number of bits we can store in the bitmap */ +#define NBITS (8 * sizeof(((struct unrb*)NULL)->map)) + +/* Is the unrb empty in at least the first len bits? */ +static inline bool +ub_empty(struct unrb *ub, int len) { + int first_set; + + bit_ffs(ub->map, len, &first_set); + return (first_set == -1); +} + +/* Is the unrb full? That is, is the number of set elements equal to len? */ +static inline bool +ub_full(struct unrb *ub, int len) +{ + int first_clear; + + bit_ffc(ub->map, len, &first_clear); + return (first_clear == -1); +} -/* Number of bits in the bitmap */ -#define NBITS ((int)sizeof(((struct unrb *)NULL)->map) * 8) #if defined(DIAGNOSTIC) || !defined(_KERNEL) /* @@ -214,16 +233,13 @@ check_unrhdr(struct unrhdr *uh, int line) if (up->ptr != uh && up->ptr != NULL) { ub = up->ptr; KASSERT (up->len <= NBITS, - ("UNR inconsistency: len %u max %d (line %d)\n", + ("UNR inconsistency: len %u max %zd (line %d)\n", up->len, NBITS, line)); z++; w = 0; for (x = 0; x < up->len; x++) if (bit_test(ub->map, x)) w++; - KASSERT (w == ub->busy, - ("UNR inconsistency: busy %u found %u (line %d)\n", - ub->busy, w, line)); y += w; } else if (up->ptr != NULL) y += up->len; @@ -239,7 +255,7 @@ check_unrhdr(struct unrhdr *uh, int line) #else static __inline void -check_unrhdr(struct unrhdr *uh, int line) +check_unrhdr(struct unrhdr *uh __unused, int line __unused) { } @@ -417,32 +433,24 @@ optimize_unr(struct unrhdr *uh) a = us->len; l = us->ptr == uh ? 1 : 0; ub = (void *)us; - ub->busy = 0; - if (l) { + bit_nclear(ub->map, 0, NBITS - 1); + if (l) bit_nset(ub->map, 0, a); - ub->busy += a; - } else { - bit_nclear(ub->map, 0, a); - } if (!is_bitmap(uh, uf)) { - if (uf->ptr == NULL) { + if (uf->ptr == NULL) bit_nclear(ub->map, a, a + uf->len - 1); - } else { + else bit_nset(ub->map, a, a + uf->len - 1); - ub->busy += uf->len; - } uf->ptr = ub; uf->len += a; us = uf; } else { ubf = uf->ptr; for (l = 0; l < uf->len; l++, a++) { - if (bit_test(ubf->map, l)) { + if (bit_test(ubf->map, l)) bit_set(ub->map, a); - ub->busy++; - } else { + else bit_clear(ub->map, a); - } } uf->len = a; delete_unr(uh, uf->ptr); @@ -464,19 +472,16 @@ optimize_unr(struct unrhdr *uh) delete_unr(uh, uf); } else if (uf->ptr == uh) { bit_nset(ub->map, us->len, us->len + uf->len - 1); - ub->busy += uf->len; us->len += uf->len; TAILQ_REMOVE(&uh->head, uf, list); delete_unr(uh, uf); } else { ubf = uf->ptr; for (l = 0; l < uf->len; l++, us->len++) { - if (bit_test(ubf->map, l)) { + if (bit_test(ubf->map, l)) bit_set(ub->map, us->len); - ub->busy++; - } else { + else bit_clear(ub->map, us->len); - } } TAILQ_REMOVE(&uh->head, uf, list); delete_unr(uh, ubf); @@ -499,10 +504,10 @@ collapse_unr(struct unrhdr *uh, struct unr *up) /* If bitmap is all set or clear, change it to runlength */ if (is_bitmap(uh, up)) { ub = up->ptr; - if (ub->busy == up->len) { + if (ub_full(ub, up->len)) { delete_unr(uh, up->ptr); up->ptr = uh; - } else if (ub->busy == 0) { + } else if (ub_empty(ub, up->len)) { delete_unr(uh, up->ptr); up->ptr = NULL; } @@ -600,11 +605,9 @@ alloc_unrl(struct unrhdr *uh) up->len--; } else { /* bitmap */ ub = up->ptr; - KASSERT(ub->busy < up->len, ("UNR bitmap confusion")); bit_ffc(ub->map, up->len, &y); KASSERT(y != -1, ("UNR corruption: No clear bit in bitmap.")); bit_set(ub->map, y); - ub->busy++; x += y; } uh->busy++; @@ -688,7 +691,6 @@ alloc_unr_specificl(struct unrhdr *uh, u_int item, void **p1, void **p2) ub = up->ptr; if (bit_test(ub->map, i) == 0) { bit_set(ub->map, i); - ub->busy++; goto done; } else return (-1); @@ -807,7 +809,6 @@ free_unrl(struct unrhdr *uh, u_int item, void **p1, void **p2) ("UNR: Freeing free item %d (bitmap)\n", item)); bit_clear(ub->map, item); uh->busy--; - ub->busy--; collapse_unr(uh, up); return; } @@ -905,7 +906,7 @@ print_unr(struct unrhdr *uh, struct unr *up) printf("alloc\n"); else { ub = up->ptr; - printf("bitmap(%d) [", ub->busy); + printf("bitmap ["); for (x = 0; x < up->len; x++) { if (bit_test(ub->map, x)) printf("#"); @@ -1025,7 +1026,7 @@ main(int argc, char **argv) printf("sizeof(struct unr) %zu\n", sizeof(struct unr)); printf("sizeof(struct unrb) %zu\n", sizeof(struct unrb)); printf("sizeof(struct unrhdr) %zu\n", sizeof(struct unrhdr)); - printf("NBITS %d\n", NBITS); + printf("NBITS %lu\n", NBITS); x = 1; for (m = 0; m < count * reps; m++) { j = random(); diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index f45a687..895b233 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -741,10 +741,6 @@ flowtable_lookup_common(struct flowtable *ft, uint32_t *key, int keylen, return (flowtable_insert(ft, hash, key, keylen, fibnum)); } -/* - * used by the bit_alloc macro - */ -#define calloc(count, size) malloc((count)*(size), M_FTABLE, M_WAITOK | M_ZERO) static void flowtable_alloc(struct flowtable *ft) { @@ -759,11 +755,10 @@ flowtable_alloc(struct flowtable *ft) bitstr_t **b; b = zpcpu_get_cpu(ft->ft_masks, i); - *b = bit_alloc(ft->ft_size); + *b = bit_alloc(ft->ft_size, M_FTABLE, M_WAITOK); } - ft->ft_tmpmask = bit_alloc(ft->ft_size); + ft->ft_tmpmask = bit_alloc(ft->ft_size, M_FTABLE, M_WAITOK); } -#undef calloc static void flowtable_free_stale(struct flowtable *ft, struct rtentry *rt, int maxidle) diff --git a/sys/sys/bitstring.h b/sys/sys/bitstring.h index 125ef51..a8d5652 100644 --- a/sys/sys/bitstring.h +++ b/sys/sys/bitstring.h @@ -29,118 +29,231 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Copyright (c) 2014 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * * $FreeBSD$ */ - #ifndef _SYS_BITSTRING_H_ #define _SYS_BITSTRING_H_ -typedef unsigned char bitstr_t; +#ifdef _KERNEL +#include +#include +#endif + +typedef unsigned long bitstr_t; + +/*---------------------- Private Implementation Details ----------------------*/ +#define _BITSTR_MASK (~0UL) +#define _BITSTR_BITS (sizeof(bitstr_t) * 8) -/* internal macros */ - /* byte of the bitstring bit is in */ -#define _bit_byte(bit) \ - ((bit) >> 3) +/* bitstr_t in bit string containing the bit. */ +static inline int +_bit_idx(int _bit) +{ + return (_bit / _BITSTR_BITS); +} - /* mask for the bit within its byte */ -#define _bit_mask(bit) \ - (1 << ((bit)&0x7)) +/* bit number within bitstr_t at _bit_idx(_bit). */ +static inline int +_bit_offset(int _bit) +{ + return (_bit % _BITSTR_BITS); +} -/* external macros */ - /* bytes in a bitstring of nbits bits */ -#define bitstr_size(nbits) \ - (((nbits) + 7) >> 3) +/* Mask for the bit within its long. */ +static inline bitstr_t +_bit_mask(int _bit) +{ + return (1UL << _bit_offset(_bit)); +} - /* allocate a bitstring */ -#define bit_alloc(nbits) \ - (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t)) +static inline bitstr_t +_bit_make_mask(int _start, int _stop) +{ + return ((_BITSTR_MASK << _bit_offset(_start)) & + (_BITSTR_MASK >> (_BITSTR_BITS - _bit_offset(_stop) - 1))); +} - /* allocate a bitstring on the stack */ +/*----------------------------- Public Interface -----------------------------*/ +/* Number of bytes consumed by a bit string of nbits bits */ +#define bitstr_size(_nbits) \ + (((_nbits) + _BITSTR_BITS - 1) / 8) + +/* Allocate a bit string initialized with no bits set. */ +#ifdef _KERNEL +static inline bitstr_t * +bit_alloc(int _nbits, struct malloc_type *type, int flags) +{ + return ((bitstr_t *)malloc(bitstr_size(_nbits), type, flags | M_ZERO)); +} +#else +static inline bitstr_t * +bit_alloc(int _nbits) +{ + return ((bitstr_t *)calloc(bitstr_size(_nbits), 1)); +} +#endif + +/* Allocate a bit string on the stack with no bits set. */ #define bit_decl(name, nbits) \ - ((name)[bitstr_size(nbits)]) - - /* is bit N of bitstring name set? */ -#define bit_test(name, bit) \ - ((name)[_bit_byte(bit)] & _bit_mask(bit)) - - /* set bit N of bitstring name */ -#define bit_set(name, bit) \ - ((name)[_bit_byte(bit)] |= _bit_mask(bit)) - - /* clear bit N of bitstring name */ -#define bit_clear(name, bit) \ - ((name)[_bit_byte(bit)] &= ~_bit_mask(bit)) - - /* clear bits start ... stop in bitstring */ -#define bit_nclear(name, start, stop) do { \ - register bitstr_t *_name = (name); \ - register int _start = (start), _stop = (stop); \ - register int _startbyte = _bit_byte(_start); \ - register int _stopbyte = _bit_byte(_stop); \ - if (_startbyte == _stopbyte) { \ - _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \ - (0xff << ((_stop&0x7) + 1))); \ - } else { \ - _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \ - while (++_startbyte < _stopbyte) \ - _name[_startbyte] = 0; \ - _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \ - } \ -} while (0) - - /* set bits start ... stop in bitstring */ -#define bit_nset(name, start, stop) do { \ - register bitstr_t *_name = (name); \ - register int _start = (start), _stop = (stop); \ - register int _startbyte = _bit_byte(_start); \ - register int _stopbyte = _bit_byte(_stop); \ - if (_startbyte == _stopbyte) { \ - _name[_startbyte] |= ((0xff << (_start&0x7)) & \ - (0xff >> (7 - (_stop&0x7)))); \ - } else { \ - _name[_startbyte] |= 0xff << ((_start)&0x7); \ - while (++_startbyte < _stopbyte) \ - _name[_startbyte] = 0xff; \ - _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \ - } \ -} while (0) - - /* find first bit clear in name */ -#define bit_ffc(name, nbits, value) do { \ - register bitstr_t *_name = (name); \ - register int _byte, _nbits = (nbits); \ - register int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \ - if (_nbits > 0) \ - for (_byte = 0; _byte <= _stopbyte; ++_byte) \ - if (_name[_byte] != 0xff) { \ - bitstr_t _lb; \ - _value = _byte << 3; \ - for (_lb = _name[_byte]; (_lb&0x1); \ - ++_value, _lb >>= 1); \ - break; \ - } \ - if (_value >= nbits) \ - _value = -1; \ - *(value) = _value; \ -} while (0) - - /* find first bit set in name */ -#define bit_ffs(name, nbits, value) do { \ - register bitstr_t *_name = (name); \ - register int _byte, _nbits = (nbits); \ - register int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \ - if (_nbits > 0) \ - for (_byte = 0; _byte <= _stopbyte; ++_byte) \ - if (_name[_byte]) { \ - bitstr_t _lb; \ - _value = _byte << 3; \ - for (_lb = _name[_byte]; !(_lb&0x1); \ - ++_value, _lb >>= 1); \ - break; \ - } \ - if (_value >= nbits) \ - _value = -1; \ - *(value) = _value; \ -} while (0) - -#endif /* !_SYS_BITSTRING_H_ */ + ((name)[bitstr_size(nbits) / sizeof(bitstr_t)]) + +/* Is bit N of bit string set? */ +static inline int +bit_test(const bitstr_t *_bitstr, int _bit) +{ + return ((_bitstr[_bit_idx(_bit)] & _bit_mask(_bit)) != 0); +} + +/* Set bit N of bit string. */ +static inline void +bit_set(bitstr_t *_bitstr, int _bit) +{ + _bitstr[_bit_idx(_bit)] |= _bit_mask(_bit); +} + +/* clear bit N of bit string name */ +static inline void +bit_clear(bitstr_t *_bitstr, int _bit) +{ + _bitstr[_bit_idx(_bit)] &= ~_bit_mask(_bit); +} + +/* Set bits start ... stop inclusive in bit string. */ +static inline void +bit_nset(bitstr_t *_bitstr, int _start, int _stop) +{ + bitstr_t *_stopbitstr; + + _stopbitstr = _bitstr + _bit_idx(_stop); + _bitstr += _bit_idx(_start); + + if (_bitstr == _stopbitstr) { + *_bitstr |= _bit_make_mask(_start, _stop); + } else { + *_bitstr |= _bit_make_mask(_start, _BITSTR_BITS - 1); + while (++_bitstr < _stopbitstr) + *_bitstr = _BITSTR_MASK; + *_stopbitstr |= _bit_make_mask(0, _stop); + } +} + +/* Clear bits start ... stop inclusive in bit string. */ +static inline void +bit_nclear(bitstr_t *_bitstr, int _start, int _stop) +{ + bitstr_t *_stopbitstr; + + _stopbitstr = _bitstr + _bit_idx(_stop); + _bitstr += _bit_idx(_start); + + if (_bitstr == _stopbitstr) { + *_bitstr &= ~_bit_make_mask(_start, _stop); + } else { + *_bitstr &= ~_bit_make_mask(_start, _BITSTR_BITS - 1); + while (++_bitstr < _stopbitstr) + *_bitstr = 0; + *_stopbitstr &= ~_bit_make_mask(0, _stop); + } +} + +/* Find the first bit set in bit string at or after bit start. */ +static inline void +bit_ffs_at(bitstr_t *_bitstr, int _start, int _nbits, int *_result) +{ + bitstr_t *_curbitstr; + bitstr_t *_stopbitstr; + bitstr_t _test; + int _value, _offset; + + if (_nbits > 0) { + _curbitstr = _bitstr + _bit_idx(_start); + _stopbitstr = _bitstr + _bit_idx(_nbits - 1); + + _test = *_curbitstr; + if (_bit_offset(_start) != 0) + _test &= _bit_make_mask(_start, _BITSTR_BITS - 1); + while (_test == 0 && _curbitstr < _stopbitstr) + _test = *(++_curbitstr); + + _offset = ffsl(_test); + _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + _offset - 1; + if (_offset == 0 || _value >= _nbits) + _value = -1; + } else { + _value = -1; + } + *_result = _value; +} + +/* Find the first bit clear in bit string at or after bit start. */ +static inline void +bit_ffc_at(bitstr_t *_bitstr, int _start, int _nbits, int *_result) +{ + bitstr_t *_curbitstr; + bitstr_t *_stopbitstr; + bitstr_t _test; + int _value, _offset; + + if (_nbits > 0) { + _curbitstr = _bitstr + _bit_idx(_start); + _stopbitstr = _bitstr + _bit_idx(_nbits - 1); + + _test = *_curbitstr; + if (_bit_offset(_start) != 0) + _test |= _bit_make_mask(0, _start - 1); + while (_test == _BITSTR_MASK && _curbitstr < _stopbitstr) + _test = *(++_curbitstr); + + _offset = ffsl(~_test); + _value = ((_curbitstr - _bitstr) * _BITSTR_BITS) + _offset - 1; + if (_offset == 0 || _value >= _nbits) + _value = -1; + } else { + _value = -1; + } + *_result = _value; +} + +/* Find the first bit set in bit string. */ +static inline void +bit_ffs(bitstr_t *_bitstr, int _nbits, int *_result) +{ + bit_ffs_at(_bitstr, /*start*/0, _nbits, _result); +} + +/* Find the first bit clear in bit string. */ +static inline void +bit_ffc(bitstr_t *_bitstr, int _nbits, int *_result) +{ + bit_ffc_at(_bitstr, /*start*/0, _nbits, _result); +} + +#endif /* _SYS_BITSTRING_H_ */ diff --git a/sys/sys/param.h b/sys/sys/param.h index a0eede9..6c64074 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1100106 /* Master, propagated to newvers */ +#define __FreeBSD_version 1100107 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, -- cgit v1.1 From 76fb86ddfe6fe8cd628ebfb49b50dea38466dcef Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 4 May 2016 23:00:57 +0000 Subject: Fix the acpi attachment to always start the worker thread. The previous change to split the worker thread start out of fdc_attach() did not start the worker thread if the fdc device in the ACPI namespace did not have an _FDE method. This fixes hangs when booting with a floppy controller enabled on certain machines with ACPI. Tested by: joel --- sys/dev/fdc/fdc_acpi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/dev/fdc/fdc_acpi.c b/sys/dev/fdc/fdc_acpi.c index 9c6eb35..afef409 100644 --- a/sys/dev/fdc/fdc_acpi.c +++ b/sys/dev/fdc/fdc_acpi.c @@ -135,14 +135,13 @@ fdc_acpi_attach(device_t dev) obj = buf.Pointer; error = fdc_acpi_probe_children(bus, dev, obj->Buffer.Pointer); - if (error == 0) - fdc_start_worker(dev); - out: if (buf.Pointer) free(buf.Pointer, M_TEMP); if (error != 0) fdc_release_resources(sc); + else + fdc_start_worker(dev); return (error); } -- cgit v1.1 From 92100036c841e961994633b0de4fdbc3c8217fb7 Mon Sep 17 00:00:00 2001 From: ngie Date: Wed, 4 May 2016 23:20:53 +0000 Subject: Merge ^/user/ngie/release-pkg-fix-tests to unbreak how test files are installed after r298107 Summary of changes: - Replace all instances of FILES/TESTS with ${PACKAGE}FILES. This ensures that namespacing is kept with FILES appropriately, and that this shouldn't need to be repeated if the namespace changes -- only the definition of PACKAGE needs to be changed - Allow PACKAGE to be overridden by callers instead of forcing it to always be `tests`. In the event we get to the point where things can be split up enough in the base system, it would make more sense to group the tests with the blocks they're a part of, e.g. byacc with byacc-tests, etc - Remove PACKAGE definitions where possible, i.e. where FILES wasn't used previously. - Remove unnecessary TESTSPACKAGE definitions; this has been elided into bsd.tests.mk - Remove unnecessary BINDIRs used previously with ${PACKAGE}FILES; ${PACKAGE}FILESDIR is now automatically defined in bsd.test.mk. - Fix installation of files under data/ subdirectories in lib/libc/tests/hash and lib/libc/tests/net/getaddrinfo - Remove unnecessary .include s (some opportunistic cleanup) Document the proposed changes in share/examples/tests/tests/... via examples so it's clear that ${PACKAGES}FILES is the suggested way forward in terms of replacing FILES. share/mk/bsd.README didn't seem like the appropriate method of communicating that info. MFC after: never probably X-MFC with: r298107 PR: 209114 Relnotes: yes Tested with: buildworld, installworld, checkworld; buildworld, packageworld Sponsored by: EMC / Isilon Storage Division --- sys/modules/tests/callout_test/Makefile | 4 ---- sys/modules/tests/framework/Makefile | 4 ---- 2 files changed, 8 deletions(-) (limited to 'sys') diff --git a/sys/modules/tests/callout_test/Makefile b/sys/modules/tests/callout_test/Makefile index eadcadc..4781488 100644 --- a/sys/modules/tests/callout_test/Makefile +++ b/sys/modules/tests/callout_test/Makefile @@ -2,10 +2,6 @@ # $FreeBSD$ # -PACKAGE= tests -FILESGROUPS= TESTS -TESTSPACKAGE= ${PACKAGE} - .PATH: ${.CURDIR}/../../../tests/callout_test KMOD= callout_test diff --git a/sys/modules/tests/framework/Makefile b/sys/modules/tests/framework/Makefile index c56838d..f5f608f 100644 --- a/sys/modules/tests/framework/Makefile +++ b/sys/modules/tests/framework/Makefile @@ -2,10 +2,6 @@ # $FreeBSD$ # -PACKAGE= tests -FILESGROUPS= TESTS -TESTSPACKAGE= ${PACKAGE} - .PATH: ${.CURDIR}/../../../tests/framework KMOD= kern_testfrwk -- cgit v1.1 From 689d1f5128b60d71cb0c6d702472ae630cd3edc1 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 23:31:52 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/kern/subr_bus.c | 2 +- sys/kern/subr_rman.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'sys') diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 1202903..a891949 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -5186,7 +5186,7 @@ find_device(struct devreq *req, device_t *devp) } static bool -driver_exists(struct device *bus, const char *driver) +driver_exists(device_t bus, const char *driver) { devclass_t dc; diff --git a/sys/kern/subr_rman.c b/sys/kern/subr_rman.c index 9bbec64..d1c68b45 100644 --- a/sys/kern/subr_rman.c +++ b/sys/kern/subr_rman.c @@ -94,7 +94,7 @@ struct resource_i { rman_res_t r_end; /* index of the last entry (inclusive) */ u_int r_flags; void *r_virtual; /* virtual address of this resource */ - struct device *r_dev; /* device which has allocated this resource */ + device_t r_dev; /* device which has allocated this resource */ struct rman *r_rm; /* resource manager from whence this came */ int r_rid; /* optional rid for this resource. */ }; @@ -436,7 +436,7 @@ rman_adjust_resource(struct resource *rr, rman_res_t start, rman_res_t end) struct resource * rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, rman_res_t bound, u_int flags, - struct device *dev) + device_t dev) { u_int new_rflags; struct resource_i *r, *s, *rv; @@ -652,7 +652,7 @@ out: struct resource * rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, - rman_res_t count, u_int flags, struct device *dev) + rman_res_t count, u_int flags, device_t dev) { return (rman_reserve_resource_bound(rm, start, end, count, 0, flags, @@ -911,13 +911,13 @@ rman_get_rid(struct resource *r) } void -rman_set_device(struct resource *r, struct device *dev) +rman_set_device(struct resource *r, device_t dev) { r->__r_i->r_dev = dev; } -struct device * +device_t rman_get_device(struct resource *r) { -- cgit v1.1 From edaf61e159f77848ee76f21bb23dfcdda0329d46 Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 23:32:57 +0000 Subject: s/struct device */device_t/g Submitted by: kmacy --- sys/sys/pcpu.h | 2 +- sys/sys/rman.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h index d6d1b3d..8e6a71a 100644 --- a/sys/sys/pcpu.h +++ b/sys/sys/pcpu.h @@ -160,7 +160,7 @@ struct pcpu { struct lock_list_entry *pc_spinlocks; struct vmmeter pc_cnt; /* VM stats counters */ long pc_cp_time[CPUSTATES]; /* statclock ticks */ - struct device *pc_device; + device_t pc_device; void *pc_netisr; /* netisr SWI cookie */ int pc_unused1; /* unused field */ int pc_domain; /* Memory domain. */ diff --git a/sys/sys/rman.h b/sys/sys/rman.h index 2d58f4a..d702d25 100644 --- a/sys/sys/rman.h +++ b/sys/sys/rman.h @@ -126,7 +126,7 @@ int rman_first_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end); bus_space_handle_t rman_get_bushandle(struct resource *); bus_space_tag_t rman_get_bustag(struct resource *); rman_res_t rman_get_end(struct resource *); -struct device *rman_get_device(struct resource *); +device_t rman_get_device(struct resource *); u_int rman_get_flags(struct resource *); int rman_get_rid(struct resource *); rman_res_t rman_get_size(struct resource *); @@ -143,13 +143,13 @@ int rman_is_region_manager(struct resource *r, struct rman *rm); int rman_release_resource(struct resource *r); struct resource *rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, - u_int flags, struct device *dev); + u_int flags, device_t dev); struct resource *rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, rman_res_t bound, - u_int flags, struct device *dev); + u_int flags, device_t dev); void rman_set_bushandle(struct resource *_r, bus_space_handle_t _h); void rman_set_bustag(struct resource *_r, bus_space_tag_t _t); -void rman_set_device(struct resource *_r, struct device *_dev); +void rman_set_device(struct resource *_r, device_t _dev); void rman_set_end(struct resource *_r, rman_res_t _end); void rman_set_rid(struct resource *_r, int _rid); void rman_set_start(struct resource *_r, rman_res_t _start); -- cgit v1.1 From 1927244465ddc89990ecaa8bff88966f12bbf7dd Mon Sep 17 00:00:00 2001 From: adrian Date: Wed, 4 May 2016 23:38:27 +0000 Subject: [bwn] [bhnd] initial support for using bhnd for if_bwn devices. This is an initial work in progress to use the replacement bhnd bus code for devices which support it. * Add manpage updates for bhnd, bhndb, siba * Add kernel options for bhnd, bhndbus, etc * Add initial support in if_bwn_pci / if_bwn_mac for using bhnd as the bus transport for suppoted NICs * if_bwn_pci will eventually be the PCI bus glue to interface to bwn, which will use the right backend bus to attach to, versus direct nexus/bhnd attachments (as found in embedded broadcom devices.) The PCI glue defaults to probing at a lower level than the bwn glue, so bwn should still attach as per normal without a boot time tunable set. It's also not fully fleshed out - the bwn probe/attach code needs to be broken out into platform and bus specific things (just like ath, ath_pci, ath_ahb) before we can shift the driver over to using this. Tested: * BCM4311, STA mode * BCM4312, STA mode Submitted by: Landon Fuller Differential Revision: https://reviews.freebsd.org/D6191 --- sys/conf/files | 39 +- sys/dev/bhnd/bhndb/bhndb.c | 3 +- sys/dev/bhnd/bhndb/bhndb_pci.c | 3 +- sys/dev/bhnd/bhndb/bhndb_subr.c | 3 +- sys/dev/bwn/bwn_mac.c | 141 + sys/dev/bwn/if_bwn.c | 1 + sys/dev/bwn/if_bwn.c.c | 6881 +++++++++++++++++++++++++++++++++++++++ sys/dev/bwn/if_bwn_debug.h | 2 + sys/dev/bwn/if_bwn_pci.c | 288 ++ sys/dev/bwn/if_bwn_pcivar.h | 93 + sys/modules/Makefile | 3 + sys/modules/bwn_pci/Makefile | 11 + 12 files changed, 7457 insertions(+), 11 deletions(-) create mode 100644 sys/dev/bwn/bwn_mac.c create mode 100644 sys/dev/bwn/if_bwn.c.c create mode 100644 sys/dev/bwn/if_bwn_pci.c create mode 100644 sys/dev/bwn/if_bwn_pcivar.h create mode 100644 sys/modules/bwn_pci/Makefile (limited to 'sys') diff --git a/sys/conf/files b/sys/conf/files index 33de771..9105ae0 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1109,9 +1109,34 @@ dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \ dev/ath/ath_dfs/null/dfs_null.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" # -dev/bce/if_bce.c optional bce -dev/bfe/if_bfe.c optional bfe -dev/bge/if_bge.c optional bge +dev/bce/if_bce.c optional bce +dev/bfe/if_bfe.c optional bfe +dev/bge/if_bge.c optional bge +dev/bhnd/bhnd.c optional bhndbus | bhnd +dev/bhnd/bhnd_subr.c optional bhndbus | bhnd +dev/bhnd/bhnd_bus_if.m optional bhndbus | bhnd +dev/bhnd/bhndb/bhndb.c optional bhndbus | bhndb +dev/bhnd/bhndb/bhndb_bus_if.m optional bhndbus | bhndb +dev/bhnd/bhndb/bhndb_hwdata.c optional bhndbus | bhndb +dev/bhnd/bhndb/bhndb_if.m optional bhndbus | bhndb +dev/bhnd/bhndb/bhndb_pci.c optional bhndbus pci | bhndb pci +dev/bhnd/bhndb/bhndb_pci_hwdata.c optional bhndbus pci | bhndb pci +dev/bhnd/bhndb/bhndb_subr.c optional bhndbus pci | bhndb +dev/bhnd/bcma/bcma.c optional bhndbus | bcma +dev/bhnd/bcma/bcma_bhndb.c optional bhndbus | bcma bhndb +dev/bhnd/bcma/bcma_erom.c optional bhndbus | bcma +dev/bhnd/bcma/bcma_subr.c optional bhndbus | bcma +dev/bhnd/cores/chipc/chipc.c optional bhndbus | bhnd +dev/bhnd/cores/chipc/bhnd_chipc_if.m optional bhndbus | bhnd +dev/bhnd/cores/pci/bhnd_pci.c optional bhndbus pci | bhnd pci +dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndbus pci | bhndb pci +dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci +dev/bhnd/nvram/bhnd_nvram_if.m optional bhndbus | bhnd +dev/bhnd/siba/siba.c optional bhndbus | siba +dev/bhnd/siba/siba_bhndb.c optional bhndbus | siba bhndb +dev/bhnd/siba/siba_nexus.c optional siba_nexus siba +dev/bhnd/siba/siba_subr.c optional bhndbus | siba +# dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c optional bktr pci @@ -1132,10 +1157,12 @@ dev/bwi/if_bwi_pci.c optional bwi pci # XXX Work around clang warning, until maintainer approves fix. dev/bwn/if_bwn.c optional bwn siba_bwn \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" +dev/bwn/if_bwn_pci.c optional bwn pci bhnd | bwn pci bhndbus dev/bwn/if_bwn_phy_g.c optional bwn siba_bwn \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" dev/bwn/if_bwn_phy_lp.c optional bwn siba_bwn \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" +dev/bwn/bwn_mac.c optional bwn bhnd | bwn bhndbus dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/cardbus/cardbus_device.c optional cardbus @@ -2400,11 +2427,11 @@ dev/si/si3_t225.c optional si dev/si/si_eisa.c optional si eisa dev/si/si_isa.c optional si isa dev/si/si_pci.c optional si pci -dev/siba/siba.c optional siba +dev/siba/siba.c optional siba !bhnd !bhndbus dev/siba/siba_bwn.c optional siba_bwn pci -dev/siba/siba_cc.c optional siba +dev/siba/siba_cc.c optional siba !bhnd !bhndbus dev/siba/siba_core.c optional siba | siba_bwn pci -dev/siba/siba_pcib.c optional siba pci +dev/siba/siba_pcib.c optional siba pci !bhnd !bhndbus dev/siis/siis.c optional siis pci dev/sis/if_sis.c optional sis pci dev/sk/if_sk.c optional sk pci diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 3deae00..e2914a9 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -536,8 +536,7 @@ bhndb_attach(device_t dev, bhnd_devclass_t bridge_devclass) } /* Attach our bridged bus device */ - sc->bus_dev = BUS_ADD_CHILD(dev, 0, devclass_get_name(bhnd_devclass), - -1); + sc->bus_dev = BUS_ADD_CHILD(dev, 0, "bhnd", -1); if (sc->bus_dev == NULL) { error = ENXIO; goto failed; diff --git a/sys/dev/bhnd/bhndb/bhndb_pci.c b/sys/dev/bhnd/bhndb/bhndb_pci.c index d8fc379..847d4be 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pci.c +++ b/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -464,6 +464,7 @@ DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods, sizeof(struct bhndb_pci_softc), bhndb_driver); MODULE_VERSION(bhndb_pci, 1); -MODULE_DEPEND(bhndb_pci, bhnd_pci, 1, 1, 1); +MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1); MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1); MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1); +MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1); diff --git a/sys/dev/bhnd/bhndb/bhndb_subr.c b/sys/dev/bhnd/bhndb/bhndb_subr.c index f6b003a..de3ca10 100644 --- a/sys/dev/bhnd/bhndb/bhndb_subr.c +++ b/sys/dev/bhnd/bhndb/bhndb_subr.c @@ -52,8 +52,7 @@ bhndb_attach_bridge(device_t parent, device_t *bhndb, int unit) { int error; - *bhndb = device_add_child(parent, devclass_get_name(bhndb_devclass), - unit); + *bhndb = device_add_child(parent, "bhndb", unit); if (*bhndb == NULL) return (ENXIO); diff --git a/sys/dev/bwn/bwn_mac.c b/sys/dev/bwn/bwn_mac.c new file mode 100644 index 0000000..d1cfbfd --- /dev/null +++ b/sys/dev/bwn/bwn_mac.c @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2015 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static const struct resource_spec bwn_rspec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, -1, 0 } +}; + +#define RSPEC_LEN (sizeof(bwn_rspec)/sizeof(bwn_rspec[0])) + +struct bwn_softc { + struct resource_spec rspec[RSPEC_LEN]; + struct bhnd_resource *res[RSPEC_LEN-1]; +}; + +static const struct bwn_device { + uint16_t vendor; + uint16_t device; +} bwn_devices[] = { + { BHND_MFGID_BCM, BHND_COREID_D11 }, + { BHND_MFGID_INVALID, BHND_COREID_INVALID } +}; + +static int +bwn_probe(device_t dev) +{ + const struct bwn_device *id; + + for (id = bwn_devices; id->device != BHND_COREID_INVALID; id++) + { + if (bhnd_get_vendor(dev) == id->vendor && + bhnd_get_device(dev) == id->device) + { + device_set_desc(dev, bhnd_get_device_name(dev)); + return (BUS_PROBE_DEFAULT); + } + } + + return (ENXIO); +} + +static int +bwn_attach(device_t dev) +{ + struct bwn_softc *sc; + struct bhnd_resource *r; + int error; + + sc = device_get_softc(dev); + + memcpy(sc->rspec, bwn_rspec, sizeof(bwn_rspec)); + if ((error = bhnd_alloc_resources(dev, sc->rspec, sc->res))) + return (error); + + // XXX TODO + r = sc->res[0]; + device_printf(dev, "got rid=%d res=%p\n", sc->rspec[0].rid, r); + + return (0); +} + +static int +bwn_detach(device_t dev) +{ + struct bwn_softc *sc; + + sc = device_get_softc(dev); + bhnd_release_resources(dev, sc->rspec, sc->res); + + return (0); +} + +static int +bwn_suspend(device_t dev) +{ + return (0); +} + +static int +bwn_resume(device_t dev) +{ + return (0); +} + +static device_method_t bwn_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bwn_probe), + DEVMETHOD(device_attach, bwn_attach), + DEVMETHOD(device_detach, bwn_detach), + DEVMETHOD(device_suspend, bwn_suspend), + DEVMETHOD(device_resume, bwn_resume), + DEVMETHOD_END +}; + +static devclass_t bwn_devclass; + +DEFINE_CLASS_0(bwn, bwn_driver, bwn_methods, sizeof(struct bwn_softc)); +DRIVER_MODULE(bwn_mac, bhnd, bwn_driver, bwn_devclass, 0, 0); +MODULE_DEPEND(bwn_mac, bhnd, 1, 1, 1); +MODULE_VERSION(bwn_mac, 1); diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 60d408eb..837f4f8 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -6879,3 +6879,4 @@ MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1); MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */ MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */ MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1); +MODULE_VERSION(bwn, 1); diff --git a/sys/dev/bwn/if_bwn.c.c b/sys/dev/bwn/if_bwn.c.c new file mode 100644 index 0000000..f7dc50c --- /dev/null +++ b/sys/dev/bwn/if_bwn.c.c @@ -0,0 +1,6881 @@ +/*- + * Copyright (c) 2009-2010 Weongyo Jeong + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * The Broadcom Wireless LAN controller driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, + "Broadcom driver parameters"); + +/* + * Tunable & sysctl variables. + */ + +#ifdef BWN_DEBUG +static int bwn_debug = 0; +SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0, + "Broadcom debugging printfs"); +#endif + +static int bwn_bfp = 0; /* use "Bad Frames Preemption" */ +SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0, + "uses Bad Frames Preemption"); +static int bwn_bluetooth = 1; +SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0, + "turns on Bluetooth Coexistence"); +static int bwn_hwpctl = 0; +SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0, + "uses H/W power control"); +static int bwn_msi_disable = 0; /* MSI disabled */ +TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable); +static int bwn_usedma = 1; +SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0, + "uses DMA"); +TUNABLE_INT("hw.bwn.usedma", &bwn_usedma); +static int bwn_wme = 1; +SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0, + "uses WME support"); + +static void bwn_attach_pre(struct bwn_softc *); +static int bwn_attach_post(struct bwn_softc *); +static void bwn_sprom_bugfixes(device_t); +static int bwn_init(struct bwn_softc *); +static void bwn_parent(struct ieee80211com *); +static void bwn_start(struct bwn_softc *); +static int bwn_transmit(struct ieee80211com *, struct mbuf *); +static int bwn_attach_core(struct bwn_mac *); +static int bwn_phy_getinfo(struct bwn_mac *, int); +static int bwn_chiptest(struct bwn_mac *); +static int bwn_setup_channels(struct bwn_mac *, int, int); +static void bwn_shm_ctlword(struct bwn_mac *, uint16_t, + uint16_t); +static void bwn_addchannels(struct ieee80211_channel [], int, int *, + const struct bwn_channelinfo *, int); +static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *, + const struct ieee80211_bpf_params *); +static void bwn_updateslot(struct ieee80211com *); +static void bwn_update_promisc(struct ieee80211com *); +static void bwn_wme_init(struct bwn_mac *); +static int bwn_wme_update(struct ieee80211com *); +static void bwn_wme_clear(struct bwn_softc *); +static void bwn_wme_load(struct bwn_mac *); +static void bwn_wme_loadparams(struct bwn_mac *, + const struct wmeParams *, uint16_t); +static void bwn_scan_start(struct ieee80211com *); +static void bwn_scan_end(struct ieee80211com *); +static void bwn_set_channel(struct ieee80211com *); +static struct ieee80211vap *bwn_vap_create(struct ieee80211com *, + const char [IFNAMSIZ], int, enum ieee80211_opmode, int, + const uint8_t [IEEE80211_ADDR_LEN], + const uint8_t [IEEE80211_ADDR_LEN]); +static void bwn_vap_delete(struct ieee80211vap *); +static void bwn_stop(struct bwn_softc *); +static int bwn_core_init(struct bwn_mac *); +static void bwn_core_start(struct bwn_mac *); +static void bwn_core_exit(struct bwn_mac *); +static void bwn_bt_disable(struct bwn_mac *); +static int bwn_chip_init(struct bwn_mac *); +static void bwn_set_txretry(struct bwn_mac *, int, int); +static void bwn_rate_init(struct bwn_mac *); +static void bwn_set_phytxctl(struct bwn_mac *); +static void bwn_spu_setdelay(struct bwn_mac *, int); +static void bwn_bt_enable(struct bwn_mac *); +static void bwn_set_macaddr(struct bwn_mac *); +static void bwn_crypt_init(struct bwn_mac *); +static void bwn_chip_exit(struct bwn_mac *); +static int bwn_fw_fillinfo(struct bwn_mac *); +static int bwn_fw_loaducode(struct bwn_mac *); +static int bwn_gpio_init(struct bwn_mac *); +static int bwn_fw_loadinitvals(struct bwn_mac *); +static int bwn_phy_init(struct bwn_mac *); +static void bwn_set_txantenna(struct bwn_mac *, int); +static void bwn_set_opmode(struct bwn_mac *); +static void bwn_rate_write(struct bwn_mac *, uint16_t, int); +static uint8_t bwn_plcp_getcck(const uint8_t); +static uint8_t bwn_plcp_getofdm(const uint8_t); +static void bwn_pio_init(struct bwn_mac *); +static uint16_t bwn_pio_idx2base(struct bwn_mac *, int); +static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *, + int); +static void bwn_pio_setupqueue_rx(struct bwn_mac *, + struct bwn_pio_rxqueue *, int); +static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *); +static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *, + uint16_t); +static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *); +static int bwn_pio_rx(struct bwn_pio_rxqueue *); +static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *); +static void bwn_pio_handle_txeof(struct bwn_mac *, + const struct bwn_txstatus *); +static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t); +static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t); +static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t, + uint16_t); +static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t, + uint32_t); +static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *, + struct mbuf *); +static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t); +static uint32_t bwn_pio_write_multi_4(struct bwn_mac *, + struct bwn_pio_txqueue *, uint32_t, const void *, int); +static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *, + uint16_t, uint32_t); +static uint16_t bwn_pio_write_multi_2(struct bwn_mac *, + struct bwn_pio_txqueue *, uint16_t, const void *, int); +static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *, + struct bwn_pio_txqueue *, uint16_t, struct mbuf *); +static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *, + uint16_t, struct bwn_pio_txpkt **); +static void bwn_dma_init(struct bwn_mac *); +static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t); +static int bwn_dma_mask2type(uint64_t); +static uint64_t bwn_dma_mask(struct bwn_mac *); +static uint16_t bwn_dma_base(int, int); +static void bwn_dma_ringfree(struct bwn_dma_ring **); +static void bwn_dma_32_getdesc(struct bwn_dma_ring *, + int, struct bwn_dmadesc_generic **, + struct bwn_dmadesc_meta **); +static void bwn_dma_32_setdesc(struct bwn_dma_ring *, + struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int, + int, int); +static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int); +static void bwn_dma_32_suspend(struct bwn_dma_ring *); +static void bwn_dma_32_resume(struct bwn_dma_ring *); +static int bwn_dma_32_get_curslot(struct bwn_dma_ring *); +static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int); +static void bwn_dma_64_getdesc(struct bwn_dma_ring *, + int, struct bwn_dmadesc_generic **, + struct bwn_dmadesc_meta **); +static void bwn_dma_64_setdesc(struct bwn_dma_ring *, + struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int, + int, int); +static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int); +static void bwn_dma_64_suspend(struct bwn_dma_ring *); +static void bwn_dma_64_resume(struct bwn_dma_ring *); +static int bwn_dma_64_get_curslot(struct bwn_dma_ring *); +static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int); +static int bwn_dma_allocringmemory(struct bwn_dma_ring *); +static void bwn_dma_setup(struct bwn_dma_ring *); +static void bwn_dma_free_ringmemory(struct bwn_dma_ring *); +static void bwn_dma_cleanup(struct bwn_dma_ring *); +static void bwn_dma_free_descbufs(struct bwn_dma_ring *); +static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int); +static void bwn_dma_rx(struct bwn_dma_ring *); +static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int); +static void bwn_dma_free_descbuf(struct bwn_dma_ring *, + struct bwn_dmadesc_meta *); +static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *); +static int bwn_dma_gettype(struct bwn_mac *); +static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int); +static int bwn_dma_freeslot(struct bwn_dma_ring *); +static int bwn_dma_nextslot(struct bwn_dma_ring *, int); +static void bwn_dma_rxeof(struct bwn_dma_ring *, int *); +static int bwn_dma_newbuf(struct bwn_dma_ring *, + struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *, + int); +static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int, + bus_size_t, int); +static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *); +static void bwn_dma_handle_txeof(struct bwn_mac *, + const struct bwn_txstatus *); +static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *, + struct mbuf *); +static int bwn_dma_getslot(struct bwn_dma_ring *); +static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *, + uint8_t); +static int bwn_dma_attach(struct bwn_mac *); +static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *, + int, int, int); +static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *, + const struct bwn_txstatus *, uint16_t, int *); +static void bwn_dma_free(struct bwn_mac *); +static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype); +static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype, + const char *, struct bwn_fwfile *); +static void bwn_release_firmware(struct bwn_mac *); +static void bwn_do_release_fw(struct bwn_fwfile *); +static uint16_t bwn_fwcaps_read(struct bwn_mac *); +static int bwn_fwinitvals_write(struct bwn_mac *, + const struct bwn_fwinitvals *, size_t, size_t); +static uint16_t bwn_ant2phy(int); +static void bwn_mac_write_bssid(struct bwn_mac *); +static void bwn_mac_setfilter(struct bwn_mac *, uint16_t, + const uint8_t *); +static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t, + const uint8_t *, size_t, const uint8_t *); +static void bwn_key_macwrite(struct bwn_mac *, uint8_t, + const uint8_t *); +static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t, + const uint8_t *); +static void bwn_phy_exit(struct bwn_mac *); +static void bwn_core_stop(struct bwn_mac *); +static int bwn_switch_band(struct bwn_softc *, + struct ieee80211_channel *); +static void bwn_phy_reset(struct bwn_mac *); +static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); +static void bwn_set_pretbtt(struct bwn_mac *); +static int bwn_intr(void *); +static void bwn_intrtask(void *, int); +static void bwn_restart(struct bwn_mac *, const char *); +static void bwn_intr_ucode_debug(struct bwn_mac *); +static void bwn_intr_tbtt_indication(struct bwn_mac *); +static void bwn_intr_atim_end(struct bwn_mac *); +static void bwn_intr_beacon(struct bwn_mac *); +static void bwn_intr_pmq(struct bwn_mac *); +static void bwn_intr_noise(struct bwn_mac *); +static void bwn_intr_txeof(struct bwn_mac *); +static void bwn_hwreset(void *, int); +static void bwn_handle_fwpanic(struct bwn_mac *); +static void bwn_load_beacon0(struct bwn_mac *); +static void bwn_load_beacon1(struct bwn_mac *); +static uint32_t bwn_jssi_read(struct bwn_mac *); +static void bwn_noise_gensample(struct bwn_mac *); +static void bwn_handle_txeof(struct bwn_mac *, + const struct bwn_txstatus *); +static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *); +static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t); +static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *, + struct mbuf *); +static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *); +static int bwn_set_txhdr(struct bwn_mac *, + struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *, + uint16_t); +static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t, + const uint8_t); +static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t); +static uint8_t bwn_get_fbrate(uint8_t); +static void bwn_txpwr(void *, int); +static void bwn_tasks(void *); +static void bwn_task_15s(struct bwn_mac *); +static void bwn_task_30s(struct bwn_mac *); +static void bwn_task_60s(struct bwn_mac *); +static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *, + uint8_t); +static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *); +static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *, + const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int, + int, int); +static void bwn_tsf_read(struct bwn_mac *, uint64_t *); +static void bwn_set_slot_time(struct bwn_mac *, uint16_t); +static void bwn_watchdog(void *); +static void bwn_dma_stop(struct bwn_mac *); +static void bwn_pio_stop(struct bwn_mac *); +static void bwn_dma_ringstop(struct bwn_dma_ring **); +static void bwn_led_attach(struct bwn_mac *); +static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state); +static void bwn_led_event(struct bwn_mac *, int); +static void bwn_led_blink_start(struct bwn_mac *, int, int); +static void bwn_led_blink_next(void *); +static void bwn_led_blink_end(void *); +static void bwn_rfswitch(void *); +static void bwn_rf_turnon(struct bwn_mac *); +static void bwn_rf_turnoff(struct bwn_mac *); +static void bwn_sysctl_node(struct bwn_softc *); + +static struct resource_spec bwn_res_spec_legacy[] = { + { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, + { -1, 0, 0 } +}; + +static struct resource_spec bwn_res_spec_msi[] = { + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { -1, 0, 0 } +}; + +static const struct bwn_channelinfo bwn_chantable_bg = { + .channels = { + { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 }, + { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 }, + { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 }, + { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 }, + { 2472, 13, 30 }, { 2484, 14, 30 } }, + .nchannels = 14 +}; + +static const struct bwn_channelinfo bwn_chantable_a = { + .channels = { + { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 }, + { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 }, + { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 }, + { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 }, + { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 }, + { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 }, + { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 }, + { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 }, + { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 }, + { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 }, + { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 }, + { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 }, + { 6080, 216, 30 } }, + .nchannels = 37 +}; + +static const struct bwn_channelinfo bwn_chantable_n = { + .channels = { + { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 }, + { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 }, + { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 }, + { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 }, + { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 }, + { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 }, + { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 }, + { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 }, + { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 }, + { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 }, + { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 }, + { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 }, + { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 }, + { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 }, + { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 }, + { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 }, + { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 }, + { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 }, + { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 }, + { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 }, + { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 }, + { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 }, + { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 }, + { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 }, + { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 }, + { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 }, + { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 }, + { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 }, + { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 }, + { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 }, + { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 }, + { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 }, + { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 }, + { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 }, + { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 }, + { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 }, + { 6130, 226, 30 }, { 6140, 228, 30 } }, + .nchannels = 110 +}; + +#define VENDOR_LED_ACT(vendor) \ +{ \ + .vid = PCI_VENDOR_##vendor, \ + .led_act = { BWN_VENDOR_LED_ACT_##vendor } \ +} + +static const struct { + uint16_t vid; + uint8_t led_act[BWN_LED_MAX]; +} bwn_vendor_led_act[] = { + VENDOR_LED_ACT(COMPAQ), + VENDOR_LED_ACT(ASUSTEK) +}; + +static const uint8_t bwn_default_led_act[BWN_LED_MAX] = + { BWN_VENDOR_LED_ACT_DEFAULT }; + +#undef VENDOR_LED_ACT + +static const struct { + int on_dur; + int off_dur; +} bwn_led_duration[109] = { + [0] = { 400, 100 }, + [2] = { 150, 75 }, + [4] = { 90, 45 }, + [11] = { 66, 34 }, + [12] = { 53, 26 }, + [18] = { 42, 21 }, + [22] = { 35, 17 }, + [24] = { 32, 16 }, + [36] = { 21, 10 }, + [48] = { 16, 8 }, + [72] = { 11, 5 }, + [96] = { 9, 4 }, + [108] = { 7, 3 } +}; + +static const uint16_t bwn_wme_shm_offsets[] = { + [0] = BWN_WME_BESTEFFORT, + [1] = BWN_WME_BACKGROUND, + [2] = BWN_WME_VOICE, + [3] = BWN_WME_VIDEO, +}; + +static const struct siba_devid bwn_devs[] = { + SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"), + SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"), + SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"), + SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"), + SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"), + SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"), + SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"), + SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"), + SIBA_DEV(BROADCOM, 80211, 16, "Revision 16") +}; + +static int +bwn_probe(device_t dev) +{ + int i; + + for (i = 0; i < nitems(bwn_devs); i++) { + if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor && + siba_get_device(dev) == bwn_devs[i].sd_device && + siba_get_revid(dev) == bwn_devs[i].sd_rev) + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +bwn_attach(device_t dev) +{ + struct bwn_mac *mac; + struct bwn_softc *sc = device_get_softc(dev); + int error, i, msic, reg; + + sc->sc_dev = dev; +#ifdef BWN_DEBUG + sc->sc_debug = bwn_debug; +#endif + + if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) { + bwn_attach_pre(sc); + bwn_sprom_bugfixes(dev); + sc->sc_flags |= BWN_FLAG_ATTACHED; + } + + if (!TAILQ_EMPTY(&sc->sc_maclist)) { + if (siba_get_pci_device(dev) != 0x4313 && + siba_get_pci_device(dev) != 0x431a && + siba_get_pci_device(dev) != 0x4321) { + device_printf(sc->sc_dev, + "skip 802.11 cores\n"); + return (ENODEV); + } + } + + mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO); + mac->mac_sc = sc; + mac->mac_status = BWN_MAC_STATUS_UNINIT; + if (bwn_bfp != 0) + mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP; + + TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac); + TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac); + TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac); + + error = bwn_attach_core(mac); + if (error) + goto fail0; + bwn_led_attach(mac); + + device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) " + "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n", + siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev), + mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev, + mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver, + mac->mac_phy.rf_rev); + if (mac->mac_flags & BWN_MAC_FLAG_DMA) + device_printf(sc->sc_dev, "DMA (%d bits)\n", + mac->mac_method.dma.dmatype); + else + device_printf(sc->sc_dev, "PIO\n"); + + /* + * setup PCI resources and interrupt. + */ + if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) { + msic = pci_msi_count(dev); + if (bootverbose) + device_printf(sc->sc_dev, "MSI count : %d\n", msic); + } else + msic = 0; + + mac->mac_intr_spec = bwn_res_spec_legacy; + if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) { + if (pci_alloc_msi(dev, &msic) == 0) { + device_printf(sc->sc_dev, + "Using %d MSI messages\n", msic); + mac->mac_intr_spec = bwn_res_spec_msi; + mac->mac_msi = 1; + } + } + + error = bus_alloc_resources(dev, mac->mac_intr_spec, + mac->mac_res_irq); + if (error) { + device_printf(sc->sc_dev, + "couldn't allocate IRQ resources (%d)\n", error); + goto fail1; + } + + if (mac->mac_msi == 0) + error = bus_setup_intr(dev, mac->mac_res_irq[0], + INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac, + &mac->mac_intrhand[0]); + else { + for (i = 0; i < BWN_MSI_MESSAGES; i++) { + error = bus_setup_intr(dev, mac->mac_res_irq[i], + INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac, + &mac->mac_intrhand[i]); + if (error != 0) { + device_printf(sc->sc_dev, + "couldn't setup interrupt (%d)\n", error); + break; + } + } + } + + TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list); + + /* + * calls attach-post routine + */ + if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0) + bwn_attach_post(sc); + + return (0); +fail1: + if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) + pci_release_msi(dev); +fail0: + free(mac, M_DEVBUF); + return (error); +} + +static int +bwn_is_valid_ether_addr(uint8_t *addr) +{ + char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; + + if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) + return (FALSE); + + return (TRUE); +} + +static int +bwn_attach_post(struct bwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + ic->ic_softc = sc; + ic->ic_name = device_get_nameunit(sc->sc_dev); + /* XXX not right but it's not used anywhere important */ + ic->ic_phytype = IEEE80211_T_OFDM; + ic->ic_opmode = IEEE80211_M_STA; + ic->ic_caps = + IEEE80211_C_STA /* station mode supported */ + | IEEE80211_C_MONITOR /* monitor mode */ + | IEEE80211_C_AHDEMO /* adhoc demo mode */ + | IEEE80211_C_SHPREAMBLE /* short preamble supported */ + | IEEE80211_C_SHSLOT /* short slot time supported */ + | IEEE80211_C_WME /* WME/WMM supported */ + | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ + | IEEE80211_C_BGSCAN /* capable of bg scanning */ + | IEEE80211_C_TXPMGT /* capable of txpow mgt */ + ; + + ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */ + + IEEE80211_ADDR_COPY(ic->ic_macaddr, + bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ? + siba_sprom_get_mac_80211a(sc->sc_dev) : + siba_sprom_get_mac_80211bg(sc->sc_dev)); + + /* call MI attach routine. */ + ieee80211_ifattach(ic); + + ic->ic_headroom = sizeof(struct bwn_txhdr); + + /* override default methods */ + ic->ic_raw_xmit = bwn_raw_xmit; + ic->ic_updateslot = bwn_updateslot; + ic->ic_update_promisc = bwn_update_promisc; + ic->ic_wme.wme_update = bwn_wme_update; + ic->ic_scan_start = bwn_scan_start; + ic->ic_scan_end = bwn_scan_end; + ic->ic_set_channel = bwn_set_channel; + ic->ic_vap_create = bwn_vap_create; + ic->ic_vap_delete = bwn_vap_delete; + ic->ic_transmit = bwn_transmit; + ic->ic_parent = bwn_parent; + + ieee80211_radiotap_attach(ic, + &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), + BWN_TX_RADIOTAP_PRESENT, + &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), + BWN_RX_RADIOTAP_PRESENT); + + bwn_sysctl_node(sc); + + if (bootverbose) + ieee80211_announce(ic); + return (0); +} + +static void +bwn_phy_detach(struct bwn_mac *mac) +{ + + if (mac->mac_phy.detach != NULL) + mac->mac_phy.detach(mac); +} + +static int +bwn_detach(device_t dev) +{ + struct bwn_softc *sc = device_get_softc(dev); + struct bwn_mac *mac = sc->sc_curmac; + struct ieee80211com *ic = &sc->sc_ic; + int i; + + sc->sc_flags |= BWN_FLAG_INVALID; + + if (device_is_attached(sc->sc_dev)) { + BWN_LOCK(sc); + bwn_stop(sc); + BWN_UNLOCK(sc); + bwn_dma_free(mac); + callout_drain(&sc->sc_led_blink_ch); + callout_drain(&sc->sc_rfswitch_ch); + callout_drain(&sc->sc_task_ch); + callout_drain(&sc->sc_watchdog_ch); + bwn_phy_detach(mac); + ieee80211_draintask(ic, &mac->mac_hwreset); + ieee80211_draintask(ic, &mac->mac_txpower); + ieee80211_ifdetach(ic); + } + taskqueue_drain(sc->sc_tq, &mac->mac_intrtask); + taskqueue_free(sc->sc_tq); + + for (i = 0; i < BWN_MSI_MESSAGES; i++) { + if (mac->mac_intrhand[i] != NULL) { + bus_teardown_intr(dev, mac->mac_res_irq[i], + mac->mac_intrhand[i]); + mac->mac_intrhand[i] = NULL; + } + } + bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq); + if (mac->mac_msi != 0) + pci_release_msi(dev); + mbufq_drain(&sc->sc_snd); + BWN_LOCK_DESTROY(sc); + return (0); +} + +static void +bwn_attach_pre(struct bwn_softc *sc) +{ + + BWN_LOCK_INIT(sc); + TAILQ_INIT(&sc->sc_maclist); + callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0); + callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0); + callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0); + mbufq_init(&sc->sc_snd, ifqmaxlen); + sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT, + taskqueue_thread_enqueue, &sc->sc_tq); + taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, + "%s taskq", device_get_nameunit(sc->sc_dev)); +} + +static void +bwn_sprom_bugfixes(device_t dev) +{ +#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \ + ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \ + (siba_get_pci_device(dev) == _device) && \ + (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \ + (siba_get_pci_subdevice(dev) == _subdevice)) + + if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE && + siba_get_pci_subdevice(dev) == 0x4e && + siba_get_pci_revid(dev) > 0x40) + siba_sprom_set_bf_lo(dev, + siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL); + if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL && + siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74) + siba_sprom_set_bf_lo(dev, + siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST); + if (siba_get_type(dev) == SIBA_TYPE_PCI) { + if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) || + BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) || + BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) || + BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) || + BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) || + BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) || + BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010)) + siba_sprom_set_bf_lo(dev, + siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST); + } +#undef BWN_ISDEV +} + +static void +bwn_parent(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + int startall = 0; + + BWN_LOCK(sc); + if (ic->ic_nrunning > 0) { + if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) { + bwn_init(sc); + startall = 1; + } else + bwn_update_promisc(ic); + } else if (sc->sc_flags & BWN_FLAG_RUNNING) + bwn_stop(sc); + BWN_UNLOCK(sc); + + if (startall) + ieee80211_start_all(ic); +} + +static int +bwn_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct bwn_softc *sc = ic->ic_softc; + int error; + + BWN_LOCK(sc); + if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) { + BWN_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + BWN_UNLOCK(sc); + return (error); + } + bwn_start(sc); + BWN_UNLOCK(sc); + return (0); +} + +static void +bwn_start(struct bwn_softc *sc) +{ + struct bwn_mac *mac = sc->sc_curmac; + struct ieee80211_frame *wh; + struct ieee80211_node *ni; + struct ieee80211_key *k; + struct mbuf *m; + + BWN_ASSERT_LOCKED(sc); + + if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL || + mac->mac_status < BWN_MAC_STATUS_STARTED) + return; + + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { + if (bwn_tx_isfull(sc, m)) + break; + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + if (ni == NULL) { + device_printf(sc->sc_dev, "unexpected NULL ni\n"); + m_freem(m); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); + continue; + } + wh = mtod(m, struct ieee80211_frame *); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + k = ieee80211_crypto_encap(ni, m); + if (k == NULL) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + m_freem(m); + continue; + } + } + wh = NULL; /* Catch any invalid use */ + if (bwn_tx_start(sc, ni, m) != 0) { + if (ni != NULL) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + } + continue; + } + sc->sc_watchdog_timer = 5; + } +} + +static int +bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m) +{ + struct bwn_dma_ring *dr; + struct bwn_mac *mac = sc->sc_curmac; + struct bwn_pio_txqueue *tq; + int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); + + BWN_ASSERT_LOCKED(sc); + + if (mac->mac_flags & BWN_MAC_FLAG_DMA) { + dr = bwn_dma_select(mac, M_WME_GETAC(m)); + if (dr->dr_stop == 1 || + bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) { + dr->dr_stop = 1; + goto full; + } + } else { + tq = bwn_pio_select(mac, M_WME_GETAC(m)); + if (tq->tq_free == 0 || pktlen > tq->tq_size || + pktlen > (tq->tq_size - tq->tq_used)) + goto full; + } + return (0); +full: + mbufq_prepend(&sc->sc_snd, m); + return (1); +} + +static int +bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m) +{ + struct bwn_mac *mac = sc->sc_curmac; + int error; + + BWN_ASSERT_LOCKED(sc); + + if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) { + m_freem(m); + return (ENXIO); + } + + error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ? + bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m); + if (error) { + m_freem(m); + return (error); + } + return (0); +} + +static int +bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m) +{ + struct bwn_pio_txpkt *tp; + struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m)); + struct bwn_softc *sc = mac->mac_sc; + struct bwn_txhdr txhdr; + struct mbuf *m_new; + uint32_t ctl32; + int error; + uint16_t ctl16; + + BWN_ASSERT_LOCKED(sc); + + /* XXX TODO send packets after DTIM */ + + KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__)); + tp = TAILQ_FIRST(&tq->tq_pktlist); + tp->tp_ni = ni; + tp->tp_m = m; + + error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp)); + if (error) { + device_printf(sc->sc_dev, "tx fail\n"); + return (error); + } + + TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list); + tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); + tq->tq_free--; + + if (siba_get_revid(sc->sc_dev) >= 8) { + /* + * XXX please removes m_defrag(9) + */ + m_new = m_defrag(m, M_NOWAIT); + if (m_new == NULL) { + device_printf(sc->sc_dev, + "%s: can't defrag TX buffer\n", + __func__); + return (ENOBUFS); + } + if (m_new->m_next != NULL) + device_printf(sc->sc_dev, + "TODO: fragmented packets for PIO\n"); + tp->tp_m = m_new; + + /* send HEADER */ + ctl32 = bwn_pio_write_multi_4(mac, tq, + (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) | + BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF, + (const uint8_t *)&txhdr, BWN_HDRSIZE(mac)); + /* send BODY */ + ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32, + mtod(m_new, const void *), m_new->m_pkthdr.len); + bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL, + ctl32 | BWN_PIO8_TXCTL_EOF); + } else { + ctl16 = bwn_pio_write_multi_2(mac, tq, + (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) | + BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF, + (const uint8_t *)&txhdr, BWN_HDRSIZE(mac)); + ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m); + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, + ctl16 | BWN_PIO_TXCTL_EOF); + } + + return (0); +} + +static struct bwn_pio_txqueue * +bwn_pio_select(struct bwn_mac *mac, uint8_t prio) +{ + + if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0) + return (&mac->mac_method.pio.wme[WME_AC_BE]); + + switch (prio) { + case 0: + return (&mac->mac_method.pio.wme[WME_AC_BE]); + case 1: + return (&mac->mac_method.pio.wme[WME_AC_BK]); + case 2: + return (&mac->mac_method.pio.wme[WME_AC_VI]); + case 3: + return (&mac->mac_method.pio.wme[WME_AC_VO]); + } + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (NULL); +} + +static int +bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m) +{ +#define BWN_GET_TXHDRCACHE(slot) \ + &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)]) + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m)); + struct bwn_dmadesc_generic *desc; + struct bwn_dmadesc_meta *mt; + struct bwn_softc *sc = mac->mac_sc; + uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache; + int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot }; + + BWN_ASSERT_LOCKED(sc); + KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__)); + + /* XXX send after DTIM */ + + slot = bwn_dma_getslot(dr); + dr->getdesc(dr, slot, &desc, &mt); + KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER, + ("%s:%d: fail", __func__, __LINE__)); + + error = bwn_set_txhdr(dr->dr_mac, ni, m, + (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot), + BWN_DMA_COOKIE(dr, slot)); + if (error) + goto fail; + error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap, + BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr, + &mt->mt_paddr, BUS_DMA_NOWAIT); + if (error) { + device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n", + __func__, error); + goto fail; + } + bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap, + BUS_DMASYNC_PREWRITE); + dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0); + bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, + BUS_DMASYNC_PREWRITE); + + slot = bwn_dma_getslot(dr); + dr->getdesc(dr, slot, &desc, &mt); + KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY && + mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__)); + mt->mt_m = m; + mt->mt_ni = ni; + + error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m, + bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT); + if (error && error != EFBIG) { + device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n", + __func__, error); + goto fail; + } + if (error) { /* error == EFBIG */ + struct mbuf *m_new; + + m_new = m_defrag(m, M_NOWAIT); + if (m_new == NULL) { + device_printf(sc->sc_dev, + "%s: can't defrag TX buffer\n", + __func__); + error = ENOBUFS; + goto fail; + } else { + m = m_new; + } + + mt->mt_m = m; + error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, + m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT); + if (error) { + device_printf(sc->sc_dev, + "%s: can't load TX buffer (2) %d\n", + __func__, error); + goto fail; + } + } + bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE); + dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1); + bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, + BUS_DMASYNC_PREWRITE); + + /* XXX send after DTIM */ + + dr->start_transfer(dr, bwn_dma_nextslot(dr, slot)); + return (0); +fail: + dr->dr_curslot = backup[0]; + dr->dr_usedslot = backup[1]; + return (error); +#undef BWN_GET_TXHDRCACHE +} + +static void +bwn_watchdog(void *arg) +{ + struct bwn_softc *sc = arg; + + if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) { + device_printf(sc->sc_dev, "device timeout\n"); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); + } + callout_schedule(&sc->sc_watchdog_ch, hz); +} + +static int +bwn_attach_core(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + int error, have_bg = 0, have_a = 0; + uint32_t high; + + KASSERT(siba_get_revid(sc->sc_dev) >= 5, + ("unsupported revision %d", siba_get_revid(sc->sc_dev))); + + siba_powerup(sc->sc_dev, 0); + + high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH); + bwn_reset_core(mac, + (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0); + error = bwn_phy_getinfo(mac, high); + if (error) + goto fail; + + have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0; + have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0; + if (siba_get_pci_device(sc->sc_dev) != 0x4312 && + siba_get_pci_device(sc->sc_dev) != 0x4319 && + siba_get_pci_device(sc->sc_dev) != 0x4324) { + have_a = have_bg = 0; + if (mac->mac_phy.type == BWN_PHYTYPE_A) + have_a = 1; + else if (mac->mac_phy.type == BWN_PHYTYPE_G || + mac->mac_phy.type == BWN_PHYTYPE_N || + mac->mac_phy.type == BWN_PHYTYPE_LP) + have_bg = 1; + else + KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__, + mac->mac_phy.type)); + } + /* XXX turns off PHY A because it's not supported */ + if (mac->mac_phy.type != BWN_PHYTYPE_LP && + mac->mac_phy.type != BWN_PHYTYPE_N) { + have_a = 0; + have_bg = 1; + } + + if (mac->mac_phy.type == BWN_PHYTYPE_G) { + mac->mac_phy.attach = bwn_phy_g_attach; + mac->mac_phy.detach = bwn_phy_g_detach; + mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw; + mac->mac_phy.init_pre = bwn_phy_g_init_pre; + mac->mac_phy.init = bwn_phy_g_init; + mac->mac_phy.exit = bwn_phy_g_exit; + mac->mac_phy.phy_read = bwn_phy_g_read; + mac->mac_phy.phy_write = bwn_phy_g_write; + mac->mac_phy.rf_read = bwn_phy_g_rf_read; + mac->mac_phy.rf_write = bwn_phy_g_rf_write; + mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl; + mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff; + mac->mac_phy.switch_analog = bwn_phy_switch_analog; + mac->mac_phy.switch_channel = bwn_phy_g_switch_channel; + mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan; + mac->mac_phy.set_antenna = bwn_phy_g_set_antenna; + mac->mac_phy.set_im = bwn_phy_g_im; + mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr; + mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr; + mac->mac_phy.task_15s = bwn_phy_g_task_15s; + mac->mac_phy.task_60s = bwn_phy_g_task_60s; + } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) { + mac->mac_phy.init_pre = bwn_phy_lp_init_pre; + mac->mac_phy.init = bwn_phy_lp_init; + mac->mac_phy.phy_read = bwn_phy_lp_read; + mac->mac_phy.phy_write = bwn_phy_lp_write; + mac->mac_phy.phy_maskset = bwn_phy_lp_maskset; + mac->mac_phy.rf_read = bwn_phy_lp_rf_read; + mac->mac_phy.rf_write = bwn_phy_lp_rf_write; + mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff; + mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog; + mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel; + mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan; + mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna; + mac->mac_phy.task_60s = bwn_phy_lp_task_60s; + } else { + device_printf(sc->sc_dev, "unsupported PHY type (%d)\n", + mac->mac_phy.type); + error = ENXIO; + goto fail; + } + + mac->mac_phy.gmode = have_bg; + if (mac->mac_phy.attach != NULL) { + error = mac->mac_phy.attach(mac); + if (error) { + device_printf(sc->sc_dev, "failed\n"); + goto fail; + } + } + + bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0); + + error = bwn_chiptest(mac); + if (error) + goto fail; + error = bwn_setup_channels(mac, have_bg, have_a); + if (error) { + device_printf(sc->sc_dev, "failed to setup channels\n"); + goto fail; + } + + if (sc->sc_curmac == NULL) + sc->sc_curmac = mac; + + error = bwn_dma_attach(mac); + if (error != 0) { + device_printf(sc->sc_dev, "failed to initialize DMA\n"); + goto fail; + } + + mac->mac_phy.switch_analog(mac, 0); + + siba_dev_down(sc->sc_dev, 0); +fail: + siba_powerdown(sc->sc_dev); + return (error); +} + +void +bwn_reset_core(struct bwn_mac *mac, uint32_t flags) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t low, ctl; + + flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET); + + siba_dev_up(sc->sc_dev, flags); + DELAY(2000); + + low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) & + ~BWN_TGSLOW_PHYRESET; + siba_write_4(sc->sc_dev, SIBA_TGSLOW, low); + siba_read_4(sc->sc_dev, SIBA_TGSLOW); + DELAY(1000); + siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC); + siba_read_4(sc->sc_dev, SIBA_TGSLOW); + DELAY(1000); + + if (mac->mac_phy.switch_analog != NULL) + mac->mac_phy.switch_analog(mac, 1); + + ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE; + if (flags & BWN_TGSLOW_SUPPORT_G) + ctl |= BWN_MACCTL_GMODE; + BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON); +} + +static int +bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh) +{ + struct bwn_phy *phy = &mac->mac_phy; + struct bwn_softc *sc = mac->mac_sc; + uint32_t tmp; + + /* PHY */ + tmp = BWN_READ_2(mac, BWN_PHYVER); + phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0; + phy->rf_on = 1; + phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12; + phy->type = (tmp & BWN_PHYVER_TYPE) >> 8; + phy->rev = (tmp & BWN_PHYVER_VERSION); + if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) || + (phy->type == BWN_PHYTYPE_B && phy->rev != 2 && + phy->rev != 4 && phy->rev != 6 && phy->rev != 7) || + (phy->type == BWN_PHYTYPE_G && phy->rev > 9) || + (phy->type == BWN_PHYTYPE_N && phy->rev > 4) || + (phy->type == BWN_PHYTYPE_LP && phy->rev > 2)) + goto unsupphy; + + /* RADIO */ + if (siba_get_chipid(sc->sc_dev) == 0x4317) { + if (siba_get_chiprev(sc->sc_dev) == 0) + tmp = 0x3205017f; + else if (siba_get_chiprev(sc->sc_dev) == 1) + tmp = 0x4205017f; + else + tmp = 0x5205017f; + } else { + BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID); + tmp = BWN_READ_2(mac, BWN_RFDATALO); + BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID); + tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16; + } + phy->rf_rev = (tmp & 0xf0000000) >> 28; + phy->rf_ver = (tmp & 0x0ffff000) >> 12; + phy->rf_manuf = (tmp & 0x00000fff); + if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */ + goto unsupradio; + if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 || + phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) || + (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) || + (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) || + (phy->type == BWN_PHYTYPE_N && + phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) || + (phy->type == BWN_PHYTYPE_LP && + phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063)) + goto unsupradio; + + return (0); +unsupphy: + device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, " + "analog %#x)\n", + phy->type, phy->rev, phy->analog); + return (ENXIO); +unsupradio: + device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, " + "rev %#x)\n", + phy->rf_manuf, phy->rf_ver, phy->rf_rev); + return (ENXIO); +} + +static int +bwn_chiptest(struct bwn_mac *mac) +{ +#define TESTVAL0 0x55aaaa55 +#define TESTVAL1 0xaa5555aa + struct bwn_softc *sc = mac->mac_sc; + uint32_t v, backup; + + BWN_LOCK(sc); + + backup = bwn_shm_read_4(mac, BWN_SHARED, 0); + + bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0); + if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0) + goto error; + bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1); + if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1) + goto error; + + bwn_shm_write_4(mac, BWN_SHARED, 0, backup); + + if ((siba_get_revid(sc->sc_dev) >= 3) && + (siba_get_revid(sc->sc_dev) <= 10)) { + BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa); + BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb); + if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb) + goto error; + if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc) + goto error; + } + BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0); + + v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE; + if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON)) + goto error; + + BWN_UNLOCK(sc); + return (0); +error: + BWN_UNLOCK(sc); + device_printf(sc->sc_dev, "failed to validate the chipaccess\n"); + return (ENODEV); +} + +#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT | IEEE80211_CHAN_G) +#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT | IEEE80211_CHAN_A) + +static int +bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + + memset(ic->ic_channels, 0, sizeof(ic->ic_channels)); + ic->ic_nchans = 0; + + if (have_bg) + bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX, + &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G); + if (mac->mac_phy.type == BWN_PHYTYPE_N) { + if (have_a) + bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX, + &ic->ic_nchans, &bwn_chantable_n, + IEEE80211_CHAN_HTA); + } else { + if (have_a) + bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX, + &ic->ic_nchans, &bwn_chantable_a, + IEEE80211_CHAN_A); + } + + mac->mac_phy.supports_2ghz = have_bg; + mac->mac_phy.supports_5ghz = have_a; + + return (ic->ic_nchans == 0 ? ENXIO : 0); +} + +uint32_t +bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset) +{ + uint32_t ret; + + BWN_ASSERT_LOCKED(mac->mac_sc); + + if (way == BWN_SHARED) { + KASSERT((offset & 0x0001) == 0, + ("%s:%d warn", __func__, __LINE__)); + if (offset & 0x0003) { + bwn_shm_ctlword(mac, way, offset >> 2); + ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED); + ret <<= 16; + bwn_shm_ctlword(mac, way, (offset >> 2) + 1); + ret |= BWN_READ_2(mac, BWN_SHM_DATA); + goto out; + } + offset >>= 2; + } + bwn_shm_ctlword(mac, way, offset); + ret = BWN_READ_4(mac, BWN_SHM_DATA); +out: + return (ret); +} + +uint16_t +bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset) +{ + uint16_t ret; + + BWN_ASSERT_LOCKED(mac->mac_sc); + + if (way == BWN_SHARED) { + KASSERT((offset & 0x0001) == 0, + ("%s:%d warn", __func__, __LINE__)); + if (offset & 0x0003) { + bwn_shm_ctlword(mac, way, offset >> 2); + ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED); + goto out; + } + offset >>= 2; + } + bwn_shm_ctlword(mac, way, offset); + ret = BWN_READ_2(mac, BWN_SHM_DATA); +out: + + return (ret); +} + +static void +bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way, + uint16_t offset) +{ + uint32_t control; + + control = way; + control <<= 16; + control |= offset; + BWN_WRITE_4(mac, BWN_SHM_CONTROL, control); +} + +void +bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset, + uint32_t value) +{ + BWN_ASSERT_LOCKED(mac->mac_sc); + + if (way == BWN_SHARED) { + KASSERT((offset & 0x0001) == 0, + ("%s:%d warn", __func__, __LINE__)); + if (offset & 0x0003) { + bwn_shm_ctlword(mac, way, offset >> 2); + BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, + (value >> 16) & 0xffff); + bwn_shm_ctlword(mac, way, (offset >> 2) + 1); + BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff); + return; + } + offset >>= 2; + } + bwn_shm_ctlword(mac, way, offset); + BWN_WRITE_4(mac, BWN_SHM_DATA, value); +} + +void +bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset, + uint16_t value) +{ + BWN_ASSERT_LOCKED(mac->mac_sc); + + if (way == BWN_SHARED) { + KASSERT((offset & 0x0001) == 0, + ("%s:%d warn", __func__, __LINE__)); + if (offset & 0x0003) { + bwn_shm_ctlword(mac, way, offset >> 2); + BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value); + return; + } + offset >>= 2; + } + bwn_shm_ctlword(mac, way, offset); + BWN_WRITE_2(mac, BWN_SHM_DATA, value); +} + +static void +bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee, + int txpow) +{ + + c->ic_freq = freq; + c->ic_flags = flags; + c->ic_ieee = ieee; + c->ic_minpower = 0; + c->ic_maxpower = 2 * txpow; + c->ic_maxregpower = txpow; +} + +static void +bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans, + const struct bwn_channelinfo *ci, int flags) +{ + struct ieee80211_channel *c; + int i; + + c = &chans[*nchans]; + + for (i = 0; i < ci->nchannels; i++) { + const struct bwn_channel *hc; + + hc = &ci->channels[i]; + if (*nchans >= maxchans) + break; + bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow); + c++, (*nchans)++; + if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) { + /* g channel have a separate b-only entry */ + if (*nchans >= maxchans) + break; + c[0] = c[-1]; + c[-1].ic_flags = IEEE80211_CHAN_B; + c++, (*nchans)++; + } + if (flags == IEEE80211_CHAN_HTG) { + /* HT g channel have a separate g-only entry */ + if (*nchans >= maxchans) + break; + c[-1].ic_flags = IEEE80211_CHAN_G; + c[0] = c[-1]; + c[0].ic_flags &= ~IEEE80211_CHAN_HT; + c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */ + c++, (*nchans)++; + } + if (flags == IEEE80211_CHAN_HTA) { + /* HT a channel have a separate a-only entry */ + if (*nchans >= maxchans) + break; + c[-1].ic_flags = IEEE80211_CHAN_A; + c[0] = c[-1]; + c[0].ic_flags &= ~IEEE80211_CHAN_HT; + c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */ + c++, (*nchans)++; + } + } +} + +static int +bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params) +{ + struct ieee80211com *ic = ni->ni_ic; + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac = sc->sc_curmac; + int error; + + if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || + mac->mac_status < BWN_MAC_STATUS_STARTED) { + m_freem(m); + return (ENETDOWN); + } + + BWN_LOCK(sc); + if (bwn_tx_isfull(sc, m)) { + m_freem(m); + BWN_UNLOCK(sc); + return (ENOBUFS); + } + + error = bwn_tx_start(sc, ni, m); + if (error == 0) + sc->sc_watchdog_timer = 5; + BWN_UNLOCK(sc); + return (error); +} + +/* + * Callback from the 802.11 layer to update the slot time + * based on the current setting. We use it to notify the + * firmware of ERP changes and the f/w takes care of things + * like slot time and preamble. + */ +static void +bwn_updateslot(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac; + + BWN_LOCK(sc); + if (sc->sc_flags & BWN_FLAG_RUNNING) { + mac = (struct bwn_mac *)sc->sc_curmac; + bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic)); + } + BWN_UNLOCK(sc); +} + +/* + * Callback from the 802.11 layer after a promiscuous mode change. + * Note this interface does not check the operating mode as this + * is an internal callback and we are expected to honor the current + * state (e.g. this is used for setting the interface in promiscuous + * mode when operating in hostap mode to do ACS). + */ +static void +bwn_update_promisc(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac = sc->sc_curmac; + + BWN_LOCK(sc); + mac = sc->sc_curmac; + if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { + if (ic->ic_promisc > 0) + sc->sc_filters |= BWN_MACCTL_PROMISC; + else + sc->sc_filters &= ~BWN_MACCTL_PROMISC; + bwn_set_opmode(mac); + } + BWN_UNLOCK(sc); +} + +/* + * Callback from the 802.11 layer to update WME parameters. + */ +static int +bwn_wme_update(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac = sc->sc_curmac; + struct wmeParams *wmep; + int i; + + BWN_LOCK(sc); + mac = sc->sc_curmac; + if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { + bwn_mac_suspend(mac); + for (i = 0; i < N(sc->sc_wmeParams); i++) { + wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i]; + bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]); + } + bwn_mac_enable(mac); + } + BWN_UNLOCK(sc); + return (0); +} + +static void +bwn_scan_start(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac; + + BWN_LOCK(sc); + mac = sc->sc_curmac; + if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { + sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC; + bwn_set_opmode(mac); + /* disable CFP update during scan */ + bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE); + } + BWN_UNLOCK(sc); +} + +static void +bwn_scan_end(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac; + + BWN_LOCK(sc); + mac = sc->sc_curmac; + if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { + sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC; + bwn_set_opmode(mac); + bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE); + } + BWN_UNLOCK(sc); +} + +static void +bwn_set_channel(struct ieee80211com *ic) +{ + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac = sc->sc_curmac; + struct bwn_phy *phy = &mac->mac_phy; + int chan, error; + + BWN_LOCK(sc); + + error = bwn_switch_band(sc, ic->ic_curchan); + if (error) + goto fail; + bwn_mac_suspend(mac); + bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG); + chan = ieee80211_chan2ieee(ic, ic->ic_curchan); + if (chan != phy->chan) + bwn_switch_channel(mac, chan); + + /* TX power level */ + if (ic->ic_curchan->ic_maxpower != 0 && + ic->ic_curchan->ic_maxpower != phy->txpower) { + phy->txpower = ic->ic_curchan->ic_maxpower / 2; + bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME | + BWN_TXPWR_IGNORE_TSSI); + } + + bwn_set_txantenna(mac, BWN_ANT_DEFAULT); + if (phy->set_antenna) + phy->set_antenna(mac, BWN_ANT_DEFAULT); + + if (sc->sc_rf_enabled != phy->rf_on) { + if (sc->sc_rf_enabled) { + bwn_rf_turnon(mac); + if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)) + device_printf(sc->sc_dev, + "please turn on the RF switch\n"); + } else + bwn_rf_turnoff(mac); + } + + bwn_mac_enable(mac); + +fail: + /* + * Setup radio tap channel freq and flags + */ + sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = + htole16(ic->ic_curchan->ic_freq); + sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = + htole16(ic->ic_curchan->ic_flags & 0xffff); + + BWN_UNLOCK(sc); +} + +static struct ieee80211vap * +bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, + enum ieee80211_opmode opmode, int flags, + const uint8_t bssid[IEEE80211_ADDR_LEN], + const uint8_t mac[IEEE80211_ADDR_LEN]) +{ + struct ieee80211vap *vap; + struct bwn_vap *bvp; + + switch (opmode) { + case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: + case IEEE80211_M_STA: + case IEEE80211_M_WDS: + case IEEE80211_M_MONITOR: + case IEEE80211_M_IBSS: + case IEEE80211_M_AHDEMO: + break; + default: + return (NULL); + } + + bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO); + vap = &bvp->bv_vap; + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); + /* override with driver methods */ + bvp->bv_newstate = vap->iv_newstate; + vap->iv_newstate = bwn_newstate; + + /* override max aid so sta's cannot assoc when we're out of sta id's */ + vap->iv_max_aid = BWN_STAID_MAX; + + ieee80211_ratectl_init(vap); + + /* complete setup */ + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); + return (vap); +} + +static void +bwn_vap_delete(struct ieee80211vap *vap) +{ + struct bwn_vap *bvp = BWN_VAP(vap); + + ieee80211_ratectl_deinit(vap); + ieee80211_vap_detach(vap); + free(bvp, M_80211_VAP); +} + +static int +bwn_init(struct bwn_softc *sc) +{ + struct bwn_mac *mac; + int error; + + BWN_ASSERT_LOCKED(sc); + + bzero(sc->sc_bssid, IEEE80211_ADDR_LEN); + sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP; + sc->sc_filters = 0; + bwn_wme_clear(sc); + sc->sc_beacons[0] = sc->sc_beacons[1] = 0; + sc->sc_rf_enabled = 1; + + mac = sc->sc_curmac; + if (mac->mac_status == BWN_MAC_STATUS_UNINIT) { + error = bwn_core_init(mac); + if (error != 0) + return (error); + } + if (mac->mac_status == BWN_MAC_STATUS_INITED) + bwn_core_start(mac); + + bwn_set_opmode(mac); + bwn_set_pretbtt(mac); + bwn_spu_setdelay(mac, 0); + bwn_set_macaddr(mac); + + sc->sc_flags |= BWN_FLAG_RUNNING; + callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc); + callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc); + + return (0); +} + +static void +bwn_stop(struct bwn_softc *sc) +{ + struct bwn_mac *mac = sc->sc_curmac; + + BWN_ASSERT_LOCKED(sc); + + if (mac->mac_status >= BWN_MAC_STATUS_INITED) { + /* XXX FIXME opmode not based on VAP */ + bwn_set_opmode(mac); + bwn_set_macaddr(mac); + } + + if (mac->mac_status >= BWN_MAC_STATUS_STARTED) + bwn_core_stop(mac); + + callout_stop(&sc->sc_led_blink_ch); + sc->sc_led_blinking = 0; + + bwn_core_exit(mac); + sc->sc_rf_enabled = 0; + + sc->sc_flags &= ~BWN_FLAG_RUNNING; +} + +static void +bwn_wme_clear(struct bwn_softc *sc) +{ +#define MS(_v, _f) (((_v) & _f) >> _f##_S) + struct wmeParams *p; + unsigned int i; + + KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams), + ("%s:%d: fail", __func__, __LINE__)); + + for (i = 0; i < N(sc->sc_wmeParams); i++) { + p = &(sc->sc_wmeParams[i]); + + switch (bwn_wme_shm_offsets[i]) { + case BWN_WME_VOICE: + p->wmep_txopLimit = 0; + p->wmep_aifsn = 2; + /* XXX FIXME: log2(cwmin) */ + p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); + p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX); + break; + case BWN_WME_VIDEO: + p->wmep_txopLimit = 0; + p->wmep_aifsn = 2; + /* XXX FIXME: log2(cwmin) */ + p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); + p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX); + break; + case BWN_WME_BESTEFFORT: + p->wmep_txopLimit = 0; + p->wmep_aifsn = 3; + /* XXX FIXME: log2(cwmin) */ + p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); + p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX); + break; + case BWN_WME_BACKGROUND: + p->wmep_txopLimit = 0; + p->wmep_aifsn = 7; + /* XXX FIXME: log2(cwmin) */ + p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); + p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX); + break; + default: + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + } + } +} + +static int +bwn_core_init(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint64_t hf; + int error; + + KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT, + ("%s:%d: fail", __func__, __LINE__)); + + siba_powerup(sc->sc_dev, 0); + if (!siba_dev_isup(sc->sc_dev)) + bwn_reset_core(mac, + mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0); + + mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID; + mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON; + mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0; + BWN_GETTIME(mac->mac_phy.nexttime); + mac->mac_phy.txerrors = BWN_TXERROR_MAX; + bzero(&mac->mac_stats, sizeof(mac->mac_stats)); + mac->mac_stats.link_noise = -95; + mac->mac_reason_intr = 0; + bzero(mac->mac_reason, sizeof(mac->mac_reason)); + mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE; +#ifdef BWN_DEBUG + if (sc->sc_debug & BWN_DEBUG_XMIT) + mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR; +#endif + mac->mac_suspended = 1; + mac->mac_task_state = 0; + memset(&mac->mac_noise, 0, sizeof(mac->mac_noise)); + + mac->mac_phy.init_pre(mac); + + siba_pcicore_intr(sc->sc_dev); + + siba_fix_imcfglobug(sc->sc_dev); + bwn_bt_disable(mac); + if (mac->mac_phy.prepare_hw) { + error = mac->mac_phy.prepare_hw(mac); + if (error) + goto fail0; + } + error = bwn_chip_init(mac); + if (error) + goto fail0; + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV, + siba_get_revid(sc->sc_dev)); + hf = bwn_hf_read(mac); + if (mac->mac_phy.type == BWN_PHYTYPE_G) { + hf |= BWN_HF_GPHY_SYM_WORKAROUND; + if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) + hf |= BWN_HF_PAGAINBOOST_OFDM_ON; + if (mac->mac_phy.rev == 1) + hf |= BWN_HF_GPHY_DC_CANCELFILTER; + } + if (mac->mac_phy.rf_ver == 0x2050) { + if (mac->mac_phy.rf_rev < 6) + hf |= BWN_HF_FORCE_VCO_RECALC; + if (mac->mac_phy.rf_rev == 6) + hf |= BWN_HF_4318_TSSI; + } + if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW) + hf |= BWN_HF_SLOWCLOCK_REQ_OFF; + if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) && + (siba_get_pcicore_revid(sc->sc_dev) <= 10)) + hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND; + hf &= ~BWN_HF_SKIP_CFP_UPDATE; + bwn_hf_write(mac, hf); + + bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1); + + bwn_rate_init(mac); + bwn_set_phytxctl(mac); + + bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN, + (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf); + bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff); + + if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0) + bwn_pio_init(mac); + else + bwn_dma_init(mac); + bwn_wme_init(mac); + bwn_spu_setdelay(mac, 1); + bwn_bt_enable(mac); + + siba_powerup(sc->sc_dev, + !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)); + bwn_set_macaddr(mac); + bwn_crypt_init(mac); + + /* XXX LED initializatin */ + + mac->mac_status = BWN_MAC_STATUS_INITED; + + return (error); + +fail0: + siba_powerdown(sc->sc_dev); + KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT, + ("%s:%d: fail", __func__, __LINE__)); + return (error); +} + +static void +bwn_core_start(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t tmp; + + KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED, + ("%s:%d: fail", __func__, __LINE__)); + + if (siba_get_revid(sc->sc_dev) < 5) + return; + + while (1) { + tmp = BWN_READ_4(mac, BWN_XMITSTAT_0); + if (!(tmp & 0x00000001)) + break; + tmp = BWN_READ_4(mac, BWN_XMITSTAT_1); + } + + bwn_mac_enable(mac); + BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask); + callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac); + + mac->mac_status = BWN_MAC_STATUS_STARTED; +} + +static void +bwn_core_exit(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t macctl; + + BWN_ASSERT_LOCKED(mac->mac_sc); + + KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED, + ("%s:%d: fail", __func__, __LINE__)); + + if (mac->mac_status != BWN_MAC_STATUS_INITED) + return; + mac->mac_status = BWN_MAC_STATUS_UNINIT; + + macctl = BWN_READ_4(mac, BWN_MACCTL); + macctl &= ~BWN_MACCTL_MCODE_RUN; + macctl |= BWN_MACCTL_MCODE_JMP0; + BWN_WRITE_4(mac, BWN_MACCTL, macctl); + + bwn_dma_stop(mac); + bwn_pio_stop(mac); + bwn_chip_exit(mac); + mac->mac_phy.switch_analog(mac, 0); + siba_dev_down(sc->sc_dev, 0); + siba_powerdown(sc->sc_dev); +} + +static void +bwn_bt_disable(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + + (void)sc; + /* XXX do nothing yet */ +} + +static int +bwn_chip_init(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + struct bwn_phy *phy = &mac->mac_phy; + uint32_t macctl; + int error; + + macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA; + if (phy->gmode) + macctl |= BWN_MACCTL_GMODE; + BWN_WRITE_4(mac, BWN_MACCTL, macctl); + + error = bwn_fw_fillinfo(mac); + if (error) + return (error); + error = bwn_fw_loaducode(mac); + if (error) + return (error); + + error = bwn_gpio_init(mac); + if (error) + return (error); + + error = bwn_fw_loadinitvals(mac); + if (error) { + siba_gpio_set(sc->sc_dev, 0); + return (error); + } + phy->switch_analog(mac, 1); + error = bwn_phy_init(mac); + if (error) { + siba_gpio_set(sc->sc_dev, 0); + return (error); + } + if (phy->set_im) + phy->set_im(mac, BWN_IMMODE_NONE); + if (phy->set_antenna) + phy->set_antenna(mac, BWN_ANT_DEFAULT); + bwn_set_txantenna(mac, BWN_ANT_DEFAULT); + + if (phy->type == BWN_PHYTYPE_B) + BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004); + BWN_WRITE_4(mac, 0x0100, 0x01000000); + if (siba_get_revid(sc->sc_dev) < 5) + BWN_WRITE_4(mac, 0x010c, 0x01000000); + + BWN_WRITE_4(mac, BWN_MACCTL, + BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA); + BWN_WRITE_4(mac, BWN_MACCTL, + BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA); + bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000); + + bwn_set_opmode(mac); + if (siba_get_revid(sc->sc_dev) < 3) { + BWN_WRITE_2(mac, 0x060e, 0x0000); + BWN_WRITE_2(mac, 0x0610, 0x8000); + BWN_WRITE_2(mac, 0x0604, 0x0000); + BWN_WRITE_2(mac, 0x0606, 0x0200); + } else { + BWN_WRITE_4(mac, 0x0188, 0x80000000); + BWN_WRITE_4(mac, 0x018c, 0x02000000); + } + BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000); + BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00); + BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00); + BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00); + BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00); + BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00); + BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00); + siba_write_4(sc->sc_dev, SIBA_TGSLOW, + siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000); + BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev)); + return (error); +} + +/* read hostflags */ +uint64_t +bwn_hf_read(struct bwn_mac *mac) +{ + uint64_t ret; + + ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI); + ret <<= 16; + ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI); + ret <<= 16; + ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO); + return (ret); +} + +void +bwn_hf_write(struct bwn_mac *mac, uint64_t value) +{ + + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO, + (value & 0x00000000ffffull)); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI, + (value & 0x0000ffff0000ull) >> 16); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI, + (value & 0xffff00000000ULL) >> 32); +} + +static void +bwn_set_txretry(struct bwn_mac *mac, int s, int l) +{ + + bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf)); + bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf)); +} + +static void +bwn_rate_init(struct bwn_mac *mac) +{ + + switch (mac->mac_phy.type) { + case BWN_PHYTYPE_A: + case BWN_PHYTYPE_G: + case BWN_PHYTYPE_LP: + case BWN_PHYTYPE_N: + bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1); + bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1); + bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1); + bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1); + bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1); + bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1); + bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1); + if (mac->mac_phy.type == BWN_PHYTYPE_A) + break; + /* FALLTHROUGH */ + case BWN_PHYTYPE_B: + bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0); + bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0); + bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0); + bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0); + break; + default: + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + } +} + +static void +bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm) +{ + uint16_t offset; + + if (ofdm) { + offset = 0x480; + offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2; + } else { + offset = 0x4c0; + offset += (bwn_plcp_getcck(rate) & 0x000f) * 2; + } + bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20, + bwn_shm_read_2(mac, BWN_SHARED, offset)); +} + +static uint8_t +bwn_plcp_getcck(const uint8_t bitrate) +{ + + switch (bitrate) { + case BWN_CCK_RATE_1MB: + return (0x0a); + case BWN_CCK_RATE_2MB: + return (0x14); + case BWN_CCK_RATE_5MB: + return (0x37); + case BWN_CCK_RATE_11MB: + return (0x6e); + } + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (0); +} + +static uint8_t +bwn_plcp_getofdm(const uint8_t bitrate) +{ + + switch (bitrate) { + case BWN_OFDM_RATE_6MB: + return (0xb); + case BWN_OFDM_RATE_9MB: + return (0xf); + case BWN_OFDM_RATE_12MB: + return (0xa); + case BWN_OFDM_RATE_18MB: + return (0xe); + case BWN_OFDM_RATE_24MB: + return (0x9); + case BWN_OFDM_RATE_36MB: + return (0xd); + case BWN_OFDM_RATE_48MB: + return (0x8); + case BWN_OFDM_RATE_54MB: + return (0xc); + } + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (0); +} + +static void +bwn_set_phytxctl(struct bwn_mac *mac) +{ + uint16_t ctl; + + ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO | + BWN_TX_PHY_TXPWR); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl); +} + +static void +bwn_pio_init(struct bwn_mac *mac) +{ + struct bwn_pio *pio = &mac->mac_method.pio; + + BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL) + & ~BWN_MACCTL_BIGENDIAN); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0); + + bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0); + bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1); + bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2); + bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3); + bwn_pio_set_txqueue(mac, &pio->mcast, 4); + bwn_pio_setupqueue_rx(mac, &pio->rx, 0); +} + +static void +bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, + int index) +{ + struct bwn_pio_txpkt *tp; + struct bwn_softc *sc = mac->mac_sc; + unsigned int i; + + tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac); + tq->tq_index = index; + + tq->tq_free = BWN_PIO_MAX_TXPACKETS; + if (siba_get_revid(sc->sc_dev) >= 8) + tq->tq_size = 1920; + else { + tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE); + tq->tq_size -= 80; + } + + TAILQ_INIT(&tq->tq_pktlist); + for (i = 0; i < N(tq->tq_pkts); i++) { + tp = &(tq->tq_pkts[i]); + tp->tp_index = i; + tp->tp_queue = tq; + TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list); + } +} + +static uint16_t +bwn_pio_idx2base(struct bwn_mac *mac, int index) +{ + struct bwn_softc *sc = mac->mac_sc; + static const uint16_t bases[] = { + BWN_PIO_BASE0, + BWN_PIO_BASE1, + BWN_PIO_BASE2, + BWN_PIO_BASE3, + BWN_PIO_BASE4, + BWN_PIO_BASE5, + BWN_PIO_BASE6, + BWN_PIO_BASE7, + }; + static const uint16_t bases_rev11[] = { + BWN_PIO11_BASE0, + BWN_PIO11_BASE1, + BWN_PIO11_BASE2, + BWN_PIO11_BASE3, + BWN_PIO11_BASE4, + BWN_PIO11_BASE5, + }; + + if (siba_get_revid(sc->sc_dev) >= 11) { + if (index >= N(bases_rev11)) + device_printf(sc->sc_dev, "%s: warning\n", __func__); + return (bases_rev11[index]); + } + if (index >= N(bases)) + device_printf(sc->sc_dev, "%s: warning\n", __func__); + return (bases[index]); +} + +static void +bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq, + int index) +{ + struct bwn_softc *sc = mac->mac_sc; + + prq->prq_mac = mac; + prq->prq_rev = siba_get_revid(sc->sc_dev); + prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac); + bwn_dma_rxdirectfifo(mac, index, 1); +} + +static void +bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq) +{ + if (tq == NULL) + return; + bwn_pio_cancel_tx_packets(tq); +} + +static void +bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio) +{ + + bwn_destroy_pioqueue_tx(pio); +} + +static uint16_t +bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, + uint16_t offset) +{ + + return (BWN_READ_2(mac, tq->tq_base + offset)); +} + +static void +bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable) +{ + uint32_t ctl; + int type; + uint16_t base; + + type = bwn_dma_mask2type(bwn_dma_mask(mac)); + base = bwn_dma_base(type, idx); + if (type == BWN_DMA_64BIT) { + ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL); + ctl &= ~BWN_DMA64_RXDIRECTFIFO; + if (enable) + ctl |= BWN_DMA64_RXDIRECTFIFO; + BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl); + } else { + ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL); + ctl &= ~BWN_DMA32_RXDIRECTFIFO; + if (enable) + ctl |= BWN_DMA32_RXDIRECTFIFO; + BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl); + } +} + +static uint64_t +bwn_dma_mask(struct bwn_mac *mac) +{ + uint32_t tmp; + uint16_t base; + + tmp = BWN_READ_4(mac, SIBA_TGSHIGH); + if (tmp & SIBA_TGSHIGH_DMA64) + return (BWN_DMA_BIT_MASK(64)); + base = bwn_dma_base(0, 0); + BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK); + tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL); + if (tmp & BWN_DMA32_TXADDREXT_MASK) + return (BWN_DMA_BIT_MASK(32)); + + return (BWN_DMA_BIT_MASK(30)); +} + +static int +bwn_dma_mask2type(uint64_t dmamask) +{ + + if (dmamask == BWN_DMA_BIT_MASK(30)) + return (BWN_DMA_30BIT); + if (dmamask == BWN_DMA_BIT_MASK(32)) + return (BWN_DMA_32BIT); + if (dmamask == BWN_DMA_BIT_MASK(64)) + return (BWN_DMA_64BIT); + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (BWN_DMA_30BIT); +} + +static void +bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq) +{ + struct bwn_pio_txpkt *tp; + unsigned int i; + + for (i = 0; i < N(tq->tq_pkts); i++) { + tp = &(tq->tq_pkts[i]); + if (tp->tp_m) { + m_freem(tp->tp_m); + tp->tp_m = NULL; + } + } +} + +static uint16_t +bwn_dma_base(int type, int controller_idx) +{ + static const uint16_t map64[] = { + BWN_DMA64_BASE0, + BWN_DMA64_BASE1, + BWN_DMA64_BASE2, + BWN_DMA64_BASE3, + BWN_DMA64_BASE4, + BWN_DMA64_BASE5, + }; + static const uint16_t map32[] = { + BWN_DMA32_BASE0, + BWN_DMA32_BASE1, + BWN_DMA32_BASE2, + BWN_DMA32_BASE3, + BWN_DMA32_BASE4, + BWN_DMA32_BASE5, + }; + + if (type == BWN_DMA_64BIT) { + KASSERT(controller_idx >= 0 && controller_idx < N(map64), + ("%s:%d: fail", __func__, __LINE__)); + return (map64[controller_idx]); + } + KASSERT(controller_idx >= 0 && controller_idx < N(map32), + ("%s:%d: fail", __func__, __LINE__)); + return (map32[controller_idx]); +} + +static void +bwn_dma_init(struct bwn_mac *mac) +{ + struct bwn_dma *dma = &mac->mac_method.dma; + + /* setup TX DMA channels. */ + bwn_dma_setup(dma->wme[WME_AC_BK]); + bwn_dma_setup(dma->wme[WME_AC_BE]); + bwn_dma_setup(dma->wme[WME_AC_VI]); + bwn_dma_setup(dma->wme[WME_AC_VO]); + bwn_dma_setup(dma->mcast); + /* setup RX DMA channel. */ + bwn_dma_setup(dma->rx); +} + +static struct bwn_dma_ring * +bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index, + int for_tx, int type) +{ + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_dma_ring *dr; + struct bwn_dmadesc_generic *desc; + struct bwn_dmadesc_meta *mt; + struct bwn_softc *sc = mac->mac_sc; + int error, i; + + dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO); + if (dr == NULL) + goto out; + dr->dr_numslots = BWN_RXRING_SLOTS; + if (for_tx) + dr->dr_numslots = BWN_TXRING_SLOTS; + + dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta), + M_DEVBUF, M_NOWAIT | M_ZERO); + if (dr->dr_meta == NULL) + goto fail0; + + dr->dr_type = type; + dr->dr_mac = mac; + dr->dr_base = bwn_dma_base(type, controller_index); + dr->dr_index = controller_index; + if (type == BWN_DMA_64BIT) { + dr->getdesc = bwn_dma_64_getdesc; + dr->setdesc = bwn_dma_64_setdesc; + dr->start_transfer = bwn_dma_64_start_transfer; + dr->suspend = bwn_dma_64_suspend; + dr->resume = bwn_dma_64_resume; + dr->get_curslot = bwn_dma_64_get_curslot; + dr->set_curslot = bwn_dma_64_set_curslot; + } else { + dr->getdesc = bwn_dma_32_getdesc; + dr->setdesc = bwn_dma_32_setdesc; + dr->start_transfer = bwn_dma_32_start_transfer; + dr->suspend = bwn_dma_32_suspend; + dr->resume = bwn_dma_32_resume; + dr->get_curslot = bwn_dma_32_get_curslot; + dr->set_curslot = bwn_dma_32_set_curslot; + } + if (for_tx) { + dr->dr_tx = 1; + dr->dr_curslot = -1; + } else { + if (dr->dr_index == 0) { + dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE; + dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET; + } else + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + } + + error = bwn_dma_allocringmemory(dr); + if (error) + goto fail2; + + if (for_tx) { + /* + * Assumption: BWN_TXRING_SLOTS can be divided by + * BWN_TX_SLOTS_PER_FRAME + */ + KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0, + ("%s:%d: fail", __func__, __LINE__)); + + dr->dr_txhdr_cache = + malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) * + BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO); + KASSERT(dr->dr_txhdr_cache != NULL, + ("%s:%d: fail", __func__, __LINE__)); + + /* + * Create TX ring DMA stuffs + */ + error = bus_dma_tag_create(dma->parent_dtag, + BWN_ALIGN, 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + BWN_HDRSIZE(mac), + 1, + BUS_SPACE_MAXSIZE_32BIT, + 0, + NULL, NULL, + &dr->dr_txring_dtag); + if (error) { + device_printf(sc->sc_dev, + "can't create TX ring DMA tag: TODO frees\n"); + goto fail1; + } + + for (i = 0; i < dr->dr_numslots; i += 2) { + dr->getdesc(dr, i, &desc, &mt); + + mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER; + mt->mt_m = NULL; + mt->mt_ni = NULL; + mt->mt_islast = 0; + error = bus_dmamap_create(dr->dr_txring_dtag, 0, + &mt->mt_dmap); + if (error) { + device_printf(sc->sc_dev, + "can't create RX buf DMA map\n"); + goto fail1; + } + + dr->getdesc(dr, i + 1, &desc, &mt); + + mt->mt_txtype = BWN_DMADESC_METATYPE_BODY; + mt->mt_m = NULL; + mt->mt_ni = NULL; + mt->mt_islast = 1; + error = bus_dmamap_create(dma->txbuf_dtag, 0, + &mt->mt_dmap); + if (error) { + device_printf(sc->sc_dev, + "can't create RX buf DMA map\n"); + goto fail1; + } + } + } else { + error = bus_dmamap_create(dma->rxbuf_dtag, 0, + &dr->dr_spare_dmap); + if (error) { + device_printf(sc->sc_dev, + "can't create RX buf DMA map\n"); + goto out; /* XXX wrong! */ + } + + for (i = 0; i < dr->dr_numslots; i++) { + dr->getdesc(dr, i, &desc, &mt); + + error = bus_dmamap_create(dma->rxbuf_dtag, 0, + &mt->mt_dmap); + if (error) { + device_printf(sc->sc_dev, + "can't create RX buf DMA map\n"); + goto out; /* XXX wrong! */ + } + error = bwn_dma_newbuf(dr, desc, mt, 1); + if (error) { + device_printf(sc->sc_dev, + "failed to allocate RX buf\n"); + goto out; /* XXX wrong! */ + } + } + + bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, + BUS_DMASYNC_PREWRITE); + + dr->dr_usedslot = dr->dr_numslots; + } + + out: + return (dr); + +fail2: + free(dr->dr_txhdr_cache, M_DEVBUF); +fail1: + free(dr->dr_meta, M_DEVBUF); +fail0: + free(dr, M_DEVBUF); + return (NULL); +} + +static void +bwn_dma_ringfree(struct bwn_dma_ring **dr) +{ + + if (dr == NULL) + return; + + bwn_dma_free_descbufs(*dr); + bwn_dma_free_ringmemory(*dr); + + free((*dr)->dr_txhdr_cache, M_DEVBUF); + free((*dr)->dr_meta, M_DEVBUF); + free(*dr, M_DEVBUF); + + *dr = NULL; +} + +static void +bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot, + struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta) +{ + struct bwn_dmadesc32 *desc; + + *meta = &(dr->dr_meta[slot]); + desc = dr->dr_ring_descbase; + desc = &(desc[slot]); + + *gdesc = (struct bwn_dmadesc_generic *)desc; +} + +static void +bwn_dma_32_setdesc(struct bwn_dma_ring *dr, + struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize, + int start, int end, int irq) +{ + struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase; + struct bwn_softc *sc = dr->dr_mac->mac_sc; + uint32_t addr, addrext, ctl; + int slot; + + slot = (int)(&(desc->dma.dma32) - descbase); + KASSERT(slot >= 0 && slot < dr->dr_numslots, + ("%s:%d: fail", __func__, __LINE__)); + + addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK); + addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30; + addr |= siba_dma_translation(sc->sc_dev); + ctl = bufsize & BWN_DMA32_DCTL_BYTECNT; + if (slot == dr->dr_numslots - 1) + ctl |= BWN_DMA32_DCTL_DTABLEEND; + if (start) + ctl |= BWN_DMA32_DCTL_FRAMESTART; + if (end) + ctl |= BWN_DMA32_DCTL_FRAMEEND; + if (irq) + ctl |= BWN_DMA32_DCTL_IRQ; + ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT) + & BWN_DMA32_DCTL_ADDREXT_MASK; + + desc->dma.dma32.control = htole32(ctl); + desc->dma.dma32.address = htole32(addr); +} + +static void +bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot) +{ + + BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX, + (uint32_t)(slot * sizeof(struct bwn_dmadesc32))); +} + +static void +bwn_dma_32_suspend(struct bwn_dma_ring *dr) +{ + + BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, + BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND); +} + +static void +bwn_dma_32_resume(struct bwn_dma_ring *dr) +{ + + BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, + BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND); +} + +static int +bwn_dma_32_get_curslot(struct bwn_dma_ring *dr) +{ + uint32_t val; + + val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS); + val &= BWN_DMA32_RXDPTR; + + return (val / sizeof(struct bwn_dmadesc32)); +} + +static void +bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot) +{ + + BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, + (uint32_t) (slot * sizeof(struct bwn_dmadesc32))); +} + +static void +bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot, + struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta) +{ + struct bwn_dmadesc64 *desc; + + *meta = &(dr->dr_meta[slot]); + desc = dr->dr_ring_descbase; + desc = &(desc[slot]); + + *gdesc = (struct bwn_dmadesc_generic *)desc; +} + +static void +bwn_dma_64_setdesc(struct bwn_dma_ring *dr, + struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize, + int start, int end, int irq) +{ + struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase; + struct bwn_softc *sc = dr->dr_mac->mac_sc; + int slot; + uint32_t ctl0 = 0, ctl1 = 0; + uint32_t addrlo, addrhi; + uint32_t addrext; + + slot = (int)(&(desc->dma.dma64) - descbase); + KASSERT(slot >= 0 && slot < dr->dr_numslots, + ("%s:%d: fail", __func__, __LINE__)); + + addrlo = (uint32_t) (dmaaddr & 0xffffffff); + addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK); + addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >> + 30; + addrhi |= (siba_dma_translation(sc->sc_dev) << 1); + if (slot == dr->dr_numslots - 1) + ctl0 |= BWN_DMA64_DCTL0_DTABLEEND; + if (start) + ctl0 |= BWN_DMA64_DCTL0_FRAMESTART; + if (end) + ctl0 |= BWN_DMA64_DCTL0_FRAMEEND; + if (irq) + ctl0 |= BWN_DMA64_DCTL0_IRQ; + ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT; + ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT) + & BWN_DMA64_DCTL1_ADDREXT_MASK; + + desc->dma.dma64.control0 = htole32(ctl0); + desc->dma.dma64.control1 = htole32(ctl1); + desc->dma.dma64.address_low = htole32(addrlo); + desc->dma.dma64.address_high = htole32(addrhi); +} + +static void +bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot) +{ + + BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX, + (uint32_t)(slot * sizeof(struct bwn_dmadesc64))); +} + +static void +bwn_dma_64_suspend(struct bwn_dma_ring *dr) +{ + + BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, + BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND); +} + +static void +bwn_dma_64_resume(struct bwn_dma_ring *dr) +{ + + BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, + BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND); +} + +static int +bwn_dma_64_get_curslot(struct bwn_dma_ring *dr) +{ + uint32_t val; + + val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS); + val &= BWN_DMA64_RXSTATDPTR; + + return (val / sizeof(struct bwn_dmadesc64)); +} + +static void +bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot) +{ + + BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, + (uint32_t)(slot * sizeof(struct bwn_dmadesc64))); +} + +static int +bwn_dma_allocringmemory(struct bwn_dma_ring *dr) +{ + struct bwn_mac *mac = dr->dr_mac; + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_softc *sc = mac->mac_sc; + int error; + + error = bus_dma_tag_create(dma->parent_dtag, + BWN_ALIGN, 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + BWN_DMA_RINGMEMSIZE, + 1, + BUS_SPACE_MAXSIZE_32BIT, + 0, + NULL, NULL, + &dr->dr_ring_dtag); + if (error) { + device_printf(sc->sc_dev, + "can't create TX ring DMA tag: TODO frees\n"); + return (-1); + } + + error = bus_dmamem_alloc(dr->dr_ring_dtag, + &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO, + &dr->dr_ring_dmap); + if (error) { + device_printf(sc->sc_dev, + "can't allocate DMA mem: TODO frees\n"); + return (-1); + } + error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap, + dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE, + bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT); + if (error) { + device_printf(sc->sc_dev, + "can't load DMA mem: TODO free\n"); + return (-1); + } + + return (0); +} + +static void +bwn_dma_setup(struct bwn_dma_ring *dr) +{ + struct bwn_softc *sc = dr->dr_mac->mac_sc; + uint64_t ring64; + uint32_t addrext, ring32, value; + uint32_t trans = siba_dma_translation(sc->sc_dev); + + if (dr->dr_tx) { + dr->dr_curslot = -1; + + if (dr->dr_type == BWN_DMA_64BIT) { + ring64 = (uint64_t)(dr->dr_ring_dmabase); + addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) + >> 30; + value = BWN_DMA64_TXENABLE; + value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT) + & BWN_DMA64_TXADDREXT_MASK; + BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value); + BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, + (ring64 & 0xffffffff)); + BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, + ((ring64 >> 32) & + ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1)); + } else { + ring32 = (uint32_t)(dr->dr_ring_dmabase); + addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30; + value = BWN_DMA32_TXENABLE; + value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT) + & BWN_DMA32_TXADDREXT_MASK; + BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value); + BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, + (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans); + } + return; + } + + /* + * set for RX + */ + dr->dr_usedslot = dr->dr_numslots; + + if (dr->dr_type == BWN_DMA_64BIT) { + ring64 = (uint64_t)(dr->dr_ring_dmabase); + addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30; + value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT); + value |= BWN_DMA64_RXENABLE; + value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT) + & BWN_DMA64_RXADDREXT_MASK; + BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value); + BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff)); + BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, + ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK) + | (trans << 1)); + BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots * + sizeof(struct bwn_dmadesc64)); + } else { + ring32 = (uint32_t)(dr->dr_ring_dmabase); + addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30; + value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT); + value |= BWN_DMA32_RXENABLE; + value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT) + & BWN_DMA32_RXADDREXT_MASK; + BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value); + BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, + (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans); + BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots * + sizeof(struct bwn_dmadesc32)); + } +} + +static void +bwn_dma_free_ringmemory(struct bwn_dma_ring *dr) +{ + + bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap); + bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase, + dr->dr_ring_dmap); +} + +static void +bwn_dma_cleanup(struct bwn_dma_ring *dr) +{ + + if (dr->dr_tx) { + bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type); + if (dr->dr_type == BWN_DMA_64BIT) { + BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0); + BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0); + } else + BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0); + } else { + bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type); + if (dr->dr_type == BWN_DMA_64BIT) { + BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0); + BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0); + } else + BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0); + } +} + +static void +bwn_dma_free_descbufs(struct bwn_dma_ring *dr) +{ + struct bwn_dmadesc_generic *desc; + struct bwn_dmadesc_meta *meta; + struct bwn_mac *mac = dr->dr_mac; + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_softc *sc = mac->mac_sc; + int i; + + if (!dr->dr_usedslot) + return; + for (i = 0; i < dr->dr_numslots; i++) { + dr->getdesc(dr, i, &desc, &meta); + + if (meta->mt_m == NULL) { + if (!dr->dr_tx) + device_printf(sc->sc_dev, "%s: not TX?\n", + __func__); + continue; + } + if (dr->dr_tx) { + if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) + bus_dmamap_unload(dr->dr_txring_dtag, + meta->mt_dmap); + else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) + bus_dmamap_unload(dma->txbuf_dtag, + meta->mt_dmap); + } else + bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap); + bwn_dma_free_descbuf(dr, meta); + } +} + +static int +bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base, + int type) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t value; + int i; + uint16_t offset; + + for (i = 0; i < 10; i++) { + offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS : + BWN_DMA32_TXSTATUS; + value = BWN_READ_4(mac, base + offset); + if (type == BWN_DMA_64BIT) { + value &= BWN_DMA64_TXSTAT; + if (value == BWN_DMA64_TXSTAT_DISABLED || + value == BWN_DMA64_TXSTAT_IDLEWAIT || + value == BWN_DMA64_TXSTAT_STOPPED) + break; + } else { + value &= BWN_DMA32_TXSTATE; + if (value == BWN_DMA32_TXSTAT_DISABLED || + value == BWN_DMA32_TXSTAT_IDLEWAIT || + value == BWN_DMA32_TXSTAT_STOPPED) + break; + } + DELAY(1000); + } + offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL; + BWN_WRITE_4(mac, base + offset, 0); + for (i = 0; i < 10; i++) { + offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS : + BWN_DMA32_TXSTATUS; + value = BWN_READ_4(mac, base + offset); + if (type == BWN_DMA_64BIT) { + value &= BWN_DMA64_TXSTAT; + if (value == BWN_DMA64_TXSTAT_DISABLED) { + i = -1; + break; + } + } else { + value &= BWN_DMA32_TXSTATE; + if (value == BWN_DMA32_TXSTAT_DISABLED) { + i = -1; + break; + } + } + DELAY(1000); + } + if (i != -1) { + device_printf(sc->sc_dev, "%s: timed out\n", __func__); + return (ENODEV); + } + DELAY(1000); + + return (0); +} + +static int +bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base, + int type) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t value; + int i; + uint16_t offset; + + offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL; + BWN_WRITE_4(mac, base + offset, 0); + for (i = 0; i < 10; i++) { + offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS : + BWN_DMA32_RXSTATUS; + value = BWN_READ_4(mac, base + offset); + if (type == BWN_DMA_64BIT) { + value &= BWN_DMA64_RXSTAT; + if (value == BWN_DMA64_RXSTAT_DISABLED) { + i = -1; + break; + } + } else { + value &= BWN_DMA32_RXSTATE; + if (value == BWN_DMA32_RXSTAT_DISABLED) { + i = -1; + break; + } + } + DELAY(1000); + } + if (i != -1) { + device_printf(sc->sc_dev, "%s: timed out\n", __func__); + return (ENODEV); + } + + return (0); +} + +static void +bwn_dma_free_descbuf(struct bwn_dma_ring *dr, + struct bwn_dmadesc_meta *meta) +{ + + if (meta->mt_m != NULL) { + m_freem(meta->mt_m); + meta->mt_m = NULL; + } + if (meta->mt_ni != NULL) { + ieee80211_free_node(meta->mt_ni); + meta->mt_ni = NULL; + } +} + +static void +bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m) +{ + struct bwn_rxhdr4 *rxhdr; + unsigned char *frame; + + rxhdr = mtod(m, struct bwn_rxhdr4 *); + rxhdr->frame_len = 0; + + KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset + + sizeof(struct bwn_plcp6) + 2, + ("%s:%d: fail", __func__, __LINE__)); + frame = mtod(m, char *) + dr->dr_frameoffset; + memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */); +} + +static uint8_t +bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m) +{ + unsigned char *f = mtod(m, char *) + dr->dr_frameoffset; + + return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7]) + == 0xff); +} + +static void +bwn_wme_init(struct bwn_mac *mac) +{ + + bwn_wme_load(mac); + + /* enable WME support. */ + bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF); + BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) | + BWN_IFSCTL_USE_EDCF); +} + +static void +bwn_spu_setdelay(struct bwn_mac *mac, int idle) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint16_t delay; /* microsec */ + + delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050; + if (ic->ic_opmode == IEEE80211_M_IBSS || idle) + delay = 500; + if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8)) + delay = max(delay, (uint16_t)2400); + + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay); +} + +static void +bwn_bt_enable(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint64_t hf; + + if (bwn_bluetooth == 0) + return; + if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0) + return; + if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode) + return; + + hf = bwn_hf_read(mac); + if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD) + hf |= BWN_HF_BT_COEXISTALT; + else + hf |= BWN_HF_BT_COEXIST; + bwn_hf_write(mac, hf); +} + +static void +bwn_set_macaddr(struct bwn_mac *mac) +{ + + bwn_mac_write_bssid(mac); + bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, + mac->mac_sc->sc_ic.ic_macaddr); +} + +static void +bwn_clear_keys(struct bwn_mac *mac) +{ + int i; + + for (i = 0; i < mac->mac_max_nr_keys; i++) { + KASSERT(i >= 0 && i < mac->mac_max_nr_keys, + ("%s:%d: fail", __func__, __LINE__)); + + bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE, + NULL, BWN_SEC_KEYSIZE, NULL); + if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) { + bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE, + NULL, BWN_SEC_KEYSIZE, NULL); + } + mac->mac_key[i].keyconf = NULL; + } +} + +static void +bwn_crypt_init(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + + mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20; + KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key), + ("%s:%d: fail", __func__, __LINE__)); + mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP); + mac->mac_ktp *= 2; + if (siba_get_revid(sc->sc_dev) >= 5) + BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8); + bwn_clear_keys(mac); +} + +static void +bwn_chip_exit(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + + bwn_phy_exit(mac); + siba_gpio_set(sc->sc_dev, 0); +} + +static int +bwn_fw_fillinfo(struct bwn_mac *mac) +{ + int error; + + error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT); + if (error == 0) + return (0); + error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE); + if (error == 0) + return (0); + return (error); +} + +static int +bwn_gpio_init(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t mask = 0x1f, set = 0xf, value; + + BWN_WRITE_4(mac, BWN_MACCTL, + BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK); + BWN_WRITE_2(mac, BWN_GPIO_MASK, + BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f); + + if (siba_get_chipid(sc->sc_dev) == 0x4301) { + mask |= 0x0060; + set |= 0x0060; + } + if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) { + BWN_WRITE_2(mac, BWN_GPIO_MASK, + BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200); + mask |= 0x0200; + set |= 0x0200; + } + if (siba_get_revid(sc->sc_dev) >= 2) + mask |= 0x0010; + + value = siba_gpio_get(sc->sc_dev); + if (value == -1) + return (0); + siba_gpio_set(sc->sc_dev, (value & mask) | set); + + return (0); +} + +static int +bwn_fw_loadinitvals(struct bwn_mac *mac) +{ +#define GETFWOFFSET(fwp, offset) \ + ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset)) + const size_t hdr_len = sizeof(struct bwn_fwhdr); + const struct bwn_fwhdr *hdr; + struct bwn_fw *fw = &mac->mac_fw; + int error; + + hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data); + error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len), + be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len); + if (error) + return (error); + if (fw->initvals_band.fw) { + hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data); + error = bwn_fwinitvals_write(mac, + GETFWOFFSET(fw->initvals_band, hdr_len), + be32toh(hdr->size), + fw->initvals_band.fw->datasize - hdr_len); + } + return (error); +#undef GETFWOFFSET +} + +static int +bwn_phy_init(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + int error; + + mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac); + mac->mac_phy.rf_onoff(mac, 1); + error = mac->mac_phy.init(mac); + if (error) { + device_printf(sc->sc_dev, "PHY init failed\n"); + goto fail0; + } + error = bwn_switch_channel(mac, + mac->mac_phy.get_default_chan(mac)); + if (error) { + device_printf(sc->sc_dev, + "failed to switch default channel\n"); + goto fail1; + } + return (0); +fail1: + if (mac->mac_phy.exit) + mac->mac_phy.exit(mac); +fail0: + mac->mac_phy.rf_onoff(mac, 0); + + return (error); +} + +static void +bwn_set_txantenna(struct bwn_mac *mac, int antenna) +{ + uint16_t ant; + uint16_t tmp; + + ant = bwn_ant2phy(antenna); + + /* For ACK/CTS */ + tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL); + tmp = (tmp & ~BWN_TX_PHY_ANT) | ant; + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp); + /* For Probe Resposes */ + tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL); + tmp = (tmp & ~BWN_TX_PHY_ANT) | ant; + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp); +} + +static void +bwn_set_opmode(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint32_t ctl; + uint16_t cfp_pretbtt; + + ctl = BWN_READ_4(mac, BWN_MACCTL); + ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL | + BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS | + BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC); + ctl |= BWN_MACCTL_STA; + + if (ic->ic_opmode == IEEE80211_M_HOSTAP || + ic->ic_opmode == IEEE80211_M_MBSS) + ctl |= BWN_MACCTL_HOSTAP; + else if (ic->ic_opmode == IEEE80211_M_IBSS) + ctl &= ~BWN_MACCTL_STA; + ctl |= sc->sc_filters; + + if (siba_get_revid(sc->sc_dev) <= 4) + ctl |= BWN_MACCTL_PROMISC; + + BWN_WRITE_4(mac, BWN_MACCTL, ctl); + + cfp_pretbtt = 2; + if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) { + if (siba_get_chipid(sc->sc_dev) == 0x4306 && + siba_get_chiprev(sc->sc_dev) == 3) + cfp_pretbtt = 100; + else + cfp_pretbtt = 50; + } + BWN_WRITE_2(mac, 0x612, cfp_pretbtt); +} + +static int +bwn_dma_gettype(struct bwn_mac *mac) +{ + uint32_t tmp; + uint16_t base; + + tmp = BWN_READ_4(mac, SIBA_TGSHIGH); + if (tmp & SIBA_TGSHIGH_DMA64) + return (BWN_DMA_64BIT); + base = bwn_dma_base(0, 0); + BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK); + tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL); + if (tmp & BWN_DMA32_TXADDREXT_MASK) + return (BWN_DMA_32BIT); + + return (BWN_DMA_30BIT); +} + +static void +bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) +{ + if (!error) { + KASSERT(nseg == 1, ("too many segments(%d)\n", nseg)); + *((bus_addr_t *)arg) = seg->ds_addr; + } +} + +void +bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon) +{ + struct bwn_phy *phy = &mac->mac_phy; + struct bwn_softc *sc = mac->mac_sc; + unsigned int i, max_loop; + uint16_t value; + uint32_t buffer[5] = { + 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 + }; + + if (ofdm) { + max_loop = 0x1e; + buffer[0] = 0x000201cc; + } else { + max_loop = 0xfa; + buffer[0] = 0x000b846e; + } + + BWN_ASSERT_LOCKED(mac->mac_sc); + + for (i = 0; i < 5; i++) + bwn_ram_write(mac, i * 4, buffer[i]); + + BWN_WRITE_2(mac, 0x0568, 0x0000); + BWN_WRITE_2(mac, 0x07c0, + (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100); + + value = (ofdm ? 0x41 : 0x40); + BWN_WRITE_2(mac, 0x050c, value); + + if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP || + phy->type == BWN_PHYTYPE_LCN) + BWN_WRITE_2(mac, 0x0514, 0x1a02); + BWN_WRITE_2(mac, 0x0508, 0x0000); + BWN_WRITE_2(mac, 0x050a, 0x0000); + BWN_WRITE_2(mac, 0x054c, 0x0000); + BWN_WRITE_2(mac, 0x056a, 0x0014); + BWN_WRITE_2(mac, 0x0568, 0x0826); + BWN_WRITE_2(mac, 0x0500, 0x0000); + + /* XXX TODO: n phy pa override? */ + + switch (phy->type) { + case BWN_PHYTYPE_N: + case BWN_PHYTYPE_LCN: + BWN_WRITE_2(mac, 0x0502, 0x00d0); + break; + case BWN_PHYTYPE_LP: + BWN_WRITE_2(mac, 0x0502, 0x0050); + break; + default: + BWN_WRITE_2(mac, 0x0502, 0x0030); + break; + } + + /* flush */ + BWN_READ_2(mac, 0x0502); + + if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5) + BWN_RF_WRITE(mac, 0x0051, 0x0017); + for (i = 0x00; i < max_loop; i++) { + value = BWN_READ_2(mac, 0x050e); + if (value & 0x0080) + break; + DELAY(10); + } + for (i = 0x00; i < 0x0a; i++) { + value = BWN_READ_2(mac, 0x050e); + if (value & 0x0400) + break; + DELAY(10); + } + for (i = 0x00; i < 0x19; i++) { + value = BWN_READ_2(mac, 0x0690); + if (!(value & 0x0100)) + break; + DELAY(10); + } + if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5) + BWN_RF_WRITE(mac, 0x0051, 0x0037); +} + +void +bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val) +{ + uint32_t macctl; + + KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__)); + + macctl = BWN_READ_4(mac, BWN_MACCTL); + if (macctl & BWN_MACCTL_BIGENDIAN) + printf("TODO: need swap\n"); + + BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset); + BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE); + BWN_WRITE_4(mac, BWN_RAM_DATA, val); +} + +void +bwn_mac_suspend(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + int i; + uint32_t tmp; + + KASSERT(mac->mac_suspended >= 0, + ("%s:%d: fail", __func__, __LINE__)); + + if (mac->mac_suspended == 0) { + bwn_psctl(mac, BWN_PS_AWAKE); + BWN_WRITE_4(mac, BWN_MACCTL, + BWN_READ_4(mac, BWN_MACCTL) + & ~BWN_MACCTL_ON); + BWN_READ_4(mac, BWN_MACCTL); + for (i = 35; i; i--) { + tmp = BWN_READ_4(mac, BWN_INTR_REASON); + if (tmp & BWN_INTR_MAC_SUSPENDED) + goto out; + DELAY(10); + } + for (i = 40; i; i--) { + tmp = BWN_READ_4(mac, BWN_INTR_REASON); + if (tmp & BWN_INTR_MAC_SUSPENDED) + goto out; + DELAY(1000); + } + device_printf(sc->sc_dev, "MAC suspend failed\n"); + } +out: + mac->mac_suspended++; +} + +void +bwn_mac_enable(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint16_t state; + + state = bwn_shm_read_2(mac, BWN_SHARED, + BWN_SHARED_UCODESTAT); + if (state != BWN_SHARED_UCODESTAT_SUSPEND && + state != BWN_SHARED_UCODESTAT_SLEEP) + device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state); + + mac->mac_suspended--; + KASSERT(mac->mac_suspended >= 0, + ("%s:%d: fail", __func__, __LINE__)); + if (mac->mac_suspended == 0) { + BWN_WRITE_4(mac, BWN_MACCTL, + BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON); + BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED); + BWN_READ_4(mac, BWN_MACCTL); + BWN_READ_4(mac, BWN_INTR_REASON); + bwn_psctl(mac, 0); + } +} + +void +bwn_psctl(struct bwn_mac *mac, uint32_t flags) +{ + struct bwn_softc *sc = mac->mac_sc; + int i; + uint16_t ucstat; + + KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)), + ("%s:%d: fail", __func__, __LINE__)); + KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)), + ("%s:%d: fail", __func__, __LINE__)); + + /* XXX forcibly awake and hwps-off */ + + BWN_WRITE_4(mac, BWN_MACCTL, + (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) & + ~BWN_MACCTL_HWPS); + BWN_READ_4(mac, BWN_MACCTL); + if (siba_get_revid(sc->sc_dev) >= 5) { + for (i = 0; i < 100; i++) { + ucstat = bwn_shm_read_2(mac, BWN_SHARED, + BWN_SHARED_UCODESTAT); + if (ucstat != BWN_SHARED_UCODESTAT_SLEEP) + break; + DELAY(10); + } + } +} + +static int +bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type) +{ + struct bwn_softc *sc = mac->mac_sc; + struct bwn_fw *fw = &mac->mac_fw; + const uint8_t rev = siba_get_revid(sc->sc_dev); + const char *filename; + uint32_t high; + int error; + + /* microcode */ + if (rev >= 5 && rev <= 10) + filename = "ucode5"; + else if (rev >= 11 && rev <= 12) + filename = "ucode11"; + else if (rev == 13) + filename = "ucode13"; + else if (rev == 14) + filename = "ucode14"; + else if (rev >= 15) + filename = "ucode15"; + else { + device_printf(sc->sc_dev, "no ucode for rev %d\n", rev); + bwn_release_firmware(mac); + return (EOPNOTSUPP); + } + error = bwn_fw_get(mac, type, filename, &fw->ucode); + if (error) { + bwn_release_firmware(mac); + return (error); + } + + /* PCM */ + KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__)); + if (rev >= 5 && rev <= 10) { + error = bwn_fw_get(mac, type, "pcm5", &fw->pcm); + if (error == ENOENT) + fw->no_pcmfile = 1; + else if (error) { + bwn_release_firmware(mac); + return (error); + } + } else if (rev < 11) { + device_printf(sc->sc_dev, "no PCM for rev %d\n", rev); + return (EOPNOTSUPP); + } + + /* initvals */ + high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH); + switch (mac->mac_phy.type) { + case BWN_PHYTYPE_A: + if (rev < 5 || rev > 10) + goto fail1; + if (high & BWN_TGSHIGH_HAVE_2GHZ) + filename = "a0g1initvals5"; + else + filename = "a0g0initvals5"; + break; + case BWN_PHYTYPE_G: + if (rev >= 5 && rev <= 10) + filename = "b0g0initvals5"; + else if (rev >= 13) + filename = "b0g0initvals13"; + else + goto fail1; + break; + case BWN_PHYTYPE_LP: + if (rev == 13) + filename = "lp0initvals13"; + else if (rev == 14) + filename = "lp0initvals14"; + else if (rev >= 15) + filename = "lp0initvals15"; + else + goto fail1; + break; + case BWN_PHYTYPE_N: + if (rev >= 11 && rev <= 12) + filename = "n0initvals11"; + else + goto fail1; + break; + default: + goto fail1; + } + error = bwn_fw_get(mac, type, filename, &fw->initvals); + if (error) { + bwn_release_firmware(mac); + return (error); + } + + /* bandswitch initvals */ + switch (mac->mac_phy.type) { + case BWN_PHYTYPE_A: + if (rev >= 5 && rev <= 10) { + if (high & BWN_TGSHIGH_HAVE_2GHZ) + filename = "a0g1bsinitvals5"; + else + filename = "a0g0bsinitvals5"; + } else if (rev >= 11) + filename = NULL; + else + goto fail1; + break; + case BWN_PHYTYPE_G: + if (rev >= 5 && rev <= 10) + filename = "b0g0bsinitvals5"; + else if (rev >= 11) + filename = NULL; + else + goto fail1; + break; + case BWN_PHYTYPE_LP: + if (rev == 13) + filename = "lp0bsinitvals13"; + else if (rev == 14) + filename = "lp0bsinitvals14"; + else if (rev >= 15) + filename = "lp0bsinitvals15"; + else + goto fail1; + break; + case BWN_PHYTYPE_N: + if (rev >= 11 && rev <= 12) + filename = "n0bsinitvals11"; + else + goto fail1; + break; + default: + goto fail1; + } + error = bwn_fw_get(mac, type, filename, &fw->initvals_band); + if (error) { + bwn_release_firmware(mac); + return (error); + } + return (0); +fail1: + device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev); + bwn_release_firmware(mac); + return (EOPNOTSUPP); +} + +static int +bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type, + const char *name, struct bwn_fwfile *bfw) +{ + const struct bwn_fwhdr *hdr; + struct bwn_softc *sc = mac->mac_sc; + const struct firmware *fw; + char namebuf[64]; + + if (name == NULL) { + bwn_do_release_fw(bfw); + return (0); + } + if (bfw->filename != NULL) { + if (bfw->type == type && (strcmp(bfw->filename, name) == 0)) + return (0); + bwn_do_release_fw(bfw); + } + + snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s", + (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", + (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name); + /* XXX Sleeping on "fwload" with the non-sleepable locks held */ + fw = firmware_get(namebuf); + if (fw == NULL) { + device_printf(sc->sc_dev, "the fw file(%s) not found\n", + namebuf); + return (ENOENT); + } + if (fw->datasize < sizeof(struct bwn_fwhdr)) + goto fail; + hdr = (const struct bwn_fwhdr *)(fw->data); + switch (hdr->type) { + case BWN_FWTYPE_UCODE: + case BWN_FWTYPE_PCM: + if (be32toh(hdr->size) != + (fw->datasize - sizeof(struct bwn_fwhdr))) + goto fail; + /* FALLTHROUGH */ + case BWN_FWTYPE_IV: + if (hdr->ver != 1) + goto fail; + break; + default: + goto fail; + } + bfw->filename = name; + bfw->fw = fw; + bfw->type = type; + return (0); +fail: + device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf); + if (fw != NULL) + firmware_put(fw, FIRMWARE_UNLOAD); + return (EPROTO); +} + +static void +bwn_release_firmware(struct bwn_mac *mac) +{ + + bwn_do_release_fw(&mac->mac_fw.ucode); + bwn_do_release_fw(&mac->mac_fw.pcm); + bwn_do_release_fw(&mac->mac_fw.initvals); + bwn_do_release_fw(&mac->mac_fw.initvals_band); +} + +static void +bwn_do_release_fw(struct bwn_fwfile *bfw) +{ + + if (bfw->fw != NULL) + firmware_put(bfw->fw, FIRMWARE_UNLOAD); + bfw->fw = NULL; + bfw->filename = NULL; +} + +static int +bwn_fw_loaducode(struct bwn_mac *mac) +{ +#define GETFWOFFSET(fwp, offset) \ + ((const uint32_t *)((const char *)fwp.fw->data + offset)) +#define GETFWSIZE(fwp, offset) \ + ((fwp.fw->datasize - offset) / sizeof(uint32_t)) + struct bwn_softc *sc = mac->mac_sc; + const uint32_t *data; + unsigned int i; + uint32_t ctl; + uint16_t date, fwcaps, time; + int error = 0; + + ctl = BWN_READ_4(mac, BWN_MACCTL); + ctl |= BWN_MACCTL_MCODE_JMP0; + KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__, + __LINE__)); + BWN_WRITE_4(mac, BWN_MACCTL, ctl); + for (i = 0; i < 64; i++) + bwn_shm_write_2(mac, BWN_SCRATCH, i, 0); + for (i = 0; i < 4096; i += 2) + bwn_shm_write_2(mac, BWN_SHARED, i, 0); + + data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr)); + bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000); + for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr)); + i++) { + BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i])); + DELAY(10); + } + + if (mac->mac_fw.pcm.fw) { + data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr)); + bwn_shm_ctlword(mac, BWN_HW, 0x01ea); + BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000); + bwn_shm_ctlword(mac, BWN_HW, 0x01eb); + for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm, + sizeof(struct bwn_fwhdr)); i++) { + BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i])); + DELAY(10); + } + } + + BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL); + BWN_WRITE_4(mac, BWN_MACCTL, + (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) | + BWN_MACCTL_MCODE_RUN); + + for (i = 0; i < 21; i++) { + if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED) + break; + if (i >= 20) { + device_printf(sc->sc_dev, "ucode timeout\n"); + error = ENXIO; + goto error; + } + DELAY(50000); + } + BWN_READ_4(mac, BWN_INTR_REASON); + + mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV); + if (mac->mac_fw.rev <= 0x128) { + device_printf(sc->sc_dev, "the firmware is too old\n"); + error = EOPNOTSUPP; + goto error; + } + mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED, + BWN_SHARED_UCODE_PATCH); + date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE); + mac->mac_fw.opensource = (date == 0xffff); + if (bwn_wme != 0) + mac->mac_flags |= BWN_MAC_FLAG_WME; + mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO; + + time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME); + if (mac->mac_fw.opensource == 0) { + device_printf(sc->sc_dev, + "firmware version (rev %u patch %u date %#x time %#x)\n", + mac->mac_fw.rev, mac->mac_fw.patch, date, time); + if (mac->mac_fw.no_pcmfile) + device_printf(sc->sc_dev, + "no HW crypto acceleration due to pcm5\n"); + } else { + mac->mac_fw.patch = time; + fwcaps = bwn_fwcaps_read(mac); + if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) { + device_printf(sc->sc_dev, + "disabling HW crypto acceleration\n"); + mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO; + } + if (!(fwcaps & BWN_FWCAPS_WME)) { + device_printf(sc->sc_dev, "disabling WME support\n"); + mac->mac_flags &= ~BWN_MAC_FLAG_WME; + } + } + + if (BWN_ISOLDFMT(mac)) + device_printf(sc->sc_dev, "using old firmware image\n"); + + return (0); + +error: + BWN_WRITE_4(mac, BWN_MACCTL, + (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) | + BWN_MACCTL_MCODE_JMP0); + + return (error); +#undef GETFWSIZE +#undef GETFWOFFSET +} + +/* OpenFirmware only */ +static uint16_t +bwn_fwcaps_read(struct bwn_mac *mac) +{ + + KASSERT(mac->mac_fw.opensource == 1, + ("%s:%d: fail", __func__, __LINE__)); + return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS)); +} + +static int +bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals, + size_t count, size_t array_size) +{ +#define GET_NEXTIV16(iv) \ + ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \ + sizeof(uint16_t) + sizeof(uint16_t))) +#define GET_NEXTIV32(iv) \ + ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \ + sizeof(uint16_t) + sizeof(uint32_t))) + struct bwn_softc *sc = mac->mac_sc; + const struct bwn_fwinitvals *iv; + uint16_t offset; + size_t i; + uint8_t bit32; + + KASSERT(sizeof(struct bwn_fwinitvals) == 6, + ("%s:%d: fail", __func__, __LINE__)); + iv = ivals; + for (i = 0; i < count; i++) { + if (array_size < sizeof(iv->offset_size)) + goto fail; + array_size -= sizeof(iv->offset_size); + offset = be16toh(iv->offset_size); + bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0; + offset &= BWN_FWINITVALS_OFFSET_MASK; + if (offset >= 0x1000) + goto fail; + if (bit32) { + if (array_size < sizeof(iv->data.d32)) + goto fail; + array_size -= sizeof(iv->data.d32); + BWN_WRITE_4(mac, offset, be32toh(iv->data.d32)); + iv = GET_NEXTIV32(iv); + } else { + + if (array_size < sizeof(iv->data.d16)) + goto fail; + array_size -= sizeof(iv->data.d16); + BWN_WRITE_2(mac, offset, be16toh(iv->data.d16)); + + iv = GET_NEXTIV16(iv); + } + } + if (array_size != 0) + goto fail; + return (0); +fail: + device_printf(sc->sc_dev, "initvals: invalid format\n"); + return (EPROTO); +#undef GET_NEXTIV16 +#undef GET_NEXTIV32 +} + +int +bwn_switch_channel(struct bwn_mac *mac, int chan) +{ + struct bwn_phy *phy = &(mac->mac_phy); + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint16_t channelcookie, savedcookie; + int error; + + if (chan == 0xffff) + chan = phy->get_default_chan(mac); + + channelcookie = chan; + if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) + channelcookie |= 0x100; + savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie); + error = phy->switch_channel(mac, chan); + if (error) + goto fail; + + mac->mac_phy.chan = chan; + DELAY(8000); + return (0); +fail: + device_printf(sc->sc_dev, "failed to switch channel\n"); + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie); + return (error); +} + +static uint16_t +bwn_ant2phy(int antenna) +{ + + switch (antenna) { + case BWN_ANT0: + return (BWN_TX_PHY_ANT0); + case BWN_ANT1: + return (BWN_TX_PHY_ANT1); + case BWN_ANT2: + return (BWN_TX_PHY_ANT2); + case BWN_ANT3: + return (BWN_TX_PHY_ANT3); + case BWN_ANTAUTO: + return (BWN_TX_PHY_ANT01AUTO); + } + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (0); +} + +static void +bwn_wme_load(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + int i; + + KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams), + ("%s:%d: fail", __func__, __LINE__)); + + bwn_mac_suspend(mac); + for (i = 0; i < N(sc->sc_wmeParams); i++) + bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]), + bwn_wme_shm_offsets[i]); + bwn_mac_enable(mac); +} + +static void +bwn_wme_loadparams(struct bwn_mac *mac, + const struct wmeParams *p, uint16_t shm_offset) +{ +#define SM(_v, _f) (((_v) << _f##_S) & _f) + struct bwn_softc *sc = mac->mac_sc; + uint16_t params[BWN_NR_WMEPARAMS]; + int slot, tmp; + unsigned int i; + + slot = BWN_READ_2(mac, BWN_RNG) & + SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN); + + memset(¶ms, 0, sizeof(params)); + + DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d " + "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit, + p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn); + + params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32; + params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN); + params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX); + params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN); + params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn; + params[BWN_WMEPARAM_BSLOTS] = slot; + params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn; + + for (i = 0; i < N(params); i++) { + if (i == BWN_WMEPARAM_STATUS) { + tmp = bwn_shm_read_2(mac, BWN_SHARED, + shm_offset + (i * 2)); + tmp |= 0x100; + bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2), + tmp); + } else { + bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2), + params[i]); + } + } +} + +static void +bwn_mac_write_bssid(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t tmp; + int i; + uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2]; + + bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid); + memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN); + memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid, + IEEE80211_ADDR_LEN); + + for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) { + tmp = (uint32_t) (mac_bssid[i + 0]); + tmp |= (uint32_t) (mac_bssid[i + 1]) << 8; + tmp |= (uint32_t) (mac_bssid[i + 2]) << 16; + tmp |= (uint32_t) (mac_bssid[i + 3]) << 24; + bwn_ram_write(mac, 0x20 + i, tmp); + } +} + +static void +bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset, + const uint8_t *macaddr) +{ + static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 }; + uint16_t data; + + if (!mac) + macaddr = zero; + + offset |= 0x0020; + BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset); + + data = macaddr[0]; + data |= macaddr[1] << 8; + BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data); + data = macaddr[2]; + data |= macaddr[3] << 8; + BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data); + data = macaddr[4]; + data |= macaddr[5] << 8; + BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data); +} + +static void +bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm, + const uint8_t *key, size_t key_len, const uint8_t *mac_addr) +{ + uint8_t buf[BWN_SEC_KEYSIZE] = { 0, }; + uint8_t per_sta_keys_start = 8; + + if (BWN_SEC_NEWAPI(mac)) + per_sta_keys_start = 4; + + KASSERT(index < mac->mac_max_nr_keys, + ("%s:%d: fail", __func__, __LINE__)); + KASSERT(key_len <= BWN_SEC_KEYSIZE, + ("%s:%d: fail", __func__, __LINE__)); + + if (index >= per_sta_keys_start) + bwn_key_macwrite(mac, index, NULL); + if (key) + memcpy(buf, key, key_len); + bwn_key_write(mac, index, algorithm, buf); + if (index >= per_sta_keys_start) + bwn_key_macwrite(mac, index, mac_addr); + + mac->mac_key[index].algorithm = algorithm; +} + +static void +bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t addrtmp[2] = { 0, 0 }; + uint8_t start = 8; + + if (BWN_SEC_NEWAPI(mac)) + start = 4; + + KASSERT(index >= start, + ("%s:%d: fail", __func__, __LINE__)); + index -= start; + + if (addr) { + addrtmp[0] = addr[0]; + addrtmp[0] |= ((uint32_t) (addr[1]) << 8); + addrtmp[0] |= ((uint32_t) (addr[2]) << 16); + addrtmp[0] |= ((uint32_t) (addr[3]) << 24); + addrtmp[1] = addr[4]; + addrtmp[1] |= ((uint32_t) (addr[5]) << 8); + } + + if (siba_get_revid(sc->sc_dev) >= 5) { + bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]); + bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]); + } else { + if (index >= 8) { + bwn_shm_write_4(mac, BWN_SHARED, + BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]); + bwn_shm_write_2(mac, BWN_SHARED, + BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]); + } + } +} + +static void +bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm, + const uint8_t *key) +{ + unsigned int i; + uint32_t offset; + uint16_t kidx, value; + + kidx = BWN_SEC_KEY2FW(mac, index); + bwn_shm_write_2(mac, BWN_SHARED, + BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm); + + offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE); + for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) { + value = key[i]; + value |= (uint16_t)(key[i + 1]) << 8; + bwn_shm_write_2(mac, BWN_SHARED, offset + i, value); + } +} + +static void +bwn_phy_exit(struct bwn_mac *mac) +{ + + mac->mac_phy.rf_onoff(mac, 0); + if (mac->mac_phy.exit != NULL) + mac->mac_phy.exit(mac); +} + +static void +bwn_dma_free(struct bwn_mac *mac) +{ + struct bwn_dma *dma; + + if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0) + return; + dma = &mac->mac_method.dma; + + bwn_dma_ringfree(&dma->rx); + bwn_dma_ringfree(&dma->wme[WME_AC_BK]); + bwn_dma_ringfree(&dma->wme[WME_AC_BE]); + bwn_dma_ringfree(&dma->wme[WME_AC_VI]); + bwn_dma_ringfree(&dma->wme[WME_AC_VO]); + bwn_dma_ringfree(&dma->mcast); +} + +static void +bwn_core_stop(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + + BWN_ASSERT_LOCKED(sc); + + if (mac->mac_status < BWN_MAC_STATUS_STARTED) + return; + + callout_stop(&sc->sc_rfswitch_ch); + callout_stop(&sc->sc_task_ch); + callout_stop(&sc->sc_watchdog_ch); + sc->sc_watchdog_timer = 0; + BWN_WRITE_4(mac, BWN_INTR_MASK, 0); + BWN_READ_4(mac, BWN_INTR_MASK); + bwn_mac_suspend(mac); + + mac->mac_status = BWN_MAC_STATUS_INITED; +} + +static int +bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan) +{ + struct bwn_mac *up_dev = NULL; + struct bwn_mac *down_dev; + struct bwn_mac *mac; + int err, status; + uint8_t gmode; + + BWN_ASSERT_LOCKED(sc); + + TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) { + if (IEEE80211_IS_CHAN_2GHZ(chan) && + mac->mac_phy.supports_2ghz) { + up_dev = mac; + gmode = 1; + } else if (IEEE80211_IS_CHAN_5GHZ(chan) && + mac->mac_phy.supports_5ghz) { + up_dev = mac; + gmode = 0; + } else { + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (EINVAL); + } + if (up_dev != NULL) + break; + } + if (up_dev == NULL) { + device_printf(sc->sc_dev, "Could not find a device\n"); + return (ENODEV); + } + if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode) + return (0); + + device_printf(sc->sc_dev, "switching to %s-GHz band\n", + IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5"); + + down_dev = sc->sc_curmac; + status = down_dev->mac_status; + if (status >= BWN_MAC_STATUS_STARTED) + bwn_core_stop(down_dev); + if (status >= BWN_MAC_STATUS_INITED) + bwn_core_exit(down_dev); + + if (down_dev != up_dev) + bwn_phy_reset(down_dev); + + up_dev->mac_phy.gmode = gmode; + if (status >= BWN_MAC_STATUS_INITED) { + err = bwn_core_init(up_dev); + if (err) { + device_printf(sc->sc_dev, + "fatal: failed to initialize for %s-GHz\n", + IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5"); + goto fail; + } + } + if (status >= BWN_MAC_STATUS_STARTED) + bwn_core_start(up_dev); + KASSERT(up_dev->mac_status == status, ("%s: fail", __func__)); + sc->sc_curmac = up_dev; + + return (0); +fail: + sc->sc_curmac = NULL; + return (err); +} + +static void +bwn_rf_turnon(struct bwn_mac *mac) +{ + + bwn_mac_suspend(mac); + mac->mac_phy.rf_onoff(mac, 1); + mac->mac_phy.rf_on = 1; + bwn_mac_enable(mac); +} + +static void +bwn_rf_turnoff(struct bwn_mac *mac) +{ + + bwn_mac_suspend(mac); + mac->mac_phy.rf_onoff(mac, 0); + mac->mac_phy.rf_on = 0; + bwn_mac_enable(mac); +} + +static void +bwn_phy_reset(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + + siba_write_4(sc->sc_dev, SIBA_TGSLOW, + ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) | + BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC); + DELAY(1000); + siba_write_4(sc->sc_dev, SIBA_TGSLOW, + (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) | + BWN_TGSLOW_PHYRESET); + DELAY(1000); +} + +static int +bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) +{ + struct bwn_vap *bvp = BWN_VAP(vap); + struct ieee80211com *ic= vap->iv_ic; + enum ieee80211_state ostate = vap->iv_state; + struct bwn_softc *sc = ic->ic_softc; + struct bwn_mac *mac = sc->sc_curmac; + int error; + + DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__, + ieee80211_state_name[vap->iv_state], + ieee80211_state_name[nstate]); + + error = bvp->bv_newstate(vap, nstate, arg); + if (error != 0) + return (error); + + BWN_LOCK(sc); + + bwn_led_newstate(mac, nstate); + + /* + * Clear the BSSID when we stop a STA + */ + if (vap->iv_opmode == IEEE80211_M_STA) { + if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) { + /* + * Clear out the BSSID. If we reassociate to + * the same AP, this will reinialize things + * correctly... + */ + if (ic->ic_opmode == IEEE80211_M_STA && + (sc->sc_flags & BWN_FLAG_INVALID) == 0) { + memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN); + bwn_set_macaddr(mac); + } + } + } + + if (vap->iv_opmode == IEEE80211_M_MONITOR || + vap->iv_opmode == IEEE80211_M_AHDEMO) { + /* XXX nothing to do? */ + } else if (nstate == IEEE80211_S_RUN) { + memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN); + bwn_set_opmode(mac); + bwn_set_pretbtt(mac); + bwn_spu_setdelay(mac, 0); + bwn_set_macaddr(mac); + } + + BWN_UNLOCK(sc); + + return (error); +} + +static void +bwn_set_pretbtt(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint16_t pretbtt; + + if (ic->ic_opmode == IEEE80211_M_IBSS) + pretbtt = 2; + else + pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250; + bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt); + BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt); +} + +static int +bwn_intr(void *arg) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + uint32_t reason; + + if (mac->mac_status < BWN_MAC_STATUS_STARTED || + (sc->sc_flags & BWN_FLAG_INVALID)) + return (FILTER_STRAY); + + reason = BWN_READ_4(mac, BWN_INTR_REASON); + if (reason == 0xffffffff) /* shared IRQ */ + return (FILTER_STRAY); + reason &= mac->mac_intr_mask; + if (reason == 0) + return (FILTER_HANDLED); + + mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00; + mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00; + mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00; + mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00; + mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00; + BWN_WRITE_4(mac, BWN_INTR_REASON, reason); + BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]); + BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]); + BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]); + BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]); + BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]); + + /* Disable interrupts. */ + BWN_WRITE_4(mac, BWN_INTR_MASK, 0); + + mac->mac_reason_intr = reason; + + BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ); + BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE); + + taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask); + return (FILTER_HANDLED); +} + +static void +bwn_intrtask(void *arg, int npending) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + uint32_t merged = 0; + int i, tx = 0, rx = 0; + + BWN_LOCK(sc); + if (mac->mac_status < BWN_MAC_STATUS_STARTED || + (sc->sc_flags & BWN_FLAG_INVALID)) { + BWN_UNLOCK(sc); + return; + } + + for (i = 0; i < N(mac->mac_reason); i++) + merged |= mac->mac_reason[i]; + + if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR) + device_printf(sc->sc_dev, "MAC trans error\n"); + + if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) { + DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__); + mac->mac_phy.txerrors--; + if (mac->mac_phy.txerrors == 0) { + mac->mac_phy.txerrors = BWN_TXERROR_MAX; + bwn_restart(mac, "PHY TX errors"); + } + } + + if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) { + if (merged & BWN_DMAINTR_FATALMASK) { + device_printf(sc->sc_dev, + "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n", + mac->mac_reason[0], mac->mac_reason[1], + mac->mac_reason[2], mac->mac_reason[3], + mac->mac_reason[4], mac->mac_reason[5]); + bwn_restart(mac, "DMA error"); + BWN_UNLOCK(sc); + return; + } + if (merged & BWN_DMAINTR_NONFATALMASK) { + device_printf(sc->sc_dev, + "DMA error: %#x %#x %#x %#x %#x %#x\n", + mac->mac_reason[0], mac->mac_reason[1], + mac->mac_reason[2], mac->mac_reason[3], + mac->mac_reason[4], mac->mac_reason[5]); + } + } + + if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG) + bwn_intr_ucode_debug(mac); + if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI) + bwn_intr_tbtt_indication(mac); + if (mac->mac_reason_intr & BWN_INTR_ATIM_END) + bwn_intr_atim_end(mac); + if (mac->mac_reason_intr & BWN_INTR_BEACON) + bwn_intr_beacon(mac); + if (mac->mac_reason_intr & BWN_INTR_PMQ) + bwn_intr_pmq(mac); + if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK) + bwn_intr_noise(mac); + + if (mac->mac_flags & BWN_MAC_FLAG_DMA) { + if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) { + bwn_dma_rx(mac->mac_method.dma.rx); + rx = 1; + } + } else + rx = bwn_pio_rx(&mac->mac_method.pio.rx); + + KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); + KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); + KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); + KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); + KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); + + if (mac->mac_reason_intr & BWN_INTR_TX_OK) { + bwn_intr_txeof(mac); + tx = 1; + } + + BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask); + + if (sc->sc_blink_led != NULL && sc->sc_led_blink) { + int evt = BWN_LED_EVENT_NONE; + + if (tx && rx) { + if (sc->sc_rx_rate > sc->sc_tx_rate) + evt = BWN_LED_EVENT_RX; + else + evt = BWN_LED_EVENT_TX; + } else if (tx) { + evt = BWN_LED_EVENT_TX; + } else if (rx) { + evt = BWN_LED_EVENT_RX; + } else if (rx == 0) { + evt = BWN_LED_EVENT_POLL; + } + + if (evt != BWN_LED_EVENT_NONE) + bwn_led_event(mac, evt); + } + + if (mbufq_first(&sc->sc_snd) != NULL) + bwn_start(sc); + + BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ); + BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE); + + BWN_UNLOCK(sc); +} + +static void +bwn_restart(struct bwn_mac *mac, const char *msg) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + + if (mac->mac_status < BWN_MAC_STATUS_INITED) + return; + + device_printf(sc->sc_dev, "HW reset: %s\n", msg); + ieee80211_runtask(ic, &mac->mac_hwreset); +} + +static void +bwn_intr_ucode_debug(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint16_t reason; + + if (mac->mac_fw.opensource == 0) + return; + + reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG); + switch (reason) { + case BWN_DEBUGINTR_PANIC: + bwn_handle_fwpanic(mac); + break; + case BWN_DEBUGINTR_DUMP_SHM: + device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n"); + break; + case BWN_DEBUGINTR_DUMP_REGS: + device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n"); + break; + case BWN_DEBUGINTR_MARKER: + device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n"); + break; + default: + device_printf(sc->sc_dev, + "ucode debug unknown reason: %#x\n", reason); + } + + bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG, + BWN_DEBUGINTR_ACK); +} + +static void +bwn_intr_tbtt_indication(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + + if (ic->ic_opmode != IEEE80211_M_HOSTAP) + bwn_psctl(mac, 0); + if (ic->ic_opmode == IEEE80211_M_IBSS) + mac->mac_flags |= BWN_MAC_FLAG_DFQVALID; +} + +static void +bwn_intr_atim_end(struct bwn_mac *mac) +{ + + if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) { + BWN_WRITE_4(mac, BWN_MACCMD, + BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID); + mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID; + } +} + +static void +bwn_intr_beacon(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint32_t cmd, beacon0, beacon1; + + if (ic->ic_opmode == IEEE80211_M_HOSTAP || + ic->ic_opmode == IEEE80211_M_MBSS) + return; + + mac->mac_intr_mask &= ~BWN_INTR_BEACON; + + cmd = BWN_READ_4(mac, BWN_MACCMD); + beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID); + beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID); + + if (beacon0 && beacon1) { + BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON); + mac->mac_intr_mask |= BWN_INTR_BEACON; + return; + } + + if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) { + sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP; + bwn_load_beacon0(mac); + bwn_load_beacon1(mac); + cmd = BWN_READ_4(mac, BWN_MACCMD); + cmd |= BWN_MACCMD_BEACON0_VALID; + BWN_WRITE_4(mac, BWN_MACCMD, cmd); + } else { + if (!beacon0) { + bwn_load_beacon0(mac); + cmd = BWN_READ_4(mac, BWN_MACCMD); + cmd |= BWN_MACCMD_BEACON0_VALID; + BWN_WRITE_4(mac, BWN_MACCMD, cmd); + } else if (!beacon1) { + bwn_load_beacon1(mac); + cmd = BWN_READ_4(mac, BWN_MACCMD); + cmd |= BWN_MACCMD_BEACON1_VALID; + BWN_WRITE_4(mac, BWN_MACCMD, cmd); + } + } +} + +static void +bwn_intr_pmq(struct bwn_mac *mac) +{ + uint32_t tmp; + + while (1) { + tmp = BWN_READ_4(mac, BWN_PS_STATUS); + if (!(tmp & 0x00000008)) + break; + } + BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002); +} + +static void +bwn_intr_noise(struct bwn_mac *mac) +{ + struct bwn_phy_g *pg = &mac->mac_phy.phy_g; + uint16_t tmp; + uint8_t noise[4]; + uint8_t i, j; + int32_t average; + + if (mac->mac_phy.type != BWN_PHYTYPE_G) + return; + + KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__)); + *((uint32_t *)noise) = htole32(bwn_jssi_read(mac)); + if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f || + noise[3] == 0x7f) + goto new; + + KASSERT(mac->mac_noise.noi_nsamples < 8, + ("%s:%d: fail", __func__, __LINE__)); + i = mac->mac_noise.noi_nsamples; + noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1); + noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1); + noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1); + noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1); + mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]]; + mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]]; + mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]]; + mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]]; + mac->mac_noise.noi_nsamples++; + if (mac->mac_noise.noi_nsamples == 8) { + average = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 4; j++) + average += mac->mac_noise.noi_samples[i][j]; + } + average = (((average / 32) * 125) + 64) / 128; + tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f; + if (tmp >= 8) + average += 2; + else + average -= 25; + average -= (tmp == 8) ? 72 : 48; + + mac->mac_stats.link_noise = average; + mac->mac_noise.noi_running = 0; + return; + } +new: + bwn_noise_gensample(mac); +} + +static int +bwn_pio_rx(struct bwn_pio_rxqueue *prq) +{ + struct bwn_mac *mac = prq->prq_mac; + struct bwn_softc *sc = mac->mac_sc; + unsigned int i; + + BWN_ASSERT_LOCKED(sc); + + if (mac->mac_status < BWN_MAC_STATUS_STARTED) + return (0); + + for (i = 0; i < 5000; i++) { + if (bwn_pio_rxeof(prq) == 0) + break; + } + if (i >= 5000) + device_printf(sc->sc_dev, "too many RX frames in PIO mode\n"); + return ((i > 0) ? 1 : 0); +} + +static void +bwn_dma_rx(struct bwn_dma_ring *dr) +{ + int slot, curslot; + + KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__)); + curslot = dr->get_curslot(dr); + KASSERT(curslot >= 0 && curslot < dr->dr_numslots, + ("%s:%d: fail", __func__, __LINE__)); + + slot = dr->dr_curslot; + for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot)) + bwn_dma_rxeof(dr, &slot); + + bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, + BUS_DMASYNC_PREWRITE); + + dr->set_curslot(dr, slot); + dr->dr_curslot = slot; +} + +static void +bwn_intr_txeof(struct bwn_mac *mac) +{ + struct bwn_txstatus stat; + uint32_t stat0, stat1; + uint16_t tmp; + + BWN_ASSERT_LOCKED(mac->mac_sc); + + while (1) { + stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0); + if (!(stat0 & 0x00000001)) + break; + stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1); + + stat.cookie = (stat0 >> 16); + stat.seq = (stat1 & 0x0000ffff); + stat.phy_stat = ((stat1 & 0x00ff0000) >> 16); + tmp = (stat0 & 0x0000ffff); + stat.framecnt = ((tmp & 0xf000) >> 12); + stat.rtscnt = ((tmp & 0x0f00) >> 8); + stat.sreason = ((tmp & 0x001c) >> 2); + stat.pm = (tmp & 0x0080) ? 1 : 0; + stat.im = (tmp & 0x0040) ? 1 : 0; + stat.ampdu = (tmp & 0x0020) ? 1 : 0; + stat.ack = (tmp & 0x0002) ? 1 : 0; + + bwn_handle_txeof(mac, &stat); + } +} + +static void +bwn_hwreset(void *arg, int npending) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + int error = 0; + int prev_status; + + BWN_LOCK(sc); + + prev_status = mac->mac_status; + if (prev_status >= BWN_MAC_STATUS_STARTED) + bwn_core_stop(mac); + if (prev_status >= BWN_MAC_STATUS_INITED) + bwn_core_exit(mac); + + if (prev_status >= BWN_MAC_STATUS_INITED) { + error = bwn_core_init(mac); + if (error) + goto out; + } + if (prev_status >= BWN_MAC_STATUS_STARTED) + bwn_core_start(mac); +out: + if (error) { + device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error); + sc->sc_curmac = NULL; + } + BWN_UNLOCK(sc); +} + +static void +bwn_handle_fwpanic(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + uint16_t reason; + + reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG); + device_printf(sc->sc_dev,"fw panic (%u)\n", reason); + + if (reason == BWN_FWPANIC_RESTART) + bwn_restart(mac, "ucode panic"); +} + +static void +bwn_load_beacon0(struct bwn_mac *mac) +{ + + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); +} + +static void +bwn_load_beacon1(struct bwn_mac *mac) +{ + + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); +} + +static uint32_t +bwn_jssi_read(struct bwn_mac *mac) +{ + uint32_t val = 0; + + val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a); + val <<= 16; + val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088); + + return (val); +} + +static void +bwn_noise_gensample(struct bwn_mac *mac) +{ + uint32_t jssi = 0x7f7f7f7f; + + bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff)); + bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16); + BWN_WRITE_4(mac, BWN_MACCMD, + BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE); +} + +static int +bwn_dma_freeslot(struct bwn_dma_ring *dr) +{ + BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc); + + return (dr->dr_numslots - dr->dr_usedslot); +} + +static int +bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot) +{ + BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc); + + KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1, + ("%s:%d: fail", __func__, __LINE__)); + if (slot == dr->dr_numslots - 1) + return (0); + return (slot + 1); +} + +static void +bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot) +{ + struct bwn_mac *mac = dr->dr_mac; + struct bwn_softc *sc = mac->mac_sc; + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_dmadesc_generic *desc; + struct bwn_dmadesc_meta *meta; + struct bwn_rxhdr4 *rxhdr; + struct mbuf *m; + uint32_t macstat; + int32_t tmp; + int cnt = 0; + uint16_t len; + + dr->getdesc(dr, *slot, &desc, &meta); + + bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD); + m = meta->mt_m; + + if (bwn_dma_newbuf(dr, desc, meta, 0)) { + counter_u64_add(sc->sc_ic.ic_ierrors, 1); + return; + } + + rxhdr = mtod(m, struct bwn_rxhdr4 *); + len = le16toh(rxhdr->frame_len); + if (len <= 0) { + counter_u64_add(sc->sc_ic.ic_ierrors, 1); + return; + } + if (bwn_dma_check_redzone(dr, m)) { + device_printf(sc->sc_dev, "redzone error.\n"); + bwn_dma_set_redzone(dr, m); + bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, + BUS_DMASYNC_PREWRITE); + return; + } + if (len > dr->dr_rx_bufsize) { + tmp = len; + while (1) { + dr->getdesc(dr, *slot, &desc, &meta); + bwn_dma_set_redzone(dr, meta->mt_m); + bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, + BUS_DMASYNC_PREWRITE); + *slot = bwn_dma_nextslot(dr, *slot); + cnt++; + tmp -= dr->dr_rx_bufsize; + if (tmp <= 0) + break; + } + device_printf(sc->sc_dev, "too small buffer " + "(len %u buffer %u dropped %d)\n", + len, dr->dr_rx_bufsize, cnt); + return; + } + macstat = le32toh(rxhdr->mac_status); + if (macstat & BWN_RX_MAC_FCSERR) { + if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) { + device_printf(sc->sc_dev, "RX drop\n"); + return; + } + } + + m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset; + m_adj(m, dr->dr_frameoffset); + + bwn_rxeof(dr->dr_mac, m, rxhdr); +} + +static void +bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) +{ + struct bwn_softc *sc = mac->mac_sc; + struct bwn_stats *stats = &mac->mac_stats; + + BWN_ASSERT_LOCKED(mac->mac_sc); + + if (status->im) + device_printf(sc->sc_dev, "TODO: STATUS IM\n"); + if (status->ampdu) + device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n"); + if (status->rtscnt) { + if (status->rtscnt == 0xf) + stats->rtsfail++; + else + stats->rts++; + } + + if (mac->mac_flags & BWN_MAC_FLAG_DMA) { + bwn_dma_handle_txeof(mac, status); + } else { + bwn_pio_handle_txeof(mac, status); + } + + bwn_phy_txpower_check(mac, 0); +} + +static uint8_t +bwn_pio_rxeof(struct bwn_pio_rxqueue *prq) +{ + struct bwn_mac *mac = prq->prq_mac; + struct bwn_softc *sc = mac->mac_sc; + struct bwn_rxhdr4 rxhdr; + struct mbuf *m; + uint32_t ctl32, macstat, v32; + unsigned int i, padding; + uint16_t ctl16, len, totlen, v16; + unsigned char *mp; + char *data; + + memset(&rxhdr, 0, sizeof(rxhdr)); + + if (prq->prq_rev >= 8) { + ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL); + if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY)) + return (0); + bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL, + BWN_PIO8_RXCTL_FRAMEREADY); + for (i = 0; i < 10; i++) { + ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL); + if (ctl32 & BWN_PIO8_RXCTL_DATAREADY) + goto ready; + DELAY(10); + } + } else { + ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL); + if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY)) + return (0); + bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, + BWN_PIO_RXCTL_FRAMEREADY); + for (i = 0; i < 10; i++) { + ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL); + if (ctl16 & BWN_PIO_RXCTL_DATAREADY) + goto ready; + DELAY(10); + } + } + device_printf(sc->sc_dev, "%s: timed out\n", __func__); + return (1); +ready: + if (prq->prq_rev >= 8) + siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr), + prq->prq_base + BWN_PIO8_RXDATA); + else + siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr), + prq->prq_base + BWN_PIO_RXDATA); + len = le16toh(rxhdr.frame_len); + if (len > 0x700) { + device_printf(sc->sc_dev, "%s: len is too big\n", __func__); + goto error; + } + if (len == 0) { + device_printf(sc->sc_dev, "%s: len is 0\n", __func__); + goto error; + } + + macstat = le32toh(rxhdr.mac_status); + if (macstat & BWN_RX_MAC_FCSERR) { + if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) { + device_printf(sc->sc_dev, "%s: FCS error", __func__); + goto error; + } + } + + padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0; + totlen = len + padding; + KASSERT(totlen <= MCLBYTES, ("too big..\n")); + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { + device_printf(sc->sc_dev, "%s: out of memory", __func__); + goto error; + } + mp = mtod(m, unsigned char *); + if (prq->prq_rev >= 8) { + siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3), + prq->prq_base + BWN_PIO8_RXDATA); + if (totlen & 3) { + v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA); + data = &(mp[totlen - 1]); + switch (totlen & 3) { + case 3: + *data = (v32 >> 16); + data--; + case 2: + *data = (v32 >> 8); + data--; + case 1: + *data = v32; + } + } + } else { + siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1), + prq->prq_base + BWN_PIO_RXDATA); + if (totlen & 1) { + v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA); + mp[totlen - 1] = v16; + } + } + + m->m_len = m->m_pkthdr.len = totlen; + + bwn_rxeof(prq->prq_mac, m, &rxhdr); + + return (1); +error: + if (prq->prq_rev >= 8) + bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL, + BWN_PIO8_RXCTL_DATAREADY); + else + bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY); + return (1); +} + +static int +bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc, + struct bwn_dmadesc_meta *meta, int init) +{ + struct bwn_mac *mac = dr->dr_mac; + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_rxhdr4 *hdr; + bus_dmamap_t map; + bus_addr_t paddr; + struct mbuf *m; + int error; + + m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { + error = ENOBUFS; + + /* + * If the NIC is up and running, we need to: + * - Clear RX buffer's header. + * - Restore RX descriptor settings. + */ + if (init) + return (error); + else + goto back; + } + m->m_len = m->m_pkthdr.len = MCLBYTES; + + bwn_dma_set_redzone(dr, m); + + /* + * Try to load RX buf into temporary DMA map + */ + error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m, + bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); + if (error) { + m_freem(m); + + /* + * See the comment above + */ + if (init) + return (error); + else + goto back; + } + + if (!init) + bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap); + meta->mt_m = m; + meta->mt_paddr = paddr; + + /* + * Swap RX buf's DMA map with the loaded temporary one + */ + map = meta->mt_dmap; + meta->mt_dmap = dr->dr_spare_dmap; + dr->dr_spare_dmap = map; + +back: + /* + * Clear RX buf header + */ + hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *); + bzero(hdr, sizeof(*hdr)); + bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, + BUS_DMASYNC_PREWRITE); + + /* + * Setup RX buf descriptor + */ + dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len - + sizeof(*hdr), 0, 0, 0); + return (error); +} + +static void +bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg, + bus_size_t mapsz __unused, int error) +{ + + if (!error) { + KASSERT(nseg == 1, ("too many segments(%d)\n", nseg)); + *((bus_addr_t *)arg) = seg->ds_addr; + } +} + +static int +bwn_hwrate2ieeerate(int rate) +{ + + switch (rate) { + case BWN_CCK_RATE_1MB: + return (2); + case BWN_CCK_RATE_2MB: + return (4); + case BWN_CCK_RATE_5MB: + return (11); + case BWN_CCK_RATE_11MB: + return (22); + case BWN_OFDM_RATE_6MB: + return (12); + case BWN_OFDM_RATE_9MB: + return (18); + case BWN_OFDM_RATE_12MB: + return (24); + case BWN_OFDM_RATE_18MB: + return (36); + case BWN_OFDM_RATE_24MB: + return (48); + case BWN_OFDM_RATE_36MB: + return (72); + case BWN_OFDM_RATE_48MB: + return (96); + case BWN_OFDM_RATE_54MB: + return (108); + default: + printf("Ooops\n"); + return (0); + } +} + +static void +bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) +{ + const struct bwn_rxhdr4 *rxhdr = _rxhdr; + struct bwn_plcp6 *plcp; + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211_frame_min *wh; + struct ieee80211_node *ni; + struct ieee80211com *ic = &sc->sc_ic; + uint32_t macstat; + int padding, rate, rssi = 0, noise = 0, type; + uint16_t phytype, phystat0, phystat3, chanstat; + unsigned char *mp = mtod(m, unsigned char *); + static int rx_mac_dec_rpt = 0; + + BWN_ASSERT_LOCKED(sc); + + phystat0 = le16toh(rxhdr->phy_status0); + phystat3 = le16toh(rxhdr->phy_status3); + macstat = le32toh(rxhdr->mac_status); + chanstat = le16toh(rxhdr->channel); + phytype = chanstat & BWN_RX_CHAN_PHYTYPE; + + if (macstat & BWN_RX_MAC_FCSERR) + device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n"); + if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV)) + device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n"); + if (macstat & BWN_RX_MAC_DECERR) + goto drop; + + padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0; + if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) { + device_printf(sc->sc_dev, "frame too short (length=%d)\n", + m->m_pkthdr.len); + goto drop; + } + plcp = (struct bwn_plcp6 *)(mp + padding); + m_adj(m, sizeof(struct bwn_plcp6) + padding); + if (m->m_pkthdr.len < IEEE80211_MIN_LEN) { + device_printf(sc->sc_dev, "frame too short (length=%d)\n", + m->m_pkthdr.len); + goto drop; + } + wh = mtod(m, struct ieee80211_frame_min *); + + if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50) + device_printf(sc->sc_dev, + "RX decryption attempted (old %d keyidx %#x)\n", + BWN_ISOLDFMT(mac), + (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT); + + /* XXX calculating RSSI & noise & antenna */ + + if (phystat0 & BWN_RX_PHYST0_OFDM) + rate = bwn_plcp_get_ofdmrate(mac, plcp, + phytype == BWN_PHYTYPE_A); + else + rate = bwn_plcp_get_cckrate(mac, plcp); + if (rate == -1) { + if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP)) + goto drop; + } + sc->sc_rx_rate = bwn_hwrate2ieeerate(rate); + + /* RX radio tap */ + if (ieee80211_radiotap_active(ic)) + bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise); + m_adj(m, -IEEE80211_CRC_LEN); + + rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */ + noise = mac->mac_stats.link_noise; + + BWN_UNLOCK(sc); + + ni = ieee80211_find_rxnode(ic, wh); + if (ni != NULL) { + type = ieee80211_input(ni, m, rssi, noise); + ieee80211_free_node(ni); + } else + type = ieee80211_input_all(ic, m, rssi, noise); + + BWN_LOCK(sc); + return; +drop: + device_printf(sc->sc_dev, "%s: dropped\n", __func__); +} + +static void +bwn_dma_handle_txeof(struct bwn_mac *mac, + const struct bwn_txstatus *status) +{ + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_dma_ring *dr; + struct bwn_dmadesc_generic *desc; + struct bwn_dmadesc_meta *meta; + struct bwn_softc *sc = mac->mac_sc; + int slot; + int retrycnt = 0; + + BWN_ASSERT_LOCKED(sc); + + dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot); + if (dr == NULL) { + device_printf(sc->sc_dev, "failed to parse cookie\n"); + return; + } + KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__)); + + while (1) { + KASSERT(slot >= 0 && slot < dr->dr_numslots, + ("%s:%d: fail", __func__, __LINE__)); + dr->getdesc(dr, slot, &desc, &meta); + + if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) + bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap); + else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) + bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap); + + if (meta->mt_islast) { + KASSERT(meta->mt_m != NULL, + ("%s:%d: fail", __func__, __LINE__)); + + /* XXX */ + if (status->ack == 0) + retrycnt = 1; + else + retrycnt = 0; + ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni, + status->ack ? + IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, 0); + ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0); + meta->mt_ni = NULL; + meta->mt_m = NULL; + } else + KASSERT(meta->mt_m == NULL, + ("%s:%d: fail", __func__, __LINE__)); + + dr->dr_usedslot--; + if (meta->mt_islast) + break; + slot = bwn_dma_nextslot(dr, slot); + } + sc->sc_watchdog_timer = 0; + if (dr->dr_stop) { + KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME, + ("%s:%d: fail", __func__, __LINE__)); + dr->dr_stop = 0; + } +} + +static void +bwn_pio_handle_txeof(struct bwn_mac *mac, + const struct bwn_txstatus *status) +{ + struct bwn_pio_txqueue *tq; + struct bwn_pio_txpkt *tp = NULL; + struct bwn_softc *sc = mac->mac_sc; + int retrycnt = 0; + + BWN_ASSERT_LOCKED(sc); + + tq = bwn_pio_parse_cookie(mac, status->cookie, &tp); + if (tq == NULL) + return; + + tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); + tq->tq_free++; + + if (tp->tp_ni != NULL) { + /* + * Do any tx complete callback. Note this must + * be done before releasing the node reference. + */ + + /* XXX */ + if (status->ack == 0) + retrycnt = 1; + else + retrycnt = 0; + ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni, + status->ack ? + IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, 0); + + if (tp->tp_m->m_flags & M_TXCB) + ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0); + ieee80211_free_node(tp->tp_ni); + tp->tp_ni = NULL; + } + m_freem(tp->tp_m); + tp->tp_m = NULL; + TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list); + + sc->sc_watchdog_timer = 0; +} + +static void +bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags) +{ + struct bwn_softc *sc = mac->mac_sc; + struct bwn_phy *phy = &mac->mac_phy; + struct ieee80211com *ic = &sc->sc_ic; + unsigned long now; + int result; + + BWN_GETTIME(now); + + if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime)) + return; + phy->nexttime = now + 2 * 1000; + + if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM && + siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306) + return; + + if (phy->recalc_txpwr != NULL) { + result = phy->recalc_txpwr(mac, + (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0); + if (result == BWN_TXPWR_RES_DONE) + return; + KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST, + ("%s: fail", __func__)); + KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__)); + + ieee80211_runtask(ic, &mac->mac_txpower); + } +} + +static uint16_t +bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset) +{ + + return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset)); +} + +static uint32_t +bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset) +{ + + return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset)); +} + +static void +bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value) +{ + + BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value); +} + +static void +bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value) +{ + + BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value); +} + +static int +bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate) +{ + + switch (rate) { + /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ + case 12: + return (BWN_OFDM_RATE_6MB); + case 18: + return (BWN_OFDM_RATE_9MB); + case 24: + return (BWN_OFDM_RATE_12MB); + case 36: + return (BWN_OFDM_RATE_18MB); + case 48: + return (BWN_OFDM_RATE_24MB); + case 72: + return (BWN_OFDM_RATE_36MB); + case 96: + return (BWN_OFDM_RATE_48MB); + case 108: + return (BWN_OFDM_RATE_54MB); + /* CCK rates (NB: not IEEE std, device-specific) */ + case 2: + return (BWN_CCK_RATE_1MB); + case 4: + return (BWN_CCK_RATE_2MB); + case 11: + return (BWN_CCK_RATE_5MB); + case 22: + return (BWN_CCK_RATE_11MB); + } + + device_printf(sc->sc_dev, "unsupported rate %d\n", rate); + return (BWN_CCK_RATE_1MB); +} + +static int +bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, + struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie) +{ + const struct bwn_phy *phy = &mac->mac_phy; + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211_frame *wh; + struct ieee80211_frame *protwh; + struct ieee80211_frame_cts *cts; + struct ieee80211_frame_rts *rts; + const struct ieee80211_txparam *tp; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = &sc->sc_ic; + struct mbuf *mprot; + unsigned int len; + uint32_t macctl = 0; + int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type; + uint16_t phyctl = 0; + uint8_t rate, rate_fb; + + wh = mtod(m, struct ieee80211_frame *); + memset(txhdr, 0, sizeof(*txhdr)); + + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; + + /* + * Find TX rate + */ + tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; + if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL)) + rate = rate_fb = tp->mgmtrate; + else if (ismcast) + rate = rate_fb = tp->mcastrate; + else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) + rate = rate_fb = tp->ucastrate; + else { + /* XXX TODO: don't fall back to CCK rates for OFDM */ + rix = ieee80211_ratectl_rate(ni, NULL, 0); + rate = ni->ni_txrate; + + if (rix > 0) + rate_fb = ni->ni_rates.rs_rates[rix - 1] & + IEEE80211_RATE_VAL; + else + rate_fb = rate; + } + + sc->sc_tx_rate = rate; + + /* Note: this maps the select ieee80211 rate to hardware rate */ + rate = bwn_ieeerate2hwrate(sc, rate); + rate_fb = bwn_ieeerate2hwrate(sc, rate_fb); + + txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) : + bwn_plcp_getcck(rate); + bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc)); + bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN); + + /* XXX rate/rate_fb is the hardware rate */ + if ((rate_fb == rate) || + (*(u_int16_t *)wh->i_dur & htole16(0x8000)) || + (*(u_int16_t *)wh->i_dur == htole16(0))) + txhdr->dur_fb = *(u_int16_t *)wh->i_dur; + else + txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt, + m->m_pkthdr.len, rate, isshort); + + /* XXX TX encryption */ + bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ? + (struct bwn_plcp4 *)(&txhdr->body.old.plcp) : + (struct bwn_plcp4 *)(&txhdr->body.new.plcp), + m->m_pkthdr.len + IEEE80211_CRC_LEN, rate); + bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb), + m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb); + + txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM : + BWN_TX_EFT_FB_CCK; + txhdr->chan = phy->chan; + phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM : + BWN_TX_PHY_ENC_CCK; + /* XXX preamble? obey net80211 */ + if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB || + rate == BWN_CCK_RATE_11MB)) + phyctl |= BWN_TX_PHY_SHORTPRMBL; + + /* XXX TX antenna selection */ + + switch (bwn_antenna_sanitize(mac, 0)) { + case 0: + phyctl |= BWN_TX_PHY_ANT01AUTO; + break; + case 1: + phyctl |= BWN_TX_PHY_ANT0; + break; + case 2: + phyctl |= BWN_TX_PHY_ANT1; + break; + case 3: + phyctl |= BWN_TX_PHY_ANT2; + break; + case 4: + phyctl |= BWN_TX_PHY_ANT3; + break; + default: + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + } + + if (!ismcast) + macctl |= BWN_TX_MAC_ACK; + + macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU); + if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && + m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) + macctl |= BWN_TX_MAC_LONGFRAME; + + if (ic->ic_flags & IEEE80211_F_USEPROT) { + /* XXX RTS rate is always 1MB??? */ + /* XXX TODO: don't fall back to CCK rates for OFDM */ + rts_rate = BWN_CCK_RATE_1MB; + rts_rate_fb = bwn_get_fbrate(rts_rate); + + /* XXX 'rate' here is hardware rate now, not the net80211 rate */ + protdur = ieee80211_compute_duration(ic->ic_rt, + m->m_pkthdr.len, rate, isshort) + + + ieee80211_ack_duration(ic->ic_rt, rate, isshort); + + if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { + cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ? + (txhdr->body.old.rts_frame) : + (txhdr->body.new.rts_frame)); + mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, + protdur); + KASSERT(mprot != NULL, ("failed to alloc mbuf\n")); + bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts, + mprot->m_pkthdr.len); + m_freem(mprot); + macctl |= BWN_TX_MAC_SEND_CTSTOSELF; + len = sizeof(struct ieee80211_frame_cts); + } else { + rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ? + (txhdr->body.old.rts_frame) : + (txhdr->body.new.rts_frame)); + /* XXX rate/rate_fb is the hardware rate */ + protdur += ieee80211_ack_duration(ic->ic_rt, rate, + isshort); + mprot = ieee80211_alloc_rts(ic, wh->i_addr1, + wh->i_addr2, protdur); + KASSERT(mprot != NULL, ("failed to alloc mbuf\n")); + bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts, + mprot->m_pkthdr.len); + m_freem(mprot); + macctl |= BWN_TX_MAC_SEND_RTSCTS; + len = sizeof(struct ieee80211_frame_rts); + } + len += IEEE80211_CRC_LEN; + bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ? + &txhdr->body.old.rts_plcp : + &txhdr->body.new.rts_plcp), len, rts_rate); + bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len, + rts_rate_fb); + + protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ? + (&txhdr->body.old.rts_frame) : + (&txhdr->body.new.rts_frame)); + txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur; + + if (BWN_ISOFDMRATE(rts_rate)) { + txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM; + txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate); + } else { + txhdr->eftypes |= BWN_TX_EFT_RTS_CCK; + txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate); + } + txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ? + BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK; + } + + if (BWN_ISOLDFMT(mac)) + txhdr->body.old.cookie = htole16(cookie); + else + txhdr->body.new.cookie = htole16(cookie); + + txhdr->macctl = htole32(macctl); + txhdr->phyctl = htole16(phyctl); + + /* + * TX radio tap + */ + if (ieee80211_radiotap_active_vap(vap)) { + sc->sc_tx_th.wt_flags = 0; + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) + sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; + if (isshort && + (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB || + rate == BWN_CCK_RATE_11MB)) + sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + sc->sc_tx_th.wt_rate = rate; + + ieee80211_radiotap_tx(vap, m); + } + + return (0); +} + +static void +bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets, + const uint8_t rate) +{ + uint32_t d, plen; + uint8_t *raw = plcp->o.raw; + + if (BWN_ISOFDMRATE(rate)) { + d = bwn_plcp_getofdm(rate); + KASSERT(!(octets & 0xf000), + ("%s:%d: fail", __func__, __LINE__)); + d |= (octets << 5); + plcp->o.data = htole32(d); + } else { + plen = octets * 16 / rate; + if ((octets * 16 % rate) > 0) { + plen++; + if ((rate == BWN_CCK_RATE_11MB) + && ((octets * 8 % 11) < 4)) { + raw[1] = 0x84; + } else + raw[1] = 0x04; + } else + raw[1] = 0x04; + plcp->o.data |= htole32(plen << 16); + raw[0] = bwn_plcp_getcck(rate); + } +} + +static uint8_t +bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n) +{ + struct bwn_softc *sc = mac->mac_sc; + uint8_t mask; + + if (n == 0) + return (0); + if (mac->mac_phy.gmode) + mask = siba_sprom_get_ant_bg(sc->sc_dev); + else + mask = siba_sprom_get_ant_a(sc->sc_dev); + if (!(mask & (1 << (n - 1)))) + return (0); + return (n); +} + +/* + * Return a fallback rate for the given rate. + * + * Note: Don't fall back from OFDM to CCK. + */ +static uint8_t +bwn_get_fbrate(uint8_t bitrate) +{ + switch (bitrate) { + /* CCK */ + case BWN_CCK_RATE_1MB: + return (BWN_CCK_RATE_1MB); + case BWN_CCK_RATE_2MB: + return (BWN_CCK_RATE_1MB); + case BWN_CCK_RATE_5MB: + return (BWN_CCK_RATE_2MB); + case BWN_CCK_RATE_11MB: + return (BWN_CCK_RATE_5MB); + + /* OFDM */ + case BWN_OFDM_RATE_6MB: + return (BWN_OFDM_RATE_6MB); + case BWN_OFDM_RATE_9MB: + return (BWN_OFDM_RATE_6MB); + case BWN_OFDM_RATE_12MB: + return (BWN_OFDM_RATE_9MB); + case BWN_OFDM_RATE_18MB: + return (BWN_OFDM_RATE_12MB); + case BWN_OFDM_RATE_24MB: + return (BWN_OFDM_RATE_18MB); + case BWN_OFDM_RATE_36MB: + return (BWN_OFDM_RATE_24MB); + case BWN_OFDM_RATE_48MB: + return (BWN_OFDM_RATE_36MB); + case BWN_OFDM_RATE_54MB: + return (BWN_OFDM_RATE_48MB); + } + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (0); +} + +static uint32_t +bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, + uint32_t ctl, const void *_data, int len) +{ + struct bwn_softc *sc = mac->mac_sc; + uint32_t value = 0; + const uint8_t *data = _data; + + ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 | + BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31; + bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl); + + siba_write_multi_4(sc->sc_dev, data, (len & ~3), + tq->tq_base + BWN_PIO8_TXDATA); + if (len & 3) { + ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 | + BWN_PIO8_TXCTL_24_31); + data = &(data[len - 1]); + switch (len & 3) { + case 3: + ctl |= BWN_PIO8_TXCTL_16_23; + value |= (uint32_t)(*data) << 16; + data--; + case 2: + ctl |= BWN_PIO8_TXCTL_8_15; + value |= (uint32_t)(*data) << 8; + data--; + case 1: + value |= (uint32_t)(*data); + } + bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl); + bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value); + } + + return (ctl); +} + +static void +bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, + uint16_t offset, uint32_t value) +{ + + BWN_WRITE_4(mac, tq->tq_base + offset, value); +} + +static uint16_t +bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, + uint16_t ctl, const void *_data, int len) +{ + struct bwn_softc *sc = mac->mac_sc; + const uint8_t *data = _data; + + ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI; + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); + + siba_write_multi_2(sc->sc_dev, data, (len & ~1), + tq->tq_base + BWN_PIO_TXDATA); + if (len & 1) { + ctl &= ~BWN_PIO_TXCTL_WRITEHI; + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]); + } + + return (ctl); +} + +static uint16_t +bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, + uint16_t ctl, struct mbuf *m0) +{ + int i, j = 0; + uint16_t data = 0; + const uint8_t *buf; + struct mbuf *m = m0; + + ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI; + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); + + for (; m != NULL; m = m->m_next) { + buf = mtod(m, const uint8_t *); + for (i = 0; i < m->m_len; i++) { + if (!((j++) % 2)) + data |= buf[i]; + else { + data |= (buf[i] << 8); + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data); + data = 0; + } + } + } + if (m0->m_pkthdr.len % 2) { + ctl &= ~BWN_PIO_TXCTL_WRITEHI; + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); + BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data); + } + + return (ctl); +} + +static void +bwn_set_slot_time(struct bwn_mac *mac, uint16_t time) +{ + + if (mac->mac_phy.type != BWN_PHYTYPE_G) + return; + BWN_WRITE_2(mac, 0x684, 510 + time); + bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time); +} + +static struct bwn_dma_ring * +bwn_dma_select(struct bwn_mac *mac, uint8_t prio) +{ + + if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0) + return (mac->mac_method.dma.wme[WME_AC_BE]); + + switch (prio) { + case 3: + return (mac->mac_method.dma.wme[WME_AC_VO]); + case 2: + return (mac->mac_method.dma.wme[WME_AC_VI]); + case 0: + return (mac->mac_method.dma.wme[WME_AC_BE]); + case 1: + return (mac->mac_method.dma.wme[WME_AC_BK]); + } + KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); + return (NULL); +} + +static int +bwn_dma_getslot(struct bwn_dma_ring *dr) +{ + int slot; + + BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc); + + KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__)); + KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__)); + KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__)); + + slot = bwn_dma_nextslot(dr, dr->dr_curslot); + KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__)); + dr->dr_curslot = slot; + dr->dr_usedslot++; + + return (slot); +} + +static struct bwn_pio_txqueue * +bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie, + struct bwn_pio_txpkt **pack) +{ + struct bwn_pio *pio = &mac->mac_method.pio; + struct bwn_pio_txqueue *tq = NULL; + unsigned int index; + + switch (cookie & 0xf000) { + case 0x1000: + tq = &pio->wme[WME_AC_BK]; + break; + case 0x2000: + tq = &pio->wme[WME_AC_BE]; + break; + case 0x3000: + tq = &pio->wme[WME_AC_VI]; + break; + case 0x4000: + tq = &pio->wme[WME_AC_VO]; + break; + case 0x5000: + tq = &pio->mcast; + break; + } + KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__)); + if (tq == NULL) + return (NULL); + index = (cookie & 0x0fff); + KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__)); + if (index >= N(tq->tq_pkts)) + return (NULL); + *pack = &tq->tq_pkts[index]; + KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__)); + return (tq); +} + +static void +bwn_txpwr(void *arg, int npending) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + + BWN_LOCK(sc); + if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED && + mac->mac_phy.set_txpwr != NULL) + mac->mac_phy.set_txpwr(mac); + BWN_UNLOCK(sc); +} + +static void +bwn_task_15s(struct bwn_mac *mac) +{ + uint16_t reg; + + if (mac->mac_fw.opensource) { + reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG); + if (reg) { + bwn_restart(mac, "fw watchdog"); + return; + } + bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1); + } + if (mac->mac_phy.task_15s) + mac->mac_phy.task_15s(mac); + + mac->mac_phy.txerrors = BWN_TXERROR_MAX; +} + +static void +bwn_task_30s(struct bwn_mac *mac) +{ + + if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running) + return; + mac->mac_noise.noi_running = 1; + mac->mac_noise.noi_nsamples = 0; + + bwn_noise_gensample(mac); +} + +static void +bwn_task_60s(struct bwn_mac *mac) +{ + + if (mac->mac_phy.task_60s) + mac->mac_phy.task_60s(mac); + bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME); +} + +static void +bwn_tasks(void *arg) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + + BWN_ASSERT_LOCKED(sc); + if (mac->mac_status != BWN_MAC_STATUS_STARTED) + return; + + if (mac->mac_task_state % 4 == 0) + bwn_task_60s(mac); + if (mac->mac_task_state % 2 == 0) + bwn_task_30s(mac); + bwn_task_15s(mac); + + mac->mac_task_state++; + callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac); +} + +static int +bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a) +{ + struct bwn_softc *sc = mac->mac_sc; + + KASSERT(a == 0, ("not support APHY\n")); + + switch (plcp->o.raw[0] & 0xf) { + case 0xb: + return (BWN_OFDM_RATE_6MB); + case 0xf: + return (BWN_OFDM_RATE_9MB); + case 0xa: + return (BWN_OFDM_RATE_12MB); + case 0xe: + return (BWN_OFDM_RATE_18MB); + case 0x9: + return (BWN_OFDM_RATE_24MB); + case 0xd: + return (BWN_OFDM_RATE_36MB); + case 0x8: + return (BWN_OFDM_RATE_48MB); + case 0xc: + return (BWN_OFDM_RATE_54MB); + } + device_printf(sc->sc_dev, "incorrect OFDM rate %d\n", + plcp->o.raw[0] & 0xf); + return (-1); +} + +static int +bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp) +{ + struct bwn_softc *sc = mac->mac_sc; + + switch (plcp->o.raw[0]) { + case 0x0a: + return (BWN_CCK_RATE_1MB); + case 0x14: + return (BWN_CCK_RATE_2MB); + case 0x37: + return (BWN_CCK_RATE_5MB); + case 0x6e: + return (BWN_CCK_RATE_11MB); + } + device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]); + return (-1); +} + +static void +bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m, + const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate, + int rssi, int noise) +{ + struct bwn_softc *sc = mac->mac_sc; + const struct ieee80211_frame_min *wh; + uint64_t tsf; + uint16_t low_mactime_now; + + if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL) + sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + + wh = mtod(m, const struct ieee80211_frame_min *); + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) + sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP; + + bwn_tsf_read(mac, &tsf); + low_mactime_now = tsf; + tsf = tsf & ~0xffffULL; + tsf += le16toh(rxhdr->mac_time); + if (low_mactime_now < le16toh(rxhdr->mac_time)) + tsf -= 0x10000; + + sc->sc_rx_th.wr_tsf = tsf; + sc->sc_rx_th.wr_rate = rate; + sc->sc_rx_th.wr_antsignal = rssi; + sc->sc_rx_th.wr_antnoise = noise; +} + +static void +bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf) +{ + uint32_t low, high; + + KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3, + ("%s:%d: fail", __func__, __LINE__)); + + low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW); + high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH); + *tsf = high; + *tsf <<= 32; + *tsf |= low; +} + +static int +bwn_dma_attach(struct bwn_mac *mac) +{ + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_softc *sc = mac->mac_sc; + bus_addr_t lowaddr = 0; + int error; + + if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0) + return (0); + + KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__)); + + mac->mac_flags |= BWN_MAC_FLAG_DMA; + + dma->dmatype = bwn_dma_gettype(mac); + if (dma->dmatype == BWN_DMA_30BIT) + lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT; + else if (dma->dmatype == BWN_DMA_32BIT) + lowaddr = BUS_SPACE_MAXADDR_32BIT; + else + lowaddr = BUS_SPACE_MAXADDR; + + /* + * Create top level DMA tag + */ + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */ + BWN_ALIGN, 0, /* alignment, bounds */ + lowaddr, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE, /* maxsize */ + BUS_SPACE_UNRESTRICTED, /* nsegments */ + BUS_SPACE_MAXSIZE, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &dma->parent_dtag); + if (error) { + device_printf(sc->sc_dev, "can't create parent DMA tag\n"); + return (error); + } + + /* + * Create TX/RX mbuf DMA tag + */ + error = bus_dma_tag_create(dma->parent_dtag, + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + MCLBYTES, + 1, + BUS_SPACE_MAXSIZE_32BIT, + 0, + NULL, NULL, + &dma->rxbuf_dtag); + if (error) { + device_printf(sc->sc_dev, "can't create mbuf DMA tag\n"); + goto fail0; + } + error = bus_dma_tag_create(dma->parent_dtag, + 1, + 0, + BUS_SPACE_MAXADDR, + BUS_SPACE_MAXADDR, + NULL, NULL, + MCLBYTES, + 1, + BUS_SPACE_MAXSIZE_32BIT, + 0, + NULL, NULL, + &dma->txbuf_dtag); + if (error) { + device_printf(sc->sc_dev, "can't create mbuf DMA tag\n"); + goto fail1; + } + + dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype); + if (!dma->wme[WME_AC_BK]) + goto fail2; + + dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype); + if (!dma->wme[WME_AC_BE]) + goto fail3; + + dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype); + if (!dma->wme[WME_AC_VI]) + goto fail4; + + dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype); + if (!dma->wme[WME_AC_VO]) + goto fail5; + + dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype); + if (!dma->mcast) + goto fail6; + dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype); + if (!dma->rx) + goto fail7; + + return (error); + +fail7: bwn_dma_ringfree(&dma->mcast); +fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]); +fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]); +fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]); +fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]); +fail2: bus_dma_tag_destroy(dma->txbuf_dtag); +fail1: bus_dma_tag_destroy(dma->rxbuf_dtag); +fail0: bus_dma_tag_destroy(dma->parent_dtag); + return (error); +} + +static struct bwn_dma_ring * +bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status, + uint16_t cookie, int *slot) +{ + struct bwn_dma *dma = &mac->mac_method.dma; + struct bwn_dma_ring *dr; + struct bwn_softc *sc = mac->mac_sc; + + BWN_ASSERT_LOCKED(mac->mac_sc); + + switch (cookie & 0xf000) { + case 0x1000: + dr = dma->wme[WME_AC_BK]; + break; + case 0x2000: + dr = dma->wme[WME_AC_BE]; + break; + case 0x3000: + dr = dma->wme[WME_AC_VI]; + break; + case 0x4000: + dr = dma->wme[WME_AC_VO]; + break; + case 0x5000: + dr = dma->mcast; + break; + default: + dr = NULL; + KASSERT(0 == 1, + ("invalid cookie value %d", cookie & 0xf000)); + } + *slot = (cookie & 0x0fff); + if (*slot < 0 || *slot >= dr->dr_numslots) { + /* + * XXX FIXME: sometimes H/W returns TX DONE events duplicately + * that it occurs events which have same H/W sequence numbers. + * When it's occurred just prints a WARNING msgs and ignores. + */ + KASSERT(status->seq == dma->lastseq, + ("%s:%d: fail", __func__, __LINE__)); + device_printf(sc->sc_dev, + "out of slot ranges (0 < %d < %d)\n", *slot, + dr->dr_numslots); + return (NULL); + } + dma->lastseq = status->seq; + return (dr); +} + +static void +bwn_dma_stop(struct bwn_mac *mac) +{ + struct bwn_dma *dma; + + if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0) + return; + dma = &mac->mac_method.dma; + + bwn_dma_ringstop(&dma->rx); + bwn_dma_ringstop(&dma->wme[WME_AC_BK]); + bwn_dma_ringstop(&dma->wme[WME_AC_BE]); + bwn_dma_ringstop(&dma->wme[WME_AC_VI]); + bwn_dma_ringstop(&dma->wme[WME_AC_VO]); + bwn_dma_ringstop(&dma->mcast); +} + +static void +bwn_dma_ringstop(struct bwn_dma_ring **dr) +{ + + if (dr == NULL) + return; + + bwn_dma_cleanup(*dr); +} + +static void +bwn_pio_stop(struct bwn_mac *mac) +{ + struct bwn_pio *pio; + + if (mac->mac_flags & BWN_MAC_FLAG_DMA) + return; + pio = &mac->mac_method.pio; + + bwn_destroy_queue_tx(&pio->mcast); + bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]); + bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]); + bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]); + bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]); +} + +static void +bwn_led_attach(struct bwn_mac *mac) +{ + struct bwn_softc *sc = mac->mac_sc; + const uint8_t *led_act = NULL; + uint16_t val[BWN_LED_MAX]; + int i; + + sc->sc_led_idle = (2350 * hz) / 1000; + sc->sc_led_blink = 1; + + for (i = 0; i < N(bwn_vendor_led_act); ++i) { + if (siba_get_pci_subvendor(sc->sc_dev) == + bwn_vendor_led_act[i].vid) { + led_act = bwn_vendor_led_act[i].led_act; + break; + } + } + if (led_act == NULL) + led_act = bwn_default_led_act; + + val[0] = siba_sprom_get_gpio0(sc->sc_dev); + val[1] = siba_sprom_get_gpio1(sc->sc_dev); + val[2] = siba_sprom_get_gpio2(sc->sc_dev); + val[3] = siba_sprom_get_gpio3(sc->sc_dev); + + for (i = 0; i < BWN_LED_MAX; ++i) { + struct bwn_led *led = &sc->sc_leds[i]; + + if (val[i] == 0xff) { + led->led_act = led_act[i]; + } else { + if (val[i] & BWN_LED_ACT_LOW) + led->led_flags |= BWN_LED_F_ACTLOW; + led->led_act = val[i] & BWN_LED_ACT_MASK; + } + led->led_mask = (1 << i); + + if (led->led_act == BWN_LED_ACT_BLINK_SLOW || + led->led_act == BWN_LED_ACT_BLINK_POLL || + led->led_act == BWN_LED_ACT_BLINK) { + led->led_flags |= BWN_LED_F_BLINK; + if (led->led_act == BWN_LED_ACT_BLINK_POLL) + led->led_flags |= BWN_LED_F_POLLABLE; + else if (led->led_act == BWN_LED_ACT_BLINK_SLOW) + led->led_flags |= BWN_LED_F_SLOW; + + if (sc->sc_blink_led == NULL) { + sc->sc_blink_led = led; + if (led->led_flags & BWN_LED_F_SLOW) + BWN_LED_SLOWDOWN(sc->sc_led_idle); + } + } + + DPRINTF(sc, BWN_DEBUG_LED, + "%dth led, act %d, lowact %d\n", i, + led->led_act, led->led_flags & BWN_LED_F_ACTLOW); + } + callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0); +} + +static __inline uint16_t +bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on) +{ + + if (led->led_flags & BWN_LED_F_ACTLOW) + on = !on; + if (on) + val |= led->led_mask; + else + val &= ~led->led_mask; + return val; +} + +static void +bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate) +{ + struct bwn_softc *sc = mac->mac_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint16_t val; + int i; + + if (nstate == IEEE80211_S_INIT) { + callout_stop(&sc->sc_led_blink_ch); + sc->sc_led_blinking = 0; + } + + if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) + return; + + val = BWN_READ_2(mac, BWN_GPIO_CONTROL); + for (i = 0; i < BWN_LED_MAX; ++i) { + struct bwn_led *led = &sc->sc_leds[i]; + int on; + + if (led->led_act == BWN_LED_ACT_UNKN || + led->led_act == BWN_LED_ACT_NULL) + continue; + + if ((led->led_flags & BWN_LED_F_BLINK) && + nstate != IEEE80211_S_INIT) + continue; + + switch (led->led_act) { + case BWN_LED_ACT_ON: /* Always on */ + on = 1; + break; + case BWN_LED_ACT_OFF: /* Always off */ + case BWN_LED_ACT_5GHZ: /* TODO: 11A */ + on = 0; + break; + default: + on = 1; + switch (nstate) { + case IEEE80211_S_INIT: + on = 0; + break; + case IEEE80211_S_RUN: + if (led->led_act == BWN_LED_ACT_11G && + ic->ic_curmode != IEEE80211_MODE_11G) + on = 0; + break; + default: + if (led->led_act == BWN_LED_ACT_ASSOC) + on = 0; + break; + } + break; + } + + val = bwn_led_onoff(led, val, on); + } + BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val); +} + +static void +bwn_led_event(struct bwn_mac *mac, int event) +{ + struct bwn_softc *sc = mac->mac_sc; + struct bwn_led *led = sc->sc_blink_led; + int rate; + + if (event == BWN_LED_EVENT_POLL) { + if ((led->led_flags & BWN_LED_F_POLLABLE) == 0) + return; + if (ticks - sc->sc_led_ticks < sc->sc_led_idle) + return; + } + + sc->sc_led_ticks = ticks; + if (sc->sc_led_blinking) + return; + + switch (event) { + case BWN_LED_EVENT_RX: + rate = sc->sc_rx_rate; + break; + case BWN_LED_EVENT_TX: + rate = sc->sc_tx_rate; + break; + case BWN_LED_EVENT_POLL: + rate = 0; + break; + default: + panic("unknown LED event %d\n", event); + break; + } + bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur, + bwn_led_duration[rate].off_dur); +} + +static void +bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur) +{ + struct bwn_softc *sc = mac->mac_sc; + struct bwn_led *led = sc->sc_blink_led; + uint16_t val; + + val = BWN_READ_2(mac, BWN_GPIO_CONTROL); + val = bwn_led_onoff(led, val, 1); + BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val); + + if (led->led_flags & BWN_LED_F_SLOW) { + BWN_LED_SLOWDOWN(on_dur); + BWN_LED_SLOWDOWN(off_dur); + } + + sc->sc_led_blinking = 1; + sc->sc_led_blink_offdur = off_dur; + + callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac); +} + +static void +bwn_led_blink_next(void *arg) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + uint16_t val; + + val = BWN_READ_2(mac, BWN_GPIO_CONTROL); + val = bwn_led_onoff(sc->sc_blink_led, val, 0); + BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val); + + callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur, + bwn_led_blink_end, mac); +} + +static void +bwn_led_blink_end(void *arg) +{ + struct bwn_mac *mac = arg; + struct bwn_softc *sc = mac->mac_sc; + + sc->sc_led_blinking = 0; +} + +static int +bwn_suspend(device_t dev) +{ + struct bwn_softc *sc = device_get_softc(dev); + + BWN_LOCK(sc); + bwn_stop(sc); + BWN_UNLOCK(sc); + return (0); +} + +static int +bwn_resume(device_t dev) +{ + struct bwn_softc *sc = device_get_softc(dev); + int error = EDOOFUS; + + BWN_LOCK(sc); + if (sc->sc_ic.ic_nrunning > 0) + error = bwn_init(sc); + BWN_UNLOCK(sc); + if (error == 0) + ieee80211_start_all(&sc->sc_ic); + return (0); +} + +static void +bwn_rfswitch(void *arg) +{ + struct bwn_softc *sc = arg; + struct bwn_mac *mac = sc->sc_curmac; + int cur = 0, prev = 0; + + KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED, + ("%s: invalid MAC status %d", __func__, mac->mac_status)); + + if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) { + if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI) + & BWN_RF_HWENABLED_HI_MASK)) + cur = 1; + } else { + if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO) + & BWN_RF_HWENABLED_LO_MASK) + cur = 1; + } + + if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON) + prev = 1; + + if (cur != prev) { + if (cur) + mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON; + else + mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON; + + device_printf(sc->sc_dev, + "status of RF switch is changed to %s\n", + cur ? "ON" : "OFF"); + if (cur != mac->mac_phy.rf_on) { + if (cur) + bwn_rf_turnon(mac); + else + bwn_rf_turnoff(mac); + } + } + + callout_schedule(&sc->sc_rfswitch_ch, hz); +} + +static void +bwn_sysctl_node(struct bwn_softc *sc) +{ + device_t dev = sc->sc_dev; + struct bwn_mac *mac; + struct bwn_stats *stats; + + /* XXX assume that count of MAC is only 1. */ + + if ((mac = sc->sc_curmac) == NULL) + return; + stats = &mac->mac_stats; + + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level"); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "rts", CTLFLAG_RW, &stats->rts, 0, "RTS"); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send"); + +#ifdef BWN_DEBUG + SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags"); +#endif +} + +static device_method_t bwn_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bwn_probe), + DEVMETHOD(device_attach, bwn_attach), + DEVMETHOD(device_detach, bwn_detach), + DEVMETHOD(device_suspend, bwn_suspend), + DEVMETHOD(device_resume, bwn_resume), + DEVMETHOD_END +}; +static driver_t bwn_driver = { + "bwn", + bwn_methods, + sizeof(struct bwn_softc) +}; +static devclass_t bwn_devclass; +DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0); +MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1); +MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */ +MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */ +MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1); diff --git a/sys/dev/bwn/if_bwn_debug.h b/sys/dev/bwn/if_bwn_debug.h index c38b08f..761fc5d 100644 --- a/sys/dev/bwn/if_bwn_debug.h +++ b/sys/dev/bwn/if_bwn_debug.h @@ -32,6 +32,8 @@ #ifndef __IF_BWN_DEBUG_H__ #define __IF_BWN_DEBUG_H__ +#define BWN_DEBUG + enum { BWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ BWN_DEBUG_RECV = 0x00000002, /* basic recv operation */ diff --git a/sys/dev/bwn/if_bwn_pci.c b/sys/dev/bwn/if_bwn_pci.c new file mode 100644 index 0000000..7e145c5 --- /dev/null +++ b/sys/dev/bwn/if_bwn_pci.c @@ -0,0 +1,288 @@ +/*- + * Copyright (c) 2015 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "bhndb_bus_if.h" + +#include "if_bwn_pcivar.h" + +/* If non-zero, enable attachment of BWN_QUIRK_UNTESTED devices */ +static int attach_untested = 0; +TUNABLE_INT("hw.bwn_pci.attach_untested", &attach_untested); + +/* If non-zero, probe at a higher priority than the stable if_bwn driver. */ +static int prefer_new_driver = 0; +TUNABLE_INT("hw.bwn_pci.preferred", &prefer_new_driver); + +/* SIBA Devices */ +static const struct bwn_pci_device siba_devices[] = { + BWN_BCM_DEV(BCM4301, "BCM4301 802.11b", + BWN_QUIRK_ENET_HW_UNPOPULATED), + + BWN_BCM_DEV(BCM4306, "BCM4306 802.11b/g", 0), + BWN_BCM_DEV(BCM4306_D11G, "BCM4306 802.11g", 0), + BWN_BCM_DEV(BCM4306_D11A, "BCM4306 802.11a", + BWN_QUIRK_WLAN_DUALCORE), + BWN_BCM_DEV(BCM4306_D11DUAL, "BCM4306 802.11a/b", + BWN_QUIRK_WLAN_DUALCORE), + BWN_BCM_DEV(BCM4306_D11G_ID2, "BCM4306 802.11g", 0), + + BWN_BCM_DEV(BCM4307, "BCM4307 802.11b", 0), + + BWN_BCM_DEV(BCM4311_D11G, "BCM4311 802.11b/g", 0), + BWN_BCM_DEV(BCM4311_D11DUAL, "BCM4311 802.11a/b/g", 0), + BWN_BCM_DEV(BCM4311_D11A, "BCM4311 802.11a", + BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE), + + BWN_BCM_DEV(BCM4318_D11G, "BCM4318 802.11b/g", 0), + BWN_BCM_DEV(BCM4318_D11DUAL, "BCM4318 802.11a/b/g", 0), + BWN_BCM_DEV(BCM4318_D11A, "BCM4318 802.11a", + BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE), + + BWN_BCM_DEV(BCM4321_D11N, "BCM4321 802.11n Dual-Band", 0), + BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 2GHz", 0), + BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 5GHz", + BWN_QUIRK_UNTESTED), + + BWN_BCM_DEV(BCM4322_D11N, "BCM4322 802.11n Dual-Band", 0), + BWN_BCM_DEV(BCM4322_D11N2G, "BCM4322 802.11n 2GHz", + BWN_QUIRK_UNTESTED), + BWN_BCM_DEV(BCM4322_D11N5G, "BCM4322 802.11n 5GHz", + BWN_QUIRK_UNTESTED), + + BWN_BCM_DEV(BCM4328_D11G, "BCM4328/4312 802.11g", 0), + + { 0, 0, NULL, 0 } +}; + +/** BCMA Devices */ +static const struct bwn_pci_device bcma_devices[] = { + BWN_BCM_DEV(BCM4331_D11N, "BCM4331 802.11n Dual-Band", 0), + BWN_BCM_DEV(BCM4331_D11N2G, "BCM4331 802.11n 2GHz", 0), + BWN_BCM_DEV(BCM4331_D11N5G, "BCM4331 802.11n 5GHz", 0), + + { 0, 0, NULL, 0} +}; + +/** Device configuration table */ +static const struct bwn_pci_devcfg bwn_pci_devcfgs[] = { + /* SIBA devices */ + { + .bridge_hwcfg = &bhndb_pci_siba_generic_hwcfg, + .bridge_hwtable = bhndb_pci_generic_hw_table, + .devices = siba_devices + }, + /* BCMA devices */ + { + .bridge_hwcfg = &bhndb_pci_bcma_generic_hwcfg, + .bridge_hwtable = bhndb_pci_generic_hw_table, + .devices = bcma_devices + }, + { NULL, NULL, NULL } +}; + +/** Search the device configuration table for an entry matching @p dev. */ +static int +bwn_pci_find_devcfg(device_t dev, const struct bwn_pci_devcfg **cfg, + const struct bwn_pci_device **device) +{ + const struct bwn_pci_devcfg *dvc; + const struct bwn_pci_device *dv; + + for (dvc = bwn_pci_devcfgs; dvc->devices != NULL; dvc++) { + for (dv = dvc->devices; dv->device != 0; dv++) { + if (pci_get_vendor(dev) == dv->vendor && + pci_get_device(dev) == dv->device) + { + if (cfg != NULL) + *cfg = dvc; + + if (device != NULL) + *device = dv; + + return (0); + } + } + } + + return (ENOENT); +} + +static int +bwn_pci_probe(device_t dev) +{ + const struct bwn_pci_device *ident; + + if (bwn_pci_find_devcfg(dev, NULL, &ident)) + return (ENXIO); + + /* Skip untested devices */ + if (ident->quirks & BWN_QUIRK_UNTESTED && !attach_untested) + return (ENXIO); + + device_set_desc(dev, ident->desc); + + /* Until this driver is complete, require explicit opt-in before + * superceding if_bwn/siba_bwn. */ + if (prefer_new_driver) + return (BUS_PROBE_DEFAULT+1); + else + return (BUS_PROBE_LOW_PRIORITY); + + // return (BUS_PROBE_DEFAULT); +} + +static int +bwn_pci_attach(device_t dev) +{ + struct bwn_pci_softc *sc; + const struct bwn_pci_device *ident; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Find our hardware config */ + if (bwn_pci_find_devcfg(dev, &sc->devcfg, &ident)) + return (ENXIO); + + /* Save quirk flags */ + sc->quirks = ident->quirks; + + /* Attach bridge device */ + if ((error = bhndb_attach_bridge(dev, &sc->bhndb_dev, -1))) + return (ENXIO); + + /* Success */ + return (0); +} + +static int +bwn_pci_detach(device_t dev) +{ + return (bus_generic_detach(dev)); +} + +static void +bwn_pci_probe_nomatch(device_t dev, device_t child) +{ + const char *name; + + name = device_get_name(child); + if (name == NULL) + name = "unknown device"; + + device_printf(dev, "<%s> (no driver attached)\n", name); +} + +static const struct bhndb_hwcfg * +bwn_pci_get_generic_hwcfg(device_t dev, device_t child) +{ + struct bwn_pci_softc *sc = device_get_softc(dev); + return (sc->devcfg->bridge_hwcfg); +} + +static const struct bhndb_hw * +bwn_pci_get_bhndb_hwtable(device_t dev, device_t child) +{ + struct bwn_pci_softc *sc = device_get_softc(dev); + return (sc->devcfg->bridge_hwtable); +} + +static bool +bwn_pci_is_core_disabled(device_t dev, device_t child, + struct bhnd_core_info *core) +{ + struct bwn_pci_softc *sc; + + sc = device_get_softc(dev); + + switch (bhnd_core_class(core)) { + case BHND_DEVCLASS_WLAN: + if (core->unit > 0 && !(sc->quirks & BWN_QUIRK_WLAN_DUALCORE)) + return (true); + + return (false); + + case BHND_DEVCLASS_ENET: + case BHND_DEVCLASS_ENET_MAC: + case BHND_DEVCLASS_ENET_PHY: + return ((sc->quirks & BWN_QUIRK_ENET_HW_UNPOPULATED) != 0); + + default: + return (false); + } +} + +static device_method_t bwn_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bwn_pci_probe), + DEVMETHOD(device_attach, bwn_pci_attach), + DEVMETHOD(device_detach, bwn_pci_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_probe_nomatch, bwn_pci_probe_nomatch), + + /* BHNDB_BUS Interface */ + DEVMETHOD(bhndb_bus_get_generic_hwcfg, bwn_pci_get_generic_hwcfg), + DEVMETHOD(bhndb_bus_get_hardware_table, bwn_pci_get_bhndb_hwtable), + DEVMETHOD(bhndb_bus_is_core_disabled, bwn_pci_is_core_disabled), + + DEVMETHOD_END +}; + +static devclass_t bwn_pci_devclass; + +DEFINE_CLASS_0(bwn_pci, bwn_pci_driver, bwn_pci_methods, sizeof(struct bwn_pci_softc)); +DRIVER_MODULE(bwn_pci, pci, bwn_pci_driver, bwn_pci_devclass, NULL, NULL); +DRIVER_MODULE(bhndb, bwn_pci, bhndb_pci_driver, bhndb_devclass, NULL, NULL); + +MODULE_DEPEND(bwn_pci, bwn, 1, 1, 1); +MODULE_DEPEND(bwn_pci, bhndb, 1, 1, 1); +MODULE_DEPEND(bwn_pci, bhndb_pci, 1, 1, 1); +MODULE_DEPEND(bwn_pci, bcma_bhndb, 1, 1, 1); +MODULE_DEPEND(bwn_pci, siba_bhndb, 1, 1, 1); diff --git a/sys/dev/bwn/if_bwn_pcivar.h b/sys/dev/bwn/if_bwn_pcivar.h new file mode 100644 index 0000000..aabb3e8 --- /dev/null +++ b/sys/dev/bwn/if_bwn_pcivar.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2015 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _IF_BWN_PCIVAR_H_ +#define _IF_BWN_PCIVAR_H_ + +struct bwn_pci_devcfg; + +/** bwn_pci per-instance state. */ +struct bwn_pci_softc { + device_t dev; /**< device */ + device_t bhndb_dev; /**< bhnd bridge device */ + const struct bwn_pci_devcfg *devcfg; /**< bwn device config */ + uint32_t quirks; /**< quirk flags */ +}; + +/* bwn device quirks */ +enum { + /** No quirks */ + BWN_QUIRK_NONE = 0, + + /** + * This model/revision has not been tested and may not work. + */ + BWN_QUIRK_UNTESTED = 1<<0, + + /** + * Early dual-band devices did not support accessing multiple PHYs + * from a single WLAN core, and instead used separate 2GHz and 5GHz + * WLAN cores. + * + * However, not all cards with two WLAN cores are fully populated; + * we must whitelist the boards on which a second WLAN core is actually + * usable. + */ + BWN_QUIRK_WLAN_DUALCORE = 1<<1, + + /** + * Some early devices shipped with unconnected ethernet cores; set + * this quirk to treat these cores as unpopulated. + */ + BWN_QUIRK_ENET_HW_UNPOPULATED = 1<<2, +}; + +/* PCI device descriptor */ +struct bwn_pci_device { + uint16_t vendor; + uint16_t device; + const char *desc; + uint32_t quirks; +}; + + +#define BWN_BCM_DEV(_devid, _desc, _quirks) \ + { PCI_VENDOR_BROADCOM, PCI_DEVID_ ## _devid, \ + "Broadcom " _desc " Wireless", _quirks } + +/* Supported device table */ +struct bwn_pci_devcfg { + const struct bhndb_hwcfg *bridge_hwcfg; + const struct bhndb_hw *bridge_hwtable; + const struct bwn_pci_device *devices; +}; + +#endif /* _IF_BWN_PCIVAR_H_ */ \ No newline at end of file diff --git a/sys/modules/Makefile b/sys/modules/Makefile index e2c2205..57e27b0 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -50,7 +50,9 @@ SUBDIR= \ ${_auxio} \ ${_bce} \ bfe \ + bhnd \ bge \ + bhnd \ ${_bxe} \ ${_bios} \ ${_bktr} \ @@ -58,6 +60,7 @@ SUBDIR= \ bridgestp \ bwi \ bwn \ + bwn_pci \ cam \ ${_canbepm} \ ${_canbus} \ diff --git a/sys/modules/bwn_pci/Makefile b/sys/modules/bwn_pci/Makefile new file mode 100644 index 0000000..5e3a9db --- /dev/null +++ b/sys/modules/bwn_pci/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/bwn + +KMOD= if_bwn_pci +SRCS= if_bwn_pci.c bwn_mac.c +SRCS+= device_if.h bus_if.h pci_if.h \ + bhnd_bus_if.h bhndb_bus_if.h \ + bhndb_if.h + +.include -- cgit v1.1 From 3b02df6fd3bb6f1f89429eb1a6c6a21cb14a595d Mon Sep 17 00:00:00 2001 From: cem Date: Thu, 5 May 2016 00:07:08 +0000 Subject: efipart: Support an arbitrary number of partitions Don't crash if the user has more than 31 of them. A follow-up to r298230. Reviewed by: allanjude Relnotes: maybe Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D6212 --- sys/boot/efi/libefi/efipart.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/boot/efi/libefi/efipart.c b/sys/boot/efi/libefi/efipart.c index da420bf..410057c 100644 --- a/sys/boot/efi/libefi/efipart.c +++ b/sys/boot/efi/libefi/efipart.c @@ -65,14 +65,12 @@ struct devsw efipart_dev = { /* * info structure to support bcache */ -#define MAXPDDEV 31 /* see MAXDEV in libi386.h */ - -static struct pdinfo -{ +struct pdinfo { int pd_unit; /* unit number */ int pd_open; /* reference counter */ void *pd_bcache; /* buffer cache data */ -} pdinfo [MAXPDDEV]; +}; +static struct pdinfo *pdinfo; static int npdinfo = 0; #define PD(dev) (pdinfo[(dev)->d_unit]) @@ -109,6 +107,9 @@ efipart_init(void) nout = 0; bzero(aliases, nin * sizeof(EFI_HANDLE)); + pdinfo = malloc(nin * sizeof(*pdinfo)); + if (pdinfo == NULL) + return (ENOMEM); for (n = 0; n < nin; n++) { status = BS->HandleProtocol(hin[n], &devpath_guid, -- cgit v1.1 From 4c9675481b04358fd0b9163eff87e437f78c94fb Mon Sep 17 00:00:00 2001 From: ngie Date: Thu, 5 May 2016 02:51:31 +0000 Subject: Revert r299096 The change broke buildworld when building lib/libkvm This change likely needs to be run through a ports -exp run as a sanity check, as it might break downstream consumers. Pointyhat to: adrian Reported by: kargl (confirmed on $work workstation) Sponsored by: EMC / Isilon Storage Division --- sys/sys/pcpu.h | 2 +- sys/sys/rman.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h index 8e6a71a..d6d1b3d 100644 --- a/sys/sys/pcpu.h +++ b/sys/sys/pcpu.h @@ -160,7 +160,7 @@ struct pcpu { struct lock_list_entry *pc_spinlocks; struct vmmeter pc_cnt; /* VM stats counters */ long pc_cp_time[CPUSTATES]; /* statclock ticks */ - device_t pc_device; + struct device *pc_device; void *pc_netisr; /* netisr SWI cookie */ int pc_unused1; /* unused field */ int pc_domain; /* Memory domain. */ diff --git a/sys/sys/rman.h b/sys/sys/rman.h index d702d25..2d58f4a 100644 --- a/sys/sys/rman.h +++ b/sys/sys/rman.h @@ -126,7 +126,7 @@ int rman_first_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end); bus_space_handle_t rman_get_bushandle(struct resource *); bus_space_tag_t rman_get_bustag(struct resource *); rman_res_t rman_get_end(struct resource *); -device_t rman_get_device(struct resource *); +struct device *rman_get_device(struct resource *); u_int rman_get_flags(struct resource *); int rman_get_rid(struct resource *); rman_res_t rman_get_size(struct resource *); @@ -143,13 +143,13 @@ int rman_is_region_manager(struct resource *r, struct rman *rm); int rman_release_resource(struct resource *r); struct resource *rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, - u_int flags, device_t dev); + u_int flags, struct device *dev); struct resource *rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, rman_res_t bound, - u_int flags, device_t dev); + u_int flags, struct device *dev); void rman_set_bushandle(struct resource *_r, bus_space_handle_t _h); void rman_set_bustag(struct resource *_r, bus_space_tag_t _t); -void rman_set_device(struct resource *_r, device_t _dev); +void rman_set_device(struct resource *_r, struct device *_dev); void rman_set_end(struct resource *_r, rman_res_t _end); void rman_set_rid(struct resource *_r, int _rid); void rman_set_start(struct resource *_r, rman_res_t _start); -- cgit v1.1 From 1f0b67157f0d74631179f3566f3bbee74c2e8e5f Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 06:58:30 +0000 Subject: [bhnd] add missing bus file. --- sys/modules/bhnd/bhndb/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/modules/bhnd/bhndb/Makefile b/sys/modules/bhnd/bhndb/Makefile index 06822de..46aa6bd 100644 --- a/sys/modules/bhnd/bhndb/Makefile +++ b/sys/modules/bhnd/bhndb/Makefile @@ -8,6 +8,6 @@ SRCS= bhndb.c bhndb_subr.c bhndb_hwdata.c \ bhndb_if.c bhndb_if.h \ bhnd_bus_if.h -SRCS+= device_if.h bus_if.h +SRCS+= device_if.h bus_if.h pci_if.h .include -- cgit v1.1 From 2997dc482e53c3ddbe251464e095aa262c3559b0 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 07:04:38 +0000 Subject: [bwn] implement firmware tx/rx versioning and fix RSSI calculation. Different versions of firmware have different requirments for TX/RX packet layouts (and other things, of course.) Currently the driver checks between 3xx and 4xx firmware by using the BWN_ISOLDFMT() macro, which doesn't take into account the 5xx firmware (which I think I need for the HT and N series PHY chips. I'll know when I do the port.) BWN_HDRSIZE() also needs to learn about the 5xx series firmware as well. So: * add a firmware version enum * populate it based on the firmware version we read at load time * don't finish loading if the firmware is the 5xx firmware; any code using BWN_ISOLDFMT or BWN_HDRSIZE needs updating (most notably the TX and RX bits.) Then, for RX RSSI: * write down and reimplement the b43 rssi calculation method; * use it for the correct PHYs (which are all the ones we support); * do the RSSI calculation before radiotap, not after. Tested: * Broadcom BCM4312, STA mode Obtained from: Linux b43 (careful writing and reimplementing; lots of integer math..) --- sys/dev/bwn/if_bwn.c | 110 +++++++++++++++++++++++++++++++++++++++++++++--- sys/dev/bwn/if_bwnvar.h | 7 +++ 2 files changed, 112 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 837f4f8..550f334 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -3987,6 +3987,33 @@ bwn_fw_loaducode(struct bwn_mac *mac) error = EOPNOTSUPP; goto error; } + + /* + * Determine firmware header version; needed for TX/RX packet + * handling. + */ + if (mac->mac_fw.rev >= 598) + mac->mac_fw.fw_hdr_format = BWN_FW_HDR_598; + else if (mac->mac_fw.rev >= 410) + mac->mac_fw.fw_hdr_format = BWN_FW_HDR_410; + else + mac->mac_fw.fw_hdr_format = BWN_FW_HDR_351; + + /* + * We don't support rev 598 or later; that requires + * another round of changes to the TX/RX descriptor + * and status layout. + * + * So, complain this is the case and exit out, rather + * than attaching and then failing. + */ + if (mac->mac_fw.fw_hdr_format == BWN_FW_HDR_598) { + device_printf(sc->sc_dev, + "firmware is too new (>=598); not supported\n"); + error = EOPNOTSUPP; + goto error; + } + mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_PATCH); date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE); @@ -5401,6 +5428,63 @@ bwn_hwrate2ieeerate(int rate) } } +/* + * Post process the RX provided RSSI. + * + * Valid for A, B, G, LP PHYs. + */ +static int8_t +bwn_rx_rssi_calc(struct bwn_mac *mac, int8_t in_rssi, + int ofdm, int adjust_2053, int adjust_2050) +{ + struct bwn_phy *phy = &mac->mac_phy; + struct bwn_phy_g *gphy = &phy->phy_g; + int tmp; + + switch (phy->rf_ver) { + case 0x2050: + if (ofdm) { + tmp = in_rssi; + if (tmp > 127) + tmp -= 256; + tmp = tmp * 73 / 64; + if (adjust_2050) + tmp += 25; + else + tmp -= 3; + } else { + if (siba_sprom_get_bf_lo(mac->mac_sc->sc_dev) + & BWN_BFL_RSSI) { + if (in_rssi > 63) + in_rssi = 63; + tmp = gphy->pg_nrssi_lt[in_rssi]; + tmp = (31 - tmp) * -131 / 128 - 57; + } else { + tmp = in_rssi; + tmp = (31 - tmp) * -149 / 128 - 68; + } + if (phy->type == BWN_PHYTYPE_G && adjust_2050) + tmp += 25; + } + break; + case 0x2060: + if (in_rssi > 127) + tmp = in_rssi - 256; + else + tmp = in_rssi; + break; + default: + tmp = in_rssi; + tmp = (tmp - 11) * 103 / 64; + if (adjust_2053) + tmp -= 109; + else + tmp -= 83; + } + + return (tmp); +} + static void bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) { @@ -5420,8 +5504,11 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) phystat0 = le16toh(rxhdr->phy_status0); phystat3 = le16toh(rxhdr->phy_status3); + + /* XXX Note: mactime, macstat, chanstat need fixing for fw 598 */ macstat = le32toh(rxhdr->mac_status); chanstat = le16toh(rxhdr->channel); + phytype = chanstat & BWN_RX_CHAN_PHYTYPE; if (macstat & BWN_RX_MAC_FCSERR) @@ -5452,8 +5539,6 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) BWN_ISOLDFMT(mac), (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT); - /* XXX calculating RSSI & noise & antenna */ - if (phystat0 & BWN_RX_PHYST0_OFDM) rate = bwn_plcp_get_ofdmrate(mac, plcp, phytype == BWN_PHYTYPE_A); @@ -5465,14 +5550,29 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) } sc->sc_rx_rate = bwn_hwrate2ieeerate(rate); + /* rssi/noise */ + switch (phytype) { + case BWN_PHYTYPE_A: + case BWN_PHYTYPE_B: + case BWN_PHYTYPE_G: + case BWN_PHYTYPE_LP: + rssi = bwn_rx_rssi_calc(mac, rxhdr->phy.abg.rssi, + !! (phystat0 & BWN_RX_PHYST0_OFDM), + !! (phystat0 & BWN_RX_PHYST0_GAINCTL), + !! (phystat3 & BWN_RX_PHYST3_TRSTATE)); + break; + default: + /* XXX TODO: implement rssi for other PHYs */ + break; + } + + noise = mac->mac_stats.link_noise; + /* RX radio tap */ if (ieee80211_radiotap_active(ic)) bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise); m_adj(m, -IEEE80211_CRC_LEN); - rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */ - noise = mac->mac_stats.link_noise; - BWN_UNLOCK(sc); ni = ieee80211_find_rxnode(ic, wh); diff --git a/sys/dev/bwn/if_bwnvar.h b/sys/dev/bwn/if_bwnvar.h index b8295ec..e3e5815 100644 --- a/sys/dev/bwn/if_bwnvar.h +++ b/sys/dev/bwn/if_bwnvar.h @@ -751,6 +751,12 @@ struct bwn_fwinitvals { } __packed data; } __packed; +enum bwn_fw_hdr_format { + BWN_FW_HDR_598, + BWN_FW_HDR_410, + BWN_FW_HDR_351, +}; + enum bwn_fwtype { BWN_FWTYPE_DEFAULT, BWN_FWTYPE_OPENSOURCE, @@ -773,6 +779,7 @@ struct bwn_fw { struct bwn_fwfile pcm; struct bwn_fwfile initvals; struct bwn_fwfile initvals_band; + enum bwn_fw_hdr_format fw_hdr_format; uint16_t rev; uint16_t patch; -- cgit v1.1 From 2fab455b80c17b439af5840b372595a10dea4f4f Mon Sep 17 00:00:00 2001 From: jmcneill Date: Thu, 5 May 2016 09:41:57 +0000 Subject: Add support for the Allwinner A83T (sun8iw6p1) SoC. Clocks, GPIO, UART, SD card / eMMC, USB, watchdog, and ethernet are supported. Note that the A83T contains two clusters of four Cortex-A7 CPUs, and only CPUs in first cluster are started for now. Tested on a Sinovoip Banana Pi BPI-M3. --- sys/arm/allwinner/a10_ehci.c | 1 + sys/arm/allwinner/a10_gpio.c | 10 + sys/arm/allwinner/a83t/a83t_padconf.c | 162 ++++++++++++++++ sys/arm/allwinner/a83t/a83t_r_padconf.c | 62 +++++++ sys/arm/allwinner/a83t/files.a83t | 4 + sys/arm/allwinner/a83t/std.a83t | 15 ++ sys/arm/allwinner/allwinner_machdep.c | 24 +++ sys/arm/allwinner/allwinner_machdep.h | 2 + sys/arm/allwinner/aw_ccu.c | 133 ++++++++++--- sys/arm/allwinner/aw_mp.c | 97 ++++++++++ sys/arm/allwinner/aw_mp.h | 1 + sys/arm/allwinner/aw_usbphy.c | 1 + sys/arm/allwinner/clk/aw_ahbclk.c | 78 +++++++- sys/arm/allwinner/clk/aw_apbclk.c | 56 ++++-- sys/arm/allwinner/clk/aw_cpusclk.c | 320 ++++++++++++++++++++++++++++++++ sys/arm/allwinner/clk/aw_gate.c | 8 + sys/arm/allwinner/clk/aw_gmacclk.c | 49 ++++- sys/arm/allwinner/clk/aw_pll.c | 27 +++ sys/arm/allwinner/clk/aw_usbclk.c | 21 ++- sys/arm/allwinner/files.allwinner | 1 + sys/arm/allwinner/std.allwinner | 1 + sys/arm/conf/ALLWINNER | 2 + sys/conf/options.arm | 1 + 23 files changed, 1021 insertions(+), 55 deletions(-) create mode 100644 sys/arm/allwinner/a83t/a83t_padconf.c create mode 100644 sys/arm/allwinner/a83t/a83t_r_padconf.c create mode 100644 sys/arm/allwinner/a83t/files.a83t create mode 100644 sys/arm/allwinner/a83t/std.a83t create mode 100644 sys/arm/allwinner/clk/aw_cpusclk.c (limited to 'sys') diff --git a/sys/arm/allwinner/a10_ehci.c b/sys/arm/allwinner/a10_ehci.c index c325d60..4a9ee80 100644 --- a/sys/arm/allwinner/a10_ehci.c +++ b/sys/arm/allwinner/a10_ehci.c @@ -112,6 +112,7 @@ static struct ofw_compat_data compat_data[] = { { "allwinner,sun4i-a10-ehci", (uintptr_t)&a10_ehci_conf }, { "allwinner,sun6i-a31-ehci", (uintptr_t)&a31_ehci_conf }, { "allwinner,sun7i-a20-ehci", (uintptr_t)&a10_ehci_conf }, + { "allwinner,sun8i-a83t-ehci", (uintptr_t)&a31_ehci_conf }, { NULL, (uintptr_t)NULL } }; diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c index 4e6e612..079e715 100644 --- a/sys/arm/allwinner/a10_gpio.c +++ b/sys/arm/allwinner/a10_gpio.c @@ -99,6 +99,12 @@ extern const struct allwinner_padconf a31s_padconf; extern const struct allwinner_padconf a31_r_padconf; #endif +/* Defined in a83t_padconf.c */ +#ifdef SOC_ALLWINNER_A83T +extern const struct allwinner_padconf a83t_padconf; +extern const struct allwinner_padconf a83t_r_padconf; +#endif + static struct ofw_compat_data compat_data[] = { #ifdef SOC_ALLWINNER_A10 {"allwinner,sun4i-a10-pinctrl", (uintptr_t)&a10_padconf}, @@ -115,6 +121,10 @@ static struct ofw_compat_data compat_data[] = { #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S) {"allwinner,sun6i-a31-r-pinctrl", (uintptr_t)&a31_r_padconf}, #endif +#ifdef SOC_ALLWINNER_A83T + {"allwinner,sun8i-a83t-pinctrl", (uintptr_t)&a83t_padconf}, + {"allwinner,sun8i-a83t-r-pinctrl", (uintptr_t)&a83t_r_padconf}, +#endif {NULL, 0} }; diff --git a/sys/arm/allwinner/a83t/a83t_padconf.c b/sys/arm/allwinner/a83t/a83t_padconf.c new file mode 100644 index 0000000..bbf638e --- /dev/null +++ b/sys/arm/allwinner/a83t/a83t_padconf.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 ``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. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#ifdef SOC_ALLWINNER_A83T + +static const struct allwinner_pins a83t_pins[] = { + { "PB0", 1, 0, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } }, + { "PB1", 1, 1, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } }, + { "PB2", 1, 2, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } }, + { "PB3", 1, 3, { "gpio_in", "gpio_out", "uart2", "jtag", NULL, NULL, "eint" } }, + { "PB4", 1, 4, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } }, + { "PB5", 1, 5, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } }, + { "PB6", 1, 6, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } }, + { "PB7", 1, 7, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } }, + { "PB8", 1, 8, { "gpio_in", "gpio_out", "i2s0", "tdm", NULL, NULL, "eint" } }, + { "PB9", 1, 9, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "eint" } }, + { "PB10", 1, 10, { "gpio_in", "gpio_out", "uart0", NULL, NULL, NULL, "eint" } }, + + { "PC0", 2, 0, { "gpio_in", "gpio_out", "nand", "spi0" } }, + { "PC1", 2, 1, { "gpio_in", "gpio_out", "nand", "spi0" } }, + { "PC2", 2, 2, { "gpio_in", "gpio_out", "nand", "spi0" } }, + { "PC3", 2, 3, { "gpio_in", "gpio_out", "nand", "spi0" } }, + { "PC4", 2, 4, { "gpio_in", "gpio_out", "nand" } }, + { "PC5", 2, 5, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC6", 2, 6, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC7", 2, 7, { "gpio_in", "gpio_out", "nand" } }, + { "PC8", 2, 8, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC9", 2, 9, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC10", 2, 10, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC11", 2, 11, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC12", 2, 12, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC13", 2, 13, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC14", 2, 14, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC15", 2, 15, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC16", 2, 16, { "gpio_in", "gpio_out", "nand", "mmc2" } }, + { "PC17", 2, 17, { "gpio_in", "gpio_out", "nand" } }, + { "PC18", 2, 18, { "gpio_in", "gpio_out", "nand" } }, + + { "PD2", 3, 2, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD3", 3, 3, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD4", 3, 4, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD5", 3, 5, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD6", 3, 6, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD7", 3, 7, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD10", 3, 10, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD11", 3, 11, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD12", 3, 12, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD13", 3, 13, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD14", 3, 14, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD15", 3, 15, { "gpio_in", "gpio_out", "lcd", NULL, "emac" } }, + { "PD18", 3, 18, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } }, + { "PD19", 3, 19, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } }, + { "PD20", 3, 20, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } }, + { "PD21", 3, 21, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } }, + { "PD22", 3, 22, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } }, + { "PD23", 3, 23, { "gpio_in", "gpio_out", "lcd", "lvds", "emac" } }, + { "PD24", 3, 24, { "gpio_in", "gpio_out", "lcd", "lvds" } }, + { "PD25", 3, 25, { "gpio_in", "gpio_out", "lcd", "lvds" } }, + { "PD26", 3, 26, { "gpio_in", "gpio_out", "lcd", "lvds" } }, + { "PD27", 3, 27, { "gpio_in", "gpio_out", "lcd", "lvds" } }, + { "PD28", 3, 28, { "gpio_in", "gpio_out", "pwm" } }, + { "PD29", 3, 29, { "gpio_in", "gpio_out" } }, + + { "PE0", 4, 0, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE1", 4, 1, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE2", 4, 2, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE3", 4, 3, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE4", 4, 4, { "gpio_in", "gpio_out", "csi" } }, + { "PE5", 4, 5, { "gpio_in", "gpio_out", "csi" } }, + { "PE6", 4, 6, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE7", 4, 7, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE8", 4, 8, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE9", 4, 9, { "gpio_in", "gpio_out", "csi", NULL, "ccir" } }, + { "PE10", 4, 10, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } }, + { "PE11", 4, 11, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } }, + { "PE12", 4, 12, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } }, + { "PE13", 4, 13, { "gpio_in", "gpio_out", "csi", "uart4", "ccir" } }, + { "PE14", 4, 14, { "gpio_in", "gpio_out", "csi", "twi2" } }, + { "PE15", 4, 15, { "gpio_in", "gpio_out", "csi", "twi2" } }, + { "PE16", 4, 16, { "gpio_in", "gpio_out" } }, + { "PE17", 4, 17, { "gpio_in", "gpio_out" } }, + { "PE18", 4, 18, { "gpio_in", "gpio_out", NULL, "owa" } }, + { "PE19", 4, 19, { "gpio_in", "gpio_out" } }, + + { "PF0", 5, 0, { "gpio_in", "gpio_out", "mmc0", "jtag" } }, + { "PF1", 5, 1, { "gpio_in", "gpio_out", "mmc0", "jtag" } }, + { "PF2", 5, 2, { "gpio_in", "gpio_out", "mmc0", "uart0" } }, + { "PF3", 5, 3, { "gpio_in", "gpio_out", "mmc0", "jtag" } }, + { "PF4", 5, 4, { "gpio_in", "gpio_out", "mmc0", "uart0" } }, + { "PF5", 5, 5, { "gpio_in", "gpio_out", "mmc0", "jtag" } }, + { "PF6", 5, 6, { "gpio_in", "gpio_out" } }, + + { "PG0", 6, 0, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } }, + { "PG1", 6, 1, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } }, + { "PG2", 6, 2, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } }, + { "PG3", 6, 3, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } }, + { "PG4", 6, 4, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } }, + { "PG5", 6, 5, { "gpio_in", "gpio_out", "mmc1", NULL, NULL, NULL, "eint" } }, + { "PG6", 6, 6, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } }, + { "PG7", 6, 7, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } }, + { "PG8", 6, 8, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } }, + { "PG9", 6, 9, { "gpio_in", "gpio_out", "uart1", "spi1", NULL, NULL, "eint" } }, + { "PG10", 6, 10, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } }, + { "PG11", 6, 11, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } }, + { "PG12", 6, 12, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } }, + { "PG13", 6, 13, { "gpio_in", "gpio_out", "i2s1", "uart3", NULL, NULL, "eint" } }, + + { "PH0", 7, 0, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "eint" } }, + { "PH1", 7, 1, { "gpio_in", "gpio_out", "i2c0", NULL, NULL, NULL, "eint" } }, + { "PH2", 7, 2, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "eint" } }, + { "PH3", 7, 3, { "gpio_in", "gpio_out", "i2c1", NULL, NULL, NULL, "eint" } }, + { "PH4", 7, 4, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "eint" } }, + { "PH5", 7, 5, { "gpio_in", "gpio_out", "i2c2", NULL, NULL, NULL, "eint" } }, + { "PH6", 7, 6, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } }, + { "PH7", 7, 7, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } }, + { "PH8", 7, 8, { "gpio_in", "gpio_out", "hdmiddc", NULL, NULL, NULL, "eint" } }, + { "PH9", 7, 9, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } }, + { "PH10", 7, 10, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } }, + { "PH11", 7, 11, { "gpio_in", "gpio_out", NULL, NULL, NULL, NULL, "eint" } }, +}; + +const struct allwinner_padconf a83t_padconf = { + .npins = nitems(a83t_pins), + .pins = a83t_pins, +}; + +#endif /* !SOC_ALLWINNER_A83T */ diff --git a/sys/arm/allwinner/a83t/a83t_r_padconf.c b/sys/arm/allwinner/a83t/a83t_r_padconf.c new file mode 100644 index 0000000..e463745 --- /dev/null +++ b/sys/arm/allwinner/a83t/a83t_r_padconf.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 ``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. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#ifdef SOC_ALLWINNER_A83T + +static const struct allwinner_pins a83t_r_pins[] = { + { "PL0", 0, 0, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "eint" } }, + { "PL1", 0, 1, { "gpio_in", "gpio_out", "s_rsb", "s_i2c", NULL, NULL, "eint" } }, + { "PL2", 0, 2, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "eint" } }, + { "PL3", 0, 3, { "gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, "eint" } }, + { "PL4", 0, 4, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } }, + { "PL5", 0, 5, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } }, + { "PL6", 0, 6, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } }, + { "PL7", 0, 7, { "gpio_in", "gpio_out", "s_jtag", NULL, NULL, NULL, "eint" } }, + { "PL8", 0, 8, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "eint" } }, + { "PL9", 0, 9, { "gpio_in", "gpio_out", "s_i2c", NULL, NULL, NULL, "eint" } }, + { "PL10", 0, 10, { "gpio_in", "gpio_out", "s_pwm", NULL, NULL, NULL, "eint" } }, + { "PL11", 0, 11, { "gpio_in", "gpio_out", NULL, NULL, NULL, "eint" } }, + { "PL12", 0, 12, { "gpio_in", "gpio_out", "s_cir", NULL, NULL, NULL, "eint" } }, +}; + +const struct allwinner_padconf a83t_r_padconf = { + .npins = nitems(a83t_r_pins), + .pins = a83t_r_pins, +}; + +#endif /* !SOC_ALLWINNER_A83T */ diff --git a/sys/arm/allwinner/a83t/files.a83t b/sys/arm/allwinner/a83t/files.a83t new file mode 100644 index 0000000..45334a0 --- /dev/null +++ b/sys/arm/allwinner/a83t/files.a83t @@ -0,0 +1,4 @@ +# $FreeBSD$ + +arm/allwinner/a83t/a83t_padconf.c standard +arm/allwinner/a83t/a83t_r_padconf.c standard diff --git a/sys/arm/allwinner/a83t/std.a83t b/sys/arm/allwinner/a83t/std.a83t new file mode 100644 index 0000000..06b1ed4 --- /dev/null +++ b/sys/arm/allwinner/a83t/std.a83t @@ -0,0 +1,15 @@ +# Allwinner A83T common options +#$FreeBSD$ + +cpu CPU_CORTEXA +machine arm armv6 +makeoptions CONF_CFLAGS="-march=armv7a" + +makeoptions KERNVIRTADDR=0xc0200000 +options KERNVIRTADDR=0xc0200000 + +options IPI_IRQ_START=0 +options IPI_IRQ_END=15 + +files "../allwinner/files.allwinner" +files "../allwinner/a83t/files.a83t" diff --git a/sys/arm/allwinner/allwinner_machdep.c b/sys/arm/allwinner/allwinner_machdep.c index e5c8eb8..7916441 100644 --- a/sys/arm/allwinner/allwinner_machdep.c +++ b/sys/arm/allwinner/allwinner_machdep.c @@ -94,6 +94,15 @@ a31s_attach(platform_t plat) return (0); } +static int +a83t_attach(platform_t plat) +{ + soc_type = ALLWINNERSOC_A83T; + soc_family = ALLWINNERSOC_SUN8I; + + return (0); +} + static vm_offset_t allwinner_lastaddr(platform_t plat) { @@ -196,6 +205,21 @@ static platform_method_t a31s_methods[] = { FDT_PLATFORM_DEF(a31s, "a31s", 0, "allwinner,sun6i-a31s", 200); #endif +#if defined(SOC_ALLWINNER_A83T) +static platform_method_t a83t_methods[] = { + PLATFORMMETHOD(platform_attach, a83t_attach), + PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr), + PLATFORMMETHOD(platform_devmap_init, allwinner_devmap_init), + +#ifdef SMP + PLATFORMMETHOD(platform_mp_start_ap, a83t_mp_start_ap), + PLATFORMMETHOD(platform_mp_setmaxid, aw_mp_setmaxid), +#endif + PLATFORMMETHOD_END, +}; +FDT_PLATFORM_DEF(a83t, "a83t", 0, "allwinner,sun8i-a83t", 200); +#endif + u_int allwinner_soc_type(void) { diff --git a/sys/arm/allwinner/allwinner_machdep.h b/sys/arm/allwinner/allwinner_machdep.h index c640494..91c97ac 100644 --- a/sys/arm/allwinner/allwinner_machdep.h +++ b/sys/arm/allwinner/allwinner_machdep.h @@ -36,11 +36,13 @@ #define ALLWINNERSOC_A20 0x20000000 #define ALLWINNERSOC_A31 0x31000000 #define ALLWINNERSOC_A31S 0x31000001 +#define ALLWINNERSOC_A83T 0x83000000 #define ALLWINNERSOC_SUN4I 0x40000000 #define ALLWINNERSOC_SUN5I 0x50000000 #define ALLWINNERSOC_SUN6I 0x60000000 #define ALLWINNERSOC_SUN7I 0x70000000 +#define ALLWINNERSOC_SUN8I 0x80000000 u_int allwinner_soc_type(void); u_int allwinner_soc_family(void); diff --git a/sys/arm/allwinner/aw_ccu.c b/sys/arm/allwinner/aw_ccu.c index d2ce774..a8342ca 100644 --- a/sys/arm/allwinner/aw_ccu.c +++ b/sys/arm/allwinner/aw_ccu.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -53,40 +54,74 @@ __FBSDID("$FreeBSD$"); #define CCU_BASE 0x01c20000 #define CCU_SIZE 0x400 +#define PRCM_BASE 0x01f01400 +#define PRCM_SIZE 0x200 + +#define SYSCTRL_BASE 0x01c00000 +#define SYSCTRL_SIZE 0x34 + struct aw_ccu_softc { struct simplebus_softc sc; bus_space_tag_t bst; - bus_space_handle_t bsh; + bus_space_handle_t ccu_bsh; + bus_space_handle_t prcm_bsh; + bus_space_handle_t sysctrl_bsh; struct mtx mtx; + int flags; }; +#define CLOCK_CCU (1 << 0) +#define CLOCK_PRCM (1 << 1) +#define CLOCK_SYSCTRL (1 << 2) + static struct ofw_compat_data compat_data[] = { - { "allwinner,sun4i-a10", 1 }, - { "allwinner,sun7i-a20", 1 }, - { "allwinner,sun6i-a31", 1 }, - { "allwinner,sun6i-a31s", 1 }, + { "allwinner,sun4i-a10", CLOCK_CCU }, + { "allwinner,sun7i-a20", CLOCK_CCU }, + { "allwinner,sun6i-a31", CLOCK_CCU }, + { "allwinner,sun6i-a31s", CLOCK_CCU }, + { "allwinner,sun8i-a83t", CLOCK_CCU|CLOCK_PRCM|CLOCK_SYSCTRL }, { NULL, 0 } }; static int -aw_ccu_check_addr(bus_addr_t addr) +aw_ccu_check_addr(struct aw_ccu_softc *sc, bus_addr_t addr, + bus_space_handle_t *pbsh, bus_size_t *poff) { - if (addr < CCU_BASE || addr >= (CCU_BASE + CCU_SIZE)) - return (EINVAL); - return (0); + if (addr >= CCU_BASE && addr < (CCU_BASE + CCU_SIZE) && + (sc->flags & CLOCK_CCU) != 0) { + *poff = addr - CCU_BASE; + *pbsh = sc->ccu_bsh; + return (0); + } + if (addr >= PRCM_BASE && addr < (PRCM_BASE + PRCM_SIZE) && + (sc->flags & CLOCK_PRCM) != 0) { + *poff = addr - PRCM_BASE; + *pbsh = sc->prcm_bsh; + return (0); + } + if (addr >= SYSCTRL_BASE && addr < (SYSCTRL_BASE + SYSCTRL_SIZE) && + (sc->flags & CLOCK_SYSCTRL) != 0) { + *poff = addr - SYSCTRL_BASE; + *pbsh = sc->sysctrl_bsh; + return (0); + } + return (EINVAL); } static int aw_ccu_write_4(device_t dev, bus_addr_t addr, uint32_t val) { struct aw_ccu_softc *sc; + bus_space_handle_t bsh; + bus_size_t reg; - if (aw_ccu_check_addr(addr) != 0) + sc = device_get_softc(dev); + + if (aw_ccu_check_addr(sc, addr, &bsh, ®) != 0) return (EINVAL); - sc = device_get_softc(dev); mtx_assert(&sc->mtx, MA_OWNED); - bus_space_write_4(sc->bst, sc->bsh, addr - CCU_BASE, val); + bus_space_write_4(sc->bst, bsh, reg, val); return (0); } @@ -95,13 +130,16 @@ static int aw_ccu_read_4(device_t dev, bus_addr_t addr, uint32_t *val) { struct aw_ccu_softc *sc; + bus_space_handle_t bsh; + bus_size_t reg; + + sc = device_get_softc(dev); - if (aw_ccu_check_addr(addr) != 0) + if (aw_ccu_check_addr(sc, addr, &bsh, ®) != 0) return (EINVAL); - sc = device_get_softc(dev); mtx_assert(&sc->mtx, MA_OWNED); - *val = bus_space_read_4(sc->bst, sc->bsh, addr - CCU_BASE); + *val = bus_space_read_4(sc->bst, bsh, reg); return (0); } @@ -110,17 +148,20 @@ static int aw_ccu_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) { struct aw_ccu_softc *sc; + bus_space_handle_t bsh; + bus_size_t reg; uint32_t val; - if (aw_ccu_check_addr(addr) != 0) + sc = device_get_softc(dev); + + if (aw_ccu_check_addr(sc, addr, &bsh, ®) != 0) return (EINVAL); - sc = device_get_softc(dev); mtx_assert(&sc->mtx, MA_OWNED); - val = bus_space_read_4(sc->bst, sc->bsh, addr - CCU_BASE); + val = bus_space_read_4(sc->bst, bsh, reg); val &= ~clr; val |= set; - bus_space_write_4(sc->bst, sc->bsh, addr - CCU_BASE, val); + bus_space_write_4(sc->bst, bsh, reg, val); return (0); } @@ -143,20 +184,32 @@ aw_ccu_device_unlock(device_t dev) mtx_unlock(&sc->mtx); } +static const struct ofw_compat_data * +aw_ccu_search_compatible(void) +{ + const struct ofw_compat_data *compat; + phandle_t root; + + root = OF_finddevice("/"); + for (compat = compat_data; compat_data->ocd_str != NULL; compat++) + if (fdt_is_compatible(root, compat->ocd_str)) + break; + + return (compat); +} + static int aw_ccu_probe(device_t dev) { const char *name; - device_t pdev; name = ofw_bus_get_name(dev); if (name == NULL || strcmp(name, "clocks") != 0) return (ENXIO); - pdev = device_get_parent(dev); - if (ofw_bus_search_compatible(pdev, compat_data)->ocd_data == 0) - return (0); + if (aw_ccu_search_compatible()->ocd_data == 0) + return (ENXIO); device_set_desc(dev, "Allwinner Clock Control Unit"); return (BUS_PROBE_SPECIFIC); @@ -175,15 +228,37 @@ aw_ccu_attach(device_t dev) simplebus_init(dev, node); + sc->flags = aw_ccu_search_compatible()->ocd_data; + /* - * Map CCU registers. The DT doesn't have a "reg" property for the - * /clocks node and child nodes have conflicting "reg" properties. + * Map registers. The DT doesn't have a "reg" property + * for the /clocks node and child nodes have conflicting "reg" + * properties. */ sc->bst = bus_get_bus_tag(dev); - error = bus_space_map(sc->bst, CCU_BASE, CCU_SIZE, 0, &sc->bsh); - if (error != 0) { - device_printf(dev, "couldn't map CCU: %d\n", error); - return (error); + if (sc->flags & CLOCK_CCU) { + error = bus_space_map(sc->bst, CCU_BASE, CCU_SIZE, 0, + &sc->ccu_bsh); + if (error != 0) { + device_printf(dev, "couldn't map CCU: %d\n", error); + return (error); + } + } + if (sc->flags & CLOCK_PRCM) { + error = bus_space_map(sc->bst, PRCM_BASE, PRCM_SIZE, 0, + &sc->prcm_bsh); + if (error != 0) { + device_printf(dev, "couldn't map PRCM: %d\n", error); + return (error); + } + } + if (sc->flags & CLOCK_SYSCTRL) { + error = bus_space_map(sc->bst, SYSCTRL_BASE, SYSCTRL_SIZE, 0, + &sc->sysctrl_bsh); + if (error != 0) { + device_printf(dev, "couldn't map SYSCTRL: %d\n", error); + return (error); + } } mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); diff --git a/sys/arm/allwinner/aw_mp.c b/sys/arm/allwinner/aw_mp.c index 9e46f2d..ce0dddd 100644 --- a/sys/arm/allwinner/aw_mp.c +++ b/sys/arm/allwinner/aw_mp.c @@ -55,6 +55,9 @@ __FBSDID("$FreeBSD$"); #define CPUCFG_SIZE 0x400 #define PRCM_BASE 0x01f01400 #define PRCM_SIZE 0x800 +/* Register for multi-cluster SoC */ +#define CPUXCFG_BASE 0x01700000 +#define CPUXCFG_SIZE 0x400 #define CPU_OFFSET 0x40 #define CPU_OFFSET_CTL 0x04 @@ -80,6 +83,14 @@ __FBSDID("$FreeBSD$"); #define CPUCFG_DBGCTL0 0x1e0 #define CPUCFG_DBGCTL1 0x1e4 +#define CPUS_CL_RST(cl) (0x30 + (cluster) * 0x4) +#define CPUX_CL_CTRL0(cl) (0x0 + (cluster) * 0x10) +#define CPUX_CL_CTRL1(cl) (0x4 + (cluster) * 0x10) +#define CPUX_CL_CPU_STATUS(cl) (0x30 + (cluster) * 0x4) +#define CPUX_CL_RST(cl) (0x80 + (cluster) * 0x4) +#define PRCM_CL_PWROFF(cl) (0x100 + (cluster) * 0x4) +#define PRCM_CL_PWR_CLAMP(cl, cpu) (0x140 + (cluster) * 0x4 + (cpu) * 0x4) + void aw_mp_setmaxid(platform_t plat) { @@ -202,3 +213,89 @@ a31_mp_start_ap(platform_t plat) bus_space_unmap(fdtbus_bs_tag, cpucfg, CPUCFG_SIZE); bus_space_unmap(fdtbus_bs_tag, prcm, PRCM_SIZE); } + +static void +aw_mc_mp_start_cpu(bus_space_handle_t cpuscfg, bus_space_handle_t cpuxcfg, + bus_space_handle_t prcm, int cluster, int cpu) +{ + uint32_t val; + int i; + + /* Assert core reset */ + val = bus_space_read_4(fdtbus_bs_tag, cpuxcfg, CPUX_CL_RST(cluster)); + val &= ~(1 << cpu); + bus_space_write_4(fdtbus_bs_tag, cpuxcfg, CPUX_CL_RST(cluster), val); + + /* Assert power-on reset */ + val = bus_space_read_4(fdtbus_bs_tag, cpuscfg, CPUS_CL_RST(cluster)); + val &= ~(1 << cpu); + bus_space_write_4(fdtbus_bs_tag, cpuscfg, CPUS_CL_RST(cluster), val); + + /* Disable automatic L1 cache invalidate at reset */ + val = bus_space_read_4(fdtbus_bs_tag, cpuxcfg, CPUX_CL_CTRL0(cluster)); + val &= ~(1 << cpu); + bus_space_write_4(fdtbus_bs_tag, cpuxcfg, CPUX_CL_CTRL0(cluster), val); + + /* Release power clamp */ + for (i = 0; i <= CPU_PWR_CLAMP_STEPS; i++) + bus_space_write_4(fdtbus_bs_tag, prcm, + PRCM_CL_PWR_CLAMP(cluster, cpu), 0xff >> i); + while (bus_space_read_4(fdtbus_bs_tag, prcm, + PRCM_CL_PWR_CLAMP(cluster, cpu)) != 0) + ; + + /* Clear power-off gating */ + val = bus_space_read_4(fdtbus_bs_tag, prcm, PRCM_CL_PWROFF(cluster)); + val &= ~(1 << cpu); + bus_space_write_4(fdtbus_bs_tag, prcm, PRCM_CL_PWROFF(cluster), val); + + /* De-assert power-on reset */ + val = bus_space_read_4(fdtbus_bs_tag, cpuscfg, CPUS_CL_RST(cluster)); + val |= (1 << cpu); + bus_space_write_4(fdtbus_bs_tag, cpuscfg, CPUS_CL_RST(cluster), val); + + /* De-assert core reset */ + val = bus_space_read_4(fdtbus_bs_tag, cpuxcfg, CPUX_CL_RST(cluster)); + val |= (1 << cpu); + bus_space_write_4(fdtbus_bs_tag, cpuxcfg, CPUX_CL_RST(cluster), val); +} + +static void +aw_mc_mp_start_ap(bus_space_handle_t cpuscfg, bus_space_handle_t cpuxcfg, + bus_space_handle_t prcm) +{ + int cluster, cpu; + + KASSERT(mp_ncpus <= 4, ("multiple clusters not yet supported")); + + dcache_wbinv_poc_all(); + + bus_space_write_4(fdtbus_bs_tag, cpuscfg, CPUCFG_P_REG0, + pmap_kextract((vm_offset_t)mpentry)); + + cluster = 0; + for (cpu = 1; cpu < mp_ncpus; cpu++) + aw_mc_mp_start_cpu(cpuscfg, cpuxcfg, prcm, cluster, cpu); +} + +void +a83t_mp_start_ap(platform_t plat) +{ + bus_space_handle_t cpuscfg, cpuxcfg, prcm; + + if (bus_space_map(fdtbus_bs_tag, CPUCFG_BASE, CPUCFG_SIZE, + 0, &cpuscfg) != 0) + panic("Couldn't map the CPUCFG\n"); + if (bus_space_map(fdtbus_bs_tag, CPUXCFG_BASE, CPUXCFG_SIZE, + 0, &cpuxcfg) != 0) + panic("Couldn't map the CPUXCFG\n"); + if (bus_space_map(fdtbus_bs_tag, PRCM_BASE, PRCM_SIZE, 0, + &prcm) != 0) + panic("Couldn't map the PRCM\n"); + + aw_mc_mp_start_ap(cpuscfg, cpuxcfg, prcm); + armv7_sev(); + bus_space_unmap(fdtbus_bs_tag, cpuxcfg, CPUXCFG_SIZE); + bus_space_unmap(fdtbus_bs_tag, cpuscfg, CPUCFG_SIZE); + bus_space_unmap(fdtbus_bs_tag, prcm, PRCM_SIZE); +} diff --git a/sys/arm/allwinner/aw_mp.h b/sys/arm/allwinner/aw_mp.h index 402147a..591ecea 100644 --- a/sys/arm/allwinner/aw_mp.h +++ b/sys/arm/allwinner/aw_mp.h @@ -31,5 +31,6 @@ void aw_mp_setmaxid(platform_t plat); void a20_mp_start_ap(platform_t plat); void a31_mp_start_ap(platform_t plat); +void a83t_mp_start_ap(platform_t plat); #endif /* _AW_MP_H_ */ diff --git a/sys/arm/allwinner/aw_usbphy.c b/sys/arm/allwinner/aw_usbphy.c index 25e8da0..31d2313 100644 --- a/sys/arm/allwinner/aw_usbphy.c +++ b/sys/arm/allwinner/aw_usbphy.c @@ -55,6 +55,7 @@ static struct ofw_compat_data compat_data[] = { { "allwinner,sun5i-a13-usb-phy", 1 }, { "allwinner,sun6i-a31-usb-phy", 1 }, { "allwinner,sun7i-a20-usb-phy", 1 }, + { "allwinner,sun8i-a83t-usb-phy", 1 }, { NULL, 0 } }; diff --git a/sys/arm/allwinner/clk/aw_ahbclk.c b/sys/arm/allwinner/clk/aw_ahbclk.c index 1d3b1a4..00a0afe 100644 --- a/sys/arm/allwinner/clk/aw_ahbclk.c +++ b/sys/arm/allwinner/clk/aw_ahbclk.c @@ -63,16 +63,35 @@ __FBSDID("$FreeBSD$"); #define A31_AHB1_CLK_SRC_SEL_MAX 3 #define A31_AHB1_CLK_SRC_SEL_SHIFT 12 +#define A83T_AHB1_CLK_SRC_SEL (0x3 << 12) +#define A83T_AHB1_CLK_SRC_SEL_ISPLL(x) ((x) & 0x2) +#define A83T_AHB1_CLK_SRC_SEL_MAX 3 +#define A83T_AHB1_CLK_SRC_SEL_SHIFT 12 +#define A83T_AHB1_PRE_DIV (0x3 << 6) +#define A83T_AHB1_PRE_DIV_SHIFT 6 +#define A83T_AHB1_CLK_DIV_RATIO (0x3 << 4) +#define A83T_AHB1_CLK_DIV_RATIO_SHIFT 4 + +#define H3_AHB2_CLK_CFG (0x3 << 0) +#define H3_AHB2_CLK_CFG_SHIFT 0 +#define H3_AHB2_CLK_CFG_AHB1 0 +#define H3_AHB2_CLK_CFG_PLL_PERIPH_DIV2 1 +#define H3_AHB2_CLK_CFG_MAX 1 + enum aw_ahbclk_type { AW_A10_AHB = 1, AW_A13_AHB, AW_A31_AHB1, + AW_A83T_AHB1, + AW_H3_AHB2, }; static struct ofw_compat_data compat_data[] = { { "allwinner,sun4i-a10-ahb-clk", AW_A10_AHB }, { "allwinner,sun5i-a13-ahb-clk", AW_A13_AHB }, { "allwinner,sun6i-a31-ahb1-clk", AW_A31_AHB1 }, + { "allwinner,sun8i-a83t-ahb1-clk", AW_A83T_AHB1 }, + { "allwinner,sun8i-h3-ahb2-clk", AW_H3_AHB2 }, { NULL, 0 } }; @@ -113,6 +132,19 @@ aw_ahbclk_init(struct clknode *clk, device_t dev) index = (val & A31_AHB1_CLK_SRC_SEL) >> A31_AHB1_CLK_SRC_SEL_SHIFT; break; + case AW_A83T_AHB1: + DEVICE_LOCK(sc); + AHBCLK_READ(sc, &val); + DEVICE_UNLOCK(sc); + index = (val & A83T_AHB1_CLK_SRC_SEL) >> + A83T_AHB1_CLK_SRC_SEL_SHIFT; + break; + case AW_H3_AHB2: + DEVICE_LOCK(sc); + AHBCLK_READ(sc, &val); + DEVICE_UNLOCK(sc); + index = (val & H3_AHB2_CLK_CFG) >> H3_AHB2_CLK_CFG_SHIFT; + break; default: return (ENXIO); } @@ -133,11 +165,10 @@ aw_ahbclk_recalc_freq(struct clknode *clk, uint64_t *freq) AHBCLK_READ(sc, &val); DEVICE_UNLOCK(sc); - div = 1 << ((val & A10_AHB_CLK_DIV_RATIO) >> - A10_AHB_CLK_DIV_RATIO_SHIFT); - switch (sc->type) { case AW_A31_AHB1: + div = 1 << ((val & A10_AHB_CLK_DIV_RATIO) >> + A10_AHB_CLK_DIV_RATIO_SHIFT); src_sel = (val & A31_AHB1_CLK_SRC_SEL) >> A31_AHB1_CLK_SRC_SEL_SHIFT; if (src_sel == A31_AHB1_CLK_SRC_SEL_PLL6) @@ -146,7 +177,28 @@ aw_ahbclk_recalc_freq(struct clknode *clk, uint64_t *freq) else pre_div = 1; break; + case AW_A83T_AHB1: + div = 1 << ((val & A83T_AHB1_CLK_DIV_RATIO) >> + A83T_AHB1_CLK_DIV_RATIO_SHIFT); + src_sel = (val & A83T_AHB1_CLK_SRC_SEL) >> + A83T_AHB1_CLK_SRC_SEL_SHIFT; + if (A83T_AHB1_CLK_SRC_SEL_ISPLL(src_sel)) + pre_div = ((val & A83T_AHB1_PRE_DIV) >> + A83T_AHB1_PRE_DIV_SHIFT) + 1; + else + pre_div = 1; + break; + case AW_H3_AHB2: + src_sel = (val & H3_AHB2_CLK_CFG) >> H3_AHB2_CLK_CFG_SHIFT; + if (src_sel == H3_AHB2_CLK_CFG_PLL_PERIPH_DIV2) + div = 2; + else + div = 1; + pre_div = 1; + break; default: + div = 1 << ((val & A10_AHB_CLK_DIV_RATIO) >> + A10_AHB_CLK_DIV_RATIO_SHIFT); pre_div = 1; break; } @@ -179,6 +231,26 @@ aw_ahbclk_set_mux(struct clknode *clk, int index) AHBCLK_WRITE(sc, val); DEVICE_UNLOCK(sc); break; + case AW_A83T_AHB1: + if (index < 0 || index > A83T_AHB1_CLK_SRC_SEL_MAX) + return (ERANGE); + DEVICE_LOCK(sc); + AHBCLK_READ(sc, &val); + val &= ~A83T_AHB1_CLK_SRC_SEL; + val |= (index << A83T_AHB1_CLK_SRC_SEL_SHIFT); + AHBCLK_WRITE(sc, val); + DEVICE_UNLOCK(sc); + break; + case AW_H3_AHB2: + if (index < 0 || index > H3_AHB2_CLK_CFG) + return (ERANGE); + DEVICE_LOCK(sc); + AHBCLK_READ(sc, &val); + val &= ~H3_AHB2_CLK_CFG; + val |= (index << H3_AHB2_CLK_CFG_SHIFT); + AHBCLK_WRITE(sc, val); + DEVICE_UNLOCK(sc); + break; default: return (ENXIO); } diff --git a/sys/arm/allwinner/clk/aw_apbclk.c b/sys/arm/allwinner/clk/aw_apbclk.c index a56387b..7620c45 100644 --- a/sys/arm/allwinner/clk/aw_apbclk.c +++ b/sys/arm/allwinner/clk/aw_apbclk.c @@ -49,24 +49,32 @@ __FBSDID("$FreeBSD$"); #include "clkdev_if.h" -#define APB0_CLK_RATIO (0x3 << 8) -#define APB0_CLK_RATIO_SHIFT 8 -#define APB1_CLK_SRC_SEL (0x3 << 24) -#define APB1_CLK_SRC_SEL_SHIFT 24 -#define APB1_CLK_SRC_SEL_MAX 0x3 -#define APB1_CLK_RAT_N (0x3 << 16) -#define APB1_CLK_RAT_N_SHIFT 16 -#define APB1_CLK_RAT_M (0x1f << 0) -#define APB1_CLK_RAT_M_SHIFT 0 +#define A10_APB0_CLK_RATIO (0x3 << 8) +#define A10_APB0_CLK_RATIO_SHIFT 8 +#define A10_APB1_CLK_SRC_SEL (0x3 << 24) +#define A10_APB1_CLK_SRC_SEL_SHIFT 24 +#define A10_APB1_CLK_SRC_SEL_MAX 0x3 +#define A10_APB1_CLK_RAT_N (0x3 << 16) +#define A10_APB1_CLK_RAT_N_SHIFT 16 +#define A10_APB1_CLK_RAT_M (0x1f << 0) +#define A10_APB1_CLK_RAT_M_SHIFT 0 +#define A23_APB0_CLK_RATIO (0x3 << 0) +#define A23_APB0_CLK_RATIO_SHIFT 0 +#define A83T_APB1_CLK_RATIO (0x3 << 8) +#define A83T_APB1_CLK_RATIO_SHIFT 8 enum aw_apbclk_type { AW_A10_APB0 = 1, AW_A10_APB1, + AW_A23_APB0, + AW_A83T_APB1, }; static struct ofw_compat_data compat_data[] = { { "allwinner,sun4i-a10-apb0-clk", AW_A10_APB0 }, { "allwinner,sun4i-a10-apb1-clk", AW_A10_APB1 }, + { "allwinner,sun8i-a23-apb0-clk", AW_A23_APB0 }, + { "allwinner,sun8i-a83t-apb1-clk", AW_A83T_APB1 }, { NULL, 0 } }; @@ -91,13 +99,16 @@ aw_apbclk_init(struct clknode *clk, device_t dev) switch (sc->type) { case AW_A10_APB0: + case AW_A23_APB0: + case AW_A83T_APB1: index = 0; break; case AW_A10_APB1: DEVICE_LOCK(sc); APBCLK_READ(sc, &val); DEVICE_UNLOCK(sc); - index = (val & APB1_CLK_SRC_SEL) >> APB1_CLK_SRC_SEL_SHIFT; + index = (val & A10_APB1_CLK_SRC_SEL) >> + A10_APB1_CLK_SRC_SEL_SHIFT; break; default: return (ENXIO); @@ -121,16 +132,29 @@ aw_apbclk_recalc_freq(struct clknode *clk, uint64_t *freq) switch (sc->type) { case AW_A10_APB0: - div = 1 << ((val & APB0_CLK_RATIO) >> APB0_CLK_RATIO_SHIFT); + div = 1 << ((val & A10_APB0_CLK_RATIO) >> + A10_APB0_CLK_RATIO_SHIFT); if (div == 1) div = 2; *freq = *freq / div; break; case AW_A10_APB1: - n = 1 << ((val & APB1_CLK_RAT_N) >> APB1_CLK_RAT_N_SHIFT); - m = ((val & APB1_CLK_RAT_N) >> APB1_CLK_RAT_M_SHIFT) + 1; + n = 1 << ((val & A10_APB1_CLK_RAT_N) >> + A10_APB1_CLK_RAT_N_SHIFT); + m = ((val & A10_APB1_CLK_RAT_N) >> + A10_APB1_CLK_RAT_M_SHIFT) + 1; *freq = *freq / n / m; break; + case AW_A23_APB0: + div = 1 << ((val & A23_APB0_CLK_RATIO) >> + A23_APB0_CLK_RATIO_SHIFT); + *freq = *freq / div; + break; + case AW_A83T_APB1: + div = ((val & A83T_APB1_CLK_RATIO) >> + A83T_APB1_CLK_RATIO_SHIFT) + 1; + *freq = *freq / div; + break; default: return (ENXIO); } @@ -149,13 +173,13 @@ aw_apbclk_set_mux(struct clknode *clk, int index) if (sc->type != AW_A10_APB1) return (ENXIO); - if (index < 0 || index > APB1_CLK_SRC_SEL_MAX) + if (index < 0 || index > A10_APB1_CLK_SRC_SEL_MAX) return (ERANGE); DEVICE_LOCK(sc); APBCLK_READ(sc, &val); - val &= ~APB1_CLK_SRC_SEL; - val |= (index << APB1_CLK_SRC_SEL_SHIFT); + val &= ~A10_APB1_CLK_SRC_SEL; + val |= (index << A10_APB1_CLK_SRC_SEL_SHIFT); APBCLK_WRITE(sc, val); DEVICE_UNLOCK(sc); diff --git a/sys/arm/allwinner/clk/aw_cpusclk.c b/sys/arm/allwinner/clk/aw_cpusclk.c new file mode 100644 index 0000000..6d18284 --- /dev/null +++ b/sys/arm/allwinner/clk/aw_cpusclk.c @@ -0,0 +1,320 @@ +/*- + * Copyright (c) 2016 Jared McNeill + * 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 ``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. + * + * $FreeBSD$ + */ + +/* + * Allwinner CPUS clock + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "clkdev_if.h" + +#define A80_CPUS_CLK_SRC_SEL (0x3 << 16) +#define A80_CPUS_CLK_SRC_SEL_SHIFT 16 +#define A80_CPUS_CLK_SRC_SEL_X32KI 0 +#define A80_CPUS_CLK_SRC_SEL_OSC24M 1 +#define A80_CPUS_CLK_SRC_SEL_PLL_PERIPH 2 +#define A80_CPUS_CLK_SRC_SEL_PLL_AUDIO 3 +#define A80_CPUS_POST_DIV (0x1f << 8) +#define A80_CPUS_POST_DIV_SHIFT 8 +#define A80_CPUS_CLK_RATIO (0x3 << 4) +#define A80_CPUS_CLK_RATIO_SHIFT 4 + +#define A83T_CPUS_CLK_SRC_SEL (0x3 << 16) +#define A83T_CPUS_CLK_SRC_SEL_SHIFT 16 +#define A83T_CPUS_CLK_SRC_SEL_X32KI 0 +#define A83T_CPUS_CLK_SRC_SEL_OSC24M 1 +#define A83T_CPUS_CLK_SRC_SEL_PLL_PERIPH 2 +#define A83T_CPUS_CLK_SRC_SEL_INTERNAL_OSC 3 +#define A83T_CPUS_POST_DIV (0x1f << 8) +#define A83T_CPUS_POST_DIV_SHIFT 8 +#define A83T_CPUS_CLK_RATIO (0x3 << 4) +#define A83T_CPUS_CLK_RATIO_SHIFT 4 + +enum aw_cpusclk_type { + AW_A80_CPUS = 1, + AW_A83T_CPUS, +}; + +static struct ofw_compat_data compat_data[] = { + { "allwinner,sun9i-a80-cpus-clk", AW_A80_CPUS }, + { "allwinner,sun8i-a83t-cpus-clk", AW_A83T_CPUS }, + { NULL, 0 } +}; + +struct aw_cpusclk_sc { + device_t clkdev; + bus_addr_t reg; + enum aw_cpusclk_type type; +}; + +#define CPUSCLK_READ(sc, val) CLKDEV_READ_4((sc)->clkdev, (sc)->reg, (val)) +#define CPUSCLK_WRITE(sc, val) CLKDEV_WRITE_4((sc)->clkdev, (sc)->reg, (val)) +#define DEVICE_LOCK(sc) CLKDEV_DEVICE_LOCK((sc)->clkdev) +#define DEVICE_UNLOCK(sc) CLKDEV_DEVICE_UNLOCK((sc)->clkdev) + +static int +aw_cpusclk_init(struct clknode *clk, device_t dev) +{ + struct aw_cpusclk_sc *sc; + uint32_t val, mask, shift, index; + + sc = clknode_get_softc(clk); + + switch (sc->type) { + case AW_A80_CPUS: + mask = A80_CPUS_CLK_SRC_SEL; + shift = A80_CPUS_CLK_SRC_SEL_SHIFT; + break; + case AW_A83T_CPUS: + mask = A83T_CPUS_CLK_SRC_SEL; + shift = A83T_CPUS_CLK_SRC_SEL_SHIFT; + break; + default: + return (ENXIO); + } + + DEVICE_LOCK(sc); + CPUSCLK_READ(sc, &val); + DEVICE_UNLOCK(sc); + index = (val & mask) >> shift; + + clknode_init_parent_idx(clk, index); + return (0); +} + +static int +aw_cpusclk_recalc_freq(struct clknode *clk, uint64_t *freq) +{ + struct aw_cpusclk_sc *sc; + uint32_t val, src_sel, post_div, clk_ratio; + + sc = clknode_get_softc(clk); + + DEVICE_LOCK(sc); + CPUSCLK_READ(sc, &val); + DEVICE_UNLOCK(sc); + + switch (sc->type) { + case AW_A80_CPUS: + src_sel = (val & A80_CPUS_CLK_SRC_SEL) >> + A80_CPUS_CLK_SRC_SEL_SHIFT; + post_div = ((val & A80_CPUS_POST_DIV) >> + A80_CPUS_POST_DIV_SHIFT) + 1; + clk_ratio = ((val & A80_CPUS_CLK_RATIO) >> + A80_CPUS_CLK_RATIO_SHIFT) + 1; + if (src_sel == A80_CPUS_CLK_SRC_SEL_PLL_PERIPH) + *freq = *freq / post_div / clk_ratio; + else + *freq = *freq / clk_ratio; + break; + case AW_A83T_CPUS: + src_sel = (val & A83T_CPUS_CLK_SRC_SEL) >> + A83T_CPUS_CLK_SRC_SEL_SHIFT; + post_div = ((val & A83T_CPUS_POST_DIV) >> + A83T_CPUS_POST_DIV_SHIFT) + 1; + clk_ratio = 1 << ((val & A83T_CPUS_CLK_RATIO) >> + A83T_CPUS_CLK_RATIO_SHIFT); + if (src_sel == A83T_CPUS_CLK_SRC_SEL_PLL_PERIPH) + *freq = *freq / post_div / clk_ratio; + else + *freq = *freq / clk_ratio; + break; + default: + return (EINVAL); + } + + return (0); +} + +static int +aw_cpusclk_set_mux(struct clknode *clk, int index) +{ + struct aw_cpusclk_sc *sc; + uint32_t mask, shift, val; + + sc = clknode_get_softc(clk); + + switch (sc->type) { + case AW_A80_CPUS: + mask = A80_CPUS_CLK_SRC_SEL; + shift = A80_CPUS_CLK_SRC_SEL_SHIFT; + break; + case AW_A83T_CPUS: + mask = A83T_CPUS_CLK_SRC_SEL; + shift = A83T_CPUS_CLK_SRC_SEL_SHIFT; + break; + default: + return (ENXIO); + } + + DEVICE_LOCK(sc); + CPUSCLK_READ(sc, &val); + val &= ~mask; + val |= (index << shift); + CPUSCLK_WRITE(sc, val); + DEVICE_UNLOCK(sc); + + return (0); +} + +static clknode_method_t aw_cpusclk_clknode_methods[] = { + /* Device interface */ + CLKNODEMETHOD(clknode_init, aw_cpusclk_init), + CLKNODEMETHOD(clknode_recalc_freq, aw_cpusclk_recalc_freq), + CLKNODEMETHOD(clknode_set_mux, aw_cpusclk_set_mux), + CLKNODEMETHOD_END +}; +DEFINE_CLASS_1(aw_cpusclk_clknode, aw_cpusclk_clknode_class, + aw_cpusclk_clknode_methods, sizeof(struct aw_cpusclk_sc), clknode_class); + +static int +aw_cpusclk_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Allwinner CPUS Clock"); + return (BUS_PROBE_DEFAULT); +} + +static int +aw_cpusclk_attach(device_t dev) +{ + struct clknode_init_def def; + struct aw_cpusclk_sc *sc; + struct clkdom *clkdom; + struct clknode *clk; + clk_t clk_parent; + bus_addr_t paddr; + bus_size_t psize; + phandle_t node; + int error, ncells, i; + + node = ofw_bus_get_node(dev); + + if (ofw_reg_to_paddr(node, 0, &paddr, &psize, NULL) != 0) { + device_printf(dev, "cannot parse 'reg' property\n"); + return (ENXIO); + } + + error = ofw_bus_parse_xref_list_get_length(node, "clocks", + "#clock-cells", &ncells); + if (error != 0) { + device_printf(dev, "cannot get clock count\n"); + return (error); + } + + clkdom = clkdom_create(dev); + + memset(&def, 0, sizeof(def)); + def.id = 1; + def.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP, + M_WAITOK); + for (i = 0; i < ncells; i++) { + error = clk_get_by_ofw_index(dev, i, &clk_parent); + if (error != 0) { + device_printf(dev, "cannot get clock %d\n", i); + goto fail; + } + def.parent_names[i] = clk_get_name(clk_parent); + clk_release(clk_parent); + } + def.parent_cnt = ncells; + + error = clk_parse_ofw_clk_name(dev, node, &def.name); + if (error != 0) { + device_printf(dev, "cannot parse clock name\n"); + error = ENXIO; + goto fail; + } + + clk = clknode_create(clkdom, &aw_cpusclk_clknode_class, &def); + if (clk == NULL) { + device_printf(dev, "cannot create clknode\n"); + error = ENXIO; + goto fail; + } + sc = clknode_get_softc(clk); + sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + sc->reg = paddr; + sc->clkdev = device_get_parent(dev); + + clknode_register(clkdom, clk); + + if (clkdom_finit(clkdom) != 0) { + device_printf(dev, "cannot finalize clkdom initialization\n"); + error = ENXIO; + goto fail; + } + + if (bootverbose) + clkdom_dump(clkdom); + + return (0); + +fail: + return (error); +} + +static device_method_t aw_cpusclk_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, aw_cpusclk_probe), + DEVMETHOD(device_attach, aw_cpusclk_attach), + + DEVMETHOD_END +}; + +static driver_t aw_cpusclk_driver = { + "aw_cpusclk", + aw_cpusclk_methods, + 0 +}; + +static devclass_t aw_cpusclk_devclass; + +EARLY_DRIVER_MODULE(aw_cpusclk, simplebus, aw_cpusclk_driver, + aw_cpusclk_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); diff --git a/sys/arm/allwinner/clk/aw_gate.c b/sys/arm/allwinner/clk/aw_gate.c index d43d021..6634c57 100644 --- a/sys/arm/allwinner/clk/aw_gate.c +++ b/sys/arm/allwinner/clk/aw_gate.c @@ -76,6 +76,14 @@ static struct ofw_compat_data compat_data[] = { { "allwinner,sun6i-a31-apb2-gates-clk", (uintptr_t)"Allwinner APB2 Clock Gates" }, + { "allwinner,sun8i-a83t-bus-gates-clk", + (uintptr_t)"Allwinner Bus Clock Gates" }, + { "allwinner,sun8i-a83t-apb0-gates-clk", + (uintptr_t)"Allwinner APB0 Clock Gates" }, + + { "allwinner,sun9i-a80-apbs-gates-clk", + (uintptr_t)"Allwinner APBS Clock Gates" }, + { NULL, 0 } }; diff --git a/sys/arm/allwinner/clk/aw_gmacclk.c b/sys/arm/allwinner/clk/aw_gmacclk.c index 5e2f618..72495fd 100644 --- a/sys/arm/allwinner/clk/aw_gmacclk.c +++ b/sys/arm/allwinner/clk/aw_gmacclk.c @@ -60,18 +60,41 @@ __FBSDID("$FreeBSD$"); #define GMAC_CLK_SRC_EXT_RGMII 1 #define GMAC_CLK_SRC_RGMII 2 +#define EMAC_TXC_DIV_CFG (1 << 15) +#define EMAC_TXC_DIV_CFG_SHIFT 15 +#define EMAC_TXC_DIV_CFG_125MHZ 0 +#define EMAC_TXC_DIV_CFG_25MHZ 1 +#define EMAC_PHY_SELECT (1 << 16) +#define EMAC_PHY_SELECT_SHIFT 16 +#define EMAC_PHY_SELECT_INT 0 +#define EMAC_PHY_SELECT_EXT 1 +#define EMAC_ETXDC (0x7 << 10) +#define EMAC_ETXDC_SHIFT 10 +#define EMAC_ERXDC (0x1f << 5) +#define EMAC_ERXDC_SHIFT 5 + #define CLK_IDX_MII 0 #define CLK_IDX_RGMII 1 #define CLK_IDX_COUNT 2 +enum aw_gmacclk_type { + GMACCLK_A20 = 1, + GMACCLK_A83T, +}; + static struct ofw_compat_data compat_data[] = { - { "allwinner,sun7i-a20-gmac-clk", 1 }, + { "allwinner,sun7i-a20-gmac-clk", GMACCLK_A20 }, + { "allwinner,sun8i-a83t-emac-clk", GMACCLK_A83T }, { NULL, 0 } }; struct aw_gmacclk_sc { device_t clkdev; bus_addr_t reg; + enum aw_gmacclk_type type; + + int rx_delay; + int tx_delay; }; #define GMACCLK_READ(sc, val) CLKDEV_READ_4((sc)->clkdev, (sc)->reg, (val)) @@ -110,7 +133,7 @@ static int aw_gmacclk_set_mux(struct clknode *clk, int index) { struct aw_gmacclk_sc *sc; - uint32_t val, clk_src, pit; + uint32_t val, clk_src, pit, txc_div; int error; sc = clknode_get_softc(clk); @@ -120,10 +143,12 @@ aw_gmacclk_set_mux(struct clknode *clk, int index) case CLK_IDX_MII: clk_src = GMAC_CLK_SRC_MII; pit = GMAC_CLK_PIT_MII; + txc_div = EMAC_TXC_DIV_CFG_25MHZ; break; case CLK_IDX_RGMII: clk_src = GMAC_CLK_SRC_RGMII; pit = GMAC_CLK_PIT_RGMII; + txc_div = EMAC_TXC_DIV_CFG_125MHZ; break; default: return (ENXIO); @@ -134,6 +159,20 @@ aw_gmacclk_set_mux(struct clknode *clk, int index) val &= ~(GMAC_CLK_SRC | GMAC_CLK_PIT); val |= (clk_src << GMAC_CLK_SRC_SHIFT); val |= (pit << GMAC_CLK_PIT_SHIFT); + if (sc->type == GMACCLK_A83T) { + val &= ~EMAC_TXC_DIV_CFG; + val |= (txc_div << EMAC_TXC_DIV_CFG_SHIFT); + val &= ~EMAC_PHY_SELECT; + val |= (EMAC_PHY_SELECT_EXT << EMAC_PHY_SELECT_SHIFT); + if (sc->tx_delay >= 0) { + val &= ~EMAC_ETXDC; + val |= (sc->tx_delay << EMAC_ETXDC_SHIFT); + } + if (sc->rx_delay >= 0) { + val &= ~EMAC_ERXDC; + val |= (sc->rx_delay << EMAC_ERXDC_SHIFT); + } + } GMACCLK_WRITE(sc, val); DEVICE_UNLOCK(sc); @@ -158,7 +197,7 @@ aw_gmacclk_probe(device_t dev) if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); - device_set_desc(dev, "Allwinner Module Clock"); + device_set_desc(dev, "Allwinner GMAC Clock"); return (BUS_PROBE_DEFAULT); } @@ -221,6 +260,10 @@ aw_gmacclk_attach(device_t dev) sc = clknode_get_softc(clk); sc->reg = paddr; sc->clkdev = device_get_parent(dev); + sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + sc->tx_delay = sc->rx_delay = -1; + OF_getencprop(node, "tx-delay", &sc->tx_delay, sizeof(sc->tx_delay)); + OF_getencprop(node, "rx-delay", &sc->rx_delay, sizeof(sc->rx_delay)); clknode_register(clkdom, clk); diff --git a/sys/arm/allwinner/clk/aw_pll.c b/sys/arm/allwinner/clk/aw_pll.c index 2e67646..b7c2a7e 100644 --- a/sys/arm/allwinner/clk/aw_pll.c +++ b/sys/arm/allwinner/clk/aw_pll.c @@ -124,6 +124,12 @@ __FBSDID("$FreeBSD$"); #define A31_PLL6_DEFAULT_K 0x1 #define A31_PLL6_TIMEOUT 10 +#define A80_PLL4_CLK_OUT_EN (1 << 20) +#define A80_PLL4_PLL_DIV2 (1 << 18) +#define A80_PLL4_PLL_DIV1 (1 << 16) +#define A80_PLL4_FACTOR_N (0xff << 8) +#define A80_PLL4_FACTOR_N_SHIFT 8 + #define CLKID_A10_PLL3_1X 0 #define CLKID_A10_PLL3_2X 1 @@ -146,6 +152,7 @@ enum aw_pll_type { AWPLL_A10_PLL6, AWPLL_A31_PLL1, AWPLL_A31_PLL6, + AWPLL_A80_PLL4, }; struct aw_pll_sc { @@ -524,6 +531,24 @@ a31_pll6_recalc(struct aw_pll_sc *sc, uint64_t *freq) return (0); } +static int +a80_pll4_recalc(struct aw_pll_sc *sc, uint64_t *freq) +{ + uint32_t val, n, div1, div2; + + DEVICE_LOCK(sc); + PLL_READ(sc, &val); + DEVICE_UNLOCK(sc); + + n = (val & A80_PLL4_FACTOR_N) >> A80_PLL4_FACTOR_N_SHIFT; + div1 = (val & A80_PLL4_PLL_DIV1) == 0 ? 1 : 2; + div2 = (val & A80_PLL4_PLL_DIV2) == 0 ? 1 : 2; + + *freq = (*freq * n) / div1 / div2; + + return (0); +} + #define PLL(_type, _recalc, _set_freq, _init) \ [(_type)] = { \ .recalc = (_recalc), \ @@ -539,6 +564,7 @@ static struct aw_pll_funcs aw_pll_func[] = { PLL(AWPLL_A10_PLL6, a10_pll6_recalc, a10_pll6_set_freq, a10_pll6_init), PLL(AWPLL_A31_PLL1, a31_pll1_recalc, NULL, NULL), PLL(AWPLL_A31_PLL6, a31_pll6_recalc, NULL, a31_pll6_init), + PLL(AWPLL_A80_PLL4, a80_pll4_recalc, NULL, NULL), }; static struct ofw_compat_data compat_data[] = { @@ -549,6 +575,7 @@ static struct ofw_compat_data compat_data[] = { { "allwinner,sun4i-a10-pll6-clk", AWPLL_A10_PLL6 }, { "allwinner,sun6i-a31-pll1-clk", AWPLL_A31_PLL1 }, { "allwinner,sun6i-a31-pll6-clk", AWPLL_A31_PLL6 }, + { "allwinner,sun9i-a80-pll4-clk", AWPLL_A80_PLL4 }, { NULL, 0 } }; diff --git a/sys/arm/allwinner/clk/aw_usbclk.c b/sys/arm/allwinner/clk/aw_usbclk.c index bac9991..cd935c4 100644 --- a/sys/arm/allwinner/clk/aw_usbclk.c +++ b/sys/arm/allwinner/clk/aw_usbclk.c @@ -62,11 +62,13 @@ __FBSDID("$FreeBSD$"); enum aw_usbclk_type { AW_A10_USBCLK = 1, AW_A31_USBCLK, + AW_A83T_USBCLK, }; static struct ofw_compat_data compat_data[] = { { "allwinner,sun4i-a10-usb-clk", AW_A10_USBCLK }, { "allwinner,sun6i-a31-usb-clk", AW_A31_USBCLK }, + { "allwinner,sun8i-a83t-usb-clk", AW_A83T_USBCLK }, { NULL, 0 } }; @@ -162,10 +164,11 @@ aw_usbclk_attach(device_t dev) struct aw_usbclk_softc *sc; struct clkdom *clkdom; const char **names; + const char *pname; int index, nout, error; enum aw_usbclk_type type; uint32_t *indices; - clk_t clk_parent; + clk_t clk_parent, clk_parent_pll; bus_size_t psize; phandle_t node; @@ -196,11 +199,21 @@ aw_usbclk_attach(device_t dev) device_printf(dev, "cannot parse clock parent\n"); return (ENXIO); } + if (type == AW_A83T_USBCLK) { + error = clk_get_by_ofw_index(dev, 1, &clk_parent_pll); + if (error != 0) { + device_printf(dev, "cannot parse pll clock parent\n"); + return (ENXIO); + } + } for (index = 0; index < nout; index++) { - error = aw_usbclk_create(dev, sc->reg, clkdom, - clk_get_name(clk_parent), names[index], - indices != NULL ? indices[index] : index); + if (strcmp(names[index], "usb_hsic_pll") == 0) + pname = clk_get_name(clk_parent_pll); + else + pname = clk_get_name(clk_parent); + error = aw_usbclk_create(dev, sc->reg, clkdom, pname, + names[index], indices != NULL ? indices[index] : index); if (error) goto fail; } diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner index 84453a6..a138989 100644 --- a/sys/arm/allwinner/files.allwinner +++ b/sys/arm/allwinner/files.allwinner @@ -36,6 +36,7 @@ arm/allwinner/clk/aw_apbclk.c standard arm/allwinner/clk/aw_axiclk.c standard arm/allwinner/clk/aw_codecclk.c standard arm/allwinner/clk/aw_cpuclk.c standard +arm/allwinner/clk/aw_cpusclk.c standard arm/allwinner/clk/aw_debeclk.c standard arm/allwinner/clk/aw_gate.c standard arm/allwinner/clk/aw_gmacclk.c standard diff --git a/sys/arm/allwinner/std.allwinner b/sys/arm/allwinner/std.allwinner index 885d41d..5ac9dd6 100644 --- a/sys/arm/allwinner/std.allwinner +++ b/sys/arm/allwinner/std.allwinner @@ -14,3 +14,4 @@ options IPI_IRQ_END=15 files "../allwinner/files.allwinner" files "../allwinner/a20/files.a20" files "../allwinner/a31/files.a31" +files "../allwinner/a83t/files.a83t" diff --git a/sys/arm/conf/ALLWINNER b/sys/arm/conf/ALLWINNER index 9bb0e0a..3d0acb5 100644 --- a/sys/arm/conf/ALLWINNER +++ b/sys/arm/conf/ALLWINNER @@ -28,6 +28,7 @@ options INTRNG options SOC_ALLWINNER_A20 options SOC_ALLWINNER_A31 options SOC_ALLWINNER_A31S +options SOC_ALLWINNER_A83T options HZ=100 options SCHED_ULE # ULE scheduler @@ -121,6 +122,7 @@ device bpf #device emac # 10/100 integrated EMAC controller device dwc # 10/100/1000 integrated GMAC controller +device awg # 10/100/1000 integrated EMAC controller # USB ethernet support, requires miibus device miibus diff --git a/sys/conf/options.arm b/sys/conf/options.arm index 8a14da1..0d42ddb 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -44,6 +44,7 @@ SOC_ALLWINNER_A10 opt_global.h SOC_ALLWINNER_A20 opt_global.h SOC_ALLWINNER_A31 opt_global.h SOC_ALLWINNER_A31S opt_global.h +SOC_ALLWINNER_A83T opt_global.h SOC_BCM2835 opt_global.h SOC_BCM2836 opt_global.h SOC_IMX51 opt_global.h -- cgit v1.1 From 93266297055f77bcef81e5f72468bc3b338f9e61 Mon Sep 17 00:00:00 2001 From: skra Date: Thu, 5 May 2016 13:23:38 +0000 Subject: Remove superfluous check. The pic_dev member of struct pic is never NULL on PIC found by pic_lookup(). --- sys/kern/subr_intr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index c5febf5..e5fbbb0 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -971,7 +971,7 @@ intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data, return (EINVAL); pic = pic_lookup(dev, xref); - if (pic == NULL || pic->pic_dev == NULL) + if (pic == NULL) return (ESRCH); error = PIC_MAP_INTR(pic->pic_dev, data, &isrc); -- cgit v1.1 From ee35e1301377ddf7b2236efed36e044da05faa1a Mon Sep 17 00:00:00 2001 From: skra Date: Thu, 5 May 2016 13:31:19 +0000 Subject: INTRNG - redefine struct intr_map_data to avoid headers pollution. Each struct associated with some type defined in enum intr_map_data_type must have struct intr_map_data on the top of its own definition now. When such structs are used, correct type and size must be filled in. There are three such structs defined in sys/intr.h now. Their definitions should be moved to corresponding headers by follow-up commits. While this change was propagated to all INTRNG like PICs, pic_map_intr() method implementations were corrected on some places. For this specific method, it's ensured by a caller that the 'data' argument passed to this method is never NULL. Also, the return error values were standardized there. --- sys/arm/allwinner/a10/a10_intc.c | 10 ++++-- sys/arm/allwinner/aw_nmi.c | 20 +++++++----- sys/arm/arm/gic.c | 10 ++++-- sys/arm/broadcom/bcm2835/bcm2835_gpio.c | 10 ++++-- sys/arm/broadcom/bcm2835/bcm2835_intr.c | 11 ++++--- sys/arm/broadcom/bcm2835/bcm2836.c | 7 +++-- sys/arm/freescale/imx/imx_gpio.c | 12 +++++--- sys/arm/mv/mpic.c | 10 ++++-- sys/arm/nvidia/tegra_gpio.c | 42 +++++++++++++++---------- sys/arm/ti/aintc.c | 10 ++++-- sys/arm/ti/ti_gpio.c | 10 ++++-- sys/kern/subr_intr.c | 54 +++++++++++++++++++++------------ sys/mips/mediatek/mtk_gpio_v1.c | 10 ++++-- sys/mips/mediatek/mtk_gpio_v2.c | 10 ++++-- sys/mips/mediatek/mtk_intr_gic.c | 12 +++++--- sys/mips/mediatek/mtk_intr_v1.c | 12 +++++--- sys/mips/mediatek/mtk_intr_v2.c | 12 +++++--- sys/mips/mips/mips_pic.c | 12 +++++--- sys/sys/intr.h | 25 ++++++--------- 19 files changed, 190 insertions(+), 109 deletions(-) (limited to 'sys') diff --git a/sys/arm/allwinner/a10/a10_intc.c b/sys/arm/allwinner/a10/a10_intc.c index 7bd8e80..31e6ef4 100644 --- a/sys/arm/allwinner/a10/a10_intc.c +++ b/sys/arm/allwinner/a10/a10_intc.c @@ -298,14 +298,18 @@ static int a10_intr_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct a10_aintc_softc *sc; - if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells != 1 || - data->fdt.cells[0] >= A10_INTR_MAX_NIRQS) + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + + daf = (struct intr_map_data_fdt *)data; + if (daf->ncells != 1 || daf->cells[0] >= A10_INTR_MAX_NIRQS) return (EINVAL); sc = device_get_softc(dev); - *isrcp = &sc->isrcs[data->fdt.cells[0]].isrc; + *isrcp = &sc->isrcs[daf->cells[0]].isrc; return (0); } diff --git a/sys/arm/allwinner/aw_nmi.c b/sys/arm/allwinner/aw_nmi.c index 1cdd50e..2b23a4b 100644 --- a/sys/arm/allwinner/aw_nmi.c +++ b/sys/arm/allwinner/aw_nmi.c @@ -188,16 +188,18 @@ static int aw_nmi_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct aw_nmi_softc *sc; int error; u_int irq; - sc = device_get_softc(dev); if (data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); - error = aw_nmi_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq, - NULL, NULL); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; + + error = aw_nmi_map_fdt(dev, daf->ncells, daf->cells, &irq, NULL, NULL); if (error == 0) *isrcp = &sc->intr.isrc; @@ -208,6 +210,7 @@ static int aw_nmi_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { + struct intr_map_data_fdt *daf; struct aw_nmi_softc *sc; struct aw_nmi_intr *nmi_intr; int error, icfg; @@ -215,14 +218,15 @@ aw_nmi_setup_intr(device_t dev, struct intr_irqsrc *isrc, enum intr_trigger trig; enum intr_polarity pol; - sc = device_get_softc(dev); - nmi_intr = (struct aw_nmi_intr *)isrc; - /* Get config for interrupt. */ if (data == NULL || data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); - error = aw_nmi_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq, - &pol, &trig); + + sc = device_get_softc(dev); + nmi_intr = (struct aw_nmi_intr *)isrc; + daf = (struct intr_map_data_fdt *)data; + + error = aw_nmi_map_fdt(dev, daf->ncells, daf->cells, &irq, &pol, &trig); if (error != 0) return (error); if (nmi_intr->irq != irq) diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c index a898532..17e1525 100644 --- a/sys/arm/arm/gic.c +++ b/sys/arm/arm/gic.c @@ -1006,18 +1006,22 @@ gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp, enum intr_polarity pol; enum intr_trigger trig; struct arm_gic_softc *sc; +#ifdef FDT + struct intr_map_data_fdt *daf; +#endif sc = device_get_softc(dev); switch (data->type) { #ifdef FDT case INTR_MAP_DATA_FDT: - if (gic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq, - &pol, &trig) != 0) + daf = (struct intr_map_data_fdt *)data; + if (gic_map_fdt(dev, daf->ncells, daf->cells, &irq, &pol, + &trig) != 0) return (EINVAL); break; #endif default: - return (EINVAL); + return (ENOTSUP); } if (irq >= sc->nirqs) diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index 7c67a38..29b5f03 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -1078,14 +1078,16 @@ bcm_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, { int error; u_int irq; + struct intr_map_data_fdt *daf; struct bcm_gpio_softc *sc; if (data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); sc = device_get_softc(dev); - error = bcm_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, - &irq, NULL); + daf = (struct intr_map_data_fdt *)data; + + error = bcm_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, NULL); if (error == 0) *isrcp = &sc->sc_isrcs[irq].bgi_isrc; return (error); @@ -1127,15 +1129,17 @@ bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, uint32_t bank, reg; struct bcm_gpio_softc *sc; struct bcm_gpio_irqsrc *bgi; + struct intr_map_data_fdt *daf; if (data == NULL || data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); sc = device_get_softc(dev); bgi = (struct bcm_gpio_irqsrc *)isrc; + daf = (struct intr_map_data_fdt *)data; /* Get and check config for an interrupt. */ - if (bcm_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, &irq, + if (bcm_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, ®) != 0 || bgi->bgi_irq != irq) return (EINVAL); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_intr.c b/sys/arm/broadcom/bcm2835/bcm2835_intr.c index 8124c96..39ad5f7 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_intr.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_intr.c @@ -268,14 +268,17 @@ bcm_intc_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { u_int irq; + struct intr_map_data_fdt *daf; struct bcm_intc_softc *sc; if (data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); - if (data->fdt.ncells == 1) - irq = data->fdt.cells[0]; - else if (data->fdt.ncells == 2) - irq = data->fdt.cells[0] * 32 + data->fdt.cells[1]; + + daf = (struct intr_map_data_fdt *)data; + if (daf->ncells == 1) + irq = daf->cells[0]; + else if (daf->ncells == 2) + irq = daf->cells[0] * 32 + daf->cells[1]; else return (EINVAL); diff --git a/sys/arm/broadcom/bcm2835/bcm2836.c b/sys/arm/broadcom/bcm2835/bcm2836.c index 16c1e4b..3991609 100644 --- a/sys/arm/broadcom/bcm2835/bcm2836.c +++ b/sys/arm/broadcom/bcm2835/bcm2836.c @@ -461,15 +461,18 @@ static int bcm_lintc_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct bcm_lintc_softc *sc; if (data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); - if (data->fdt.ncells != 1 || data->fdt.cells[0] >= BCM_LINTC_NIRQS) + + daf = (struct intr_map_data_fdt *)data; + if (daf->ncells != 1 || daf->cells[0] >= BCM_LINTC_NIRQS) return (EINVAL); sc = device_get_softc(dev); - *isrcp = &sc->bls_isrcs[data->fdt.cells[0]].bli_isrc; + *isrcp = &sc->bls_isrcs[daf->cells[0]].bli_isrc; return (0); } diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c index ba82f5c..c5f7b8c 100644 --- a/sys/arm/freescale/imx/imx_gpio.c +++ b/sys/arm/freescale/imx/imx_gpio.c @@ -225,13 +225,15 @@ gpio_pic_map_intr(device_t dev, struct intr_map_data *data, { int error; u_int irq; + struct intr_map_data_fdt *daf; struct imx51_gpio_softc *sc; if (data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); - error = gpio_pic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq, - NULL, NULL); + daf = (struct intr_map_data_fdt *)data; + error = gpio_pic_map_fdt(dev, daf->ncells, daf->cells, &irq, NULL, + NULL); if (error == 0) { sc = device_get_softc(dev); *isrcp = &sc->gpio_pic_irqsrc[irq].gi_isrc; @@ -265,6 +267,7 @@ static int gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { + struct intr_map_data_fdt *daf; struct imx51_gpio_softc *sc; struct gpio_irqsrc *gi; int error, icfg; @@ -278,8 +281,9 @@ gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, /* Get config for interrupt. */ if (data == NULL || data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); - error = gpio_pic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq, - &pol, &trig); + daf = (struct intr_map_data_fdt *)data; + error = gpio_pic_map_fdt(dev, daf->ncells, daf->cells, &irq, &pol, + &trig); if (error != 0) return (error); if (gi->gi_irq != irq) diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c index 7be61fc..7e07d66 100644 --- a/sys/arm/mv/mpic.c +++ b/sys/arm/mv/mpic.c @@ -339,15 +339,19 @@ static int mpic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct mv_mpic_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells !=1 || - data->fdt.cells[0] >= sc->nirqs) + if (daf->ncells !=1 || daf->cells[0] >= sc->nirqs) return (EINVAL); - *isrcp = &sc->mpic_isrcs[data->fdt.cells[0]].mmi_isrc; + *isrcp = &sc->mpic_isrcs[daf->cells[0]].mmi_isrc; return (0); } diff --git a/sys/arm/nvidia/tegra_gpio.c b/sys/arm/nvidia/tegra_gpio.c index 0b2b081..7329ce0 100644 --- a/sys/arm/nvidia/tegra_gpio.c +++ b/sys/arm/nvidia/tegra_gpio.c @@ -579,14 +579,19 @@ tegra_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, sc = device_get_softc(dev); - if (data->type == INTR_MAP_DATA_FDT) - rv = tegra_gpio_pic_map_fdt(sc, data->fdt.ncells, - data->fdt.cells, &irq, NULL); - else if (data->type == INTR_MAP_DATA_GPIO) - rv = tegra_gpio_pic_map_gpio(sc, data->gpio.gpio_pin_num, - data->gpio.gpio_pin_flags, data->gpio.gpio_intr_mode, - &irq, NULL); - else + if (data->type == INTR_MAP_DATA_FDT) { + struct intr_map_data_fdt *daf; + + daf = (struct intr_map_data_fdt *)data; + rv = tegra_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, + NULL); + } else if (data->type == INTR_MAP_DATA_GPIO) { + struct intr_map_data_gpio *dag; + + dag = (struct intr_map_data_gpio *)data; + rv = tegra_gpio_pic_map_gpio(sc, dag->gpio_pin_num, + dag->gpio_pin_flags, dag->gpio_intr_mode, &irq, NULL); + } else return (ENOTSUP); if (rv == 0) @@ -648,14 +653,19 @@ tegra_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, return (ENOTSUP); /* Get and check config for an interrupt. */ - if (data->type == INTR_MAP_DATA_FDT) - rv = tegra_gpio_pic_map_fdt(sc, data->fdt.ncells, - data->fdt.cells, &irq, &cfgreg); - else if (data->type == INTR_MAP_DATA_GPIO) - rv = tegra_gpio_pic_map_gpio(sc, data->gpio.gpio_pin_num, - data->gpio.gpio_pin_flags, data->gpio.gpio_intr_mode, - &irq, &cfgreg); - else + if (data->type == INTR_MAP_DATA_FDT) { + struct intr_map_data_fdt *daf; + + daf = (struct intr_map_data_fdt *)data; + rv = tegra_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, + &cfgreg); + } else if (data->type == INTR_MAP_DATA_GPIO) { + struct intr_map_data_gpio *dag; + + dag = (struct intr_map_data_gpio *)data; + rv = tegra_gpio_pic_map_gpio(sc, dag->gpio_pin_num, + dag->gpio_pin_flags, dag->gpio_intr_mode, &irq, &cfgreg); + } else return (ENOTSUP); if (rv != 0) return (EINVAL); diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c index ebe4864..5fb4695 100644 --- a/sys/arm/ti/aintc.c +++ b/sys/arm/ti/aintc.c @@ -178,14 +178,18 @@ static int ti_aintc_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct ti_aintc_softc *sc; - if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells != 1 || - data->fdt.cells[0] >= INTC_NIRQS) + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + + daf = (struct intr_map_data_fdt *)data; + if (daf->ncells != 1 || daf->cells[0] >= INTC_NIRQS) return (EINVAL); sc = device_get_softc(dev); - *isrcp = &sc->aintc_isrcs[data->fdt.cells[0]].tai_isrc; + *isrcp = &sc->aintc_isrcs[daf->cells[0]].tai_isrc; return (0); } diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 54e5042..70c1a33 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -979,13 +979,15 @@ ti_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, int error; u_int irq; struct ti_gpio_softc *sc; + struct intr_map_data_fdt *daf; if (data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); sc = device_get_softc(dev); - error = ti_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, &irq, - NULL); + daf = (struct intr_map_data_fdt *)data; + + error = ti_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, NULL); if (error == 0) *isrcp = &sc->sc_isrcs[irq].tgi_isrc; return (error); @@ -1027,15 +1029,17 @@ ti_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, uint32_t cfgreg; struct ti_gpio_softc *sc; struct ti_gpio_irqsrc *tgi; + struct intr_map_data_fdt *daf; if (data == NULL || data->type != INTR_MAP_DATA_FDT) return (ENOTSUP); sc = device_get_softc(dev); tgi = (struct ti_gpio_irqsrc *)isrc; + daf = (struct intr_map_data_fdt *)data; /* Get and check config for an interrupt. */ - if (ti_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, &irq, + if (ti_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, &cfgreg) != 0 || tgi->tgi_irq != irq) return (EINVAL); diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index e5fbbb0..366ccf9 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -128,7 +128,7 @@ struct intr_dev_data { device_t idd_dev; intptr_t idd_xref; u_int idd_irq; - struct intr_map_data idd_data; + struct intr_map_data * idd_data; struct intr_irqsrc * idd_isrc; }; @@ -495,8 +495,10 @@ static struct intr_dev_data * intr_ddata_alloc(u_int extsize) { struct intr_dev_data *ddata; + size_t size; - ddata = malloc(sizeof(*ddata) + extsize, M_INTRNG, M_WAITOK | M_ZERO); + size = sizeof(*ddata); + ddata = malloc(size + extsize, M_INTRNG, M_WAITOK | M_ZERO); mtx_lock(&isrc_table_lock); if (intr_ddata_first_unused >= nitems(intr_ddata_tab)) { @@ -507,6 +509,9 @@ intr_ddata_alloc(u_int extsize) intr_ddata_tab[intr_ddata_first_unused] = ddata; ddata->idd_irq = IRQ_DDATA_BASE + intr_ddata_first_unused++; mtx_unlock(&isrc_table_lock); + + ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size); + ddata->idd_data->size = size; return (ddata); } @@ -534,13 +539,13 @@ intr_ddata_lookup(u_int irq, struct intr_map_data **datap) ddata = intr_ddata_tab[irq]; if (ddata->idd_isrc == NULL) { error = intr_map_irq(ddata->idd_dev, ddata->idd_xref, - &ddata->idd_data, &irq); + ddata->idd_data, &irq); if (error != 0) return (NULL); ddata->idd_isrc = isrc_lookup(irq); } if (datap != NULL) - *datap = &ddata->idd_data; + *datap = ddata->idd_data; return (ddata->idd_isrc); } @@ -554,17 +559,21 @@ u_int intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol, enum intr_trigger trig) { + struct intr_map_data_acpi *daa; struct intr_dev_data *ddata; - ddata = intr_ddata_alloc(0); + ddata = intr_ddata_alloc(sizeof(struct intr_map_data_acpi)); if (ddata == NULL) return (INTR_IRQ_INVALID); /* no space left */ ddata->idd_dev = dev; - ddata->idd_data.type = INTR_MAP_DATA_ACPI; - ddata->idd_data.acpi.irq = irq; - ddata->idd_data.acpi.pol = pol; - ddata->idd_data.acpi.trig = trig; + ddata->idd_data->type = INTR_MAP_DATA_ACPI; + + daa = (struct intr_map_data_acpi *)ddata->idd_data; + daa->irq = irq; + daa->pol = pol; + daa->trig = trig; + return (ddata->idd_irq); } #endif @@ -577,19 +586,21 @@ intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol, u_int intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells) { + size_t cellsize; struct intr_dev_data *ddata; - u_int cellsize; + struct intr_map_data_fdt *daf; cellsize = ncells * sizeof(*cells); - ddata = intr_ddata_alloc(cellsize); + ddata = intr_ddata_alloc(sizeof(struct intr_map_data_fdt) + cellsize); if (ddata == NULL) return (INTR_IRQ_INVALID); /* no space left */ ddata->idd_xref = (intptr_t)node; - ddata->idd_data.type = INTR_MAP_DATA_FDT; - ddata->idd_data.fdt.ncells = ncells; - ddata->idd_data.fdt.cells = (pcell_t *)(ddata + 1); - memcpy(ddata->idd_data.fdt.cells, cells, cellsize); + ddata->idd_data->type = INTR_MAP_DATA_FDT; + + daf = (struct intr_map_data_fdt *)ddata->idd_data; + daf->ncells = ncells; + memcpy(daf->cells, cells, cellsize); return (ddata->idd_irq); } #endif @@ -602,16 +613,19 @@ u_int intr_gpio_map_irq(device_t dev, u_int pin_num, u_int pin_flags, u_int intr_mode) { struct intr_dev_data *ddata; + struct intr_map_data_gpio *dag; - ddata = intr_ddata_alloc(0); + ddata = intr_ddata_alloc(sizeof(struct intr_map_data_gpio)); if (ddata == NULL) return (INTR_IRQ_INVALID); /* no space left */ ddata->idd_dev = dev; - ddata->idd_data.type = INTR_MAP_DATA_GPIO; - ddata->idd_data.gpio.gpio_pin_num = pin_num; - ddata->idd_data.gpio.gpio_pin_flags = pin_flags; - ddata->idd_data.gpio.gpio_intr_mode = intr_mode; + ddata->idd_data->type = INTR_MAP_DATA_GPIO; + + dag = (struct intr_map_data_gpio *)ddata->idd_data; + dag->gpio_pin_num = pin_num; + dag->gpio_pin_flags = pin_flags; + dag->gpio_intr_mode = intr_mode; return (ddata->idd_irq); } diff --git a/sys/mips/mediatek/mtk_gpio_v1.c b/sys/mips/mediatek/mtk_gpio_v1.c index 5499263..ec56360 100644 --- a/sys/mips/mediatek/mtk_gpio_v1.c +++ b/sys/mips/mediatek/mtk_gpio_v1.c @@ -514,15 +514,19 @@ static int mtk_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct mtk_gpio_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 1 || data->fdt.cells[0] >= sc->num_pins) + if (daf->ncells != 1 || daf->cells[0] >= sc->num_pins) return (EINVAL); - *isrcp = PIC_INTR_ISRC(sc, data->fdt.cells[0]); + *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); return (0); } diff --git a/sys/mips/mediatek/mtk_gpio_v2.c b/sys/mips/mediatek/mtk_gpio_v2.c index c7c0326..66236cc 100644 --- a/sys/mips/mediatek/mtk_gpio_v2.c +++ b/sys/mips/mediatek/mtk_gpio_v2.c @@ -511,15 +511,19 @@ static int mtk_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { + struct intr_map_data_fdt *daf; struct mtk_gpio_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 1 || data->fdt.cells[0] >= sc->num_pins) + if (daf->ncells != 1 || daf->cells[0] >= sc->num_pins) return (EINVAL); - *isrcp = PIC_INTR_ISRC(sc, data->fdt.cells[0]); + *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); return (0); } diff --git a/sys/mips/mediatek/mtk_intr_gic.c b/sys/mips/mediatek/mtk_intr_gic.c index 5c25045..ea8c887 100644 --- a/sys/mips/mediatek/mtk_intr_gic.c +++ b/sys/mips/mediatek/mtk_intr_gic.c @@ -265,18 +265,22 @@ mtk_gic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { #ifdef FDT + struct intr_map_data_fdt *daf; struct mtk_gic_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 3 || data->fdt.cells[1] >= sc->nirqs) + if (daf->ncells != 3 || daf->cells[1] >= sc->nirqs) return (EINVAL); - *isrcp = GIC_INTR_ISRC(sc, data->fdt.cells[1]); + *isrcp = GIC_INTR_ISRC(sc, daf->cells[1]); return (0); #else - return (EINVAL); + return (ENOTSUP); #endif } diff --git a/sys/mips/mediatek/mtk_intr_v1.c b/sys/mips/mediatek/mtk_intr_v1.c index f1ae3a2..58b610d 100644 --- a/sys/mips/mediatek/mtk_intr_v1.c +++ b/sys/mips/mediatek/mtk_intr_v1.c @@ -275,18 +275,22 @@ mtk_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { #ifdef FDT + struct intr_map_data_fdt *daf; struct mtk_pic_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 1 || data->fdt.cells[0] >= sc->nirqs) + if (daf->ncells != 1 || daf->cells[0] >= sc->nirqs) return (EINVAL); - *isrcp = PIC_INTR_ISRC(sc, data->fdt.cells[0]); + *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); return (0); #else - return (EINVAL); + return (ENOTSUP); #endif } diff --git a/sys/mips/mediatek/mtk_intr_v2.c b/sys/mips/mediatek/mtk_intr_v2.c index 5a9646e..556738f 100644 --- a/sys/mips/mediatek/mtk_intr_v2.c +++ b/sys/mips/mediatek/mtk_intr_v2.c @@ -270,18 +270,22 @@ mtk_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { #ifdef FDT + struct intr_map_data_fdt *daf; struct mtk_pic_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 1 || data->fdt.cells[0] >= sc->nirqs) + if (daf->ncells != 1 || daf->cells[0] >= sc->nirqs) return (EINVAL); - *isrcp = PIC_INTR_ISRC(sc, data->fdt.cells[0]); + *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); return (0); #else - return (EINVAL); + return (ENOTSUP); #endif } diff --git a/sys/mips/mips/mips_pic.c b/sys/mips/mips/mips_pic.c index a24647d..9b7eeb0 100644 --- a/sys/mips/mips/mips_pic.c +++ b/sys/mips/mips/mips_pic.c @@ -305,18 +305,22 @@ mips_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { #ifdef FDT + struct intr_map_data_fdt *daf; struct mips_pic_softc *sc; + if (data->type != INTR_MAP_DATA_FDT) + return (ENOTSUP); + sc = device_get_softc(dev); + daf = (struct intr_map_data_fdt *)data; - if (data == NULL || data->type != INTR_MAP_DATA_FDT || - data->fdt.ncells != 1 || data->fdt.cells[0] >= sc->nirqs) + if (daf->ncells != 1 || daf->cells[0] >= sc->nirqs) return (EINVAL); - *isrcp = PIC_INTR_ISRC(sc, data->fdt.cells[0]); + *isrcp = PIC_INTR_ISRC(sc, daf->cells[0]); return (0); #else - return (EINVAL); + return (ENOTSUP); #endif } diff --git a/sys/sys/intr.h b/sys/sys/intr.h index 7d309f5..e1e2a22 100644 --- a/sys/sys/intr.h +++ b/sys/sys/intr.h @@ -40,8 +40,14 @@ enum intr_map_data_type { INTR_MAP_DATA_GPIO, }; +struct intr_map_data { + enum intr_map_data_type type; + size_t size; +}; + #ifdef DEV_ACPI struct intr_map_data_acpi { + struct intr_map_data hdr; u_int irq; enum intr_polarity pol; enum intr_trigger trig; @@ -49,30 +55,19 @@ struct intr_map_data_acpi { #endif #ifdef FDT struct intr_map_data_fdt { - u_int ncells; - pcell_t *cells; + struct intr_map_data hdr; + u_int ncells; + pcell_t cells[0]; }; #endif struct intr_map_data_gpio { + struct intr_map_data hdr; u_int gpio_pin_num; u_int gpio_pin_flags; u_int gpio_intr_mode; }; -struct intr_map_data { - enum intr_map_data_type type; - union { -#ifdef DEV_ACPI - struct intr_map_data_acpi acpi; -#endif -#ifdef FDT - struct intr_map_data_fdt fdt; -#endif - struct intr_map_data_gpio gpio; - }; -}; - #ifdef notyet #define INTR_SOLO INTR_MD1 typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); -- cgit v1.1 From 229f59004efd5514c40b23e3e6a5dd5d5dda54fd Mon Sep 17 00:00:00 2001 From: br Date: Thu, 5 May 2016 13:54:50 +0000 Subject: Implement FBT provider (MD part) for DTrace on MIPS. Tested on MIPS64. Sponsored by: DARPA, AFRL Sponsored by: HEIF5 --- .../contrib/opensolaris/uts/common/sys/dtrace.h | 12 ++ sys/cddl/dev/dtrace/mips/dtrace_asm.S | 23 --- sys/cddl/dev/dtrace/mips/dtrace_subr.c | 87 ++++++++++- sys/cddl/dev/fbt/mips/fbt_isa.c | 165 +++++++++++++++++++++ sys/cddl/dev/fbt/mips/fbt_isa.h | 30 ++++ sys/conf/files.mips | 6 + sys/mips/mips/exception.S | 7 - sys/mips/mips/trap.c | 12 +- 8 files changed, 309 insertions(+), 33 deletions(-) create mode 100644 sys/cddl/dev/fbt/mips/fbt_isa.c create mode 100644 sys/cddl/dev/fbt/mips/fbt_isa.h (limited to 'sys') diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index 139a93d..730b423 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -2483,6 +2483,18 @@ extern void dtrace_helpers_destroy(proc_t *); #define DTRACE_INVOP_RET 2 #define DTRACE_INVOP_B 3 +#elif defined(__mips__) + +#define INSN_SIZE 4 + +/* Load/Store double RA to/from SP */ +#define LDSD_RA_SP_MASK 0xffff0000 +#define LDSD_DATA_MASK 0x0000ffff +#define SD_RA_SP 0xffbf0000 +#define LD_RA_SP 0xdfbf0000 + +#define DTRACE_INVOP_SD 1 +#define DTRACE_INVOP_LD 2 #endif #ifdef __cplusplus diff --git a/sys/cddl/dev/dtrace/mips/dtrace_asm.S b/sys/cddl/dev/dtrace/mips/dtrace_asm.S index 199d16be..a3b24aa 100644 --- a/sys/cddl/dev/dtrace/mips/dtrace_asm.S +++ b/sys/cddl/dev/dtrace/mips/dtrace_asm.S @@ -28,7 +28,6 @@ #define _ASM #define _LOCORE -#define LOCORE #include #include @@ -227,28 +226,6 @@ LEAF(dtrace_copystr) END(dtrace_copystr) /* -void dtrace_invop_init(void) -*/ -LEAF(dtrace_invop_init) - /* XXX: impement it properly */ - PTR_LA t0, dtrace_invop_jump_addr - /* dla t1, dtrace_invop_start */ - PTR_S zero, 0(t0) - j ra - nop -END(dtrace_invop_init) - -/* -void dtrace_invop_uninit(void) -*/ -LEAF(dtrace_invop_uninit) - PTR_LA t0, dtrace_invop_jump_addr - PTR_S zero, 0(t0) - j ra - nop -END(dtrace_invop_uninit) - -/* uintptr_t dtrace_caller(int aframes) */ diff --git a/sys/cddl/dev/dtrace/mips/dtrace_subr.c b/sys/cddl/dev/dtrace/mips/dtrace_subr.c index 9702274..1ed3cd0 100644 --- a/sys/cddl/dev/dtrace/mips/dtrace_subr.c +++ b/sys/cddl/dev/dtrace/mips/dtrace_subr.c @@ -45,13 +45,14 @@ __FBSDID("$FreeBSD$"); #include #define DELAYBRANCH(x) ((int)(x) < 0) - + +extern int (*dtrace_invop_jump_addr)(struct trapframe *); extern dtrace_id_t dtrace_probeid_error; int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t); typedef struct dtrace_invop_hdlr { - int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t); + int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t); struct dtrace_invop_hdlr *dtih_next; } dtrace_invop_hdlr_t; @@ -70,6 +71,46 @@ dtrace_invop(uintptr_t addr, struct trapframe *stack, uintptr_t eax) return (0); } +void +dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t)) +{ + dtrace_invop_hdlr_t *hdlr; + + hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP); + hdlr->dtih_func = func; + hdlr->dtih_next = dtrace_invop_hdlr; + dtrace_invop_hdlr = hdlr; +} + +void +dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t)) +{ + dtrace_invop_hdlr_t *hdlr, *prev; + + hdlr = dtrace_invop_hdlr; + prev = NULL; + + for (;;) { + if (hdlr == NULL) + panic("attempt to remove non-existent invop handler"); + + if (hdlr->dtih_func == func) + break; + + prev = hdlr; + hdlr = hdlr->dtih_next; + } + + if (prev == NULL) { + ASSERT(dtrace_invop_hdlr == hdlr); + dtrace_invop_hdlr = hdlr->dtih_next; + } else { + ASSERT(dtrace_invop_hdlr != hdlr); + prev->dtih_next = hdlr->dtih_next; + } + + kmem_free(hdlr, 0); +} /*ARGSUSED*/ void @@ -199,3 +240,45 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, (uintptr_t)epid, (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs); } + +static int +dtrace_invop_start(struct trapframe *frame) +{ + register_t *sp; + int16_t offs; + int invop; + + invop = dtrace_invop(frame->pc, frame, frame->pc); + offs = (invop & LDSD_DATA_MASK); + sp = (register_t *)((uint8_t *)frame->sp + offs); + + switch (invop & LDSD_RA_SP_MASK) { + case LD_RA_SP: + frame->ra = *sp; + frame->pc += INSN_SIZE; + break; + case SD_RA_SP: + *(sp) = frame->ra; + frame->pc += INSN_SIZE; + break; + default: + printf("%s: 0x%x undefined\n", __func__, invop); + return (-1); + }; + + return (0); +} + +void +dtrace_invop_init(void) +{ + + dtrace_invop_jump_addr = dtrace_invop_start; +} + +void +dtrace_invop_uninit(void) +{ + + dtrace_invop_jump_addr = 0; +} diff --git a/sys/cddl/dev/fbt/mips/fbt_isa.c b/sys/cddl/dev/fbt/mips/fbt_isa.c new file mode 100644 index 0000000..a4e9e8b --- /dev/null +++ b/sys/cddl/dev/fbt/mips/fbt_isa.c @@ -0,0 +1,165 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Portions Copyright 2006-2008 John Birrell jb@freebsd.org + * Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org + * Portions Copyright 2013 Howard Su howardsu@freebsd.org + * Portions Copyright 2015-2016 Ruslan Bukin + * + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include + +#include +#include + +#include "fbt.h" + +#define FBT_PATCHVAL (MIPS_BREAK_INSTR) +#define FBT_ENTRY "entry" +#define FBT_RETURN "return" + +int +fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval) +{ + solaris_cpu_t *cpu; + fbt_probe_t *fbt; + + cpu = &solaris_cpu[curcpu]; + fbt = fbt_probetab[FBT_ADDR2NDX(addr)]; + + for (; fbt != NULL; fbt = fbt->fbtp_hashnext) { + if ((uintptr_t)fbt->fbtp_patchpoint == addr) { + cpu->cpu_dtrace_caller = addr; + + dtrace_probe(fbt->fbtp_id, frame->a0, + frame->a1, frame->a2, + frame->a3, frame->a4); + + cpu->cpu_dtrace_caller = 0; + return (fbt->fbtp_savedval); + } + } + + return (0); +} + +void +fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val) +{ + + *fbt->fbtp_patchpoint = val; + mips_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4); +} + +int +fbt_provide_module_function(linker_file_t lf, int symindx, + linker_symval_t *symval, void *opaque) +{ + fbt_probe_t *fbt, *retfbt; + uint32_t *target, *start; + uint32_t *instr, *limit; + const char *name; + char *modname; + + modname = opaque; + name = symval->name; + + /* Check if function is excluded from instrumentation */ + if (fbt_excluded(name)) + return (0); + + instr = (uint32_t *)(symval->value); + limit = (uint32_t *)(symval->value + symval->size); + + /* Look for store double to ra register */ + for (; instr < limit; instr++) { + if ((*instr & LDSD_RA_SP_MASK) == SD_RA_SP) + break; + } + + if (instr >= limit) + return (0); + + fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); + fbt->fbtp_name = name; + fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, + name, FBT_ENTRY, 3, fbt); + fbt->fbtp_patchpoint = instr; + fbt->fbtp_ctl = lf; + fbt->fbtp_loadcnt = lf->loadcnt; + fbt->fbtp_savedval = *instr; + fbt->fbtp_patchval = FBT_PATCHVAL; + fbt->fbtp_rval = DTRACE_INVOP_SD; + fbt->fbtp_symindx = symindx; + + fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; + fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; + + lf->fbt_nentries++; + + retfbt = NULL; +again: + for (; instr < limit; instr++) { + if ((*instr & LDSD_RA_SP_MASK) == LD_RA_SP) { + break; + } + } + + if (instr >= limit) + return (0); + + /* + * We have a winner! + */ + fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); + fbt->fbtp_name = name; + if (retfbt == NULL) { + fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, + name, FBT_RETURN, 3, fbt); + } else { + retfbt->fbtp_next = fbt; + fbt->fbtp_id = retfbt->fbtp_id; + } + retfbt = fbt; + + fbt->fbtp_patchpoint = instr; + fbt->fbtp_ctl = lf; + fbt->fbtp_loadcnt = lf->loadcnt; + fbt->fbtp_symindx = symindx; + fbt->fbtp_rval = DTRACE_INVOP_LD; + fbt->fbtp_savedval = *instr; + fbt->fbtp_patchval = FBT_PATCHVAL; + fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; + fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; + + lf->fbt_nentries++; + + instr++; + goto again; +} diff --git a/sys/cddl/dev/fbt/mips/fbt_isa.h b/sys/cddl/dev/fbt/mips/fbt_isa.h new file mode 100644 index 0000000..5552f31 --- /dev/null +++ b/sys/cddl/dev/fbt/mips/fbt_isa.h @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + * + */ + +#ifndef _FBT_ISA_H_ +#define _FBT_ISA_H_ + +typedef uint32_t fbt_patchval_t; + +#endif diff --git a/sys/conf/files.mips b/sys/conf/files.mips index 4cacac4..0fe0795 100644 --- a/sys/conf/files.mips +++ b/sys/conf/files.mips @@ -95,3 +95,9 @@ dev/hwpmc/hwpmc_mips74k.c optional hwpmc_mips74k # ofw support dev/ofw/ofwpci.c optional fdt pci + +# DTrace +cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/dev/dtrace/mips/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" +cddl/dev/dtrace/mips/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" +cddl/dev/fbt/mips/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S index ed02e5a..725ae65 100644 --- a/sys/mips/mips/exception.S +++ b/sys/mips/mips/exception.S @@ -69,13 +69,6 @@ #ifdef KDTRACE_HOOKS .data - .globl dtrace_invop_jump_addr - .align 4 - .type dtrace_invop_jump_addr, @object - .size dtrace_invop_jump_addr, 8 -dtrace_invop_jump_addr: - .word 0 - .word 0 .globl dtrace_invop_calltrap_addr .align 4 .type dtrace_invop_calltrap_addr, @object diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index f3ef629..f98fc97 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -160,6 +160,8 @@ static void log_bad_page_fault(char *, struct trapframe *, int); static void log_frame_dump(struct trapframe *frame); static void get_mapping_info(vm_offset_t, pd_entry_t **, pt_entry_t **); +int (*dtrace_invop_jump_addr)(struct trapframe *); + #ifdef TRAP_DEBUG static void trap_frame_dump(struct trapframe *frame); #endif @@ -808,11 +810,19 @@ dofault: return (trapframe->pc); } -#ifdef DDB +#if defined(KDTRACE_HOOKS) || defined(DDB) case T_BREAK: +#ifdef KDTRACE_HOOKS + if (!usermode && dtrace_invop_jump_addr != 0) { + dtrace_invop_jump_addr(trapframe); + return (trapframe->pc); + } +#endif +#ifdef DDB kdb_trap(type, 0, trapframe); return (trapframe->pc); #endif +#endif case T_BREAK + T_USER: { -- cgit v1.1 From a846752fb2cbbd763183a6e9939a23972929942f Mon Sep 17 00:00:00 2001 From: emaste Date: Thu, 5 May 2016 15:07:40 +0000 Subject: bhnd: fix build on gcc architectures "make tinderbox" fails on sparc64 GENERIC-NODEBUG with: bhnd_subr.c:188: warning: control reaches end of non-void function Sponsored by: The FreeBSD Foundation --- sys/dev/bhnd/bhnd_subr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sys') diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c index 1d5557b..5f92e9d 100644 --- a/sys/dev/bhnd/bhnd_subr.c +++ b/sys/dev/bhnd/bhnd_subr.c @@ -184,6 +184,8 @@ bhnd_port_type_name(bhnd_port_type port_type) return ("bridge"); case BHND_PORT_AGENT: return ("agent"); + default: + return "unknown"; } } -- cgit v1.1 From d0cc83784b0bf94c11cc731fa163477e424b3c72 Mon Sep 17 00:00:00 2001 From: emaste Date: Thu, 5 May 2016 15:21:33 +0000 Subject: Add explicit cast to fix mips and powerpc build after r299090 Sponsored by: The FreeBSD Foundation --- sys/kern/subr_unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/kern/subr_unit.c b/sys/kern/subr_unit.c index f39f001..9da9160 100644 --- a/sys/kern/subr_unit.c +++ b/sys/kern/subr_unit.c @@ -1026,7 +1026,7 @@ main(int argc, char **argv) printf("sizeof(struct unr) %zu\n", sizeof(struct unr)); printf("sizeof(struct unrb) %zu\n", sizeof(struct unrb)); printf("sizeof(struct unrhdr) %zu\n", sizeof(struct unrhdr)); - printf("NBITS %lu\n", NBITS); + printf("NBITS %lu\n", (unsigned long)NBITS); x = 1; for (m = 0; m < count * reps; m++) { j = random(); -- cgit v1.1 From dd1669b9149d66a6a92446416bc4f0ba990fd311 Mon Sep 17 00:00:00 2001 From: asomers Date: Thu, 5 May 2016 15:32:47 +0000 Subject: mpr(4) and mps(4) shouldn't indefinitely retry for "terminated ioc" errors Submitted by: ken Reviewed by: slm MFC after: 4 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D6210 --- sys/dev/mpr/mpr_sas.c | 17 +++++++++++++---- sys/dev/mps/mps_sas.c | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index eac3360..dc9a62e 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -2465,11 +2465,20 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: /* - * Since these are generally external (i.e. hopefully - * transient transport-related) errors, retry these without - * decrementing the retry count. + * These can sometimes be transient transport-related + * errors, and sometimes persistent drive-related errors. + * We used to retry these without decrementing the retry + * count by returning CAM_REQUEUE_REQ. Unfortunately, if + * we hit a persistent drive problem that returns one of + * these error codes, we would retry indefinitely. So, + * return CAM_REQ_CMP_ERROR so that we decrement the retry + * count and avoid infinite retries. We're taking the + * potential risk of flagging false failures in the event + * of a topology-related error (e.g. a SAS expander problem + * causes a command addressed to a drive to fail), but + * avoiding getting into an infinite retry loop. */ - mprsas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); + mprsas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); mprsas_log_command(cm, MPR_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index a4dd3e1..3790e8f 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -2408,11 +2408,20 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: /* - * Since these are generally external (i.e. hopefully - * transient transport-related) errors, retry these without - * decrementing the retry count. + * These can sometimes be transient transport-related + * errors, and sometimes persistent drive-related errors. + * We used to retry these without decrementing the retry + * count by returning CAM_REQUEUE_REQ. Unfortunately, if + * we hit a persistent drive problem that returns one of + * these error codes, we would retry indefinitely. So, + * return CAM_REQ_CMP_ERROR so that we decrement the retry + * count and avoid infinite retries. We're taking the + * potential risk of flagging false failures in the event + * of a topology-related error (e.g. a SAS expander problem + * causes a command addressed to a drive to fail), but + * avoiding getting into an infinite retry loop. */ - mpssas_set_ccbstatus(ccb, CAM_REQUEUE_REQ); + mpssas_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); mpssas_log_command(cm, MPS_INFO, "terminated ioc %x scsi %x state %x xfer %u\n", le16toh(rep->IOCStatus), rep->SCSIStatus, rep->SCSIState, -- cgit v1.1 From 469bc5c41441a4733c0bdb31f842c9ffccbf8048 Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 5 May 2016 15:43:26 +0000 Subject: Fix and to not require . - Hardcode '8' instead of NBBY in _BITSET_BITS. - Define a private version of 'howmany' for use in __bitset_words(). - While here, move a few more things out of _bitset.h and _cpuset.h to bitset.h and cpuset.h, respectively. The only things left in _bitset.h and _cpuset.h are the bits needed to define a bitset structure. Reviewed by: bde, kib (ish) --- sys/arm/arm/genassym.c | 1 + sys/sys/_bitset.h | 17 +++-------------- sys/sys/_cpuset.h | 6 ------ sys/sys/bitset.h | 15 ++++++++++++++- sys/sys/cpuset.h | 6 ++++++ 5 files changed, 24 insertions(+), 21 deletions(-) (limited to 'sys') diff --git a/sys/arm/arm/genassym.c b/sys/arm/arm/genassym.c index f9cb23e..9c67018 100644 --- a/sys/arm/arm/genassym.c +++ b/sys/arm/arm/genassym.c @@ -28,6 +28,7 @@ #include __FBSDID("$FreeBSD$"); #include +#include #include #include #include diff --git a/sys/sys/_bitset.h b/sys/sys/_bitset.h index 26a8848..86cf539 100644 --- a/sys/sys/_bitset.h +++ b/sys/sys/_bitset.h @@ -36,26 +36,15 @@ * Macros addressing word and bit within it, tuned to make compiler * optimize cases when SETSIZE fits into single machine word. */ -#define _BITSET_BITS (sizeof(long) * NBBY) +#define _BITSET_BITS (sizeof(long) * 8) -#define __bitset_words(_s) (howmany(_s, _BITSET_BITS)) +#define __howmany(x, y) (((x) + ((y) - 1)) / (y)) -#define __bitset_mask(_s, n) \ - (1L << ((__bitset_words((_s)) == 1) ? \ - (__size_t)(n) : ((n) % _BITSET_BITS))) - -#define __bitset_word(_s, n) \ - ((__bitset_words((_s)) == 1) ? 0 : ((n) / _BITSET_BITS)) +#define __bitset_words(_s) (__howmany(_s, _BITSET_BITS)) #define BITSET_DEFINE(t, _s) \ struct t { \ long __bits[__bitset_words((_s))]; \ } -#define BITSET_T_INITIALIZER(x) \ - { .__bits = { x } } - -#define BITSET_FSET(n) \ - [ 0 ... ((n) - 1) ] = (-1L) - #endif /* !_SYS__BITSET_H_ */ diff --git a/sys/sys/_cpuset.h b/sys/sys/_cpuset.h index cd384848..1ddafac 100644 --- a/sys/sys/_cpuset.h +++ b/sys/sys/_cpuset.h @@ -44,13 +44,7 @@ #define CPU_SETSIZE CPU_MAXSIZE #endif -#define _NCPUBITS _BITSET_BITS -#define _NCPUWORDS __bitset_words(CPU_SETSIZE) - BITSET_DEFINE(_cpuset, CPU_SETSIZE); typedef struct _cpuset cpuset_t; -#define CPUSET_FSET BITSET_FSET(_NCPUWORDS) -#define CPUSET_T_INITIALIZER BITSET_T_INITIALIZER - #endif /* !_SYS__CPUSET_H_ */ diff --git a/sys/sys/bitset.h b/sys/sys/bitset.h index d130522..f1c7bf8 100644 --- a/sys/sys/bitset.h +++ b/sys/sys/bitset.h @@ -32,6 +32,13 @@ #ifndef _SYS_BITSET_H_ #define _SYS_BITSET_H_ +#define __bitset_mask(_s, n) \ + (1L << ((__bitset_words((_s)) == 1) ? \ + (__size_t)(n) : ((n) % _BITSET_BITS))) + +#define __bitset_word(_s, n) \ + ((__bitset_words((_s)) == 1) ? 0 : ((n) / _BITSET_BITS)) + #define BIT_CLR(_s, n, p) \ ((p)->__bits[__bitset_word(_s, n)] &= ~__bitset_mask((_s), (n))) @@ -185,5 +192,11 @@ __count += __bitcountl((p)->__bits[__i]); \ __count; \ }) - + +#define BITSET_T_INITIALIZER(x) \ + { .__bits = { x } } + +#define BITSET_FSET(n) \ + [ 0 ... ((n) - 1) ] = (-1L) + #endif /* !_SYS_BITSET_H_ */ diff --git a/sys/sys/cpuset.h b/sys/sys/cpuset.h index 4fa55a9..e017883 100644 --- a/sys/sys/cpuset.h +++ b/sys/sys/cpuset.h @@ -35,6 +35,10 @@ #include #include +#include + +#define _NCPUBITS _BITSET_BITS +#define _NCPUWORDS __bitset_words(CPU_SETSIZE) #define CPUSETBUFSIZ ((2 + sizeof(long) * 2) * _NCPUWORDS) @@ -61,6 +65,8 @@ #define CPU_COPY_STORE_REL(f, t) BIT_COPY_STORE_REL(CPU_SETSIZE, f, t) #define CPU_FFS(p) BIT_FFS(CPU_SETSIZE, p) #define CPU_COUNT(p) BIT_COUNT(CPU_SETSIZE, p) +#define CPUSET_FSET BITSET_FSET(_NCPUWORDS) +#define CPUSET_T_INITIALIZER BITSET_T_INITIALIZER /* * Valid cpulevel_t values. -- cgit v1.1 From b01f61207a7838e23d83e03418d45f45d0374dcd Mon Sep 17 00:00:00 2001 From: emaste Date: Thu, 5 May 2016 17:47:03 +0000 Subject: bhnd: another build fix for GCC-using architectures Further to r299119. GCC architectures failed with bcma_subr.c:138: warning: control reaches end of non-void function Sponsored by: The FreeBSD Foundation --- sys/dev/bhnd/bcma/bcma_subr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sys') diff --git a/sys/dev/bhnd/bcma/bcma_subr.c b/sys/dev/bhnd/bcma/bcma_subr.c index 53d7564..c493f9c 100644 --- a/sys/dev/bhnd/bcma/bcma_subr.c +++ b/sys/dev/bhnd/bcma/bcma_subr.c @@ -134,6 +134,8 @@ bcma_corecfg_get_port_list(struct bcma_corecfg *cfg, bhnd_port_type type) case BHND_PORT_AGENT: return (&cfg->wrapper_ports); break; + default: + return (NULL); } } -- cgit v1.1 From 726fcfebaba27d4673ab531ae33234ce097787cc Mon Sep 17 00:00:00 2001 From: zbb Date: Thu, 5 May 2016 17:51:14 +0000 Subject: Fix GICv3 build after r299090 Obtained from: Semihalf Sponsored by: Cavium --- sys/arm64/arm64/gic_v3.c | 1 + sys/arm64/arm64/gic_v3_fdt.c | 1 + sys/arm64/arm64/gic_v3_its.c | 9 +++------ sys/arm64/arm64/gic_v3_var.h | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'sys') diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c index d8434cf..15a51a3 100644 --- a/sys/arm64/arm64/gic_v3.c +++ b/sys/arm64/arm64/gic_v3.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/arm64/arm64/gic_v3_fdt.c b/sys/arm64/arm64/gic_v3_fdt.c index e5d75c3..3f21fee 100644 --- a/sys/arm64/arm64/gic_v3_fdt.c +++ b/sys/arm64/arm64/gic_v3_fdt.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include diff --git a/sys/arm64/arm64/gic_v3_its.c b/sys/arm64/arm64/gic_v3_its.c index c830c99..5dd56cf 100644 --- a/sys/arm64/arm64/gic_v3_its.c +++ b/sys/arm64/arm64/gic_v3_its.c @@ -852,7 +852,7 @@ lpi_alloc_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic, { u_int *col_ids; int fclr; /* First cleared bit */ - uint8_t *bitmap; + bitstr_t *bitmap; size_t nb, i; col_ids = malloc(sizeof(*col_ids) * nvecs, M_GIC_V3_ITS, @@ -861,7 +861,7 @@ lpi_alloc_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic, return (ENOMEM); mtx_lock_spin(&sc->its_dev_lock); - bitmap = (uint8_t *)sc->its_lpi_bitmap; + bitmap = sc->its_lpi_bitmap; fclr = 0; retry: @@ -901,9 +901,6 @@ static void lpi_free_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic) { int start, end; - uint8_t *bitmap; - - bitmap = (uint8_t *)sc->its_lpi_bitmap; KASSERT((lpic->lpi_free == lpic->lpi_num), ("Trying to free LPI chunk that is still in use.\n")); @@ -915,7 +912,7 @@ lpi_free_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic) end = start + lpic->lpi_num - 1; /* Finally free this chunk */ - bit_nclear(bitmap, start, end); + bit_nclear(sc->its_lpi_bitmap, start, end); mtx_unlock_spin(&sc->its_dev_lock); free(lpic->lpi_col_ids, M_GIC_V3_ITS); diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h index b3c0e52..2e780c3 100644 --- a/sys/arm64/arm64/gic_v3_var.h +++ b/sys/arm64/arm64/gic_v3_var.h @@ -236,7 +236,7 @@ struct gic_v3_its_softc { struct its_dev_list its_dev_list; - unsigned long * its_lpi_bitmap; + bitstr_t * its_lpi_bitmap; uint32_t its_lpi_maxid; struct mtx its_dev_lock; -- cgit v1.1 From fcf205eab33d36c7cb0137556705c9c312162f56 Mon Sep 17 00:00:00 2001 From: zeising Date: Thu, 5 May 2016 17:55:10 +0000 Subject: Fix kernel build with parallel make. Approved by: jhb --- sys/modules/bhnd/bhndb_pci/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/modules/bhnd/bhndb_pci/Makefile b/sys/modules/bhnd/bhndb_pci/Makefile index a327aa5..75621c5 100644 --- a/sys/modules/bhnd/bhndb_pci/Makefile +++ b/sys/modules/bhnd/bhndb_pci/Makefile @@ -6,6 +6,6 @@ KMOD= bhndb_pci SRCS= bhndb_pci.c bhndb_pci_hwdata.c SRCS+= bhnd_bus_if.h bhndb_bus_if.h bhndb_if.h -SRCS+= device_if.h bus_if.h +SRCS+= device_if.h bus_if.h pci_if.h .include -- cgit v1.1 From 22076bc3305d5a6dc31063d324769c3e9fb60a27 Mon Sep 17 00:00:00 2001 From: jkim Date: Thu, 5 May 2016 18:43:31 +0000 Subject: Fix intmax_t to uintptr_t casting on 32-bit platforms. Found by GCC. Submitted by: bde --- sys/dev/acpica/acpi_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c index 4acf3c4..dab1ac9 100644 --- a/sys/dev/acpica/acpi_thermal.c +++ b/sys/dev/acpica/acpi_thermal.c @@ -785,7 +785,7 @@ acpi_tz_temp_sysctl(SYSCTL_HANDLER_ARGS) int error; sc = oidp->oid_arg1; - temp_ptr = (int *)((uintptr_t)sc + oidp->oid_arg2); + temp_ptr = (int *)(void *)(uintptr_t)((uintptr_t)sc + oidp->oid_arg2); temp = *temp_ptr; error = sysctl_handle_int(oidp, &temp, 0, req); @@ -814,7 +814,7 @@ acpi_tz_passive_sysctl(SYSCTL_HANDLER_ARGS) int error; sc = oidp->oid_arg1; - val_ptr = (int *)((uintptr_t)sc + oidp->oid_arg2); + val_ptr = (int *)(void *)(uintptr_t)((uintptr_t)sc + oidp->oid_arg2); val = *val_ptr; error = sysctl_handle_int(oidp, &val, 0, req); -- cgit v1.1 From 251aa10f1cf344e390e84868f3c4627d803c622f Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 19:30:14 +0000 Subject: [bhnd] handle unknown port type. Reported by: emaste --- sys/dev/bhnd/bcma/bcma.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sys') diff --git a/sys/dev/bhnd/bcma/bcma.c b/sys/dev/bhnd/bcma/bcma.c index f1387e7..987eee2 100644 --- a/sys/dev/bhnd/bcma/bcma.c +++ b/sys/dev/bhnd/bcma/bcma.c @@ -251,6 +251,11 @@ bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type) return (dinfo->corecfg->num_bridge_ports); case BHND_PORT_AGENT: return (dinfo->corecfg->num_wrapper_ports); + default: + device_printf(dev, "%s: unknown type (%d)\n", + __func__, + type); + return (0); } } -- cgit v1.1 From b53c7f24e6aa6063f3ae52e7c4be3c5545323759 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 19:38:53 +0000 Subject: [bhnd] quieten gcc warning. --- sys/dev/bhnd/bhndb/bhndb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sys') diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index e2914a9..0d5f661 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -867,6 +867,9 @@ bhndb_get_rman(struct bhndb_softc *sc, device_t child, int type) return (NULL); }; } + + /* Quieten gcc */ + return (NULL); } /** -- cgit v1.1 From 998c7a9b2387c679147094a410bca56aada0b193 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 19:40:26 +0000 Subject: [bwn] fix signed-ness of the rssi parameter. It's a uint8_t from the hardware. Found by: gcc --- sys/dev/bwn/if_bwn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 550f334..4cddf8d 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -5434,7 +5434,7 @@ bwn_hwrate2ieeerate(int rate) * Valid for A, B, G, LP PHYs. */ static int8_t -bwn_rx_rssi_calc(struct bwn_mac *mac, int8_t in_rssi, +bwn_rx_rssi_calc(struct bwn_mac *mac, uint8_t in_rssi, int ofdm, int adjust_2053, int adjust_2050) { struct bwn_phy *phy = &mac->mac_phy; -- cgit v1.1 From 67670e1f19663a78fd3f925adbb7fcca210762f9 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 19:54:17 +0000 Subject: [bhnd] handle unknown bhnd port type. --- sys/dev/bhnd/siba/siba_subr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/bhnd/siba/siba_subr.c b/sys/dev/bhnd/siba/siba_subr.c index 555c603..e688006 100644 --- a/sys/dev/bhnd/siba/siba_subr.c +++ b/sys/dev/bhnd/siba/siba_subr.c @@ -187,6 +187,11 @@ siba_dinfo_get_port(struct siba_devinfo *dinfo, bhnd_port_type port_type, return (NULL); case BHND_PORT_AGENT: return (NULL); + default: + printf("%s: unknown port_type (%d)\n", + __func__, + port_type); + return (NULL); } } @@ -369,4 +374,4 @@ siba_parse_admatch(uint32_t am, uint32_t *addr, uint32_t *size) } return (0); -} \ No newline at end of file +} -- cgit v1.1 From 23979c2ef7b7af1eaa15474976fc7078fe9186ad Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 19:55:16 +0000 Subject: [bhnd] default to BUS_PROBE_DEFAULT for unknown BHND classes. Found by: gcc-4.2 --- sys/dev/bhnd/bhnd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sys') diff --git a/sys/dev/bhnd/bhnd.c b/sys/dev/bhnd/bhnd.c index 01911f63..88b75ad 100644 --- a/sys/dev/bhnd/bhnd.c +++ b/sys/dev/bhnd/bhnd.c @@ -351,6 +351,8 @@ bhnd_generic_get_probe_order(device_t dev, device_t child) return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY); return (BHND_PROBE_DEFAULT); + default: + return (BHND_PROBE_DEFAULT); } } -- cgit v1.1 From fa522a56a9895ea777233ca5af1045cb2220c1e1 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 19:56:18 +0000 Subject: [bhnd] don't use anonymous unions. Found by: gcc-4.2 --- sys/dev/bhnd/bhndb/bhndb.c | 6 ++-- sys/dev/bhnd/bhndb/bhndb.h | 4 +-- sys/dev/bhnd/bhndb/bhndb_pci.c | 4 +-- sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c | 56 +++++++++++++++++++++++------------ sys/dev/bhnd/bhndb/bhndb_subr.c | 18 +++++------ 5 files changed, 53 insertions(+), 35 deletions(-) (limited to 'sys') diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 0d5f661..434a324 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -259,9 +259,9 @@ bhndb_initialize_region_cfg(struct bhndb_softc *sc, device_t *devs, int ndevs, continue; /* Fetch the base address of the mapped port. */ - error = bhnd_get_region_addr(child, - regw->core.port_type, regw->core.port, - regw->core.region, &addr, &size); + error = bhnd_get_region_addr(child, + regw->d.core.port_type, regw->d.core.port, + regw->d.core.region, &addr, &size); if (error) return (error); diff --git a/sys/dev/bhnd/bhndb/bhndb.h b/sys/dev/bhnd/bhndb/bhndb.h index 7ece8ae..366f119 100644 --- a/sys/dev/bhnd/bhndb/bhndb.h +++ b/sys/dev/bhnd/bhndb/bhndb.h @@ -98,7 +98,7 @@ struct bhndb_regwin { struct { bus_size_t cfg_offset; /**< window address config offset. */ } dyn; - }; + } d; }; #define BHNDB_REGWIN_TABLE_END { BHNDB_REGWIN_T_INVALID, 0, 0, { 0, 0 } } @@ -170,4 +170,4 @@ struct bhndb_hw_priority { #define BHNDB_HW_PRIORITY_TABLE_END { {}, BHNDB_PRIORITY_NONE, NULL, 0 } -#endif /* _BHND_BHNDB_H_ */ \ No newline at end of file +#endif /* _BHND_BHNDB_H_ */ diff --git a/sys/dev/bhnd/bhndb/bhndb_pci.c b/sys/dev/bhnd/bhndb/bhndb_pci.c index 847d4be..9b3f260 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pci.c +++ b/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -313,7 +313,7 @@ bhndb_pci_compat_setregwin(struct bhndb_pci_softc *sc, if ((error = bhndb_pci_fast_setregwin(sc, rw, addr))) return (error); - if (pci_read_config(parent, rw->dyn.cfg_offset, 4) == addr) + if (pci_read_config(parent, rw->d.dyn.cfg_offset, 4) == addr) return (0); DELAY(10); @@ -343,7 +343,7 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc, if (addr % rw->win_size != 0) return (EINVAL); - pci_write_config(parent, rw->dyn.cfg_offset, addr, 4); + pci_write_config(parent, rw->d.dyn.cfg_offset, addr, 4); break; default: return (ENODEV); diff --git a/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c b/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c index 0ebb2cb..b2cc58e 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c +++ b/sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c @@ -93,7 +93,9 @@ const struct bhndb_hwcfg bhndb_pci_siba_generic_hwcfg = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, BHNDB_REGWIN_TABLE_END @@ -122,7 +124,9 @@ const struct bhndb_hwcfg bhndb_pci_bcma_generic_hwcfg = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -131,7 +135,7 @@ const struct bhndb_hwcfg bhndb_pci_bcma_generic_hwcfg = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_CCREGS_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -327,7 +331,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v0 = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V0_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V0_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V0_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V0_BAR0_WIN0_CONTROL + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -344,7 +350,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v0 = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V0_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V0_BAR0_PCIREG_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_PCI, .unit = 0, .port = 0, @@ -375,7 +381,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pci = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -392,7 +400,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pci = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_PCIREG_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_PCI, .unit = 0, .port = 0, @@ -407,7 +415,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pci = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_CCREGS_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -439,7 +447,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pcie = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -456,7 +466,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pcie = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_PCIREG_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_PCIE, .unit = 0, .port = 0, @@ -471,7 +481,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pcie = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_CCREGS_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -503,7 +513,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v2 = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V2_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V2_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V2_BAR0_WIN0_CONTROL, + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -512,7 +524,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v2 = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V2_BAR0_WIN1_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_WIN1_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V2_BAR0_WIN1_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V2_BAR0_WIN1_CONTROL, + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -521,7 +535,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v2 = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V2_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_PCIREG_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_PCIE, .unit = 0, .port = 0, @@ -536,7 +550,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v2 = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V2_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_CCREGS_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -568,7 +582,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v3 = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V3_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V3_BAR0_WIN0_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V3_BAR0_WIN0_CONTROL, + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -577,7 +593,9 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v3 = { .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V3_BAR0_WIN1_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_WIN1_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V3_BAR0_WIN1_CONTROL, + .d.dyn = { + .cfg_offset = BHNDB_PCI_V3_BAR0_WIN1_CONTROL, + }, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -586,7 +604,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v3 = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V3_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_PCIREG_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_PCIE, .unit = 0, .port = 0, @@ -601,7 +619,7 @@ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v3 = { .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V3_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_CCREGS_SIZE, - .core = { + .d.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, diff --git a/sys/dev/bhnd/bhndb/bhndb_subr.c b/sys/dev/bhnd/bhndb/bhndb_subr.c index de3ca10..c9dd99c 100644 --- a/sys/dev/bhnd/bhndb/bhndb_subr.c +++ b/sys/dev/bhnd/bhndb/bhndb_subr.c @@ -873,19 +873,19 @@ bhndb_regwin_find_core(const struct bhndb_regwin *table, bhnd_devclass_t class, if (rw->win_type != BHNDB_REGWIN_T_CORE) continue; - if (rw->core.class != class) + if (rw->d.core.class != class) continue; - if (unit != -1 && rw->core.unit != unit) + if (unit != -1 && rw->d.core.unit != unit) continue; - if (rw->core.port_type != port_type) + if (rw->d.core.port_type != port_type) continue; - if (rw->core.port != port) + if (rw->d.core.port != port) continue; - if (rw->core.region != region) + if (rw->d.core.region != region) continue; return (rw); @@ -944,16 +944,16 @@ bhndb_regwin_matches_device(const struct bhndb_regwin *regw, device_t dev) return (false); /* Device class must match */ - if (bhnd_get_class(dev) != regw->core.class) + if (bhnd_get_class(dev) != regw->d.core.class) return (false); /* Device unit must match */ - if (bhnd_get_core_unit(dev) != regw->core.unit) + if (bhnd_get_core_unit(dev) != regw->d.core.unit) return (false); /* The regwin port/region must be defined. */ - if (!bhnd_is_region_valid(dev, regw->core.port_type, regw->core.port, - regw->core.region)) + if (!bhnd_is_region_valid(dev, regw->d.core.port_type, regw->d.core.port, + regw->d.core.region)) { return (false); } -- cgit v1.1 From 59075b268839813ba48a47fcfb3c05955b0839cc Mon Sep 17 00:00:00 2001 From: ae Date: Thu, 5 May 2016 20:15:46 +0000 Subject: Rename find_name_tlv_type() to ipfw_find_name_tlv_type() and make it global. Use it in ip_fw_table.c instead of find_name_tlv() to reduce duplicated code. Obtained from: Yandex LLC Sponsored by: Yandex LLC --- sys/netpfil/ipfw/ip_fw_private.h | 2 ++ sys/netpfil/ipfw/ip_fw_sockopt.c | 6 +++--- sys/netpfil/ipfw/ip_fw_table.c | 45 ++++------------------------------------ 3 files changed, 9 insertions(+), 44 deletions(-) (limited to 'sys') diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 62e1a9a..0a722bd 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -684,6 +684,8 @@ void ipfw_objhash_set_funcs(struct namedobj_instance *ni, int ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, uint32_t etlv, struct named_object **pno); void ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv); +ipfw_obj_ntlv *ipfw_find_name_tlv_type(void *tlvs, int len, uint16_t uidx, + uint32_t etlv); void ipfw_init_obj_rewriter(void); void ipfw_destroy_obj_rewriter(void); void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index c2b9a79..72d40ca 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -4089,8 +4089,8 @@ ipfw_objhash_lookup_name(struct namedobj_instance *ni, uint32_t set, char *name) * * Returns pointer to found TLV or NULL. */ -static ipfw_obj_ntlv * -find_name_tlv_type(void *tlvs, int len, uint16_t uidx, uint32_t etlv) +ipfw_obj_ntlv * +ipfw_find_name_tlv_type(void *tlvs, int len, uint16_t uidx, uint32_t etlv) { ipfw_obj_ntlv *ntlv; uintptr_t pa, pe; @@ -4145,7 +4145,7 @@ ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, if (ti->tlvs == NULL) return (EINVAL); - ntlv = find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, etlv); + ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, etlv); if (ntlv == NULL) return (EINVAL); name = ntlv->name; diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 2bb70d6..060fd94 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -1879,7 +1879,6 @@ create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3, /* * Creates new table based on @ti and @aname. * - * Relies on table name checking inside find_name_tlv() * Assume @aname to be checked and valid. * Stores allocated table kidx inside @pkidx (if non-NULL). * Reference created table if @compat is non-zero. @@ -2927,44 +2926,6 @@ check_table_name(const char *name) } /* - * Find tablename TLV by @uid. - * Check @tlvs for valid data inside. - * - * Returns pointer to found TLV or NULL. - */ -static ipfw_obj_ntlv * -find_name_tlv(void *tlvs, int len, uint16_t uidx) -{ - ipfw_obj_ntlv *ntlv; - uintptr_t pa, pe; - int l; - - pa = (uintptr_t)tlvs; - pe = pa + len; - l = 0; - for (; pa < pe; pa += l) { - ntlv = (ipfw_obj_ntlv *)pa; - l = ntlv->head.length; - - if (l != sizeof(*ntlv)) - return (NULL); - - if (ntlv->head.type != IPFW_TLV_TBL_NAME) - continue; - - if (ntlv->idx != uidx) - continue; - - if (check_table_name(ntlv->name) != 0) - return (NULL); - - return (ntlv); - } - - return (NULL); -} - -/* * Finds table config based on either legacy index * or name in ntlv. * Note @ti structure contains unchecked data from userland. @@ -2981,7 +2942,8 @@ find_table_err(struct namedobj_instance *ni, struct tid_info *ti, uint32_t set; if (ti->tlvs != NULL) { - ntlv = find_name_tlv(ti->tlvs, ti->tlen, ti->uidx); + ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, + IPFW_TLV_TBL_NAME); if (ntlv == NULL) return (EINVAL); name = ntlv->name; @@ -3039,7 +3001,8 @@ alloc_table_config(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t set; if (ti->tlvs != NULL) { - ntlv = find_name_tlv(ti->tlvs, ti->tlen, ti->uidx); + ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, + IPFW_TLV_TBL_NAME); if (ntlv == NULL) return (NULL); name = ntlv->name; -- cgit v1.1 From b140a920a4eeb79f8e95860c3bac4664a12f01dc Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 5 May 2016 20:16:58 +0000 Subject: .. delete this; I don't know why this was here. oops! --- sys/dev/bwn/if_bwn.c.c | 6881 ------------------------------------------------ 1 file changed, 6881 deletions(-) delete mode 100644 sys/dev/bwn/if_bwn.c.c (limited to 'sys') diff --git a/sys/dev/bwn/if_bwn.c.c b/sys/dev/bwn/if_bwn.c.c deleted file mode 100644 index f7dc50c..0000000 --- a/sys/dev/bwn/if_bwn.c.c +++ /dev/null @@ -1,6881 +0,0 @@ -/*- - * Copyright (c) 2009-2010 Weongyo Jeong - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * The Broadcom Wireless LAN controller driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0, - "Broadcom driver parameters"); - -/* - * Tunable & sysctl variables. - */ - -#ifdef BWN_DEBUG -static int bwn_debug = 0; -SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0, - "Broadcom debugging printfs"); -#endif - -static int bwn_bfp = 0; /* use "Bad Frames Preemption" */ -SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0, - "uses Bad Frames Preemption"); -static int bwn_bluetooth = 1; -SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0, - "turns on Bluetooth Coexistence"); -static int bwn_hwpctl = 0; -SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0, - "uses H/W power control"); -static int bwn_msi_disable = 0; /* MSI disabled */ -TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable); -static int bwn_usedma = 1; -SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0, - "uses DMA"); -TUNABLE_INT("hw.bwn.usedma", &bwn_usedma); -static int bwn_wme = 1; -SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0, - "uses WME support"); - -static void bwn_attach_pre(struct bwn_softc *); -static int bwn_attach_post(struct bwn_softc *); -static void bwn_sprom_bugfixes(device_t); -static int bwn_init(struct bwn_softc *); -static void bwn_parent(struct ieee80211com *); -static void bwn_start(struct bwn_softc *); -static int bwn_transmit(struct ieee80211com *, struct mbuf *); -static int bwn_attach_core(struct bwn_mac *); -static int bwn_phy_getinfo(struct bwn_mac *, int); -static int bwn_chiptest(struct bwn_mac *); -static int bwn_setup_channels(struct bwn_mac *, int, int); -static void bwn_shm_ctlword(struct bwn_mac *, uint16_t, - uint16_t); -static void bwn_addchannels(struct ieee80211_channel [], int, int *, - const struct bwn_channelinfo *, int); -static int bwn_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void bwn_updateslot(struct ieee80211com *); -static void bwn_update_promisc(struct ieee80211com *); -static void bwn_wme_init(struct bwn_mac *); -static int bwn_wme_update(struct ieee80211com *); -static void bwn_wme_clear(struct bwn_softc *); -static void bwn_wme_load(struct bwn_mac *); -static void bwn_wme_loadparams(struct bwn_mac *, - const struct wmeParams *, uint16_t); -static void bwn_scan_start(struct ieee80211com *); -static void bwn_scan_end(struct ieee80211com *); -static void bwn_set_channel(struct ieee80211com *); -static struct ieee80211vap *bwn_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void bwn_vap_delete(struct ieee80211vap *); -static void bwn_stop(struct bwn_softc *); -static int bwn_core_init(struct bwn_mac *); -static void bwn_core_start(struct bwn_mac *); -static void bwn_core_exit(struct bwn_mac *); -static void bwn_bt_disable(struct bwn_mac *); -static int bwn_chip_init(struct bwn_mac *); -static void bwn_set_txretry(struct bwn_mac *, int, int); -static void bwn_rate_init(struct bwn_mac *); -static void bwn_set_phytxctl(struct bwn_mac *); -static void bwn_spu_setdelay(struct bwn_mac *, int); -static void bwn_bt_enable(struct bwn_mac *); -static void bwn_set_macaddr(struct bwn_mac *); -static void bwn_crypt_init(struct bwn_mac *); -static void bwn_chip_exit(struct bwn_mac *); -static int bwn_fw_fillinfo(struct bwn_mac *); -static int bwn_fw_loaducode(struct bwn_mac *); -static int bwn_gpio_init(struct bwn_mac *); -static int bwn_fw_loadinitvals(struct bwn_mac *); -static int bwn_phy_init(struct bwn_mac *); -static void bwn_set_txantenna(struct bwn_mac *, int); -static void bwn_set_opmode(struct bwn_mac *); -static void bwn_rate_write(struct bwn_mac *, uint16_t, int); -static uint8_t bwn_plcp_getcck(const uint8_t); -static uint8_t bwn_plcp_getofdm(const uint8_t); -static void bwn_pio_init(struct bwn_mac *); -static uint16_t bwn_pio_idx2base(struct bwn_mac *, int); -static void bwn_pio_set_txqueue(struct bwn_mac *, struct bwn_pio_txqueue *, - int); -static void bwn_pio_setupqueue_rx(struct bwn_mac *, - struct bwn_pio_rxqueue *, int); -static void bwn_destroy_queue_tx(struct bwn_pio_txqueue *); -static uint16_t bwn_pio_read_2(struct bwn_mac *, struct bwn_pio_txqueue *, - uint16_t); -static void bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *); -static int bwn_pio_rx(struct bwn_pio_rxqueue *); -static uint8_t bwn_pio_rxeof(struct bwn_pio_rxqueue *); -static void bwn_pio_handle_txeof(struct bwn_mac *, - const struct bwn_txstatus *); -static uint16_t bwn_pio_rx_read_2(struct bwn_pio_rxqueue *, uint16_t); -static uint32_t bwn_pio_rx_read_4(struct bwn_pio_rxqueue *, uint16_t); -static void bwn_pio_rx_write_2(struct bwn_pio_rxqueue *, uint16_t, - uint16_t); -static void bwn_pio_rx_write_4(struct bwn_pio_rxqueue *, uint16_t, - uint32_t); -static int bwn_pio_tx_start(struct bwn_mac *, struct ieee80211_node *, - struct mbuf *); -static struct bwn_pio_txqueue *bwn_pio_select(struct bwn_mac *, uint8_t); -static uint32_t bwn_pio_write_multi_4(struct bwn_mac *, - struct bwn_pio_txqueue *, uint32_t, const void *, int); -static void bwn_pio_write_4(struct bwn_mac *, struct bwn_pio_txqueue *, - uint16_t, uint32_t); -static uint16_t bwn_pio_write_multi_2(struct bwn_mac *, - struct bwn_pio_txqueue *, uint16_t, const void *, int); -static uint16_t bwn_pio_write_mbuf_2(struct bwn_mac *, - struct bwn_pio_txqueue *, uint16_t, struct mbuf *); -static struct bwn_pio_txqueue *bwn_pio_parse_cookie(struct bwn_mac *, - uint16_t, struct bwn_pio_txpkt **); -static void bwn_dma_init(struct bwn_mac *); -static void bwn_dma_rxdirectfifo(struct bwn_mac *, int, uint8_t); -static int bwn_dma_mask2type(uint64_t); -static uint64_t bwn_dma_mask(struct bwn_mac *); -static uint16_t bwn_dma_base(int, int); -static void bwn_dma_ringfree(struct bwn_dma_ring **); -static void bwn_dma_32_getdesc(struct bwn_dma_ring *, - int, struct bwn_dmadesc_generic **, - struct bwn_dmadesc_meta **); -static void bwn_dma_32_setdesc(struct bwn_dma_ring *, - struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int, - int, int); -static void bwn_dma_32_start_transfer(struct bwn_dma_ring *, int); -static void bwn_dma_32_suspend(struct bwn_dma_ring *); -static void bwn_dma_32_resume(struct bwn_dma_ring *); -static int bwn_dma_32_get_curslot(struct bwn_dma_ring *); -static void bwn_dma_32_set_curslot(struct bwn_dma_ring *, int); -static void bwn_dma_64_getdesc(struct bwn_dma_ring *, - int, struct bwn_dmadesc_generic **, - struct bwn_dmadesc_meta **); -static void bwn_dma_64_setdesc(struct bwn_dma_ring *, - struct bwn_dmadesc_generic *, bus_addr_t, uint16_t, int, - int, int); -static void bwn_dma_64_start_transfer(struct bwn_dma_ring *, int); -static void bwn_dma_64_suspend(struct bwn_dma_ring *); -static void bwn_dma_64_resume(struct bwn_dma_ring *); -static int bwn_dma_64_get_curslot(struct bwn_dma_ring *); -static void bwn_dma_64_set_curslot(struct bwn_dma_ring *, int); -static int bwn_dma_allocringmemory(struct bwn_dma_ring *); -static void bwn_dma_setup(struct bwn_dma_ring *); -static void bwn_dma_free_ringmemory(struct bwn_dma_ring *); -static void bwn_dma_cleanup(struct bwn_dma_ring *); -static void bwn_dma_free_descbufs(struct bwn_dma_ring *); -static int bwn_dma_tx_reset(struct bwn_mac *, uint16_t, int); -static void bwn_dma_rx(struct bwn_dma_ring *); -static int bwn_dma_rx_reset(struct bwn_mac *, uint16_t, int); -static void bwn_dma_free_descbuf(struct bwn_dma_ring *, - struct bwn_dmadesc_meta *); -static void bwn_dma_set_redzone(struct bwn_dma_ring *, struct mbuf *); -static int bwn_dma_gettype(struct bwn_mac *); -static void bwn_dma_ring_addr(void *, bus_dma_segment_t *, int, int); -static int bwn_dma_freeslot(struct bwn_dma_ring *); -static int bwn_dma_nextslot(struct bwn_dma_ring *, int); -static void bwn_dma_rxeof(struct bwn_dma_ring *, int *); -static int bwn_dma_newbuf(struct bwn_dma_ring *, - struct bwn_dmadesc_generic *, struct bwn_dmadesc_meta *, - int); -static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int, - bus_size_t, int); -static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *); -static void bwn_dma_handle_txeof(struct bwn_mac *, - const struct bwn_txstatus *); -static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *, - struct mbuf *); -static int bwn_dma_getslot(struct bwn_dma_ring *); -static struct bwn_dma_ring *bwn_dma_select(struct bwn_mac *, - uint8_t); -static int bwn_dma_attach(struct bwn_mac *); -static struct bwn_dma_ring *bwn_dma_ringsetup(struct bwn_mac *, - int, int, int); -static struct bwn_dma_ring *bwn_dma_parse_cookie(struct bwn_mac *, - const struct bwn_txstatus *, uint16_t, int *); -static void bwn_dma_free(struct bwn_mac *); -static int bwn_fw_gets(struct bwn_mac *, enum bwn_fwtype); -static int bwn_fw_get(struct bwn_mac *, enum bwn_fwtype, - const char *, struct bwn_fwfile *); -static void bwn_release_firmware(struct bwn_mac *); -static void bwn_do_release_fw(struct bwn_fwfile *); -static uint16_t bwn_fwcaps_read(struct bwn_mac *); -static int bwn_fwinitvals_write(struct bwn_mac *, - const struct bwn_fwinitvals *, size_t, size_t); -static uint16_t bwn_ant2phy(int); -static void bwn_mac_write_bssid(struct bwn_mac *); -static void bwn_mac_setfilter(struct bwn_mac *, uint16_t, - const uint8_t *); -static void bwn_key_dowrite(struct bwn_mac *, uint8_t, uint8_t, - const uint8_t *, size_t, const uint8_t *); -static void bwn_key_macwrite(struct bwn_mac *, uint8_t, - const uint8_t *); -static void bwn_key_write(struct bwn_mac *, uint8_t, uint8_t, - const uint8_t *); -static void bwn_phy_exit(struct bwn_mac *); -static void bwn_core_stop(struct bwn_mac *); -static int bwn_switch_band(struct bwn_softc *, - struct ieee80211_channel *); -static void bwn_phy_reset(struct bwn_mac *); -static int bwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static void bwn_set_pretbtt(struct bwn_mac *); -static int bwn_intr(void *); -static void bwn_intrtask(void *, int); -static void bwn_restart(struct bwn_mac *, const char *); -static void bwn_intr_ucode_debug(struct bwn_mac *); -static void bwn_intr_tbtt_indication(struct bwn_mac *); -static void bwn_intr_atim_end(struct bwn_mac *); -static void bwn_intr_beacon(struct bwn_mac *); -static void bwn_intr_pmq(struct bwn_mac *); -static void bwn_intr_noise(struct bwn_mac *); -static void bwn_intr_txeof(struct bwn_mac *); -static void bwn_hwreset(void *, int); -static void bwn_handle_fwpanic(struct bwn_mac *); -static void bwn_load_beacon0(struct bwn_mac *); -static void bwn_load_beacon1(struct bwn_mac *); -static uint32_t bwn_jssi_read(struct bwn_mac *); -static void bwn_noise_gensample(struct bwn_mac *); -static void bwn_handle_txeof(struct bwn_mac *, - const struct bwn_txstatus *); -static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *); -static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t); -static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *, - struct mbuf *); -static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *); -static int bwn_set_txhdr(struct bwn_mac *, - struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *, - uint16_t); -static void bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t, - const uint8_t); -static uint8_t bwn_antenna_sanitize(struct bwn_mac *, uint8_t); -static uint8_t bwn_get_fbrate(uint8_t); -static void bwn_txpwr(void *, int); -static void bwn_tasks(void *); -static void bwn_task_15s(struct bwn_mac *); -static void bwn_task_30s(struct bwn_mac *); -static void bwn_task_60s(struct bwn_mac *); -static int bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *, - uint8_t); -static int bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *); -static void bwn_rx_radiotap(struct bwn_mac *, struct mbuf *, - const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int, - int, int); -static void bwn_tsf_read(struct bwn_mac *, uint64_t *); -static void bwn_set_slot_time(struct bwn_mac *, uint16_t); -static void bwn_watchdog(void *); -static void bwn_dma_stop(struct bwn_mac *); -static void bwn_pio_stop(struct bwn_mac *); -static void bwn_dma_ringstop(struct bwn_dma_ring **); -static void bwn_led_attach(struct bwn_mac *); -static void bwn_led_newstate(struct bwn_mac *, enum ieee80211_state); -static void bwn_led_event(struct bwn_mac *, int); -static void bwn_led_blink_start(struct bwn_mac *, int, int); -static void bwn_led_blink_next(void *); -static void bwn_led_blink_end(void *); -static void bwn_rfswitch(void *); -static void bwn_rf_turnon(struct bwn_mac *); -static void bwn_rf_turnoff(struct bwn_mac *); -static void bwn_sysctl_node(struct bwn_softc *); - -static struct resource_spec bwn_res_spec_legacy[] = { - { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, - { -1, 0, 0 } -}; - -static struct resource_spec bwn_res_spec_msi[] = { - { SYS_RES_IRQ, 1, RF_ACTIVE }, - { -1, 0, 0 } -}; - -static const struct bwn_channelinfo bwn_chantable_bg = { - .channels = { - { 2412, 1, 30 }, { 2417, 2, 30 }, { 2422, 3, 30 }, - { 2427, 4, 30 }, { 2432, 5, 30 }, { 2437, 6, 30 }, - { 2442, 7, 30 }, { 2447, 8, 30 }, { 2452, 9, 30 }, - { 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 }, - { 2472, 13, 30 }, { 2484, 14, 30 } }, - .nchannels = 14 -}; - -static const struct bwn_channelinfo bwn_chantable_a = { - .channels = { - { 5170, 34, 30 }, { 5180, 36, 30 }, { 5190, 38, 30 }, - { 5200, 40, 30 }, { 5210, 42, 30 }, { 5220, 44, 30 }, - { 5230, 46, 30 }, { 5240, 48, 30 }, { 5260, 52, 30 }, - { 5280, 56, 30 }, { 5300, 60, 30 }, { 5320, 64, 30 }, - { 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 }, - { 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 }, - { 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 }, - { 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 }, - { 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 }, - { 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 }, - { 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 }, - { 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 }, - { 6080, 216, 30 } }, - .nchannels = 37 -}; - -static const struct bwn_channelinfo bwn_chantable_n = { - .channels = { - { 5160, 32, 30 }, { 5170, 34, 30 }, { 5180, 36, 30 }, - { 5190, 38, 30 }, { 5200, 40, 30 }, { 5210, 42, 30 }, - { 5220, 44, 30 }, { 5230, 46, 30 }, { 5240, 48, 30 }, - { 5250, 50, 30 }, { 5260, 52, 30 }, { 5270, 54, 30 }, - { 5280, 56, 30 }, { 5290, 58, 30 }, { 5300, 60, 30 }, - { 5310, 62, 30 }, { 5320, 64, 30 }, { 5330, 66, 30 }, - { 5340, 68, 30 }, { 5350, 70, 30 }, { 5360, 72, 30 }, - { 5370, 74, 30 }, { 5380, 76, 30 }, { 5390, 78, 30 }, - { 5400, 80, 30 }, { 5410, 82, 30 }, { 5420, 84, 30 }, - { 5430, 86, 30 }, { 5440, 88, 30 }, { 5450, 90, 30 }, - { 5460, 92, 30 }, { 5470, 94, 30 }, { 5480, 96, 30 }, - { 5490, 98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 }, - { 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 }, - { 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 }, - { 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 }, - { 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 }, - { 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 }, - { 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 }, - { 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 }, - { 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 }, - { 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 }, - { 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 }, - { 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 }, - { 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 }, - { 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 }, - { 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 }, - { 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 }, - { 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 }, - { 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 }, - { 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 }, - { 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 }, - { 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 }, - { 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 }, - { 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 }, - { 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 }, - { 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 }, - { 6130, 226, 30 }, { 6140, 228, 30 } }, - .nchannels = 110 -}; - -#define VENDOR_LED_ACT(vendor) \ -{ \ - .vid = PCI_VENDOR_##vendor, \ - .led_act = { BWN_VENDOR_LED_ACT_##vendor } \ -} - -static const struct { - uint16_t vid; - uint8_t led_act[BWN_LED_MAX]; -} bwn_vendor_led_act[] = { - VENDOR_LED_ACT(COMPAQ), - VENDOR_LED_ACT(ASUSTEK) -}; - -static const uint8_t bwn_default_led_act[BWN_LED_MAX] = - { BWN_VENDOR_LED_ACT_DEFAULT }; - -#undef VENDOR_LED_ACT - -static const struct { - int on_dur; - int off_dur; -} bwn_led_duration[109] = { - [0] = { 400, 100 }, - [2] = { 150, 75 }, - [4] = { 90, 45 }, - [11] = { 66, 34 }, - [12] = { 53, 26 }, - [18] = { 42, 21 }, - [22] = { 35, 17 }, - [24] = { 32, 16 }, - [36] = { 21, 10 }, - [48] = { 16, 8 }, - [72] = { 11, 5 }, - [96] = { 9, 4 }, - [108] = { 7, 3 } -}; - -static const uint16_t bwn_wme_shm_offsets[] = { - [0] = BWN_WME_BESTEFFORT, - [1] = BWN_WME_BACKGROUND, - [2] = BWN_WME_VOICE, - [3] = BWN_WME_VIDEO, -}; - -static const struct siba_devid bwn_devs[] = { - SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"), - SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"), - SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"), - SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"), - SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"), - SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"), - SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"), - SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"), - SIBA_DEV(BROADCOM, 80211, 16, "Revision 16") -}; - -static int -bwn_probe(device_t dev) -{ - int i; - - for (i = 0; i < nitems(bwn_devs); i++) { - if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor && - siba_get_device(dev) == bwn_devs[i].sd_device && - siba_get_revid(dev) == bwn_devs[i].sd_rev) - return (BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - -static int -bwn_attach(device_t dev) -{ - struct bwn_mac *mac; - struct bwn_softc *sc = device_get_softc(dev); - int error, i, msic, reg; - - sc->sc_dev = dev; -#ifdef BWN_DEBUG - sc->sc_debug = bwn_debug; -#endif - - if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) { - bwn_attach_pre(sc); - bwn_sprom_bugfixes(dev); - sc->sc_flags |= BWN_FLAG_ATTACHED; - } - - if (!TAILQ_EMPTY(&sc->sc_maclist)) { - if (siba_get_pci_device(dev) != 0x4313 && - siba_get_pci_device(dev) != 0x431a && - siba_get_pci_device(dev) != 0x4321) { - device_printf(sc->sc_dev, - "skip 802.11 cores\n"); - return (ENODEV); - } - } - - mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO); - mac->mac_sc = sc; - mac->mac_status = BWN_MAC_STATUS_UNINIT; - if (bwn_bfp != 0) - mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP; - - TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac); - TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac); - TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac); - - error = bwn_attach_core(mac); - if (error) - goto fail0; - bwn_led_attach(mac); - - device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) " - "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n", - siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev), - mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev, - mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver, - mac->mac_phy.rf_rev); - if (mac->mac_flags & BWN_MAC_FLAG_DMA) - device_printf(sc->sc_dev, "DMA (%d bits)\n", - mac->mac_method.dma.dmatype); - else - device_printf(sc->sc_dev, "PIO\n"); - - /* - * setup PCI resources and interrupt. - */ - if (pci_find_cap(dev, PCIY_EXPRESS, ®) == 0) { - msic = pci_msi_count(dev); - if (bootverbose) - device_printf(sc->sc_dev, "MSI count : %d\n", msic); - } else - msic = 0; - - mac->mac_intr_spec = bwn_res_spec_legacy; - if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) { - if (pci_alloc_msi(dev, &msic) == 0) { - device_printf(sc->sc_dev, - "Using %d MSI messages\n", msic); - mac->mac_intr_spec = bwn_res_spec_msi; - mac->mac_msi = 1; - } - } - - error = bus_alloc_resources(dev, mac->mac_intr_spec, - mac->mac_res_irq); - if (error) { - device_printf(sc->sc_dev, - "couldn't allocate IRQ resources (%d)\n", error); - goto fail1; - } - - if (mac->mac_msi == 0) - error = bus_setup_intr(dev, mac->mac_res_irq[0], - INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac, - &mac->mac_intrhand[0]); - else { - for (i = 0; i < BWN_MSI_MESSAGES; i++) { - error = bus_setup_intr(dev, mac->mac_res_irq[i], - INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac, - &mac->mac_intrhand[i]); - if (error != 0) { - device_printf(sc->sc_dev, - "couldn't setup interrupt (%d)\n", error); - break; - } - } - } - - TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list); - - /* - * calls attach-post routine - */ - if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0) - bwn_attach_post(sc); - - return (0); -fail1: - if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) - pci_release_msi(dev); -fail0: - free(mac, M_DEVBUF); - return (error); -} - -static int -bwn_is_valid_ether_addr(uint8_t *addr) -{ - char zero_addr[6] = { 0, 0, 0, 0, 0, 0 }; - - if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN))) - return (FALSE); - - return (TRUE); -} - -static int -bwn_attach_post(struct bwn_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - - ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(sc->sc_dev); - /* XXX not right but it's not used anywhere important */ - ic->ic_phytype = IEEE80211_T_OFDM; - ic->ic_opmode = IEEE80211_M_STA; - ic->ic_caps = - IEEE80211_C_STA /* station mode supported */ - | IEEE80211_C_MONITOR /* monitor mode */ - | IEEE80211_C_AHDEMO /* adhoc demo mode */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_WME /* WME/WMM supported */ - | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ - | IEEE80211_C_BGSCAN /* capable of bg scanning */ - | IEEE80211_C_TXPMGT /* capable of txpow mgt */ - ; - - ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */ - - IEEE80211_ADDR_COPY(ic->ic_macaddr, - bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ? - siba_sprom_get_mac_80211a(sc->sc_dev) : - siba_sprom_get_mac_80211bg(sc->sc_dev)); - - /* call MI attach routine. */ - ieee80211_ifattach(ic); - - ic->ic_headroom = sizeof(struct bwn_txhdr); - - /* override default methods */ - ic->ic_raw_xmit = bwn_raw_xmit; - ic->ic_updateslot = bwn_updateslot; - ic->ic_update_promisc = bwn_update_promisc; - ic->ic_wme.wme_update = bwn_wme_update; - ic->ic_scan_start = bwn_scan_start; - ic->ic_scan_end = bwn_scan_end; - ic->ic_set_channel = bwn_set_channel; - ic->ic_vap_create = bwn_vap_create; - ic->ic_vap_delete = bwn_vap_delete; - ic->ic_transmit = bwn_transmit; - ic->ic_parent = bwn_parent; - - ieee80211_radiotap_attach(ic, - &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), - BWN_TX_RADIOTAP_PRESENT, - &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), - BWN_RX_RADIOTAP_PRESENT); - - bwn_sysctl_node(sc); - - if (bootverbose) - ieee80211_announce(ic); - return (0); -} - -static void -bwn_phy_detach(struct bwn_mac *mac) -{ - - if (mac->mac_phy.detach != NULL) - mac->mac_phy.detach(mac); -} - -static int -bwn_detach(device_t dev) -{ - struct bwn_softc *sc = device_get_softc(dev); - struct bwn_mac *mac = sc->sc_curmac; - struct ieee80211com *ic = &sc->sc_ic; - int i; - - sc->sc_flags |= BWN_FLAG_INVALID; - - if (device_is_attached(sc->sc_dev)) { - BWN_LOCK(sc); - bwn_stop(sc); - BWN_UNLOCK(sc); - bwn_dma_free(mac); - callout_drain(&sc->sc_led_blink_ch); - callout_drain(&sc->sc_rfswitch_ch); - callout_drain(&sc->sc_task_ch); - callout_drain(&sc->sc_watchdog_ch); - bwn_phy_detach(mac); - ieee80211_draintask(ic, &mac->mac_hwreset); - ieee80211_draintask(ic, &mac->mac_txpower); - ieee80211_ifdetach(ic); - } - taskqueue_drain(sc->sc_tq, &mac->mac_intrtask); - taskqueue_free(sc->sc_tq); - - for (i = 0; i < BWN_MSI_MESSAGES; i++) { - if (mac->mac_intrhand[i] != NULL) { - bus_teardown_intr(dev, mac->mac_res_irq[i], - mac->mac_intrhand[i]); - mac->mac_intrhand[i] = NULL; - } - } - bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq); - if (mac->mac_msi != 0) - pci_release_msi(dev); - mbufq_drain(&sc->sc_snd); - BWN_LOCK_DESTROY(sc); - return (0); -} - -static void -bwn_attach_pre(struct bwn_softc *sc) -{ - - BWN_LOCK_INIT(sc); - TAILQ_INIT(&sc->sc_maclist); - callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0); - callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0); - callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0); - mbufq_init(&sc->sc_snd, ifqmaxlen); - sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT, - taskqueue_thread_enqueue, &sc->sc_tq); - taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, - "%s taskq", device_get_nameunit(sc->sc_dev)); -} - -static void -bwn_sprom_bugfixes(device_t dev) -{ -#define BWN_ISDEV(_vendor, _device, _subvendor, _subdevice) \ - ((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) && \ - (siba_get_pci_device(dev) == _device) && \ - (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) && \ - (siba_get_pci_subdevice(dev) == _subdevice)) - - if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE && - siba_get_pci_subdevice(dev) == 0x4e && - siba_get_pci_revid(dev) > 0x40) - siba_sprom_set_bf_lo(dev, - siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL); - if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL && - siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74) - siba_sprom_set_bf_lo(dev, - siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST); - if (siba_get_type(dev) == SIBA_TYPE_PCI) { - if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) || - BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) || - BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) || - BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) || - BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) || - BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) || - BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010)) - siba_sprom_set_bf_lo(dev, - siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST); - } -#undef BWN_ISDEV -} - -static void -bwn_parent(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - int startall = 0; - - BWN_LOCK(sc); - if (ic->ic_nrunning > 0) { - if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) { - bwn_init(sc); - startall = 1; - } else - bwn_update_promisc(ic); - } else if (sc->sc_flags & BWN_FLAG_RUNNING) - bwn_stop(sc); - BWN_UNLOCK(sc); - - if (startall) - ieee80211_start_all(ic); -} - -static int -bwn_transmit(struct ieee80211com *ic, struct mbuf *m) -{ - struct bwn_softc *sc = ic->ic_softc; - int error; - - BWN_LOCK(sc); - if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) { - BWN_UNLOCK(sc); - return (ENXIO); - } - error = mbufq_enqueue(&sc->sc_snd, m); - if (error) { - BWN_UNLOCK(sc); - return (error); - } - bwn_start(sc); - BWN_UNLOCK(sc); - return (0); -} - -static void -bwn_start(struct bwn_softc *sc) -{ - struct bwn_mac *mac = sc->sc_curmac; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct ieee80211_key *k; - struct mbuf *m; - - BWN_ASSERT_LOCKED(sc); - - if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL || - mac->mac_status < BWN_MAC_STATUS_STARTED) - return; - - while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { - if (bwn_tx_isfull(sc, m)) - break; - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (ni == NULL) { - device_printf(sc->sc_dev, "unexpected NULL ni\n"); - m_freem(m); - counter_u64_add(sc->sc_ic.ic_oerrors, 1); - continue; - } - wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m); - if (k == NULL) { - if_inc_counter(ni->ni_vap->iv_ifp, - IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); - m_freem(m); - continue; - } - } - wh = NULL; /* Catch any invalid use */ - if (bwn_tx_start(sc, ni, m) != 0) { - if (ni != NULL) { - if_inc_counter(ni->ni_vap->iv_ifp, - IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); - } - continue; - } - sc->sc_watchdog_timer = 5; - } -} - -static int -bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m) -{ - struct bwn_dma_ring *dr; - struct bwn_mac *mac = sc->sc_curmac; - struct bwn_pio_txqueue *tq; - int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); - - BWN_ASSERT_LOCKED(sc); - - if (mac->mac_flags & BWN_MAC_FLAG_DMA) { - dr = bwn_dma_select(mac, M_WME_GETAC(m)); - if (dr->dr_stop == 1 || - bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) { - dr->dr_stop = 1; - goto full; - } - } else { - tq = bwn_pio_select(mac, M_WME_GETAC(m)); - if (tq->tq_free == 0 || pktlen > tq->tq_size || - pktlen > (tq->tq_size - tq->tq_used)) - goto full; - } - return (0); -full: - mbufq_prepend(&sc->sc_snd, m); - return (1); -} - -static int -bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m) -{ - struct bwn_mac *mac = sc->sc_curmac; - int error; - - BWN_ASSERT_LOCKED(sc); - - if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) { - m_freem(m); - return (ENXIO); - } - - error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ? - bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m); - if (error) { - m_freem(m); - return (error); - } - return (0); -} - -static int -bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m) -{ - struct bwn_pio_txpkt *tp; - struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m)); - struct bwn_softc *sc = mac->mac_sc; - struct bwn_txhdr txhdr; - struct mbuf *m_new; - uint32_t ctl32; - int error; - uint16_t ctl16; - - BWN_ASSERT_LOCKED(sc); - - /* XXX TODO send packets after DTIM */ - - KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__)); - tp = TAILQ_FIRST(&tq->tq_pktlist); - tp->tp_ni = ni; - tp->tp_m = m; - - error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp)); - if (error) { - device_printf(sc->sc_dev, "tx fail\n"); - return (error); - } - - TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list); - tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); - tq->tq_free--; - - if (siba_get_revid(sc->sc_dev) >= 8) { - /* - * XXX please removes m_defrag(9) - */ - m_new = m_defrag(m, M_NOWAIT); - if (m_new == NULL) { - device_printf(sc->sc_dev, - "%s: can't defrag TX buffer\n", - __func__); - return (ENOBUFS); - } - if (m_new->m_next != NULL) - device_printf(sc->sc_dev, - "TODO: fragmented packets for PIO\n"); - tp->tp_m = m_new; - - /* send HEADER */ - ctl32 = bwn_pio_write_multi_4(mac, tq, - (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) | - BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF, - (const uint8_t *)&txhdr, BWN_HDRSIZE(mac)); - /* send BODY */ - ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32, - mtod(m_new, const void *), m_new->m_pkthdr.len); - bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL, - ctl32 | BWN_PIO8_TXCTL_EOF); - } else { - ctl16 = bwn_pio_write_multi_2(mac, tq, - (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) | - BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF, - (const uint8_t *)&txhdr, BWN_HDRSIZE(mac)); - ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m); - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, - ctl16 | BWN_PIO_TXCTL_EOF); - } - - return (0); -} - -static struct bwn_pio_txqueue * -bwn_pio_select(struct bwn_mac *mac, uint8_t prio) -{ - - if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0) - return (&mac->mac_method.pio.wme[WME_AC_BE]); - - switch (prio) { - case 0: - return (&mac->mac_method.pio.wme[WME_AC_BE]); - case 1: - return (&mac->mac_method.pio.wme[WME_AC_BK]); - case 2: - return (&mac->mac_method.pio.wme[WME_AC_VI]); - case 3: - return (&mac->mac_method.pio.wme[WME_AC_VO]); - } - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (NULL); -} - -static int -bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m) -{ -#define BWN_GET_TXHDRCACHE(slot) \ - &(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)]) - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m)); - struct bwn_dmadesc_generic *desc; - struct bwn_dmadesc_meta *mt; - struct bwn_softc *sc = mac->mac_sc; - uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache; - int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot }; - - BWN_ASSERT_LOCKED(sc); - KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__)); - - /* XXX send after DTIM */ - - slot = bwn_dma_getslot(dr); - dr->getdesc(dr, slot, &desc, &mt); - KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER, - ("%s:%d: fail", __func__, __LINE__)); - - error = bwn_set_txhdr(dr->dr_mac, ni, m, - (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot), - BWN_DMA_COOKIE(dr, slot)); - if (error) - goto fail; - error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap, - BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr, - &mt->mt_paddr, BUS_DMA_NOWAIT); - if (error) { - device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n", - __func__, error); - goto fail; - } - bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap, - BUS_DMASYNC_PREWRITE); - dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0); - bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, - BUS_DMASYNC_PREWRITE); - - slot = bwn_dma_getslot(dr); - dr->getdesc(dr, slot, &desc, &mt); - KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY && - mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__)); - mt->mt_m = m; - mt->mt_ni = ni; - - error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m, - bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT); - if (error && error != EFBIG) { - device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n", - __func__, error); - goto fail; - } - if (error) { /* error == EFBIG */ - struct mbuf *m_new; - - m_new = m_defrag(m, M_NOWAIT); - if (m_new == NULL) { - device_printf(sc->sc_dev, - "%s: can't defrag TX buffer\n", - __func__); - error = ENOBUFS; - goto fail; - } else { - m = m_new; - } - - mt->mt_m = m; - error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, - m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT); - if (error) { - device_printf(sc->sc_dev, - "%s: can't load TX buffer (2) %d\n", - __func__, error); - goto fail; - } - } - bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE); - dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1); - bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, - BUS_DMASYNC_PREWRITE); - - /* XXX send after DTIM */ - - dr->start_transfer(dr, bwn_dma_nextslot(dr, slot)); - return (0); -fail: - dr->dr_curslot = backup[0]; - dr->dr_usedslot = backup[1]; - return (error); -#undef BWN_GET_TXHDRCACHE -} - -static void -bwn_watchdog(void *arg) -{ - struct bwn_softc *sc = arg; - - if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - counter_u64_add(sc->sc_ic.ic_oerrors, 1); - } - callout_schedule(&sc->sc_watchdog_ch, hz); -} - -static int -bwn_attach_core(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - int error, have_bg = 0, have_a = 0; - uint32_t high; - - KASSERT(siba_get_revid(sc->sc_dev) >= 5, - ("unsupported revision %d", siba_get_revid(sc->sc_dev))); - - siba_powerup(sc->sc_dev, 0); - - high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH); - bwn_reset_core(mac, - (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0); - error = bwn_phy_getinfo(mac, high); - if (error) - goto fail; - - have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0; - have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0; - if (siba_get_pci_device(sc->sc_dev) != 0x4312 && - siba_get_pci_device(sc->sc_dev) != 0x4319 && - siba_get_pci_device(sc->sc_dev) != 0x4324) { - have_a = have_bg = 0; - if (mac->mac_phy.type == BWN_PHYTYPE_A) - have_a = 1; - else if (mac->mac_phy.type == BWN_PHYTYPE_G || - mac->mac_phy.type == BWN_PHYTYPE_N || - mac->mac_phy.type == BWN_PHYTYPE_LP) - have_bg = 1; - else - KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__, - mac->mac_phy.type)); - } - /* XXX turns off PHY A because it's not supported */ - if (mac->mac_phy.type != BWN_PHYTYPE_LP && - mac->mac_phy.type != BWN_PHYTYPE_N) { - have_a = 0; - have_bg = 1; - } - - if (mac->mac_phy.type == BWN_PHYTYPE_G) { - mac->mac_phy.attach = bwn_phy_g_attach; - mac->mac_phy.detach = bwn_phy_g_detach; - mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw; - mac->mac_phy.init_pre = bwn_phy_g_init_pre; - mac->mac_phy.init = bwn_phy_g_init; - mac->mac_phy.exit = bwn_phy_g_exit; - mac->mac_phy.phy_read = bwn_phy_g_read; - mac->mac_phy.phy_write = bwn_phy_g_write; - mac->mac_phy.rf_read = bwn_phy_g_rf_read; - mac->mac_phy.rf_write = bwn_phy_g_rf_write; - mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl; - mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff; - mac->mac_phy.switch_analog = bwn_phy_switch_analog; - mac->mac_phy.switch_channel = bwn_phy_g_switch_channel; - mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan; - mac->mac_phy.set_antenna = bwn_phy_g_set_antenna; - mac->mac_phy.set_im = bwn_phy_g_im; - mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr; - mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr; - mac->mac_phy.task_15s = bwn_phy_g_task_15s; - mac->mac_phy.task_60s = bwn_phy_g_task_60s; - } else if (mac->mac_phy.type == BWN_PHYTYPE_LP) { - mac->mac_phy.init_pre = bwn_phy_lp_init_pre; - mac->mac_phy.init = bwn_phy_lp_init; - mac->mac_phy.phy_read = bwn_phy_lp_read; - mac->mac_phy.phy_write = bwn_phy_lp_write; - mac->mac_phy.phy_maskset = bwn_phy_lp_maskset; - mac->mac_phy.rf_read = bwn_phy_lp_rf_read; - mac->mac_phy.rf_write = bwn_phy_lp_rf_write; - mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff; - mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog; - mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel; - mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan; - mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna; - mac->mac_phy.task_60s = bwn_phy_lp_task_60s; - } else { - device_printf(sc->sc_dev, "unsupported PHY type (%d)\n", - mac->mac_phy.type); - error = ENXIO; - goto fail; - } - - mac->mac_phy.gmode = have_bg; - if (mac->mac_phy.attach != NULL) { - error = mac->mac_phy.attach(mac); - if (error) { - device_printf(sc->sc_dev, "failed\n"); - goto fail; - } - } - - bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0); - - error = bwn_chiptest(mac); - if (error) - goto fail; - error = bwn_setup_channels(mac, have_bg, have_a); - if (error) { - device_printf(sc->sc_dev, "failed to setup channels\n"); - goto fail; - } - - if (sc->sc_curmac == NULL) - sc->sc_curmac = mac; - - error = bwn_dma_attach(mac); - if (error != 0) { - device_printf(sc->sc_dev, "failed to initialize DMA\n"); - goto fail; - } - - mac->mac_phy.switch_analog(mac, 0); - - siba_dev_down(sc->sc_dev, 0); -fail: - siba_powerdown(sc->sc_dev); - return (error); -} - -void -bwn_reset_core(struct bwn_mac *mac, uint32_t flags) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t low, ctl; - - flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET); - - siba_dev_up(sc->sc_dev, flags); - DELAY(2000); - - low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) & - ~BWN_TGSLOW_PHYRESET; - siba_write_4(sc->sc_dev, SIBA_TGSLOW, low); - siba_read_4(sc->sc_dev, SIBA_TGSLOW); - DELAY(1000); - siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC); - siba_read_4(sc->sc_dev, SIBA_TGSLOW); - DELAY(1000); - - if (mac->mac_phy.switch_analog != NULL) - mac->mac_phy.switch_analog(mac, 1); - - ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE; - if (flags & BWN_TGSLOW_SUPPORT_G) - ctl |= BWN_MACCTL_GMODE; - BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON); -} - -static int -bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh) -{ - struct bwn_phy *phy = &mac->mac_phy; - struct bwn_softc *sc = mac->mac_sc; - uint32_t tmp; - - /* PHY */ - tmp = BWN_READ_2(mac, BWN_PHYVER); - phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0; - phy->rf_on = 1; - phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12; - phy->type = (tmp & BWN_PHYVER_TYPE) >> 8; - phy->rev = (tmp & BWN_PHYVER_VERSION); - if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) || - (phy->type == BWN_PHYTYPE_B && phy->rev != 2 && - phy->rev != 4 && phy->rev != 6 && phy->rev != 7) || - (phy->type == BWN_PHYTYPE_G && phy->rev > 9) || - (phy->type == BWN_PHYTYPE_N && phy->rev > 4) || - (phy->type == BWN_PHYTYPE_LP && phy->rev > 2)) - goto unsupphy; - - /* RADIO */ - if (siba_get_chipid(sc->sc_dev) == 0x4317) { - if (siba_get_chiprev(sc->sc_dev) == 0) - tmp = 0x3205017f; - else if (siba_get_chiprev(sc->sc_dev) == 1) - tmp = 0x4205017f; - else - tmp = 0x5205017f; - } else { - BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID); - tmp = BWN_READ_2(mac, BWN_RFDATALO); - BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID); - tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16; - } - phy->rf_rev = (tmp & 0xf0000000) >> 28; - phy->rf_ver = (tmp & 0x0ffff000) >> 12; - phy->rf_manuf = (tmp & 0x00000fff); - if (phy->rf_manuf != 0x17f) /* 0x17f is broadcom */ - goto unsupradio; - if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 || - phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) || - (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) || - (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) || - (phy->type == BWN_PHYTYPE_N && - phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) || - (phy->type == BWN_PHYTYPE_LP && - phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063)) - goto unsupradio; - - return (0); -unsupphy: - device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, " - "analog %#x)\n", - phy->type, phy->rev, phy->analog); - return (ENXIO); -unsupradio: - device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, " - "rev %#x)\n", - phy->rf_manuf, phy->rf_ver, phy->rf_rev); - return (ENXIO); -} - -static int -bwn_chiptest(struct bwn_mac *mac) -{ -#define TESTVAL0 0x55aaaa55 -#define TESTVAL1 0xaa5555aa - struct bwn_softc *sc = mac->mac_sc; - uint32_t v, backup; - - BWN_LOCK(sc); - - backup = bwn_shm_read_4(mac, BWN_SHARED, 0); - - bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0); - if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0) - goto error; - bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1); - if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1) - goto error; - - bwn_shm_write_4(mac, BWN_SHARED, 0, backup); - - if ((siba_get_revid(sc->sc_dev) >= 3) && - (siba_get_revid(sc->sc_dev) <= 10)) { - BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa); - BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb); - if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb) - goto error; - if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc) - goto error; - } - BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0); - - v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE; - if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON)) - goto error; - - BWN_UNLOCK(sc); - return (0); -error: - BWN_UNLOCK(sc); - device_printf(sc->sc_dev, "failed to validate the chipaccess\n"); - return (ENODEV); -} - -#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT | IEEE80211_CHAN_G) -#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT | IEEE80211_CHAN_A) - -static int -bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - - memset(ic->ic_channels, 0, sizeof(ic->ic_channels)); - ic->ic_nchans = 0; - - if (have_bg) - bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX, - &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G); - if (mac->mac_phy.type == BWN_PHYTYPE_N) { - if (have_a) - bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX, - &ic->ic_nchans, &bwn_chantable_n, - IEEE80211_CHAN_HTA); - } else { - if (have_a) - bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX, - &ic->ic_nchans, &bwn_chantable_a, - IEEE80211_CHAN_A); - } - - mac->mac_phy.supports_2ghz = have_bg; - mac->mac_phy.supports_5ghz = have_a; - - return (ic->ic_nchans == 0 ? ENXIO : 0); -} - -uint32_t -bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset) -{ - uint32_t ret; - - BWN_ASSERT_LOCKED(mac->mac_sc); - - if (way == BWN_SHARED) { - KASSERT((offset & 0x0001) == 0, - ("%s:%d warn", __func__, __LINE__)); - if (offset & 0x0003) { - bwn_shm_ctlword(mac, way, offset >> 2); - ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED); - ret <<= 16; - bwn_shm_ctlword(mac, way, (offset >> 2) + 1); - ret |= BWN_READ_2(mac, BWN_SHM_DATA); - goto out; - } - offset >>= 2; - } - bwn_shm_ctlword(mac, way, offset); - ret = BWN_READ_4(mac, BWN_SHM_DATA); -out: - return (ret); -} - -uint16_t -bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset) -{ - uint16_t ret; - - BWN_ASSERT_LOCKED(mac->mac_sc); - - if (way == BWN_SHARED) { - KASSERT((offset & 0x0001) == 0, - ("%s:%d warn", __func__, __LINE__)); - if (offset & 0x0003) { - bwn_shm_ctlword(mac, way, offset >> 2); - ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED); - goto out; - } - offset >>= 2; - } - bwn_shm_ctlword(mac, way, offset); - ret = BWN_READ_2(mac, BWN_SHM_DATA); -out: - - return (ret); -} - -static void -bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way, - uint16_t offset) -{ - uint32_t control; - - control = way; - control <<= 16; - control |= offset; - BWN_WRITE_4(mac, BWN_SHM_CONTROL, control); -} - -void -bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset, - uint32_t value) -{ - BWN_ASSERT_LOCKED(mac->mac_sc); - - if (way == BWN_SHARED) { - KASSERT((offset & 0x0001) == 0, - ("%s:%d warn", __func__, __LINE__)); - if (offset & 0x0003) { - bwn_shm_ctlword(mac, way, offset >> 2); - BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, - (value >> 16) & 0xffff); - bwn_shm_ctlword(mac, way, (offset >> 2) + 1); - BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff); - return; - } - offset >>= 2; - } - bwn_shm_ctlword(mac, way, offset); - BWN_WRITE_4(mac, BWN_SHM_DATA, value); -} - -void -bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset, - uint16_t value) -{ - BWN_ASSERT_LOCKED(mac->mac_sc); - - if (way == BWN_SHARED) { - KASSERT((offset & 0x0001) == 0, - ("%s:%d warn", __func__, __LINE__)); - if (offset & 0x0003) { - bwn_shm_ctlword(mac, way, offset >> 2); - BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value); - return; - } - offset >>= 2; - } - bwn_shm_ctlword(mac, way, offset); - BWN_WRITE_2(mac, BWN_SHM_DATA, value); -} - -static void -bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee, - int txpow) -{ - - c->ic_freq = freq; - c->ic_flags = flags; - c->ic_ieee = ieee; - c->ic_minpower = 0; - c->ic_maxpower = 2 * txpow; - c->ic_maxregpower = txpow; -} - -static void -bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans, - const struct bwn_channelinfo *ci, int flags) -{ - struct ieee80211_channel *c; - int i; - - c = &chans[*nchans]; - - for (i = 0; i < ci->nchannels; i++) { - const struct bwn_channel *hc; - - hc = &ci->channels[i]; - if (*nchans >= maxchans) - break; - bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow); - c++, (*nchans)++; - if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) { - /* g channel have a separate b-only entry */ - if (*nchans >= maxchans) - break; - c[0] = c[-1]; - c[-1].ic_flags = IEEE80211_CHAN_B; - c++, (*nchans)++; - } - if (flags == IEEE80211_CHAN_HTG) { - /* HT g channel have a separate g-only entry */ - if (*nchans >= maxchans) - break; - c[-1].ic_flags = IEEE80211_CHAN_G; - c[0] = c[-1]; - c[0].ic_flags &= ~IEEE80211_CHAN_HT; - c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */ - c++, (*nchans)++; - } - if (flags == IEEE80211_CHAN_HTA) { - /* HT a channel have a separate a-only entry */ - if (*nchans >= maxchans) - break; - c[-1].ic_flags = IEEE80211_CHAN_A; - c[0] = c[-1]; - c[0].ic_flags &= ~IEEE80211_CHAN_HT; - c[0].ic_flags |= IEEE80211_CHAN_HT20; /* HT20 */ - c++, (*nchans)++; - } - } -} - -static int -bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac = sc->sc_curmac; - int error; - - if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || - mac->mac_status < BWN_MAC_STATUS_STARTED) { - m_freem(m); - return (ENETDOWN); - } - - BWN_LOCK(sc); - if (bwn_tx_isfull(sc, m)) { - m_freem(m); - BWN_UNLOCK(sc); - return (ENOBUFS); - } - - error = bwn_tx_start(sc, ni, m); - if (error == 0) - sc->sc_watchdog_timer = 5; - BWN_UNLOCK(sc); - return (error); -} - -/* - * Callback from the 802.11 layer to update the slot time - * based on the current setting. We use it to notify the - * firmware of ERP changes and the f/w takes care of things - * like slot time and preamble. - */ -static void -bwn_updateslot(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac; - - BWN_LOCK(sc); - if (sc->sc_flags & BWN_FLAG_RUNNING) { - mac = (struct bwn_mac *)sc->sc_curmac; - bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic)); - } - BWN_UNLOCK(sc); -} - -/* - * Callback from the 802.11 layer after a promiscuous mode change. - * Note this interface does not check the operating mode as this - * is an internal callback and we are expected to honor the current - * state (e.g. this is used for setting the interface in promiscuous - * mode when operating in hostap mode to do ACS). - */ -static void -bwn_update_promisc(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac = sc->sc_curmac; - - BWN_LOCK(sc); - mac = sc->sc_curmac; - if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { - if (ic->ic_promisc > 0) - sc->sc_filters |= BWN_MACCTL_PROMISC; - else - sc->sc_filters &= ~BWN_MACCTL_PROMISC; - bwn_set_opmode(mac); - } - BWN_UNLOCK(sc); -} - -/* - * Callback from the 802.11 layer to update WME parameters. - */ -static int -bwn_wme_update(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac = sc->sc_curmac; - struct wmeParams *wmep; - int i; - - BWN_LOCK(sc); - mac = sc->sc_curmac; - if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { - bwn_mac_suspend(mac); - for (i = 0; i < N(sc->sc_wmeParams); i++) { - wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i]; - bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]); - } - bwn_mac_enable(mac); - } - BWN_UNLOCK(sc); - return (0); -} - -static void -bwn_scan_start(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac; - - BWN_LOCK(sc); - mac = sc->sc_curmac; - if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { - sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC; - bwn_set_opmode(mac); - /* disable CFP update during scan */ - bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE); - } - BWN_UNLOCK(sc); -} - -static void -bwn_scan_end(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac; - - BWN_LOCK(sc); - mac = sc->sc_curmac; - if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) { - sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC; - bwn_set_opmode(mac); - bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE); - } - BWN_UNLOCK(sc); -} - -static void -bwn_set_channel(struct ieee80211com *ic) -{ - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac = sc->sc_curmac; - struct bwn_phy *phy = &mac->mac_phy; - int chan, error; - - BWN_LOCK(sc); - - error = bwn_switch_band(sc, ic->ic_curchan); - if (error) - goto fail; - bwn_mac_suspend(mac); - bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG); - chan = ieee80211_chan2ieee(ic, ic->ic_curchan); - if (chan != phy->chan) - bwn_switch_channel(mac, chan); - - /* TX power level */ - if (ic->ic_curchan->ic_maxpower != 0 && - ic->ic_curchan->ic_maxpower != phy->txpower) { - phy->txpower = ic->ic_curchan->ic_maxpower / 2; - bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME | - BWN_TXPWR_IGNORE_TSSI); - } - - bwn_set_txantenna(mac, BWN_ANT_DEFAULT); - if (phy->set_antenna) - phy->set_antenna(mac, BWN_ANT_DEFAULT); - - if (sc->sc_rf_enabled != phy->rf_on) { - if (sc->sc_rf_enabled) { - bwn_rf_turnon(mac); - if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)) - device_printf(sc->sc_dev, - "please turn on the RF switch\n"); - } else - bwn_rf_turnoff(mac); - } - - bwn_mac_enable(mac); - -fail: - /* - * Setup radio tap channel freq and flags - */ - sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq = - htole16(ic->ic_curchan->ic_freq); - sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags = - htole16(ic->ic_curchan->ic_flags & 0xffff); - - BWN_UNLOCK(sc); -} - -static struct ieee80211vap * -bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ieee80211vap *vap; - struct bwn_vap *bvp; - - switch (opmode) { - case IEEE80211_M_HOSTAP: - case IEEE80211_M_MBSS: - case IEEE80211_M_STA: - case IEEE80211_M_WDS: - case IEEE80211_M_MONITOR: - case IEEE80211_M_IBSS: - case IEEE80211_M_AHDEMO: - break; - default: - return (NULL); - } - - bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO); - vap = &bvp->bv_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); - /* override with driver methods */ - bvp->bv_newstate = vap->iv_newstate; - vap->iv_newstate = bwn_newstate; - - /* override max aid so sta's cannot assoc when we're out of sta id's */ - vap->iv_max_aid = BWN_STAID_MAX; - - ieee80211_ratectl_init(vap); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status, mac); - return (vap); -} - -static void -bwn_vap_delete(struct ieee80211vap *vap) -{ - struct bwn_vap *bvp = BWN_VAP(vap); - - ieee80211_ratectl_deinit(vap); - ieee80211_vap_detach(vap); - free(bvp, M_80211_VAP); -} - -static int -bwn_init(struct bwn_softc *sc) -{ - struct bwn_mac *mac; - int error; - - BWN_ASSERT_LOCKED(sc); - - bzero(sc->sc_bssid, IEEE80211_ADDR_LEN); - sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP; - sc->sc_filters = 0; - bwn_wme_clear(sc); - sc->sc_beacons[0] = sc->sc_beacons[1] = 0; - sc->sc_rf_enabled = 1; - - mac = sc->sc_curmac; - if (mac->mac_status == BWN_MAC_STATUS_UNINIT) { - error = bwn_core_init(mac); - if (error != 0) - return (error); - } - if (mac->mac_status == BWN_MAC_STATUS_INITED) - bwn_core_start(mac); - - bwn_set_opmode(mac); - bwn_set_pretbtt(mac); - bwn_spu_setdelay(mac, 0); - bwn_set_macaddr(mac); - - sc->sc_flags |= BWN_FLAG_RUNNING; - callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc); - callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc); - - return (0); -} - -static void -bwn_stop(struct bwn_softc *sc) -{ - struct bwn_mac *mac = sc->sc_curmac; - - BWN_ASSERT_LOCKED(sc); - - if (mac->mac_status >= BWN_MAC_STATUS_INITED) { - /* XXX FIXME opmode not based on VAP */ - bwn_set_opmode(mac); - bwn_set_macaddr(mac); - } - - if (mac->mac_status >= BWN_MAC_STATUS_STARTED) - bwn_core_stop(mac); - - callout_stop(&sc->sc_led_blink_ch); - sc->sc_led_blinking = 0; - - bwn_core_exit(mac); - sc->sc_rf_enabled = 0; - - sc->sc_flags &= ~BWN_FLAG_RUNNING; -} - -static void -bwn_wme_clear(struct bwn_softc *sc) -{ -#define MS(_v, _f) (((_v) & _f) >> _f##_S) - struct wmeParams *p; - unsigned int i; - - KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams), - ("%s:%d: fail", __func__, __LINE__)); - - for (i = 0; i < N(sc->sc_wmeParams); i++) { - p = &(sc->sc_wmeParams[i]); - - switch (bwn_wme_shm_offsets[i]) { - case BWN_WME_VOICE: - p->wmep_txopLimit = 0; - p->wmep_aifsn = 2; - /* XXX FIXME: log2(cwmin) */ - p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); - p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX); - break; - case BWN_WME_VIDEO: - p->wmep_txopLimit = 0; - p->wmep_aifsn = 2; - /* XXX FIXME: log2(cwmin) */ - p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); - p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX); - break; - case BWN_WME_BESTEFFORT: - p->wmep_txopLimit = 0; - p->wmep_aifsn = 3; - /* XXX FIXME: log2(cwmin) */ - p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); - p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX); - break; - case BWN_WME_BACKGROUND: - p->wmep_txopLimit = 0; - p->wmep_aifsn = 7; - /* XXX FIXME: log2(cwmin) */ - p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN); - p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX); - break; - default: - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - } - } -} - -static int -bwn_core_init(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint64_t hf; - int error; - - KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT, - ("%s:%d: fail", __func__, __LINE__)); - - siba_powerup(sc->sc_dev, 0); - if (!siba_dev_isup(sc->sc_dev)) - bwn_reset_core(mac, - mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0); - - mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID; - mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON; - mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0; - BWN_GETTIME(mac->mac_phy.nexttime); - mac->mac_phy.txerrors = BWN_TXERROR_MAX; - bzero(&mac->mac_stats, sizeof(mac->mac_stats)); - mac->mac_stats.link_noise = -95; - mac->mac_reason_intr = 0; - bzero(mac->mac_reason, sizeof(mac->mac_reason)); - mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE; -#ifdef BWN_DEBUG - if (sc->sc_debug & BWN_DEBUG_XMIT) - mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR; -#endif - mac->mac_suspended = 1; - mac->mac_task_state = 0; - memset(&mac->mac_noise, 0, sizeof(mac->mac_noise)); - - mac->mac_phy.init_pre(mac); - - siba_pcicore_intr(sc->sc_dev); - - siba_fix_imcfglobug(sc->sc_dev); - bwn_bt_disable(mac); - if (mac->mac_phy.prepare_hw) { - error = mac->mac_phy.prepare_hw(mac); - if (error) - goto fail0; - } - error = bwn_chip_init(mac); - if (error) - goto fail0; - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV, - siba_get_revid(sc->sc_dev)); - hf = bwn_hf_read(mac); - if (mac->mac_phy.type == BWN_PHYTYPE_G) { - hf |= BWN_HF_GPHY_SYM_WORKAROUND; - if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) - hf |= BWN_HF_PAGAINBOOST_OFDM_ON; - if (mac->mac_phy.rev == 1) - hf |= BWN_HF_GPHY_DC_CANCELFILTER; - } - if (mac->mac_phy.rf_ver == 0x2050) { - if (mac->mac_phy.rf_rev < 6) - hf |= BWN_HF_FORCE_VCO_RECALC; - if (mac->mac_phy.rf_rev == 6) - hf |= BWN_HF_4318_TSSI; - } - if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW) - hf |= BWN_HF_SLOWCLOCK_REQ_OFF; - if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) && - (siba_get_pcicore_revid(sc->sc_dev) <= 10)) - hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND; - hf &= ~BWN_HF_SKIP_CFP_UPDATE; - bwn_hf_write(mac, hf); - - bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1); - - bwn_rate_init(mac); - bwn_set_phytxctl(mac); - - bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN, - (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf); - bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff); - - if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0) - bwn_pio_init(mac); - else - bwn_dma_init(mac); - bwn_wme_init(mac); - bwn_spu_setdelay(mac, 1); - bwn_bt_enable(mac); - - siba_powerup(sc->sc_dev, - !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)); - bwn_set_macaddr(mac); - bwn_crypt_init(mac); - - /* XXX LED initializatin */ - - mac->mac_status = BWN_MAC_STATUS_INITED; - - return (error); - -fail0: - siba_powerdown(sc->sc_dev); - KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT, - ("%s:%d: fail", __func__, __LINE__)); - return (error); -} - -static void -bwn_core_start(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t tmp; - - KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED, - ("%s:%d: fail", __func__, __LINE__)); - - if (siba_get_revid(sc->sc_dev) < 5) - return; - - while (1) { - tmp = BWN_READ_4(mac, BWN_XMITSTAT_0); - if (!(tmp & 0x00000001)) - break; - tmp = BWN_READ_4(mac, BWN_XMITSTAT_1); - } - - bwn_mac_enable(mac); - BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask); - callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac); - - mac->mac_status = BWN_MAC_STATUS_STARTED; -} - -static void -bwn_core_exit(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t macctl; - - BWN_ASSERT_LOCKED(mac->mac_sc); - - KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED, - ("%s:%d: fail", __func__, __LINE__)); - - if (mac->mac_status != BWN_MAC_STATUS_INITED) - return; - mac->mac_status = BWN_MAC_STATUS_UNINIT; - - macctl = BWN_READ_4(mac, BWN_MACCTL); - macctl &= ~BWN_MACCTL_MCODE_RUN; - macctl |= BWN_MACCTL_MCODE_JMP0; - BWN_WRITE_4(mac, BWN_MACCTL, macctl); - - bwn_dma_stop(mac); - bwn_pio_stop(mac); - bwn_chip_exit(mac); - mac->mac_phy.switch_analog(mac, 0); - siba_dev_down(sc->sc_dev, 0); - siba_powerdown(sc->sc_dev); -} - -static void -bwn_bt_disable(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - - (void)sc; - /* XXX do nothing yet */ -} - -static int -bwn_chip_init(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - struct bwn_phy *phy = &mac->mac_phy; - uint32_t macctl; - int error; - - macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA; - if (phy->gmode) - macctl |= BWN_MACCTL_GMODE; - BWN_WRITE_4(mac, BWN_MACCTL, macctl); - - error = bwn_fw_fillinfo(mac); - if (error) - return (error); - error = bwn_fw_loaducode(mac); - if (error) - return (error); - - error = bwn_gpio_init(mac); - if (error) - return (error); - - error = bwn_fw_loadinitvals(mac); - if (error) { - siba_gpio_set(sc->sc_dev, 0); - return (error); - } - phy->switch_analog(mac, 1); - error = bwn_phy_init(mac); - if (error) { - siba_gpio_set(sc->sc_dev, 0); - return (error); - } - if (phy->set_im) - phy->set_im(mac, BWN_IMMODE_NONE); - if (phy->set_antenna) - phy->set_antenna(mac, BWN_ANT_DEFAULT); - bwn_set_txantenna(mac, BWN_ANT_DEFAULT); - - if (phy->type == BWN_PHYTYPE_B) - BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004); - BWN_WRITE_4(mac, 0x0100, 0x01000000); - if (siba_get_revid(sc->sc_dev) < 5) - BWN_WRITE_4(mac, 0x010c, 0x01000000); - - BWN_WRITE_4(mac, BWN_MACCTL, - BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA); - BWN_WRITE_4(mac, BWN_MACCTL, - BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA); - bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000); - - bwn_set_opmode(mac); - if (siba_get_revid(sc->sc_dev) < 3) { - BWN_WRITE_2(mac, 0x060e, 0x0000); - BWN_WRITE_2(mac, 0x0610, 0x8000); - BWN_WRITE_2(mac, 0x0604, 0x0000); - BWN_WRITE_2(mac, 0x0606, 0x0200); - } else { - BWN_WRITE_4(mac, 0x0188, 0x80000000); - BWN_WRITE_4(mac, 0x018c, 0x02000000); - } - BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000); - BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00); - BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00); - BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00); - BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00); - BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00); - BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00); - siba_write_4(sc->sc_dev, SIBA_TGSLOW, - siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000); - BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev)); - return (error); -} - -/* read hostflags */ -uint64_t -bwn_hf_read(struct bwn_mac *mac) -{ - uint64_t ret; - - ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI); - ret <<= 16; - ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI); - ret <<= 16; - ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO); - return (ret); -} - -void -bwn_hf_write(struct bwn_mac *mac, uint64_t value) -{ - - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO, - (value & 0x00000000ffffull)); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI, - (value & 0x0000ffff0000ull) >> 16); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI, - (value & 0xffff00000000ULL) >> 32); -} - -static void -bwn_set_txretry(struct bwn_mac *mac, int s, int l) -{ - - bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf)); - bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf)); -} - -static void -bwn_rate_init(struct bwn_mac *mac) -{ - - switch (mac->mac_phy.type) { - case BWN_PHYTYPE_A: - case BWN_PHYTYPE_G: - case BWN_PHYTYPE_LP: - case BWN_PHYTYPE_N: - bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1); - bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1); - bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1); - bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1); - bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1); - bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1); - bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1); - if (mac->mac_phy.type == BWN_PHYTYPE_A) - break; - /* FALLTHROUGH */ - case BWN_PHYTYPE_B: - bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0); - bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0); - bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0); - bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0); - break; - default: - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - } -} - -static void -bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm) -{ - uint16_t offset; - - if (ofdm) { - offset = 0x480; - offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2; - } else { - offset = 0x4c0; - offset += (bwn_plcp_getcck(rate) & 0x000f) * 2; - } - bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20, - bwn_shm_read_2(mac, BWN_SHARED, offset)); -} - -static uint8_t -bwn_plcp_getcck(const uint8_t bitrate) -{ - - switch (bitrate) { - case BWN_CCK_RATE_1MB: - return (0x0a); - case BWN_CCK_RATE_2MB: - return (0x14); - case BWN_CCK_RATE_5MB: - return (0x37); - case BWN_CCK_RATE_11MB: - return (0x6e); - } - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (0); -} - -static uint8_t -bwn_plcp_getofdm(const uint8_t bitrate) -{ - - switch (bitrate) { - case BWN_OFDM_RATE_6MB: - return (0xb); - case BWN_OFDM_RATE_9MB: - return (0xf); - case BWN_OFDM_RATE_12MB: - return (0xa); - case BWN_OFDM_RATE_18MB: - return (0xe); - case BWN_OFDM_RATE_24MB: - return (0x9); - case BWN_OFDM_RATE_36MB: - return (0xd); - case BWN_OFDM_RATE_48MB: - return (0x8); - case BWN_OFDM_RATE_54MB: - return (0xc); - } - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (0); -} - -static void -bwn_set_phytxctl(struct bwn_mac *mac) -{ - uint16_t ctl; - - ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO | - BWN_TX_PHY_TXPWR); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl); -} - -static void -bwn_pio_init(struct bwn_mac *mac) -{ - struct bwn_pio *pio = &mac->mac_method.pio; - - BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL) - & ~BWN_MACCTL_BIGENDIAN); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0); - - bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0); - bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1); - bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2); - bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3); - bwn_pio_set_txqueue(mac, &pio->mcast, 4); - bwn_pio_setupqueue_rx(mac, &pio->rx, 0); -} - -static void -bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, - int index) -{ - struct bwn_pio_txpkt *tp; - struct bwn_softc *sc = mac->mac_sc; - unsigned int i; - - tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac); - tq->tq_index = index; - - tq->tq_free = BWN_PIO_MAX_TXPACKETS; - if (siba_get_revid(sc->sc_dev) >= 8) - tq->tq_size = 1920; - else { - tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE); - tq->tq_size -= 80; - } - - TAILQ_INIT(&tq->tq_pktlist); - for (i = 0; i < N(tq->tq_pkts); i++) { - tp = &(tq->tq_pkts[i]); - tp->tp_index = i; - tp->tp_queue = tq; - TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list); - } -} - -static uint16_t -bwn_pio_idx2base(struct bwn_mac *mac, int index) -{ - struct bwn_softc *sc = mac->mac_sc; - static const uint16_t bases[] = { - BWN_PIO_BASE0, - BWN_PIO_BASE1, - BWN_PIO_BASE2, - BWN_PIO_BASE3, - BWN_PIO_BASE4, - BWN_PIO_BASE5, - BWN_PIO_BASE6, - BWN_PIO_BASE7, - }; - static const uint16_t bases_rev11[] = { - BWN_PIO11_BASE0, - BWN_PIO11_BASE1, - BWN_PIO11_BASE2, - BWN_PIO11_BASE3, - BWN_PIO11_BASE4, - BWN_PIO11_BASE5, - }; - - if (siba_get_revid(sc->sc_dev) >= 11) { - if (index >= N(bases_rev11)) - device_printf(sc->sc_dev, "%s: warning\n", __func__); - return (bases_rev11[index]); - } - if (index >= N(bases)) - device_printf(sc->sc_dev, "%s: warning\n", __func__); - return (bases[index]); -} - -static void -bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq, - int index) -{ - struct bwn_softc *sc = mac->mac_sc; - - prq->prq_mac = mac; - prq->prq_rev = siba_get_revid(sc->sc_dev); - prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac); - bwn_dma_rxdirectfifo(mac, index, 1); -} - -static void -bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq) -{ - if (tq == NULL) - return; - bwn_pio_cancel_tx_packets(tq); -} - -static void -bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio) -{ - - bwn_destroy_pioqueue_tx(pio); -} - -static uint16_t -bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, - uint16_t offset) -{ - - return (BWN_READ_2(mac, tq->tq_base + offset)); -} - -static void -bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable) -{ - uint32_t ctl; - int type; - uint16_t base; - - type = bwn_dma_mask2type(bwn_dma_mask(mac)); - base = bwn_dma_base(type, idx); - if (type == BWN_DMA_64BIT) { - ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL); - ctl &= ~BWN_DMA64_RXDIRECTFIFO; - if (enable) - ctl |= BWN_DMA64_RXDIRECTFIFO; - BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl); - } else { - ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL); - ctl &= ~BWN_DMA32_RXDIRECTFIFO; - if (enable) - ctl |= BWN_DMA32_RXDIRECTFIFO; - BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl); - } -} - -static uint64_t -bwn_dma_mask(struct bwn_mac *mac) -{ - uint32_t tmp; - uint16_t base; - - tmp = BWN_READ_4(mac, SIBA_TGSHIGH); - if (tmp & SIBA_TGSHIGH_DMA64) - return (BWN_DMA_BIT_MASK(64)); - base = bwn_dma_base(0, 0); - BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK); - tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL); - if (tmp & BWN_DMA32_TXADDREXT_MASK) - return (BWN_DMA_BIT_MASK(32)); - - return (BWN_DMA_BIT_MASK(30)); -} - -static int -bwn_dma_mask2type(uint64_t dmamask) -{ - - if (dmamask == BWN_DMA_BIT_MASK(30)) - return (BWN_DMA_30BIT); - if (dmamask == BWN_DMA_BIT_MASK(32)) - return (BWN_DMA_32BIT); - if (dmamask == BWN_DMA_BIT_MASK(64)) - return (BWN_DMA_64BIT); - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (BWN_DMA_30BIT); -} - -static void -bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq) -{ - struct bwn_pio_txpkt *tp; - unsigned int i; - - for (i = 0; i < N(tq->tq_pkts); i++) { - tp = &(tq->tq_pkts[i]); - if (tp->tp_m) { - m_freem(tp->tp_m); - tp->tp_m = NULL; - } - } -} - -static uint16_t -bwn_dma_base(int type, int controller_idx) -{ - static const uint16_t map64[] = { - BWN_DMA64_BASE0, - BWN_DMA64_BASE1, - BWN_DMA64_BASE2, - BWN_DMA64_BASE3, - BWN_DMA64_BASE4, - BWN_DMA64_BASE5, - }; - static const uint16_t map32[] = { - BWN_DMA32_BASE0, - BWN_DMA32_BASE1, - BWN_DMA32_BASE2, - BWN_DMA32_BASE3, - BWN_DMA32_BASE4, - BWN_DMA32_BASE5, - }; - - if (type == BWN_DMA_64BIT) { - KASSERT(controller_idx >= 0 && controller_idx < N(map64), - ("%s:%d: fail", __func__, __LINE__)); - return (map64[controller_idx]); - } - KASSERT(controller_idx >= 0 && controller_idx < N(map32), - ("%s:%d: fail", __func__, __LINE__)); - return (map32[controller_idx]); -} - -static void -bwn_dma_init(struct bwn_mac *mac) -{ - struct bwn_dma *dma = &mac->mac_method.dma; - - /* setup TX DMA channels. */ - bwn_dma_setup(dma->wme[WME_AC_BK]); - bwn_dma_setup(dma->wme[WME_AC_BE]); - bwn_dma_setup(dma->wme[WME_AC_VI]); - bwn_dma_setup(dma->wme[WME_AC_VO]); - bwn_dma_setup(dma->mcast); - /* setup RX DMA channel. */ - bwn_dma_setup(dma->rx); -} - -static struct bwn_dma_ring * -bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index, - int for_tx, int type) -{ - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_dma_ring *dr; - struct bwn_dmadesc_generic *desc; - struct bwn_dmadesc_meta *mt; - struct bwn_softc *sc = mac->mac_sc; - int error, i; - - dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO); - if (dr == NULL) - goto out; - dr->dr_numslots = BWN_RXRING_SLOTS; - if (for_tx) - dr->dr_numslots = BWN_TXRING_SLOTS; - - dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta), - M_DEVBUF, M_NOWAIT | M_ZERO); - if (dr->dr_meta == NULL) - goto fail0; - - dr->dr_type = type; - dr->dr_mac = mac; - dr->dr_base = bwn_dma_base(type, controller_index); - dr->dr_index = controller_index; - if (type == BWN_DMA_64BIT) { - dr->getdesc = bwn_dma_64_getdesc; - dr->setdesc = bwn_dma_64_setdesc; - dr->start_transfer = bwn_dma_64_start_transfer; - dr->suspend = bwn_dma_64_suspend; - dr->resume = bwn_dma_64_resume; - dr->get_curslot = bwn_dma_64_get_curslot; - dr->set_curslot = bwn_dma_64_set_curslot; - } else { - dr->getdesc = bwn_dma_32_getdesc; - dr->setdesc = bwn_dma_32_setdesc; - dr->start_transfer = bwn_dma_32_start_transfer; - dr->suspend = bwn_dma_32_suspend; - dr->resume = bwn_dma_32_resume; - dr->get_curslot = bwn_dma_32_get_curslot; - dr->set_curslot = bwn_dma_32_set_curslot; - } - if (for_tx) { - dr->dr_tx = 1; - dr->dr_curslot = -1; - } else { - if (dr->dr_index == 0) { - dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE; - dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET; - } else - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - } - - error = bwn_dma_allocringmemory(dr); - if (error) - goto fail2; - - if (for_tx) { - /* - * Assumption: BWN_TXRING_SLOTS can be divided by - * BWN_TX_SLOTS_PER_FRAME - */ - KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0, - ("%s:%d: fail", __func__, __LINE__)); - - dr->dr_txhdr_cache = - malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) * - BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO); - KASSERT(dr->dr_txhdr_cache != NULL, - ("%s:%d: fail", __func__, __LINE__)); - - /* - * Create TX ring DMA stuffs - */ - error = bus_dma_tag_create(dma->parent_dtag, - BWN_ALIGN, 0, - BUS_SPACE_MAXADDR, - BUS_SPACE_MAXADDR, - NULL, NULL, - BWN_HDRSIZE(mac), - 1, - BUS_SPACE_MAXSIZE_32BIT, - 0, - NULL, NULL, - &dr->dr_txring_dtag); - if (error) { - device_printf(sc->sc_dev, - "can't create TX ring DMA tag: TODO frees\n"); - goto fail1; - } - - for (i = 0; i < dr->dr_numslots; i += 2) { - dr->getdesc(dr, i, &desc, &mt); - - mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER; - mt->mt_m = NULL; - mt->mt_ni = NULL; - mt->mt_islast = 0; - error = bus_dmamap_create(dr->dr_txring_dtag, 0, - &mt->mt_dmap); - if (error) { - device_printf(sc->sc_dev, - "can't create RX buf DMA map\n"); - goto fail1; - } - - dr->getdesc(dr, i + 1, &desc, &mt); - - mt->mt_txtype = BWN_DMADESC_METATYPE_BODY; - mt->mt_m = NULL; - mt->mt_ni = NULL; - mt->mt_islast = 1; - error = bus_dmamap_create(dma->txbuf_dtag, 0, - &mt->mt_dmap); - if (error) { - device_printf(sc->sc_dev, - "can't create RX buf DMA map\n"); - goto fail1; - } - } - } else { - error = bus_dmamap_create(dma->rxbuf_dtag, 0, - &dr->dr_spare_dmap); - if (error) { - device_printf(sc->sc_dev, - "can't create RX buf DMA map\n"); - goto out; /* XXX wrong! */ - } - - for (i = 0; i < dr->dr_numslots; i++) { - dr->getdesc(dr, i, &desc, &mt); - - error = bus_dmamap_create(dma->rxbuf_dtag, 0, - &mt->mt_dmap); - if (error) { - device_printf(sc->sc_dev, - "can't create RX buf DMA map\n"); - goto out; /* XXX wrong! */ - } - error = bwn_dma_newbuf(dr, desc, mt, 1); - if (error) { - device_printf(sc->sc_dev, - "failed to allocate RX buf\n"); - goto out; /* XXX wrong! */ - } - } - - bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, - BUS_DMASYNC_PREWRITE); - - dr->dr_usedslot = dr->dr_numslots; - } - - out: - return (dr); - -fail2: - free(dr->dr_txhdr_cache, M_DEVBUF); -fail1: - free(dr->dr_meta, M_DEVBUF); -fail0: - free(dr, M_DEVBUF); - return (NULL); -} - -static void -bwn_dma_ringfree(struct bwn_dma_ring **dr) -{ - - if (dr == NULL) - return; - - bwn_dma_free_descbufs(*dr); - bwn_dma_free_ringmemory(*dr); - - free((*dr)->dr_txhdr_cache, M_DEVBUF); - free((*dr)->dr_meta, M_DEVBUF); - free(*dr, M_DEVBUF); - - *dr = NULL; -} - -static void -bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot, - struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta) -{ - struct bwn_dmadesc32 *desc; - - *meta = &(dr->dr_meta[slot]); - desc = dr->dr_ring_descbase; - desc = &(desc[slot]); - - *gdesc = (struct bwn_dmadesc_generic *)desc; -} - -static void -bwn_dma_32_setdesc(struct bwn_dma_ring *dr, - struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize, - int start, int end, int irq) -{ - struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase; - struct bwn_softc *sc = dr->dr_mac->mac_sc; - uint32_t addr, addrext, ctl; - int slot; - - slot = (int)(&(desc->dma.dma32) - descbase); - KASSERT(slot >= 0 && slot < dr->dr_numslots, - ("%s:%d: fail", __func__, __LINE__)); - - addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK); - addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30; - addr |= siba_dma_translation(sc->sc_dev); - ctl = bufsize & BWN_DMA32_DCTL_BYTECNT; - if (slot == dr->dr_numslots - 1) - ctl |= BWN_DMA32_DCTL_DTABLEEND; - if (start) - ctl |= BWN_DMA32_DCTL_FRAMESTART; - if (end) - ctl |= BWN_DMA32_DCTL_FRAMEEND; - if (irq) - ctl |= BWN_DMA32_DCTL_IRQ; - ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT) - & BWN_DMA32_DCTL_ADDREXT_MASK; - - desc->dma.dma32.control = htole32(ctl); - desc->dma.dma32.address = htole32(addr); -} - -static void -bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot) -{ - - BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX, - (uint32_t)(slot * sizeof(struct bwn_dmadesc32))); -} - -static void -bwn_dma_32_suspend(struct bwn_dma_ring *dr) -{ - - BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, - BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND); -} - -static void -bwn_dma_32_resume(struct bwn_dma_ring *dr) -{ - - BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, - BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND); -} - -static int -bwn_dma_32_get_curslot(struct bwn_dma_ring *dr) -{ - uint32_t val; - - val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS); - val &= BWN_DMA32_RXDPTR; - - return (val / sizeof(struct bwn_dmadesc32)); -} - -static void -bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot) -{ - - BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, - (uint32_t) (slot * sizeof(struct bwn_dmadesc32))); -} - -static void -bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot, - struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta) -{ - struct bwn_dmadesc64 *desc; - - *meta = &(dr->dr_meta[slot]); - desc = dr->dr_ring_descbase; - desc = &(desc[slot]); - - *gdesc = (struct bwn_dmadesc_generic *)desc; -} - -static void -bwn_dma_64_setdesc(struct bwn_dma_ring *dr, - struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize, - int start, int end, int irq) -{ - struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase; - struct bwn_softc *sc = dr->dr_mac->mac_sc; - int slot; - uint32_t ctl0 = 0, ctl1 = 0; - uint32_t addrlo, addrhi; - uint32_t addrext; - - slot = (int)(&(desc->dma.dma64) - descbase); - KASSERT(slot >= 0 && slot < dr->dr_numslots, - ("%s:%d: fail", __func__, __LINE__)); - - addrlo = (uint32_t) (dmaaddr & 0xffffffff); - addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK); - addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >> - 30; - addrhi |= (siba_dma_translation(sc->sc_dev) << 1); - if (slot == dr->dr_numslots - 1) - ctl0 |= BWN_DMA64_DCTL0_DTABLEEND; - if (start) - ctl0 |= BWN_DMA64_DCTL0_FRAMESTART; - if (end) - ctl0 |= BWN_DMA64_DCTL0_FRAMEEND; - if (irq) - ctl0 |= BWN_DMA64_DCTL0_IRQ; - ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT; - ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT) - & BWN_DMA64_DCTL1_ADDREXT_MASK; - - desc->dma.dma64.control0 = htole32(ctl0); - desc->dma.dma64.control1 = htole32(ctl1); - desc->dma.dma64.address_low = htole32(addrlo); - desc->dma.dma64.address_high = htole32(addrhi); -} - -static void -bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot) -{ - - BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX, - (uint32_t)(slot * sizeof(struct bwn_dmadesc64))); -} - -static void -bwn_dma_64_suspend(struct bwn_dma_ring *dr) -{ - - BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, - BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND); -} - -static void -bwn_dma_64_resume(struct bwn_dma_ring *dr) -{ - - BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, - BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND); -} - -static int -bwn_dma_64_get_curslot(struct bwn_dma_ring *dr) -{ - uint32_t val; - - val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS); - val &= BWN_DMA64_RXSTATDPTR; - - return (val / sizeof(struct bwn_dmadesc64)); -} - -static void -bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot) -{ - - BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, - (uint32_t)(slot * sizeof(struct bwn_dmadesc64))); -} - -static int -bwn_dma_allocringmemory(struct bwn_dma_ring *dr) -{ - struct bwn_mac *mac = dr->dr_mac; - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_softc *sc = mac->mac_sc; - int error; - - error = bus_dma_tag_create(dma->parent_dtag, - BWN_ALIGN, 0, - BUS_SPACE_MAXADDR, - BUS_SPACE_MAXADDR, - NULL, NULL, - BWN_DMA_RINGMEMSIZE, - 1, - BUS_SPACE_MAXSIZE_32BIT, - 0, - NULL, NULL, - &dr->dr_ring_dtag); - if (error) { - device_printf(sc->sc_dev, - "can't create TX ring DMA tag: TODO frees\n"); - return (-1); - } - - error = bus_dmamem_alloc(dr->dr_ring_dtag, - &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO, - &dr->dr_ring_dmap); - if (error) { - device_printf(sc->sc_dev, - "can't allocate DMA mem: TODO frees\n"); - return (-1); - } - error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap, - dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE, - bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT); - if (error) { - device_printf(sc->sc_dev, - "can't load DMA mem: TODO free\n"); - return (-1); - } - - return (0); -} - -static void -bwn_dma_setup(struct bwn_dma_ring *dr) -{ - struct bwn_softc *sc = dr->dr_mac->mac_sc; - uint64_t ring64; - uint32_t addrext, ring32, value; - uint32_t trans = siba_dma_translation(sc->sc_dev); - - if (dr->dr_tx) { - dr->dr_curslot = -1; - - if (dr->dr_type == BWN_DMA_64BIT) { - ring64 = (uint64_t)(dr->dr_ring_dmabase); - addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) - >> 30; - value = BWN_DMA64_TXENABLE; - value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT) - & BWN_DMA64_TXADDREXT_MASK; - BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value); - BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, - (ring64 & 0xffffffff)); - BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, - ((ring64 >> 32) & - ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1)); - } else { - ring32 = (uint32_t)(dr->dr_ring_dmabase); - addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30; - value = BWN_DMA32_TXENABLE; - value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT) - & BWN_DMA32_TXADDREXT_MASK; - BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value); - BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, - (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans); - } - return; - } - - /* - * set for RX - */ - dr->dr_usedslot = dr->dr_numslots; - - if (dr->dr_type == BWN_DMA_64BIT) { - ring64 = (uint64_t)(dr->dr_ring_dmabase); - addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30; - value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT); - value |= BWN_DMA64_RXENABLE; - value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT) - & BWN_DMA64_RXADDREXT_MASK; - BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value); - BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff)); - BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, - ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK) - | (trans << 1)); - BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots * - sizeof(struct bwn_dmadesc64)); - } else { - ring32 = (uint32_t)(dr->dr_ring_dmabase); - addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30; - value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT); - value |= BWN_DMA32_RXENABLE; - value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT) - & BWN_DMA32_RXADDREXT_MASK; - BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value); - BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, - (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans); - BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots * - sizeof(struct bwn_dmadesc32)); - } -} - -static void -bwn_dma_free_ringmemory(struct bwn_dma_ring *dr) -{ - - bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap); - bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase, - dr->dr_ring_dmap); -} - -static void -bwn_dma_cleanup(struct bwn_dma_ring *dr) -{ - - if (dr->dr_tx) { - bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type); - if (dr->dr_type == BWN_DMA_64BIT) { - BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0); - BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0); - } else - BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0); - } else { - bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type); - if (dr->dr_type == BWN_DMA_64BIT) { - BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0); - BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0); - } else - BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0); - } -} - -static void -bwn_dma_free_descbufs(struct bwn_dma_ring *dr) -{ - struct bwn_dmadesc_generic *desc; - struct bwn_dmadesc_meta *meta; - struct bwn_mac *mac = dr->dr_mac; - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_softc *sc = mac->mac_sc; - int i; - - if (!dr->dr_usedslot) - return; - for (i = 0; i < dr->dr_numslots; i++) { - dr->getdesc(dr, i, &desc, &meta); - - if (meta->mt_m == NULL) { - if (!dr->dr_tx) - device_printf(sc->sc_dev, "%s: not TX?\n", - __func__); - continue; - } - if (dr->dr_tx) { - if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) - bus_dmamap_unload(dr->dr_txring_dtag, - meta->mt_dmap); - else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) - bus_dmamap_unload(dma->txbuf_dtag, - meta->mt_dmap); - } else - bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap); - bwn_dma_free_descbuf(dr, meta); - } -} - -static int -bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base, - int type) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t value; - int i; - uint16_t offset; - - for (i = 0; i < 10; i++) { - offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS : - BWN_DMA32_TXSTATUS; - value = BWN_READ_4(mac, base + offset); - if (type == BWN_DMA_64BIT) { - value &= BWN_DMA64_TXSTAT; - if (value == BWN_DMA64_TXSTAT_DISABLED || - value == BWN_DMA64_TXSTAT_IDLEWAIT || - value == BWN_DMA64_TXSTAT_STOPPED) - break; - } else { - value &= BWN_DMA32_TXSTATE; - if (value == BWN_DMA32_TXSTAT_DISABLED || - value == BWN_DMA32_TXSTAT_IDLEWAIT || - value == BWN_DMA32_TXSTAT_STOPPED) - break; - } - DELAY(1000); - } - offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL; - BWN_WRITE_4(mac, base + offset, 0); - for (i = 0; i < 10; i++) { - offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS : - BWN_DMA32_TXSTATUS; - value = BWN_READ_4(mac, base + offset); - if (type == BWN_DMA_64BIT) { - value &= BWN_DMA64_TXSTAT; - if (value == BWN_DMA64_TXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= BWN_DMA32_TXSTATE; - if (value == BWN_DMA32_TXSTAT_DISABLED) { - i = -1; - break; - } - } - DELAY(1000); - } - if (i != -1) { - device_printf(sc->sc_dev, "%s: timed out\n", __func__); - return (ENODEV); - } - DELAY(1000); - - return (0); -} - -static int -bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base, - int type) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t value; - int i; - uint16_t offset; - - offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL; - BWN_WRITE_4(mac, base + offset, 0); - for (i = 0; i < 10; i++) { - offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS : - BWN_DMA32_RXSTATUS; - value = BWN_READ_4(mac, base + offset); - if (type == BWN_DMA_64BIT) { - value &= BWN_DMA64_RXSTAT; - if (value == BWN_DMA64_RXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= BWN_DMA32_RXSTATE; - if (value == BWN_DMA32_RXSTAT_DISABLED) { - i = -1; - break; - } - } - DELAY(1000); - } - if (i != -1) { - device_printf(sc->sc_dev, "%s: timed out\n", __func__); - return (ENODEV); - } - - return (0); -} - -static void -bwn_dma_free_descbuf(struct bwn_dma_ring *dr, - struct bwn_dmadesc_meta *meta) -{ - - if (meta->mt_m != NULL) { - m_freem(meta->mt_m); - meta->mt_m = NULL; - } - if (meta->mt_ni != NULL) { - ieee80211_free_node(meta->mt_ni); - meta->mt_ni = NULL; - } -} - -static void -bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m) -{ - struct bwn_rxhdr4 *rxhdr; - unsigned char *frame; - - rxhdr = mtod(m, struct bwn_rxhdr4 *); - rxhdr->frame_len = 0; - - KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset + - sizeof(struct bwn_plcp6) + 2, - ("%s:%d: fail", __func__, __LINE__)); - frame = mtod(m, char *) + dr->dr_frameoffset; - memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */); -} - -static uint8_t -bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m) -{ - unsigned char *f = mtod(m, char *) + dr->dr_frameoffset; - - return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7]) - == 0xff); -} - -static void -bwn_wme_init(struct bwn_mac *mac) -{ - - bwn_wme_load(mac); - - /* enable WME support. */ - bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF); - BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) | - BWN_IFSCTL_USE_EDCF); -} - -static void -bwn_spu_setdelay(struct bwn_mac *mac, int idle) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint16_t delay; /* microsec */ - - delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050; - if (ic->ic_opmode == IEEE80211_M_IBSS || idle) - delay = 500; - if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8)) - delay = max(delay, (uint16_t)2400); - - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay); -} - -static void -bwn_bt_enable(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint64_t hf; - - if (bwn_bluetooth == 0) - return; - if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0) - return; - if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode) - return; - - hf = bwn_hf_read(mac); - if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD) - hf |= BWN_HF_BT_COEXISTALT; - else - hf |= BWN_HF_BT_COEXIST; - bwn_hf_write(mac, hf); -} - -static void -bwn_set_macaddr(struct bwn_mac *mac) -{ - - bwn_mac_write_bssid(mac); - bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, - mac->mac_sc->sc_ic.ic_macaddr); -} - -static void -bwn_clear_keys(struct bwn_mac *mac) -{ - int i; - - for (i = 0; i < mac->mac_max_nr_keys; i++) { - KASSERT(i >= 0 && i < mac->mac_max_nr_keys, - ("%s:%d: fail", __func__, __LINE__)); - - bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE, - NULL, BWN_SEC_KEYSIZE, NULL); - if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) { - bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE, - NULL, BWN_SEC_KEYSIZE, NULL); - } - mac->mac_key[i].keyconf = NULL; - } -} - -static void -bwn_crypt_init(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - - mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20; - KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key), - ("%s:%d: fail", __func__, __LINE__)); - mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP); - mac->mac_ktp *= 2; - if (siba_get_revid(sc->sc_dev) >= 5) - BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8); - bwn_clear_keys(mac); -} - -static void -bwn_chip_exit(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - - bwn_phy_exit(mac); - siba_gpio_set(sc->sc_dev, 0); -} - -static int -bwn_fw_fillinfo(struct bwn_mac *mac) -{ - int error; - - error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT); - if (error == 0) - return (0); - error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE); - if (error == 0) - return (0); - return (error); -} - -static int -bwn_gpio_init(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t mask = 0x1f, set = 0xf, value; - - BWN_WRITE_4(mac, BWN_MACCTL, - BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK); - BWN_WRITE_2(mac, BWN_GPIO_MASK, - BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f); - - if (siba_get_chipid(sc->sc_dev) == 0x4301) { - mask |= 0x0060; - set |= 0x0060; - } - if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) { - BWN_WRITE_2(mac, BWN_GPIO_MASK, - BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200); - mask |= 0x0200; - set |= 0x0200; - } - if (siba_get_revid(sc->sc_dev) >= 2) - mask |= 0x0010; - - value = siba_gpio_get(sc->sc_dev); - if (value == -1) - return (0); - siba_gpio_set(sc->sc_dev, (value & mask) | set); - - return (0); -} - -static int -bwn_fw_loadinitvals(struct bwn_mac *mac) -{ -#define GETFWOFFSET(fwp, offset) \ - ((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset)) - const size_t hdr_len = sizeof(struct bwn_fwhdr); - const struct bwn_fwhdr *hdr; - struct bwn_fw *fw = &mac->mac_fw; - int error; - - hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data); - error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len), - be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len); - if (error) - return (error); - if (fw->initvals_band.fw) { - hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data); - error = bwn_fwinitvals_write(mac, - GETFWOFFSET(fw->initvals_band, hdr_len), - be32toh(hdr->size), - fw->initvals_band.fw->datasize - hdr_len); - } - return (error); -#undef GETFWOFFSET -} - -static int -bwn_phy_init(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - int error; - - mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac); - mac->mac_phy.rf_onoff(mac, 1); - error = mac->mac_phy.init(mac); - if (error) { - device_printf(sc->sc_dev, "PHY init failed\n"); - goto fail0; - } - error = bwn_switch_channel(mac, - mac->mac_phy.get_default_chan(mac)); - if (error) { - device_printf(sc->sc_dev, - "failed to switch default channel\n"); - goto fail1; - } - return (0); -fail1: - if (mac->mac_phy.exit) - mac->mac_phy.exit(mac); -fail0: - mac->mac_phy.rf_onoff(mac, 0); - - return (error); -} - -static void -bwn_set_txantenna(struct bwn_mac *mac, int antenna) -{ - uint16_t ant; - uint16_t tmp; - - ant = bwn_ant2phy(antenna); - - /* For ACK/CTS */ - tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL); - tmp = (tmp & ~BWN_TX_PHY_ANT) | ant; - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp); - /* For Probe Resposes */ - tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL); - tmp = (tmp & ~BWN_TX_PHY_ANT) | ant; - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp); -} - -static void -bwn_set_opmode(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint32_t ctl; - uint16_t cfp_pretbtt; - - ctl = BWN_READ_4(mac, BWN_MACCTL); - ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL | - BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS | - BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC); - ctl |= BWN_MACCTL_STA; - - if (ic->ic_opmode == IEEE80211_M_HOSTAP || - ic->ic_opmode == IEEE80211_M_MBSS) - ctl |= BWN_MACCTL_HOSTAP; - else if (ic->ic_opmode == IEEE80211_M_IBSS) - ctl &= ~BWN_MACCTL_STA; - ctl |= sc->sc_filters; - - if (siba_get_revid(sc->sc_dev) <= 4) - ctl |= BWN_MACCTL_PROMISC; - - BWN_WRITE_4(mac, BWN_MACCTL, ctl); - - cfp_pretbtt = 2; - if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) { - if (siba_get_chipid(sc->sc_dev) == 0x4306 && - siba_get_chiprev(sc->sc_dev) == 3) - cfp_pretbtt = 100; - else - cfp_pretbtt = 50; - } - BWN_WRITE_2(mac, 0x612, cfp_pretbtt); -} - -static int -bwn_dma_gettype(struct bwn_mac *mac) -{ - uint32_t tmp; - uint16_t base; - - tmp = BWN_READ_4(mac, SIBA_TGSHIGH); - if (tmp & SIBA_TGSHIGH_DMA64) - return (BWN_DMA_64BIT); - base = bwn_dma_base(0, 0); - BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK); - tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL); - if (tmp & BWN_DMA32_TXADDREXT_MASK) - return (BWN_DMA_32BIT); - - return (BWN_DMA_30BIT); -} - -static void -bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) -{ - if (!error) { - KASSERT(nseg == 1, ("too many segments(%d)\n", nseg)); - *((bus_addr_t *)arg) = seg->ds_addr; - } -} - -void -bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon) -{ - struct bwn_phy *phy = &mac->mac_phy; - struct bwn_softc *sc = mac->mac_sc; - unsigned int i, max_loop; - uint16_t value; - uint32_t buffer[5] = { - 0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 - }; - - if (ofdm) { - max_loop = 0x1e; - buffer[0] = 0x000201cc; - } else { - max_loop = 0xfa; - buffer[0] = 0x000b846e; - } - - BWN_ASSERT_LOCKED(mac->mac_sc); - - for (i = 0; i < 5; i++) - bwn_ram_write(mac, i * 4, buffer[i]); - - BWN_WRITE_2(mac, 0x0568, 0x0000); - BWN_WRITE_2(mac, 0x07c0, - (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100); - - value = (ofdm ? 0x41 : 0x40); - BWN_WRITE_2(mac, 0x050c, value); - - if (phy->type == BWN_PHYTYPE_N || phy->type == BWN_PHYTYPE_LP || - phy->type == BWN_PHYTYPE_LCN) - BWN_WRITE_2(mac, 0x0514, 0x1a02); - BWN_WRITE_2(mac, 0x0508, 0x0000); - BWN_WRITE_2(mac, 0x050a, 0x0000); - BWN_WRITE_2(mac, 0x054c, 0x0000); - BWN_WRITE_2(mac, 0x056a, 0x0014); - BWN_WRITE_2(mac, 0x0568, 0x0826); - BWN_WRITE_2(mac, 0x0500, 0x0000); - - /* XXX TODO: n phy pa override? */ - - switch (phy->type) { - case BWN_PHYTYPE_N: - case BWN_PHYTYPE_LCN: - BWN_WRITE_2(mac, 0x0502, 0x00d0); - break; - case BWN_PHYTYPE_LP: - BWN_WRITE_2(mac, 0x0502, 0x0050); - break; - default: - BWN_WRITE_2(mac, 0x0502, 0x0030); - break; - } - - /* flush */ - BWN_READ_2(mac, 0x0502); - - if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5) - BWN_RF_WRITE(mac, 0x0051, 0x0017); - for (i = 0x00; i < max_loop; i++) { - value = BWN_READ_2(mac, 0x050e); - if (value & 0x0080) - break; - DELAY(10); - } - for (i = 0x00; i < 0x0a; i++) { - value = BWN_READ_2(mac, 0x050e); - if (value & 0x0400) - break; - DELAY(10); - } - for (i = 0x00; i < 0x19; i++) { - value = BWN_READ_2(mac, 0x0690); - if (!(value & 0x0100)) - break; - DELAY(10); - } - if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5) - BWN_RF_WRITE(mac, 0x0051, 0x0037); -} - -void -bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val) -{ - uint32_t macctl; - - KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__)); - - macctl = BWN_READ_4(mac, BWN_MACCTL); - if (macctl & BWN_MACCTL_BIGENDIAN) - printf("TODO: need swap\n"); - - BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset); - BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE); - BWN_WRITE_4(mac, BWN_RAM_DATA, val); -} - -void -bwn_mac_suspend(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - int i; - uint32_t tmp; - - KASSERT(mac->mac_suspended >= 0, - ("%s:%d: fail", __func__, __LINE__)); - - if (mac->mac_suspended == 0) { - bwn_psctl(mac, BWN_PS_AWAKE); - BWN_WRITE_4(mac, BWN_MACCTL, - BWN_READ_4(mac, BWN_MACCTL) - & ~BWN_MACCTL_ON); - BWN_READ_4(mac, BWN_MACCTL); - for (i = 35; i; i--) { - tmp = BWN_READ_4(mac, BWN_INTR_REASON); - if (tmp & BWN_INTR_MAC_SUSPENDED) - goto out; - DELAY(10); - } - for (i = 40; i; i--) { - tmp = BWN_READ_4(mac, BWN_INTR_REASON); - if (tmp & BWN_INTR_MAC_SUSPENDED) - goto out; - DELAY(1000); - } - device_printf(sc->sc_dev, "MAC suspend failed\n"); - } -out: - mac->mac_suspended++; -} - -void -bwn_mac_enable(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint16_t state; - - state = bwn_shm_read_2(mac, BWN_SHARED, - BWN_SHARED_UCODESTAT); - if (state != BWN_SHARED_UCODESTAT_SUSPEND && - state != BWN_SHARED_UCODESTAT_SLEEP) - device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state); - - mac->mac_suspended--; - KASSERT(mac->mac_suspended >= 0, - ("%s:%d: fail", __func__, __LINE__)); - if (mac->mac_suspended == 0) { - BWN_WRITE_4(mac, BWN_MACCTL, - BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON); - BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED); - BWN_READ_4(mac, BWN_MACCTL); - BWN_READ_4(mac, BWN_INTR_REASON); - bwn_psctl(mac, 0); - } -} - -void -bwn_psctl(struct bwn_mac *mac, uint32_t flags) -{ - struct bwn_softc *sc = mac->mac_sc; - int i; - uint16_t ucstat; - - KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)), - ("%s:%d: fail", __func__, __LINE__)); - KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)), - ("%s:%d: fail", __func__, __LINE__)); - - /* XXX forcibly awake and hwps-off */ - - BWN_WRITE_4(mac, BWN_MACCTL, - (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) & - ~BWN_MACCTL_HWPS); - BWN_READ_4(mac, BWN_MACCTL); - if (siba_get_revid(sc->sc_dev) >= 5) { - for (i = 0; i < 100; i++) { - ucstat = bwn_shm_read_2(mac, BWN_SHARED, - BWN_SHARED_UCODESTAT); - if (ucstat != BWN_SHARED_UCODESTAT_SLEEP) - break; - DELAY(10); - } - } -} - -static int -bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type) -{ - struct bwn_softc *sc = mac->mac_sc; - struct bwn_fw *fw = &mac->mac_fw; - const uint8_t rev = siba_get_revid(sc->sc_dev); - const char *filename; - uint32_t high; - int error; - - /* microcode */ - if (rev >= 5 && rev <= 10) - filename = "ucode5"; - else if (rev >= 11 && rev <= 12) - filename = "ucode11"; - else if (rev == 13) - filename = "ucode13"; - else if (rev == 14) - filename = "ucode14"; - else if (rev >= 15) - filename = "ucode15"; - else { - device_printf(sc->sc_dev, "no ucode for rev %d\n", rev); - bwn_release_firmware(mac); - return (EOPNOTSUPP); - } - error = bwn_fw_get(mac, type, filename, &fw->ucode); - if (error) { - bwn_release_firmware(mac); - return (error); - } - - /* PCM */ - KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__)); - if (rev >= 5 && rev <= 10) { - error = bwn_fw_get(mac, type, "pcm5", &fw->pcm); - if (error == ENOENT) - fw->no_pcmfile = 1; - else if (error) { - bwn_release_firmware(mac); - return (error); - } - } else if (rev < 11) { - device_printf(sc->sc_dev, "no PCM for rev %d\n", rev); - return (EOPNOTSUPP); - } - - /* initvals */ - high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH); - switch (mac->mac_phy.type) { - case BWN_PHYTYPE_A: - if (rev < 5 || rev > 10) - goto fail1; - if (high & BWN_TGSHIGH_HAVE_2GHZ) - filename = "a0g1initvals5"; - else - filename = "a0g0initvals5"; - break; - case BWN_PHYTYPE_G: - if (rev >= 5 && rev <= 10) - filename = "b0g0initvals5"; - else if (rev >= 13) - filename = "b0g0initvals13"; - else - goto fail1; - break; - case BWN_PHYTYPE_LP: - if (rev == 13) - filename = "lp0initvals13"; - else if (rev == 14) - filename = "lp0initvals14"; - else if (rev >= 15) - filename = "lp0initvals15"; - else - goto fail1; - break; - case BWN_PHYTYPE_N: - if (rev >= 11 && rev <= 12) - filename = "n0initvals11"; - else - goto fail1; - break; - default: - goto fail1; - } - error = bwn_fw_get(mac, type, filename, &fw->initvals); - if (error) { - bwn_release_firmware(mac); - return (error); - } - - /* bandswitch initvals */ - switch (mac->mac_phy.type) { - case BWN_PHYTYPE_A: - if (rev >= 5 && rev <= 10) { - if (high & BWN_TGSHIGH_HAVE_2GHZ) - filename = "a0g1bsinitvals5"; - else - filename = "a0g0bsinitvals5"; - } else if (rev >= 11) - filename = NULL; - else - goto fail1; - break; - case BWN_PHYTYPE_G: - if (rev >= 5 && rev <= 10) - filename = "b0g0bsinitvals5"; - else if (rev >= 11) - filename = NULL; - else - goto fail1; - break; - case BWN_PHYTYPE_LP: - if (rev == 13) - filename = "lp0bsinitvals13"; - else if (rev == 14) - filename = "lp0bsinitvals14"; - else if (rev >= 15) - filename = "lp0bsinitvals15"; - else - goto fail1; - break; - case BWN_PHYTYPE_N: - if (rev >= 11 && rev <= 12) - filename = "n0bsinitvals11"; - else - goto fail1; - break; - default: - goto fail1; - } - error = bwn_fw_get(mac, type, filename, &fw->initvals_band); - if (error) { - bwn_release_firmware(mac); - return (error); - } - return (0); -fail1: - device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev); - bwn_release_firmware(mac); - return (EOPNOTSUPP); -} - -static int -bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type, - const char *name, struct bwn_fwfile *bfw) -{ - const struct bwn_fwhdr *hdr; - struct bwn_softc *sc = mac->mac_sc; - const struct firmware *fw; - char namebuf[64]; - - if (name == NULL) { - bwn_do_release_fw(bfw); - return (0); - } - if (bfw->filename != NULL) { - if (bfw->type == type && (strcmp(bfw->filename, name) == 0)) - return (0); - bwn_do_release_fw(bfw); - } - - snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s", - (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "", - (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name); - /* XXX Sleeping on "fwload" with the non-sleepable locks held */ - fw = firmware_get(namebuf); - if (fw == NULL) { - device_printf(sc->sc_dev, "the fw file(%s) not found\n", - namebuf); - return (ENOENT); - } - if (fw->datasize < sizeof(struct bwn_fwhdr)) - goto fail; - hdr = (const struct bwn_fwhdr *)(fw->data); - switch (hdr->type) { - case BWN_FWTYPE_UCODE: - case BWN_FWTYPE_PCM: - if (be32toh(hdr->size) != - (fw->datasize - sizeof(struct bwn_fwhdr))) - goto fail; - /* FALLTHROUGH */ - case BWN_FWTYPE_IV: - if (hdr->ver != 1) - goto fail; - break; - default: - goto fail; - } - bfw->filename = name; - bfw->fw = fw; - bfw->type = type; - return (0); -fail: - device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf); - if (fw != NULL) - firmware_put(fw, FIRMWARE_UNLOAD); - return (EPROTO); -} - -static void -bwn_release_firmware(struct bwn_mac *mac) -{ - - bwn_do_release_fw(&mac->mac_fw.ucode); - bwn_do_release_fw(&mac->mac_fw.pcm); - bwn_do_release_fw(&mac->mac_fw.initvals); - bwn_do_release_fw(&mac->mac_fw.initvals_band); -} - -static void -bwn_do_release_fw(struct bwn_fwfile *bfw) -{ - - if (bfw->fw != NULL) - firmware_put(bfw->fw, FIRMWARE_UNLOAD); - bfw->fw = NULL; - bfw->filename = NULL; -} - -static int -bwn_fw_loaducode(struct bwn_mac *mac) -{ -#define GETFWOFFSET(fwp, offset) \ - ((const uint32_t *)((const char *)fwp.fw->data + offset)) -#define GETFWSIZE(fwp, offset) \ - ((fwp.fw->datasize - offset) / sizeof(uint32_t)) - struct bwn_softc *sc = mac->mac_sc; - const uint32_t *data; - unsigned int i; - uint32_t ctl; - uint16_t date, fwcaps, time; - int error = 0; - - ctl = BWN_READ_4(mac, BWN_MACCTL); - ctl |= BWN_MACCTL_MCODE_JMP0; - KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__, - __LINE__)); - BWN_WRITE_4(mac, BWN_MACCTL, ctl); - for (i = 0; i < 64; i++) - bwn_shm_write_2(mac, BWN_SCRATCH, i, 0); - for (i = 0; i < 4096; i += 2) - bwn_shm_write_2(mac, BWN_SHARED, i, 0); - - data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr)); - bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000); - for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr)); - i++) { - BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i])); - DELAY(10); - } - - if (mac->mac_fw.pcm.fw) { - data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr)); - bwn_shm_ctlword(mac, BWN_HW, 0x01ea); - BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000); - bwn_shm_ctlword(mac, BWN_HW, 0x01eb); - for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm, - sizeof(struct bwn_fwhdr)); i++) { - BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i])); - DELAY(10); - } - } - - BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL); - BWN_WRITE_4(mac, BWN_MACCTL, - (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) | - BWN_MACCTL_MCODE_RUN); - - for (i = 0; i < 21; i++) { - if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED) - break; - if (i >= 20) { - device_printf(sc->sc_dev, "ucode timeout\n"); - error = ENXIO; - goto error; - } - DELAY(50000); - } - BWN_READ_4(mac, BWN_INTR_REASON); - - mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV); - if (mac->mac_fw.rev <= 0x128) { - device_printf(sc->sc_dev, "the firmware is too old\n"); - error = EOPNOTSUPP; - goto error; - } - mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED, - BWN_SHARED_UCODE_PATCH); - date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE); - mac->mac_fw.opensource = (date == 0xffff); - if (bwn_wme != 0) - mac->mac_flags |= BWN_MAC_FLAG_WME; - mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO; - - time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME); - if (mac->mac_fw.opensource == 0) { - device_printf(sc->sc_dev, - "firmware version (rev %u patch %u date %#x time %#x)\n", - mac->mac_fw.rev, mac->mac_fw.patch, date, time); - if (mac->mac_fw.no_pcmfile) - device_printf(sc->sc_dev, - "no HW crypto acceleration due to pcm5\n"); - } else { - mac->mac_fw.patch = time; - fwcaps = bwn_fwcaps_read(mac); - if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) { - device_printf(sc->sc_dev, - "disabling HW crypto acceleration\n"); - mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO; - } - if (!(fwcaps & BWN_FWCAPS_WME)) { - device_printf(sc->sc_dev, "disabling WME support\n"); - mac->mac_flags &= ~BWN_MAC_FLAG_WME; - } - } - - if (BWN_ISOLDFMT(mac)) - device_printf(sc->sc_dev, "using old firmware image\n"); - - return (0); - -error: - BWN_WRITE_4(mac, BWN_MACCTL, - (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) | - BWN_MACCTL_MCODE_JMP0); - - return (error); -#undef GETFWSIZE -#undef GETFWOFFSET -} - -/* OpenFirmware only */ -static uint16_t -bwn_fwcaps_read(struct bwn_mac *mac) -{ - - KASSERT(mac->mac_fw.opensource == 1, - ("%s:%d: fail", __func__, __LINE__)); - return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS)); -} - -static int -bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals, - size_t count, size_t array_size) -{ -#define GET_NEXTIV16(iv) \ - ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \ - sizeof(uint16_t) + sizeof(uint16_t))) -#define GET_NEXTIV32(iv) \ - ((const struct bwn_fwinitvals *)((const uint8_t *)(iv) + \ - sizeof(uint16_t) + sizeof(uint32_t))) - struct bwn_softc *sc = mac->mac_sc; - const struct bwn_fwinitvals *iv; - uint16_t offset; - size_t i; - uint8_t bit32; - - KASSERT(sizeof(struct bwn_fwinitvals) == 6, - ("%s:%d: fail", __func__, __LINE__)); - iv = ivals; - for (i = 0; i < count; i++) { - if (array_size < sizeof(iv->offset_size)) - goto fail; - array_size -= sizeof(iv->offset_size); - offset = be16toh(iv->offset_size); - bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0; - offset &= BWN_FWINITVALS_OFFSET_MASK; - if (offset >= 0x1000) - goto fail; - if (bit32) { - if (array_size < sizeof(iv->data.d32)) - goto fail; - array_size -= sizeof(iv->data.d32); - BWN_WRITE_4(mac, offset, be32toh(iv->data.d32)); - iv = GET_NEXTIV32(iv); - } else { - - if (array_size < sizeof(iv->data.d16)) - goto fail; - array_size -= sizeof(iv->data.d16); - BWN_WRITE_2(mac, offset, be16toh(iv->data.d16)); - - iv = GET_NEXTIV16(iv); - } - } - if (array_size != 0) - goto fail; - return (0); -fail: - device_printf(sc->sc_dev, "initvals: invalid format\n"); - return (EPROTO); -#undef GET_NEXTIV16 -#undef GET_NEXTIV32 -} - -int -bwn_switch_channel(struct bwn_mac *mac, int chan) -{ - struct bwn_phy *phy = &(mac->mac_phy); - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint16_t channelcookie, savedcookie; - int error; - - if (chan == 0xffff) - chan = phy->get_default_chan(mac); - - channelcookie = chan; - if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) - channelcookie |= 0x100; - savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie); - error = phy->switch_channel(mac, chan); - if (error) - goto fail; - - mac->mac_phy.chan = chan; - DELAY(8000); - return (0); -fail: - device_printf(sc->sc_dev, "failed to switch channel\n"); - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie); - return (error); -} - -static uint16_t -bwn_ant2phy(int antenna) -{ - - switch (antenna) { - case BWN_ANT0: - return (BWN_TX_PHY_ANT0); - case BWN_ANT1: - return (BWN_TX_PHY_ANT1); - case BWN_ANT2: - return (BWN_TX_PHY_ANT2); - case BWN_ANT3: - return (BWN_TX_PHY_ANT3); - case BWN_ANTAUTO: - return (BWN_TX_PHY_ANT01AUTO); - } - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (0); -} - -static void -bwn_wme_load(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - int i; - - KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams), - ("%s:%d: fail", __func__, __LINE__)); - - bwn_mac_suspend(mac); - for (i = 0; i < N(sc->sc_wmeParams); i++) - bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]), - bwn_wme_shm_offsets[i]); - bwn_mac_enable(mac); -} - -static void -bwn_wme_loadparams(struct bwn_mac *mac, - const struct wmeParams *p, uint16_t shm_offset) -{ -#define SM(_v, _f) (((_v) << _f##_S) & _f) - struct bwn_softc *sc = mac->mac_sc; - uint16_t params[BWN_NR_WMEPARAMS]; - int slot, tmp; - unsigned int i; - - slot = BWN_READ_2(mac, BWN_RNG) & - SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN); - - memset(¶ms, 0, sizeof(params)); - - DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d " - "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit, - p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn); - - params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32; - params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN); - params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX); - params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN); - params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn; - params[BWN_WMEPARAM_BSLOTS] = slot; - params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn; - - for (i = 0; i < N(params); i++) { - if (i == BWN_WMEPARAM_STATUS) { - tmp = bwn_shm_read_2(mac, BWN_SHARED, - shm_offset + (i * 2)); - tmp |= 0x100; - bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2), - tmp); - } else { - bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2), - params[i]); - } - } -} - -static void -bwn_mac_write_bssid(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t tmp; - int i; - uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2]; - - bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid); - memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN); - memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid, - IEEE80211_ADDR_LEN); - - for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) { - tmp = (uint32_t) (mac_bssid[i + 0]); - tmp |= (uint32_t) (mac_bssid[i + 1]) << 8; - tmp |= (uint32_t) (mac_bssid[i + 2]) << 16; - tmp |= (uint32_t) (mac_bssid[i + 3]) << 24; - bwn_ram_write(mac, 0x20 + i, tmp); - } -} - -static void -bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset, - const uint8_t *macaddr) -{ - static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 }; - uint16_t data; - - if (!mac) - macaddr = zero; - - offset |= 0x0020; - BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset); - - data = macaddr[0]; - data |= macaddr[1] << 8; - BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data); - data = macaddr[2]; - data |= macaddr[3] << 8; - BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data); - data = macaddr[4]; - data |= macaddr[5] << 8; - BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data); -} - -static void -bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm, - const uint8_t *key, size_t key_len, const uint8_t *mac_addr) -{ - uint8_t buf[BWN_SEC_KEYSIZE] = { 0, }; - uint8_t per_sta_keys_start = 8; - - if (BWN_SEC_NEWAPI(mac)) - per_sta_keys_start = 4; - - KASSERT(index < mac->mac_max_nr_keys, - ("%s:%d: fail", __func__, __LINE__)); - KASSERT(key_len <= BWN_SEC_KEYSIZE, - ("%s:%d: fail", __func__, __LINE__)); - - if (index >= per_sta_keys_start) - bwn_key_macwrite(mac, index, NULL); - if (key) - memcpy(buf, key, key_len); - bwn_key_write(mac, index, algorithm, buf); - if (index >= per_sta_keys_start) - bwn_key_macwrite(mac, index, mac_addr); - - mac->mac_key[index].algorithm = algorithm; -} - -static void -bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t addrtmp[2] = { 0, 0 }; - uint8_t start = 8; - - if (BWN_SEC_NEWAPI(mac)) - start = 4; - - KASSERT(index >= start, - ("%s:%d: fail", __func__, __LINE__)); - index -= start; - - if (addr) { - addrtmp[0] = addr[0]; - addrtmp[0] |= ((uint32_t) (addr[1]) << 8); - addrtmp[0] |= ((uint32_t) (addr[2]) << 16); - addrtmp[0] |= ((uint32_t) (addr[3]) << 24); - addrtmp[1] = addr[4]; - addrtmp[1] |= ((uint32_t) (addr[5]) << 8); - } - - if (siba_get_revid(sc->sc_dev) >= 5) { - bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]); - bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]); - } else { - if (index >= 8) { - bwn_shm_write_4(mac, BWN_SHARED, - BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]); - bwn_shm_write_2(mac, BWN_SHARED, - BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]); - } - } -} - -static void -bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm, - const uint8_t *key) -{ - unsigned int i; - uint32_t offset; - uint16_t kidx, value; - - kidx = BWN_SEC_KEY2FW(mac, index); - bwn_shm_write_2(mac, BWN_SHARED, - BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm); - - offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE); - for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) { - value = key[i]; - value |= (uint16_t)(key[i + 1]) << 8; - bwn_shm_write_2(mac, BWN_SHARED, offset + i, value); - } -} - -static void -bwn_phy_exit(struct bwn_mac *mac) -{ - - mac->mac_phy.rf_onoff(mac, 0); - if (mac->mac_phy.exit != NULL) - mac->mac_phy.exit(mac); -} - -static void -bwn_dma_free(struct bwn_mac *mac) -{ - struct bwn_dma *dma; - - if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0) - return; - dma = &mac->mac_method.dma; - - bwn_dma_ringfree(&dma->rx); - bwn_dma_ringfree(&dma->wme[WME_AC_BK]); - bwn_dma_ringfree(&dma->wme[WME_AC_BE]); - bwn_dma_ringfree(&dma->wme[WME_AC_VI]); - bwn_dma_ringfree(&dma->wme[WME_AC_VO]); - bwn_dma_ringfree(&dma->mcast); -} - -static void -bwn_core_stop(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - - BWN_ASSERT_LOCKED(sc); - - if (mac->mac_status < BWN_MAC_STATUS_STARTED) - return; - - callout_stop(&sc->sc_rfswitch_ch); - callout_stop(&sc->sc_task_ch); - callout_stop(&sc->sc_watchdog_ch); - sc->sc_watchdog_timer = 0; - BWN_WRITE_4(mac, BWN_INTR_MASK, 0); - BWN_READ_4(mac, BWN_INTR_MASK); - bwn_mac_suspend(mac); - - mac->mac_status = BWN_MAC_STATUS_INITED; -} - -static int -bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan) -{ - struct bwn_mac *up_dev = NULL; - struct bwn_mac *down_dev; - struct bwn_mac *mac; - int err, status; - uint8_t gmode; - - BWN_ASSERT_LOCKED(sc); - - TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) { - if (IEEE80211_IS_CHAN_2GHZ(chan) && - mac->mac_phy.supports_2ghz) { - up_dev = mac; - gmode = 1; - } else if (IEEE80211_IS_CHAN_5GHZ(chan) && - mac->mac_phy.supports_5ghz) { - up_dev = mac; - gmode = 0; - } else { - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (EINVAL); - } - if (up_dev != NULL) - break; - } - if (up_dev == NULL) { - device_printf(sc->sc_dev, "Could not find a device\n"); - return (ENODEV); - } - if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode) - return (0); - - device_printf(sc->sc_dev, "switching to %s-GHz band\n", - IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5"); - - down_dev = sc->sc_curmac; - status = down_dev->mac_status; - if (status >= BWN_MAC_STATUS_STARTED) - bwn_core_stop(down_dev); - if (status >= BWN_MAC_STATUS_INITED) - bwn_core_exit(down_dev); - - if (down_dev != up_dev) - bwn_phy_reset(down_dev); - - up_dev->mac_phy.gmode = gmode; - if (status >= BWN_MAC_STATUS_INITED) { - err = bwn_core_init(up_dev); - if (err) { - device_printf(sc->sc_dev, - "fatal: failed to initialize for %s-GHz\n", - IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5"); - goto fail; - } - } - if (status >= BWN_MAC_STATUS_STARTED) - bwn_core_start(up_dev); - KASSERT(up_dev->mac_status == status, ("%s: fail", __func__)); - sc->sc_curmac = up_dev; - - return (0); -fail: - sc->sc_curmac = NULL; - return (err); -} - -static void -bwn_rf_turnon(struct bwn_mac *mac) -{ - - bwn_mac_suspend(mac); - mac->mac_phy.rf_onoff(mac, 1); - mac->mac_phy.rf_on = 1; - bwn_mac_enable(mac); -} - -static void -bwn_rf_turnoff(struct bwn_mac *mac) -{ - - bwn_mac_suspend(mac); - mac->mac_phy.rf_onoff(mac, 0); - mac->mac_phy.rf_on = 0; - bwn_mac_enable(mac); -} - -static void -bwn_phy_reset(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - - siba_write_4(sc->sc_dev, SIBA_TGSLOW, - ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) | - BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC); - DELAY(1000); - siba_write_4(sc->sc_dev, SIBA_TGSLOW, - (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) | - BWN_TGSLOW_PHYRESET); - DELAY(1000); -} - -static int -bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct bwn_vap *bvp = BWN_VAP(vap); - struct ieee80211com *ic= vap->iv_ic; - enum ieee80211_state ostate = vap->iv_state; - struct bwn_softc *sc = ic->ic_softc; - struct bwn_mac *mac = sc->sc_curmac; - int error; - - DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - error = bvp->bv_newstate(vap, nstate, arg); - if (error != 0) - return (error); - - BWN_LOCK(sc); - - bwn_led_newstate(mac, nstate); - - /* - * Clear the BSSID when we stop a STA - */ - if (vap->iv_opmode == IEEE80211_M_STA) { - if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) { - /* - * Clear out the BSSID. If we reassociate to - * the same AP, this will reinialize things - * correctly... - */ - if (ic->ic_opmode == IEEE80211_M_STA && - (sc->sc_flags & BWN_FLAG_INVALID) == 0) { - memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN); - bwn_set_macaddr(mac); - } - } - } - - if (vap->iv_opmode == IEEE80211_M_MONITOR || - vap->iv_opmode == IEEE80211_M_AHDEMO) { - /* XXX nothing to do? */ - } else if (nstate == IEEE80211_S_RUN) { - memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN); - bwn_set_opmode(mac); - bwn_set_pretbtt(mac); - bwn_spu_setdelay(mac, 0); - bwn_set_macaddr(mac); - } - - BWN_UNLOCK(sc); - - return (error); -} - -static void -bwn_set_pretbtt(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint16_t pretbtt; - - if (ic->ic_opmode == IEEE80211_M_IBSS) - pretbtt = 2; - else - pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250; - bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt); - BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt); -} - -static int -bwn_intr(void *arg) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - uint32_t reason; - - if (mac->mac_status < BWN_MAC_STATUS_STARTED || - (sc->sc_flags & BWN_FLAG_INVALID)) - return (FILTER_STRAY); - - reason = BWN_READ_4(mac, BWN_INTR_REASON); - if (reason == 0xffffffff) /* shared IRQ */ - return (FILTER_STRAY); - reason &= mac->mac_intr_mask; - if (reason == 0) - return (FILTER_HANDLED); - - mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00; - mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00; - mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00; - mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00; - mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00; - BWN_WRITE_4(mac, BWN_INTR_REASON, reason); - BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]); - BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]); - BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]); - BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]); - BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]); - - /* Disable interrupts. */ - BWN_WRITE_4(mac, BWN_INTR_MASK, 0); - - mac->mac_reason_intr = reason; - - BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ); - BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE); - - taskqueue_enqueue(sc->sc_tq, &mac->mac_intrtask); - return (FILTER_HANDLED); -} - -static void -bwn_intrtask(void *arg, int npending) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - uint32_t merged = 0; - int i, tx = 0, rx = 0; - - BWN_LOCK(sc); - if (mac->mac_status < BWN_MAC_STATUS_STARTED || - (sc->sc_flags & BWN_FLAG_INVALID)) { - BWN_UNLOCK(sc); - return; - } - - for (i = 0; i < N(mac->mac_reason); i++) - merged |= mac->mac_reason[i]; - - if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR) - device_printf(sc->sc_dev, "MAC trans error\n"); - - if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) { - DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__); - mac->mac_phy.txerrors--; - if (mac->mac_phy.txerrors == 0) { - mac->mac_phy.txerrors = BWN_TXERROR_MAX; - bwn_restart(mac, "PHY TX errors"); - } - } - - if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) { - if (merged & BWN_DMAINTR_FATALMASK) { - device_printf(sc->sc_dev, - "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n", - mac->mac_reason[0], mac->mac_reason[1], - mac->mac_reason[2], mac->mac_reason[3], - mac->mac_reason[4], mac->mac_reason[5]); - bwn_restart(mac, "DMA error"); - BWN_UNLOCK(sc); - return; - } - if (merged & BWN_DMAINTR_NONFATALMASK) { - device_printf(sc->sc_dev, - "DMA error: %#x %#x %#x %#x %#x %#x\n", - mac->mac_reason[0], mac->mac_reason[1], - mac->mac_reason[2], mac->mac_reason[3], - mac->mac_reason[4], mac->mac_reason[5]); - } - } - - if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG) - bwn_intr_ucode_debug(mac); - if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI) - bwn_intr_tbtt_indication(mac); - if (mac->mac_reason_intr & BWN_INTR_ATIM_END) - bwn_intr_atim_end(mac); - if (mac->mac_reason_intr & BWN_INTR_BEACON) - bwn_intr_beacon(mac); - if (mac->mac_reason_intr & BWN_INTR_PMQ) - bwn_intr_pmq(mac); - if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK) - bwn_intr_noise(mac); - - if (mac->mac_flags & BWN_MAC_FLAG_DMA) { - if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) { - bwn_dma_rx(mac->mac_method.dma.rx); - rx = 1; - } - } else - rx = bwn_pio_rx(&mac->mac_method.pio.rx); - - KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); - KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); - KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); - KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); - KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__)); - - if (mac->mac_reason_intr & BWN_INTR_TX_OK) { - bwn_intr_txeof(mac); - tx = 1; - } - - BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask); - - if (sc->sc_blink_led != NULL && sc->sc_led_blink) { - int evt = BWN_LED_EVENT_NONE; - - if (tx && rx) { - if (sc->sc_rx_rate > sc->sc_tx_rate) - evt = BWN_LED_EVENT_RX; - else - evt = BWN_LED_EVENT_TX; - } else if (tx) { - evt = BWN_LED_EVENT_TX; - } else if (rx) { - evt = BWN_LED_EVENT_RX; - } else if (rx == 0) { - evt = BWN_LED_EVENT_POLL; - } - - if (evt != BWN_LED_EVENT_NONE) - bwn_led_event(mac, evt); - } - - if (mbufq_first(&sc->sc_snd) != NULL) - bwn_start(sc); - - BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ); - BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE); - - BWN_UNLOCK(sc); -} - -static void -bwn_restart(struct bwn_mac *mac, const char *msg) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - - if (mac->mac_status < BWN_MAC_STATUS_INITED) - return; - - device_printf(sc->sc_dev, "HW reset: %s\n", msg); - ieee80211_runtask(ic, &mac->mac_hwreset); -} - -static void -bwn_intr_ucode_debug(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint16_t reason; - - if (mac->mac_fw.opensource == 0) - return; - - reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG); - switch (reason) { - case BWN_DEBUGINTR_PANIC: - bwn_handle_fwpanic(mac); - break; - case BWN_DEBUGINTR_DUMP_SHM: - device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n"); - break; - case BWN_DEBUGINTR_DUMP_REGS: - device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n"); - break; - case BWN_DEBUGINTR_MARKER: - device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n"); - break; - default: - device_printf(sc->sc_dev, - "ucode debug unknown reason: %#x\n", reason); - } - - bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG, - BWN_DEBUGINTR_ACK); -} - -static void -bwn_intr_tbtt_indication(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - bwn_psctl(mac, 0); - if (ic->ic_opmode == IEEE80211_M_IBSS) - mac->mac_flags |= BWN_MAC_FLAG_DFQVALID; -} - -static void -bwn_intr_atim_end(struct bwn_mac *mac) -{ - - if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) { - BWN_WRITE_4(mac, BWN_MACCMD, - BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID); - mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID; - } -} - -static void -bwn_intr_beacon(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint32_t cmd, beacon0, beacon1; - - if (ic->ic_opmode == IEEE80211_M_HOSTAP || - ic->ic_opmode == IEEE80211_M_MBSS) - return; - - mac->mac_intr_mask &= ~BWN_INTR_BEACON; - - cmd = BWN_READ_4(mac, BWN_MACCMD); - beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID); - beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID); - - if (beacon0 && beacon1) { - BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON); - mac->mac_intr_mask |= BWN_INTR_BEACON; - return; - } - - if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) { - sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP; - bwn_load_beacon0(mac); - bwn_load_beacon1(mac); - cmd = BWN_READ_4(mac, BWN_MACCMD); - cmd |= BWN_MACCMD_BEACON0_VALID; - BWN_WRITE_4(mac, BWN_MACCMD, cmd); - } else { - if (!beacon0) { - bwn_load_beacon0(mac); - cmd = BWN_READ_4(mac, BWN_MACCMD); - cmd |= BWN_MACCMD_BEACON0_VALID; - BWN_WRITE_4(mac, BWN_MACCMD, cmd); - } else if (!beacon1) { - bwn_load_beacon1(mac); - cmd = BWN_READ_4(mac, BWN_MACCMD); - cmd |= BWN_MACCMD_BEACON1_VALID; - BWN_WRITE_4(mac, BWN_MACCMD, cmd); - } - } -} - -static void -bwn_intr_pmq(struct bwn_mac *mac) -{ - uint32_t tmp; - - while (1) { - tmp = BWN_READ_4(mac, BWN_PS_STATUS); - if (!(tmp & 0x00000008)) - break; - } - BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002); -} - -static void -bwn_intr_noise(struct bwn_mac *mac) -{ - struct bwn_phy_g *pg = &mac->mac_phy.phy_g; - uint16_t tmp; - uint8_t noise[4]; - uint8_t i, j; - int32_t average; - - if (mac->mac_phy.type != BWN_PHYTYPE_G) - return; - - KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__)); - *((uint32_t *)noise) = htole32(bwn_jssi_read(mac)); - if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f || - noise[3] == 0x7f) - goto new; - - KASSERT(mac->mac_noise.noi_nsamples < 8, - ("%s:%d: fail", __func__, __LINE__)); - i = mac->mac_noise.noi_nsamples; - noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1); - noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1); - noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1); - noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1); - mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]]; - mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]]; - mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]]; - mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]]; - mac->mac_noise.noi_nsamples++; - if (mac->mac_noise.noi_nsamples == 8) { - average = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 4; j++) - average += mac->mac_noise.noi_samples[i][j]; - } - average = (((average / 32) * 125) + 64) / 128; - tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f; - if (tmp >= 8) - average += 2; - else - average -= 25; - average -= (tmp == 8) ? 72 : 48; - - mac->mac_stats.link_noise = average; - mac->mac_noise.noi_running = 0; - return; - } -new: - bwn_noise_gensample(mac); -} - -static int -bwn_pio_rx(struct bwn_pio_rxqueue *prq) -{ - struct bwn_mac *mac = prq->prq_mac; - struct bwn_softc *sc = mac->mac_sc; - unsigned int i; - - BWN_ASSERT_LOCKED(sc); - - if (mac->mac_status < BWN_MAC_STATUS_STARTED) - return (0); - - for (i = 0; i < 5000; i++) { - if (bwn_pio_rxeof(prq) == 0) - break; - } - if (i >= 5000) - device_printf(sc->sc_dev, "too many RX frames in PIO mode\n"); - return ((i > 0) ? 1 : 0); -} - -static void -bwn_dma_rx(struct bwn_dma_ring *dr) -{ - int slot, curslot; - - KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__)); - curslot = dr->get_curslot(dr); - KASSERT(curslot >= 0 && curslot < dr->dr_numslots, - ("%s:%d: fail", __func__, __LINE__)); - - slot = dr->dr_curslot; - for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot)) - bwn_dma_rxeof(dr, &slot); - - bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap, - BUS_DMASYNC_PREWRITE); - - dr->set_curslot(dr, slot); - dr->dr_curslot = slot; -} - -static void -bwn_intr_txeof(struct bwn_mac *mac) -{ - struct bwn_txstatus stat; - uint32_t stat0, stat1; - uint16_t tmp; - - BWN_ASSERT_LOCKED(mac->mac_sc); - - while (1) { - stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0); - if (!(stat0 & 0x00000001)) - break; - stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1); - - stat.cookie = (stat0 >> 16); - stat.seq = (stat1 & 0x0000ffff); - stat.phy_stat = ((stat1 & 0x00ff0000) >> 16); - tmp = (stat0 & 0x0000ffff); - stat.framecnt = ((tmp & 0xf000) >> 12); - stat.rtscnt = ((tmp & 0x0f00) >> 8); - stat.sreason = ((tmp & 0x001c) >> 2); - stat.pm = (tmp & 0x0080) ? 1 : 0; - stat.im = (tmp & 0x0040) ? 1 : 0; - stat.ampdu = (tmp & 0x0020) ? 1 : 0; - stat.ack = (tmp & 0x0002) ? 1 : 0; - - bwn_handle_txeof(mac, &stat); - } -} - -static void -bwn_hwreset(void *arg, int npending) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - int error = 0; - int prev_status; - - BWN_LOCK(sc); - - prev_status = mac->mac_status; - if (prev_status >= BWN_MAC_STATUS_STARTED) - bwn_core_stop(mac); - if (prev_status >= BWN_MAC_STATUS_INITED) - bwn_core_exit(mac); - - if (prev_status >= BWN_MAC_STATUS_INITED) { - error = bwn_core_init(mac); - if (error) - goto out; - } - if (prev_status >= BWN_MAC_STATUS_STARTED) - bwn_core_start(mac); -out: - if (error) { - device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error); - sc->sc_curmac = NULL; - } - BWN_UNLOCK(sc); -} - -static void -bwn_handle_fwpanic(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - uint16_t reason; - - reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG); - device_printf(sc->sc_dev,"fw panic (%u)\n", reason); - - if (reason == BWN_FWPANIC_RESTART) - bwn_restart(mac, "ucode panic"); -} - -static void -bwn_load_beacon0(struct bwn_mac *mac) -{ - - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); -} - -static void -bwn_load_beacon1(struct bwn_mac *mac) -{ - - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); -} - -static uint32_t -bwn_jssi_read(struct bwn_mac *mac) -{ - uint32_t val = 0; - - val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a); - val <<= 16; - val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088); - - return (val); -} - -static void -bwn_noise_gensample(struct bwn_mac *mac) -{ - uint32_t jssi = 0x7f7f7f7f; - - bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff)); - bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16); - BWN_WRITE_4(mac, BWN_MACCMD, - BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE); -} - -static int -bwn_dma_freeslot(struct bwn_dma_ring *dr) -{ - BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc); - - return (dr->dr_numslots - dr->dr_usedslot); -} - -static int -bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot) -{ - BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc); - - KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1, - ("%s:%d: fail", __func__, __LINE__)); - if (slot == dr->dr_numslots - 1) - return (0); - return (slot + 1); -} - -static void -bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot) -{ - struct bwn_mac *mac = dr->dr_mac; - struct bwn_softc *sc = mac->mac_sc; - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_dmadesc_generic *desc; - struct bwn_dmadesc_meta *meta; - struct bwn_rxhdr4 *rxhdr; - struct mbuf *m; - uint32_t macstat; - int32_t tmp; - int cnt = 0; - uint16_t len; - - dr->getdesc(dr, *slot, &desc, &meta); - - bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD); - m = meta->mt_m; - - if (bwn_dma_newbuf(dr, desc, meta, 0)) { - counter_u64_add(sc->sc_ic.ic_ierrors, 1); - return; - } - - rxhdr = mtod(m, struct bwn_rxhdr4 *); - len = le16toh(rxhdr->frame_len); - if (len <= 0) { - counter_u64_add(sc->sc_ic.ic_ierrors, 1); - return; - } - if (bwn_dma_check_redzone(dr, m)) { - device_printf(sc->sc_dev, "redzone error.\n"); - bwn_dma_set_redzone(dr, m); - bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, - BUS_DMASYNC_PREWRITE); - return; - } - if (len > dr->dr_rx_bufsize) { - tmp = len; - while (1) { - dr->getdesc(dr, *slot, &desc, &meta); - bwn_dma_set_redzone(dr, meta->mt_m); - bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, - BUS_DMASYNC_PREWRITE); - *slot = bwn_dma_nextslot(dr, *slot); - cnt++; - tmp -= dr->dr_rx_bufsize; - if (tmp <= 0) - break; - } - device_printf(sc->sc_dev, "too small buffer " - "(len %u buffer %u dropped %d)\n", - len, dr->dr_rx_bufsize, cnt); - return; - } - macstat = le32toh(rxhdr->mac_status); - if (macstat & BWN_RX_MAC_FCSERR) { - if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) { - device_printf(sc->sc_dev, "RX drop\n"); - return; - } - } - - m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset; - m_adj(m, dr->dr_frameoffset); - - bwn_rxeof(dr->dr_mac, m, rxhdr); -} - -static void -bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) -{ - struct bwn_softc *sc = mac->mac_sc; - struct bwn_stats *stats = &mac->mac_stats; - - BWN_ASSERT_LOCKED(mac->mac_sc); - - if (status->im) - device_printf(sc->sc_dev, "TODO: STATUS IM\n"); - if (status->ampdu) - device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n"); - if (status->rtscnt) { - if (status->rtscnt == 0xf) - stats->rtsfail++; - else - stats->rts++; - } - - if (mac->mac_flags & BWN_MAC_FLAG_DMA) { - bwn_dma_handle_txeof(mac, status); - } else { - bwn_pio_handle_txeof(mac, status); - } - - bwn_phy_txpower_check(mac, 0); -} - -static uint8_t -bwn_pio_rxeof(struct bwn_pio_rxqueue *prq) -{ - struct bwn_mac *mac = prq->prq_mac; - struct bwn_softc *sc = mac->mac_sc; - struct bwn_rxhdr4 rxhdr; - struct mbuf *m; - uint32_t ctl32, macstat, v32; - unsigned int i, padding; - uint16_t ctl16, len, totlen, v16; - unsigned char *mp; - char *data; - - memset(&rxhdr, 0, sizeof(rxhdr)); - - if (prq->prq_rev >= 8) { - ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL); - if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY)) - return (0); - bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL, - BWN_PIO8_RXCTL_FRAMEREADY); - for (i = 0; i < 10; i++) { - ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL); - if (ctl32 & BWN_PIO8_RXCTL_DATAREADY) - goto ready; - DELAY(10); - } - } else { - ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL); - if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY)) - return (0); - bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, - BWN_PIO_RXCTL_FRAMEREADY); - for (i = 0; i < 10; i++) { - ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL); - if (ctl16 & BWN_PIO_RXCTL_DATAREADY) - goto ready; - DELAY(10); - } - } - device_printf(sc->sc_dev, "%s: timed out\n", __func__); - return (1); -ready: - if (prq->prq_rev >= 8) - siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr), - prq->prq_base + BWN_PIO8_RXDATA); - else - siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr), - prq->prq_base + BWN_PIO_RXDATA); - len = le16toh(rxhdr.frame_len); - if (len > 0x700) { - device_printf(sc->sc_dev, "%s: len is too big\n", __func__); - goto error; - } - if (len == 0) { - device_printf(sc->sc_dev, "%s: len is 0\n", __func__); - goto error; - } - - macstat = le32toh(rxhdr.mac_status); - if (macstat & BWN_RX_MAC_FCSERR) { - if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) { - device_printf(sc->sc_dev, "%s: FCS error", __func__); - goto error; - } - } - - padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0; - totlen = len + padding; - KASSERT(totlen <= MCLBYTES, ("too big..\n")); - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - device_printf(sc->sc_dev, "%s: out of memory", __func__); - goto error; - } - mp = mtod(m, unsigned char *); - if (prq->prq_rev >= 8) { - siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3), - prq->prq_base + BWN_PIO8_RXDATA); - if (totlen & 3) { - v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA); - data = &(mp[totlen - 1]); - switch (totlen & 3) { - case 3: - *data = (v32 >> 16); - data--; - case 2: - *data = (v32 >> 8); - data--; - case 1: - *data = v32; - } - } - } else { - siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1), - prq->prq_base + BWN_PIO_RXDATA); - if (totlen & 1) { - v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA); - mp[totlen - 1] = v16; - } - } - - m->m_len = m->m_pkthdr.len = totlen; - - bwn_rxeof(prq->prq_mac, m, &rxhdr); - - return (1); -error: - if (prq->prq_rev >= 8) - bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL, - BWN_PIO8_RXCTL_DATAREADY); - else - bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY); - return (1); -} - -static int -bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc, - struct bwn_dmadesc_meta *meta, int init) -{ - struct bwn_mac *mac = dr->dr_mac; - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_rxhdr4 *hdr; - bus_dmamap_t map; - bus_addr_t paddr; - struct mbuf *m; - int error; - - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - error = ENOBUFS; - - /* - * If the NIC is up and running, we need to: - * - Clear RX buffer's header. - * - Restore RX descriptor settings. - */ - if (init) - return (error); - else - goto back; - } - m->m_len = m->m_pkthdr.len = MCLBYTES; - - bwn_dma_set_redzone(dr, m); - - /* - * Try to load RX buf into temporary DMA map - */ - error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m, - bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); - if (error) { - m_freem(m); - - /* - * See the comment above - */ - if (init) - return (error); - else - goto back; - } - - if (!init) - bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap); - meta->mt_m = m; - meta->mt_paddr = paddr; - - /* - * Swap RX buf's DMA map with the loaded temporary one - */ - map = meta->mt_dmap; - meta->mt_dmap = dr->dr_spare_dmap; - dr->dr_spare_dmap = map; - -back: - /* - * Clear RX buf header - */ - hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *); - bzero(hdr, sizeof(*hdr)); - bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, - BUS_DMASYNC_PREWRITE); - - /* - * Setup RX buf descriptor - */ - dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len - - sizeof(*hdr), 0, 0, 0); - return (error); -} - -static void -bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg, - bus_size_t mapsz __unused, int error) -{ - - if (!error) { - KASSERT(nseg == 1, ("too many segments(%d)\n", nseg)); - *((bus_addr_t *)arg) = seg->ds_addr; - } -} - -static int -bwn_hwrate2ieeerate(int rate) -{ - - switch (rate) { - case BWN_CCK_RATE_1MB: - return (2); - case BWN_CCK_RATE_2MB: - return (4); - case BWN_CCK_RATE_5MB: - return (11); - case BWN_CCK_RATE_11MB: - return (22); - case BWN_OFDM_RATE_6MB: - return (12); - case BWN_OFDM_RATE_9MB: - return (18); - case BWN_OFDM_RATE_12MB: - return (24); - case BWN_OFDM_RATE_18MB: - return (36); - case BWN_OFDM_RATE_24MB: - return (48); - case BWN_OFDM_RATE_36MB: - return (72); - case BWN_OFDM_RATE_48MB: - return (96); - case BWN_OFDM_RATE_54MB: - return (108); - default: - printf("Ooops\n"); - return (0); - } -} - -static void -bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr) -{ - const struct bwn_rxhdr4 *rxhdr = _rxhdr; - struct bwn_plcp6 *plcp; - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211_frame_min *wh; - struct ieee80211_node *ni; - struct ieee80211com *ic = &sc->sc_ic; - uint32_t macstat; - int padding, rate, rssi = 0, noise = 0, type; - uint16_t phytype, phystat0, phystat3, chanstat; - unsigned char *mp = mtod(m, unsigned char *); - static int rx_mac_dec_rpt = 0; - - BWN_ASSERT_LOCKED(sc); - - phystat0 = le16toh(rxhdr->phy_status0); - phystat3 = le16toh(rxhdr->phy_status3); - macstat = le32toh(rxhdr->mac_status); - chanstat = le16toh(rxhdr->channel); - phytype = chanstat & BWN_RX_CHAN_PHYTYPE; - - if (macstat & BWN_RX_MAC_FCSERR) - device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n"); - if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV)) - device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n"); - if (macstat & BWN_RX_MAC_DECERR) - goto drop; - - padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0; - if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) { - device_printf(sc->sc_dev, "frame too short (length=%d)\n", - m->m_pkthdr.len); - goto drop; - } - plcp = (struct bwn_plcp6 *)(mp + padding); - m_adj(m, sizeof(struct bwn_plcp6) + padding); - if (m->m_pkthdr.len < IEEE80211_MIN_LEN) { - device_printf(sc->sc_dev, "frame too short (length=%d)\n", - m->m_pkthdr.len); - goto drop; - } - wh = mtod(m, struct ieee80211_frame_min *); - - if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50) - device_printf(sc->sc_dev, - "RX decryption attempted (old %d keyidx %#x)\n", - BWN_ISOLDFMT(mac), - (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT); - - /* XXX calculating RSSI & noise & antenna */ - - if (phystat0 & BWN_RX_PHYST0_OFDM) - rate = bwn_plcp_get_ofdmrate(mac, plcp, - phytype == BWN_PHYTYPE_A); - else - rate = bwn_plcp_get_cckrate(mac, plcp); - if (rate == -1) { - if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP)) - goto drop; - } - sc->sc_rx_rate = bwn_hwrate2ieeerate(rate); - - /* RX radio tap */ - if (ieee80211_radiotap_active(ic)) - bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise); - m_adj(m, -IEEE80211_CRC_LEN); - - rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */ - noise = mac->mac_stats.link_noise; - - BWN_UNLOCK(sc); - - ni = ieee80211_find_rxnode(ic, wh); - if (ni != NULL) { - type = ieee80211_input(ni, m, rssi, noise); - ieee80211_free_node(ni); - } else - type = ieee80211_input_all(ic, m, rssi, noise); - - BWN_LOCK(sc); - return; -drop: - device_printf(sc->sc_dev, "%s: dropped\n", __func__); -} - -static void -bwn_dma_handle_txeof(struct bwn_mac *mac, - const struct bwn_txstatus *status) -{ - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_dma_ring *dr; - struct bwn_dmadesc_generic *desc; - struct bwn_dmadesc_meta *meta; - struct bwn_softc *sc = mac->mac_sc; - int slot; - int retrycnt = 0; - - BWN_ASSERT_LOCKED(sc); - - dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot); - if (dr == NULL) { - device_printf(sc->sc_dev, "failed to parse cookie\n"); - return; - } - KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__)); - - while (1) { - KASSERT(slot >= 0 && slot < dr->dr_numslots, - ("%s:%d: fail", __func__, __LINE__)); - dr->getdesc(dr, slot, &desc, &meta); - - if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER) - bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap); - else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY) - bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap); - - if (meta->mt_islast) { - KASSERT(meta->mt_m != NULL, - ("%s:%d: fail", __func__, __LINE__)); - - /* XXX */ - if (status->ack == 0) - retrycnt = 1; - else - retrycnt = 0; - ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni, - status->ack ? - IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, 0); - ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0); - meta->mt_ni = NULL; - meta->mt_m = NULL; - } else - KASSERT(meta->mt_m == NULL, - ("%s:%d: fail", __func__, __LINE__)); - - dr->dr_usedslot--; - if (meta->mt_islast) - break; - slot = bwn_dma_nextslot(dr, slot); - } - sc->sc_watchdog_timer = 0; - if (dr->dr_stop) { - KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME, - ("%s:%d: fail", __func__, __LINE__)); - dr->dr_stop = 0; - } -} - -static void -bwn_pio_handle_txeof(struct bwn_mac *mac, - const struct bwn_txstatus *status) -{ - struct bwn_pio_txqueue *tq; - struct bwn_pio_txpkt *tp = NULL; - struct bwn_softc *sc = mac->mac_sc; - int retrycnt = 0; - - BWN_ASSERT_LOCKED(sc); - - tq = bwn_pio_parse_cookie(mac, status->cookie, &tp); - if (tq == NULL) - return; - - tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); - tq->tq_free++; - - if (tp->tp_ni != NULL) { - /* - * Do any tx complete callback. Note this must - * be done before releasing the node reference. - */ - - /* XXX */ - if (status->ack == 0) - retrycnt = 1; - else - retrycnt = 0; - ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni, - status->ack ? - IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, 0); - - if (tp->tp_m->m_flags & M_TXCB) - ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0); - ieee80211_free_node(tp->tp_ni); - tp->tp_ni = NULL; - } - m_freem(tp->tp_m); - tp->tp_m = NULL; - TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list); - - sc->sc_watchdog_timer = 0; -} - -static void -bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags) -{ - struct bwn_softc *sc = mac->mac_sc; - struct bwn_phy *phy = &mac->mac_phy; - struct ieee80211com *ic = &sc->sc_ic; - unsigned long now; - int result; - - BWN_GETTIME(now); - - if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime)) - return; - phy->nexttime = now + 2 * 1000; - - if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM && - siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306) - return; - - if (phy->recalc_txpwr != NULL) { - result = phy->recalc_txpwr(mac, - (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0); - if (result == BWN_TXPWR_RES_DONE) - return; - KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST, - ("%s: fail", __func__)); - KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__)); - - ieee80211_runtask(ic, &mac->mac_txpower); - } -} - -static uint16_t -bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset) -{ - - return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset)); -} - -static uint32_t -bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset) -{ - - return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset)); -} - -static void -bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value) -{ - - BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value); -} - -static void -bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value) -{ - - BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value); -} - -static int -bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate) -{ - - switch (rate) { - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: - return (BWN_OFDM_RATE_6MB); - case 18: - return (BWN_OFDM_RATE_9MB); - case 24: - return (BWN_OFDM_RATE_12MB); - case 36: - return (BWN_OFDM_RATE_18MB); - case 48: - return (BWN_OFDM_RATE_24MB); - case 72: - return (BWN_OFDM_RATE_36MB); - case 96: - return (BWN_OFDM_RATE_48MB); - case 108: - return (BWN_OFDM_RATE_54MB); - /* CCK rates (NB: not IEEE std, device-specific) */ - case 2: - return (BWN_CCK_RATE_1MB); - case 4: - return (BWN_CCK_RATE_2MB); - case 11: - return (BWN_CCK_RATE_5MB); - case 22: - return (BWN_CCK_RATE_11MB); - } - - device_printf(sc->sc_dev, "unsupported rate %d\n", rate); - return (BWN_CCK_RATE_1MB); -} - -static int -bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni, - struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie) -{ - const struct bwn_phy *phy = &mac->mac_phy; - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211_frame *wh; - struct ieee80211_frame *protwh; - struct ieee80211_frame_cts *cts; - struct ieee80211_frame_rts *rts; - const struct ieee80211_txparam *tp; - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = &sc->sc_ic; - struct mbuf *mprot; - unsigned int len; - uint32_t macctl = 0; - int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type; - uint16_t phyctl = 0; - uint8_t rate, rate_fb; - - wh = mtod(m, struct ieee80211_frame *); - memset(txhdr, 0, sizeof(*txhdr)); - - type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); - isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; - - /* - * Find TX rate - */ - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL)) - rate = rate_fb = tp->mgmtrate; - else if (ismcast) - rate = rate_fb = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = rate_fb = tp->ucastrate; - else { - /* XXX TODO: don't fall back to CCK rates for OFDM */ - rix = ieee80211_ratectl_rate(ni, NULL, 0); - rate = ni->ni_txrate; - - if (rix > 0) - rate_fb = ni->ni_rates.rs_rates[rix - 1] & - IEEE80211_RATE_VAL; - else - rate_fb = rate; - } - - sc->sc_tx_rate = rate; - - /* Note: this maps the select ieee80211 rate to hardware rate */ - rate = bwn_ieeerate2hwrate(sc, rate); - rate_fb = bwn_ieeerate2hwrate(sc, rate_fb); - - txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) : - bwn_plcp_getcck(rate); - bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc)); - bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN); - - /* XXX rate/rate_fb is the hardware rate */ - if ((rate_fb == rate) || - (*(u_int16_t *)wh->i_dur & htole16(0x8000)) || - (*(u_int16_t *)wh->i_dur == htole16(0))) - txhdr->dur_fb = *(u_int16_t *)wh->i_dur; - else - txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt, - m->m_pkthdr.len, rate, isshort); - - /* XXX TX encryption */ - bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ? - (struct bwn_plcp4 *)(&txhdr->body.old.plcp) : - (struct bwn_plcp4 *)(&txhdr->body.new.plcp), - m->m_pkthdr.len + IEEE80211_CRC_LEN, rate); - bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb), - m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb); - - txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM : - BWN_TX_EFT_FB_CCK; - txhdr->chan = phy->chan; - phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM : - BWN_TX_PHY_ENC_CCK; - /* XXX preamble? obey net80211 */ - if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB || - rate == BWN_CCK_RATE_11MB)) - phyctl |= BWN_TX_PHY_SHORTPRMBL; - - /* XXX TX antenna selection */ - - switch (bwn_antenna_sanitize(mac, 0)) { - case 0: - phyctl |= BWN_TX_PHY_ANT01AUTO; - break; - case 1: - phyctl |= BWN_TX_PHY_ANT0; - break; - case 2: - phyctl |= BWN_TX_PHY_ANT1; - break; - case 3: - phyctl |= BWN_TX_PHY_ANT2; - break; - case 4: - phyctl |= BWN_TX_PHY_ANT3; - break; - default: - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - } - - if (!ismcast) - macctl |= BWN_TX_MAC_ACK; - - macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU); - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) - macctl |= BWN_TX_MAC_LONGFRAME; - - if (ic->ic_flags & IEEE80211_F_USEPROT) { - /* XXX RTS rate is always 1MB??? */ - /* XXX TODO: don't fall back to CCK rates for OFDM */ - rts_rate = BWN_CCK_RATE_1MB; - rts_rate_fb = bwn_get_fbrate(rts_rate); - - /* XXX 'rate' here is hardware rate now, not the net80211 rate */ - protdur = ieee80211_compute_duration(ic->ic_rt, - m->m_pkthdr.len, rate, isshort) + - + ieee80211_ack_duration(ic->ic_rt, rate, isshort); - - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { - cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ? - (txhdr->body.old.rts_frame) : - (txhdr->body.new.rts_frame)); - mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, - protdur); - KASSERT(mprot != NULL, ("failed to alloc mbuf\n")); - bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts, - mprot->m_pkthdr.len); - m_freem(mprot); - macctl |= BWN_TX_MAC_SEND_CTSTOSELF; - len = sizeof(struct ieee80211_frame_cts); - } else { - rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ? - (txhdr->body.old.rts_frame) : - (txhdr->body.new.rts_frame)); - /* XXX rate/rate_fb is the hardware rate */ - protdur += ieee80211_ack_duration(ic->ic_rt, rate, - isshort); - mprot = ieee80211_alloc_rts(ic, wh->i_addr1, - wh->i_addr2, protdur); - KASSERT(mprot != NULL, ("failed to alloc mbuf\n")); - bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts, - mprot->m_pkthdr.len); - m_freem(mprot); - macctl |= BWN_TX_MAC_SEND_RTSCTS; - len = sizeof(struct ieee80211_frame_rts); - } - len += IEEE80211_CRC_LEN; - bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ? - &txhdr->body.old.rts_plcp : - &txhdr->body.new.rts_plcp), len, rts_rate); - bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len, - rts_rate_fb); - - protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ? - (&txhdr->body.old.rts_frame) : - (&txhdr->body.new.rts_frame)); - txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur; - - if (BWN_ISOFDMRATE(rts_rate)) { - txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM; - txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate); - } else { - txhdr->eftypes |= BWN_TX_EFT_RTS_CCK; - txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate); - } - txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ? - BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK; - } - - if (BWN_ISOLDFMT(mac)) - txhdr->body.old.cookie = htole16(cookie); - else - txhdr->body.new.cookie = htole16(cookie); - - txhdr->macctl = htole32(macctl); - txhdr->phyctl = htole16(phyctl); - - /* - * TX radio tap - */ - if (ieee80211_radiotap_active_vap(vap)) { - sc->sc_tx_th.wt_flags = 0; - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP; - if (isshort && - (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB || - rate == BWN_CCK_RATE_11MB)) - sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - sc->sc_tx_th.wt_rate = rate; - - ieee80211_radiotap_tx(vap, m); - } - - return (0); -} - -static void -bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets, - const uint8_t rate) -{ - uint32_t d, plen; - uint8_t *raw = plcp->o.raw; - - if (BWN_ISOFDMRATE(rate)) { - d = bwn_plcp_getofdm(rate); - KASSERT(!(octets & 0xf000), - ("%s:%d: fail", __func__, __LINE__)); - d |= (octets << 5); - plcp->o.data = htole32(d); - } else { - plen = octets * 16 / rate; - if ((octets * 16 % rate) > 0) { - plen++; - if ((rate == BWN_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) { - raw[1] = 0x84; - } else - raw[1] = 0x04; - } else - raw[1] = 0x04; - plcp->o.data |= htole32(plen << 16); - raw[0] = bwn_plcp_getcck(rate); - } -} - -static uint8_t -bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n) -{ - struct bwn_softc *sc = mac->mac_sc; - uint8_t mask; - - if (n == 0) - return (0); - if (mac->mac_phy.gmode) - mask = siba_sprom_get_ant_bg(sc->sc_dev); - else - mask = siba_sprom_get_ant_a(sc->sc_dev); - if (!(mask & (1 << (n - 1)))) - return (0); - return (n); -} - -/* - * Return a fallback rate for the given rate. - * - * Note: Don't fall back from OFDM to CCK. - */ -static uint8_t -bwn_get_fbrate(uint8_t bitrate) -{ - switch (bitrate) { - /* CCK */ - case BWN_CCK_RATE_1MB: - return (BWN_CCK_RATE_1MB); - case BWN_CCK_RATE_2MB: - return (BWN_CCK_RATE_1MB); - case BWN_CCK_RATE_5MB: - return (BWN_CCK_RATE_2MB); - case BWN_CCK_RATE_11MB: - return (BWN_CCK_RATE_5MB); - - /* OFDM */ - case BWN_OFDM_RATE_6MB: - return (BWN_OFDM_RATE_6MB); - case BWN_OFDM_RATE_9MB: - return (BWN_OFDM_RATE_6MB); - case BWN_OFDM_RATE_12MB: - return (BWN_OFDM_RATE_9MB); - case BWN_OFDM_RATE_18MB: - return (BWN_OFDM_RATE_12MB); - case BWN_OFDM_RATE_24MB: - return (BWN_OFDM_RATE_18MB); - case BWN_OFDM_RATE_36MB: - return (BWN_OFDM_RATE_24MB); - case BWN_OFDM_RATE_48MB: - return (BWN_OFDM_RATE_36MB); - case BWN_OFDM_RATE_54MB: - return (BWN_OFDM_RATE_48MB); - } - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (0); -} - -static uint32_t -bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, - uint32_t ctl, const void *_data, int len) -{ - struct bwn_softc *sc = mac->mac_sc; - uint32_t value = 0; - const uint8_t *data = _data; - - ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 | - BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31; - bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl); - - siba_write_multi_4(sc->sc_dev, data, (len & ~3), - tq->tq_base + BWN_PIO8_TXDATA); - if (len & 3) { - ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 | - BWN_PIO8_TXCTL_24_31); - data = &(data[len - 1]); - switch (len & 3) { - case 3: - ctl |= BWN_PIO8_TXCTL_16_23; - value |= (uint32_t)(*data) << 16; - data--; - case 2: - ctl |= BWN_PIO8_TXCTL_8_15; - value |= (uint32_t)(*data) << 8; - data--; - case 1: - value |= (uint32_t)(*data); - } - bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl); - bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value); - } - - return (ctl); -} - -static void -bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, - uint16_t offset, uint32_t value) -{ - - BWN_WRITE_4(mac, tq->tq_base + offset, value); -} - -static uint16_t -bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, - uint16_t ctl, const void *_data, int len) -{ - struct bwn_softc *sc = mac->mac_sc; - const uint8_t *data = _data; - - ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI; - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); - - siba_write_multi_2(sc->sc_dev, data, (len & ~1), - tq->tq_base + BWN_PIO_TXDATA); - if (len & 1) { - ctl &= ~BWN_PIO_TXCTL_WRITEHI; - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]); - } - - return (ctl); -} - -static uint16_t -bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq, - uint16_t ctl, struct mbuf *m0) -{ - int i, j = 0; - uint16_t data = 0; - const uint8_t *buf; - struct mbuf *m = m0; - - ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI; - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); - - for (; m != NULL; m = m->m_next) { - buf = mtod(m, const uint8_t *); - for (i = 0; i < m->m_len; i++) { - if (!((j++) % 2)) - data |= buf[i]; - else { - data |= (buf[i] << 8); - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data); - data = 0; - } - } - } - if (m0->m_pkthdr.len % 2) { - ctl &= ~BWN_PIO_TXCTL_WRITEHI; - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl); - BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data); - } - - return (ctl); -} - -static void -bwn_set_slot_time(struct bwn_mac *mac, uint16_t time) -{ - - if (mac->mac_phy.type != BWN_PHYTYPE_G) - return; - BWN_WRITE_2(mac, 0x684, 510 + time); - bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time); -} - -static struct bwn_dma_ring * -bwn_dma_select(struct bwn_mac *mac, uint8_t prio) -{ - - if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0) - return (mac->mac_method.dma.wme[WME_AC_BE]); - - switch (prio) { - case 3: - return (mac->mac_method.dma.wme[WME_AC_VO]); - case 2: - return (mac->mac_method.dma.wme[WME_AC_VI]); - case 0: - return (mac->mac_method.dma.wme[WME_AC_BE]); - case 1: - return (mac->mac_method.dma.wme[WME_AC_BK]); - } - KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); - return (NULL); -} - -static int -bwn_dma_getslot(struct bwn_dma_ring *dr) -{ - int slot; - - BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc); - - KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__)); - KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__)); - KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__)); - - slot = bwn_dma_nextslot(dr, dr->dr_curslot); - KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__)); - dr->dr_curslot = slot; - dr->dr_usedslot++; - - return (slot); -} - -static struct bwn_pio_txqueue * -bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie, - struct bwn_pio_txpkt **pack) -{ - struct bwn_pio *pio = &mac->mac_method.pio; - struct bwn_pio_txqueue *tq = NULL; - unsigned int index; - - switch (cookie & 0xf000) { - case 0x1000: - tq = &pio->wme[WME_AC_BK]; - break; - case 0x2000: - tq = &pio->wme[WME_AC_BE]; - break; - case 0x3000: - tq = &pio->wme[WME_AC_VI]; - break; - case 0x4000: - tq = &pio->wme[WME_AC_VO]; - break; - case 0x5000: - tq = &pio->mcast; - break; - } - KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__)); - if (tq == NULL) - return (NULL); - index = (cookie & 0x0fff); - KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__)); - if (index >= N(tq->tq_pkts)) - return (NULL); - *pack = &tq->tq_pkts[index]; - KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__)); - return (tq); -} - -static void -bwn_txpwr(void *arg, int npending) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - - BWN_LOCK(sc); - if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED && - mac->mac_phy.set_txpwr != NULL) - mac->mac_phy.set_txpwr(mac); - BWN_UNLOCK(sc); -} - -static void -bwn_task_15s(struct bwn_mac *mac) -{ - uint16_t reg; - - if (mac->mac_fw.opensource) { - reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG); - if (reg) { - bwn_restart(mac, "fw watchdog"); - return; - } - bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1); - } - if (mac->mac_phy.task_15s) - mac->mac_phy.task_15s(mac); - - mac->mac_phy.txerrors = BWN_TXERROR_MAX; -} - -static void -bwn_task_30s(struct bwn_mac *mac) -{ - - if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running) - return; - mac->mac_noise.noi_running = 1; - mac->mac_noise.noi_nsamples = 0; - - bwn_noise_gensample(mac); -} - -static void -bwn_task_60s(struct bwn_mac *mac) -{ - - if (mac->mac_phy.task_60s) - mac->mac_phy.task_60s(mac); - bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME); -} - -static void -bwn_tasks(void *arg) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - - BWN_ASSERT_LOCKED(sc); - if (mac->mac_status != BWN_MAC_STATUS_STARTED) - return; - - if (mac->mac_task_state % 4 == 0) - bwn_task_60s(mac); - if (mac->mac_task_state % 2 == 0) - bwn_task_30s(mac); - bwn_task_15s(mac); - - mac->mac_task_state++; - callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac); -} - -static int -bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a) -{ - struct bwn_softc *sc = mac->mac_sc; - - KASSERT(a == 0, ("not support APHY\n")); - - switch (plcp->o.raw[0] & 0xf) { - case 0xb: - return (BWN_OFDM_RATE_6MB); - case 0xf: - return (BWN_OFDM_RATE_9MB); - case 0xa: - return (BWN_OFDM_RATE_12MB); - case 0xe: - return (BWN_OFDM_RATE_18MB); - case 0x9: - return (BWN_OFDM_RATE_24MB); - case 0xd: - return (BWN_OFDM_RATE_36MB); - case 0x8: - return (BWN_OFDM_RATE_48MB); - case 0xc: - return (BWN_OFDM_RATE_54MB); - } - device_printf(sc->sc_dev, "incorrect OFDM rate %d\n", - plcp->o.raw[0] & 0xf); - return (-1); -} - -static int -bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp) -{ - struct bwn_softc *sc = mac->mac_sc; - - switch (plcp->o.raw[0]) { - case 0x0a: - return (BWN_CCK_RATE_1MB); - case 0x14: - return (BWN_CCK_RATE_2MB); - case 0x37: - return (BWN_CCK_RATE_5MB); - case 0x6e: - return (BWN_CCK_RATE_11MB); - } - device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]); - return (-1); -} - -static void -bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m, - const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate, - int rssi, int noise) -{ - struct bwn_softc *sc = mac->mac_sc; - const struct ieee80211_frame_min *wh; - uint64_t tsf; - uint16_t low_mactime_now; - - if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL) - sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - wh = mtod(m, const struct ieee80211_frame_min *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) - sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP; - - bwn_tsf_read(mac, &tsf); - low_mactime_now = tsf; - tsf = tsf & ~0xffffULL; - tsf += le16toh(rxhdr->mac_time); - if (low_mactime_now < le16toh(rxhdr->mac_time)) - tsf -= 0x10000; - - sc->sc_rx_th.wr_tsf = tsf; - sc->sc_rx_th.wr_rate = rate; - sc->sc_rx_th.wr_antsignal = rssi; - sc->sc_rx_th.wr_antnoise = noise; -} - -static void -bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf) -{ - uint32_t low, high; - - KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3, - ("%s:%d: fail", __func__, __LINE__)); - - low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW); - high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH); - *tsf = high; - *tsf <<= 32; - *tsf |= low; -} - -static int -bwn_dma_attach(struct bwn_mac *mac) -{ - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_softc *sc = mac->mac_sc; - bus_addr_t lowaddr = 0; - int error; - - if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0) - return (0); - - KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__)); - - mac->mac_flags |= BWN_MAC_FLAG_DMA; - - dma->dmatype = bwn_dma_gettype(mac); - if (dma->dmatype == BWN_DMA_30BIT) - lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT; - else if (dma->dmatype == BWN_DMA_32BIT) - lowaddr = BUS_SPACE_MAXADDR_32BIT; - else - lowaddr = BUS_SPACE_MAXADDR; - - /* - * Create top level DMA tag - */ - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */ - BWN_ALIGN, 0, /* alignment, bounds */ - lowaddr, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE, /* maxsize */ - BUS_SPACE_UNRESTRICTED, /* nsegments */ - BUS_SPACE_MAXSIZE, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &dma->parent_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create parent DMA tag\n"); - return (error); - } - - /* - * Create TX/RX mbuf DMA tag - */ - error = bus_dma_tag_create(dma->parent_dtag, - 1, - 0, - BUS_SPACE_MAXADDR, - BUS_SPACE_MAXADDR, - NULL, NULL, - MCLBYTES, - 1, - BUS_SPACE_MAXSIZE_32BIT, - 0, - NULL, NULL, - &dma->rxbuf_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create mbuf DMA tag\n"); - goto fail0; - } - error = bus_dma_tag_create(dma->parent_dtag, - 1, - 0, - BUS_SPACE_MAXADDR, - BUS_SPACE_MAXADDR, - NULL, NULL, - MCLBYTES, - 1, - BUS_SPACE_MAXSIZE_32BIT, - 0, - NULL, NULL, - &dma->txbuf_dtag); - if (error) { - device_printf(sc->sc_dev, "can't create mbuf DMA tag\n"); - goto fail1; - } - - dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype); - if (!dma->wme[WME_AC_BK]) - goto fail2; - - dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype); - if (!dma->wme[WME_AC_BE]) - goto fail3; - - dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype); - if (!dma->wme[WME_AC_VI]) - goto fail4; - - dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype); - if (!dma->wme[WME_AC_VO]) - goto fail5; - - dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype); - if (!dma->mcast) - goto fail6; - dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype); - if (!dma->rx) - goto fail7; - - return (error); - -fail7: bwn_dma_ringfree(&dma->mcast); -fail6: bwn_dma_ringfree(&dma->wme[WME_AC_VO]); -fail5: bwn_dma_ringfree(&dma->wme[WME_AC_VI]); -fail4: bwn_dma_ringfree(&dma->wme[WME_AC_BE]); -fail3: bwn_dma_ringfree(&dma->wme[WME_AC_BK]); -fail2: bus_dma_tag_destroy(dma->txbuf_dtag); -fail1: bus_dma_tag_destroy(dma->rxbuf_dtag); -fail0: bus_dma_tag_destroy(dma->parent_dtag); - return (error); -} - -static struct bwn_dma_ring * -bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status, - uint16_t cookie, int *slot) -{ - struct bwn_dma *dma = &mac->mac_method.dma; - struct bwn_dma_ring *dr; - struct bwn_softc *sc = mac->mac_sc; - - BWN_ASSERT_LOCKED(mac->mac_sc); - - switch (cookie & 0xf000) { - case 0x1000: - dr = dma->wme[WME_AC_BK]; - break; - case 0x2000: - dr = dma->wme[WME_AC_BE]; - break; - case 0x3000: - dr = dma->wme[WME_AC_VI]; - break; - case 0x4000: - dr = dma->wme[WME_AC_VO]; - break; - case 0x5000: - dr = dma->mcast; - break; - default: - dr = NULL; - KASSERT(0 == 1, - ("invalid cookie value %d", cookie & 0xf000)); - } - *slot = (cookie & 0x0fff); - if (*slot < 0 || *slot >= dr->dr_numslots) { - /* - * XXX FIXME: sometimes H/W returns TX DONE events duplicately - * that it occurs events which have same H/W sequence numbers. - * When it's occurred just prints a WARNING msgs and ignores. - */ - KASSERT(status->seq == dma->lastseq, - ("%s:%d: fail", __func__, __LINE__)); - device_printf(sc->sc_dev, - "out of slot ranges (0 < %d < %d)\n", *slot, - dr->dr_numslots); - return (NULL); - } - dma->lastseq = status->seq; - return (dr); -} - -static void -bwn_dma_stop(struct bwn_mac *mac) -{ - struct bwn_dma *dma; - - if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0) - return; - dma = &mac->mac_method.dma; - - bwn_dma_ringstop(&dma->rx); - bwn_dma_ringstop(&dma->wme[WME_AC_BK]); - bwn_dma_ringstop(&dma->wme[WME_AC_BE]); - bwn_dma_ringstop(&dma->wme[WME_AC_VI]); - bwn_dma_ringstop(&dma->wme[WME_AC_VO]); - bwn_dma_ringstop(&dma->mcast); -} - -static void -bwn_dma_ringstop(struct bwn_dma_ring **dr) -{ - - if (dr == NULL) - return; - - bwn_dma_cleanup(*dr); -} - -static void -bwn_pio_stop(struct bwn_mac *mac) -{ - struct bwn_pio *pio; - - if (mac->mac_flags & BWN_MAC_FLAG_DMA) - return; - pio = &mac->mac_method.pio; - - bwn_destroy_queue_tx(&pio->mcast); - bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]); - bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]); - bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]); - bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]); -} - -static void -bwn_led_attach(struct bwn_mac *mac) -{ - struct bwn_softc *sc = mac->mac_sc; - const uint8_t *led_act = NULL; - uint16_t val[BWN_LED_MAX]; - int i; - - sc->sc_led_idle = (2350 * hz) / 1000; - sc->sc_led_blink = 1; - - for (i = 0; i < N(bwn_vendor_led_act); ++i) { - if (siba_get_pci_subvendor(sc->sc_dev) == - bwn_vendor_led_act[i].vid) { - led_act = bwn_vendor_led_act[i].led_act; - break; - } - } - if (led_act == NULL) - led_act = bwn_default_led_act; - - val[0] = siba_sprom_get_gpio0(sc->sc_dev); - val[1] = siba_sprom_get_gpio1(sc->sc_dev); - val[2] = siba_sprom_get_gpio2(sc->sc_dev); - val[3] = siba_sprom_get_gpio3(sc->sc_dev); - - for (i = 0; i < BWN_LED_MAX; ++i) { - struct bwn_led *led = &sc->sc_leds[i]; - - if (val[i] == 0xff) { - led->led_act = led_act[i]; - } else { - if (val[i] & BWN_LED_ACT_LOW) - led->led_flags |= BWN_LED_F_ACTLOW; - led->led_act = val[i] & BWN_LED_ACT_MASK; - } - led->led_mask = (1 << i); - - if (led->led_act == BWN_LED_ACT_BLINK_SLOW || - led->led_act == BWN_LED_ACT_BLINK_POLL || - led->led_act == BWN_LED_ACT_BLINK) { - led->led_flags |= BWN_LED_F_BLINK; - if (led->led_act == BWN_LED_ACT_BLINK_POLL) - led->led_flags |= BWN_LED_F_POLLABLE; - else if (led->led_act == BWN_LED_ACT_BLINK_SLOW) - led->led_flags |= BWN_LED_F_SLOW; - - if (sc->sc_blink_led == NULL) { - sc->sc_blink_led = led; - if (led->led_flags & BWN_LED_F_SLOW) - BWN_LED_SLOWDOWN(sc->sc_led_idle); - } - } - - DPRINTF(sc, BWN_DEBUG_LED, - "%dth led, act %d, lowact %d\n", i, - led->led_act, led->led_flags & BWN_LED_F_ACTLOW); - } - callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0); -} - -static __inline uint16_t -bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on) -{ - - if (led->led_flags & BWN_LED_F_ACTLOW) - on = !on; - if (on) - val |= led->led_mask; - else - val &= ~led->led_mask; - return val; -} - -static void -bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate) -{ - struct bwn_softc *sc = mac->mac_sc; - struct ieee80211com *ic = &sc->sc_ic; - uint16_t val; - int i; - - if (nstate == IEEE80211_S_INIT) { - callout_stop(&sc->sc_led_blink_ch); - sc->sc_led_blinking = 0; - } - - if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) - return; - - val = BWN_READ_2(mac, BWN_GPIO_CONTROL); - for (i = 0; i < BWN_LED_MAX; ++i) { - struct bwn_led *led = &sc->sc_leds[i]; - int on; - - if (led->led_act == BWN_LED_ACT_UNKN || - led->led_act == BWN_LED_ACT_NULL) - continue; - - if ((led->led_flags & BWN_LED_F_BLINK) && - nstate != IEEE80211_S_INIT) - continue; - - switch (led->led_act) { - case BWN_LED_ACT_ON: /* Always on */ - on = 1; - break; - case BWN_LED_ACT_OFF: /* Always off */ - case BWN_LED_ACT_5GHZ: /* TODO: 11A */ - on = 0; - break; - default: - on = 1; - switch (nstate) { - case IEEE80211_S_INIT: - on = 0; - break; - case IEEE80211_S_RUN: - if (led->led_act == BWN_LED_ACT_11G && - ic->ic_curmode != IEEE80211_MODE_11G) - on = 0; - break; - default: - if (led->led_act == BWN_LED_ACT_ASSOC) - on = 0; - break; - } - break; - } - - val = bwn_led_onoff(led, val, on); - } - BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val); -} - -static void -bwn_led_event(struct bwn_mac *mac, int event) -{ - struct bwn_softc *sc = mac->mac_sc; - struct bwn_led *led = sc->sc_blink_led; - int rate; - - if (event == BWN_LED_EVENT_POLL) { - if ((led->led_flags & BWN_LED_F_POLLABLE) == 0) - return; - if (ticks - sc->sc_led_ticks < sc->sc_led_idle) - return; - } - - sc->sc_led_ticks = ticks; - if (sc->sc_led_blinking) - return; - - switch (event) { - case BWN_LED_EVENT_RX: - rate = sc->sc_rx_rate; - break; - case BWN_LED_EVENT_TX: - rate = sc->sc_tx_rate; - break; - case BWN_LED_EVENT_POLL: - rate = 0; - break; - default: - panic("unknown LED event %d\n", event); - break; - } - bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur, - bwn_led_duration[rate].off_dur); -} - -static void -bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur) -{ - struct bwn_softc *sc = mac->mac_sc; - struct bwn_led *led = sc->sc_blink_led; - uint16_t val; - - val = BWN_READ_2(mac, BWN_GPIO_CONTROL); - val = bwn_led_onoff(led, val, 1); - BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val); - - if (led->led_flags & BWN_LED_F_SLOW) { - BWN_LED_SLOWDOWN(on_dur); - BWN_LED_SLOWDOWN(off_dur); - } - - sc->sc_led_blinking = 1; - sc->sc_led_blink_offdur = off_dur; - - callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac); -} - -static void -bwn_led_blink_next(void *arg) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - uint16_t val; - - val = BWN_READ_2(mac, BWN_GPIO_CONTROL); - val = bwn_led_onoff(sc->sc_blink_led, val, 0); - BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val); - - callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur, - bwn_led_blink_end, mac); -} - -static void -bwn_led_blink_end(void *arg) -{ - struct bwn_mac *mac = arg; - struct bwn_softc *sc = mac->mac_sc; - - sc->sc_led_blinking = 0; -} - -static int -bwn_suspend(device_t dev) -{ - struct bwn_softc *sc = device_get_softc(dev); - - BWN_LOCK(sc); - bwn_stop(sc); - BWN_UNLOCK(sc); - return (0); -} - -static int -bwn_resume(device_t dev) -{ - struct bwn_softc *sc = device_get_softc(dev); - int error = EDOOFUS; - - BWN_LOCK(sc); - if (sc->sc_ic.ic_nrunning > 0) - error = bwn_init(sc); - BWN_UNLOCK(sc); - if (error == 0) - ieee80211_start_all(&sc->sc_ic); - return (0); -} - -static void -bwn_rfswitch(void *arg) -{ - struct bwn_softc *sc = arg; - struct bwn_mac *mac = sc->sc_curmac; - int cur = 0, prev = 0; - - KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED, - ("%s: invalid MAC status %d", __func__, mac->mac_status)); - - if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) { - if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI) - & BWN_RF_HWENABLED_HI_MASK)) - cur = 1; - } else { - if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO) - & BWN_RF_HWENABLED_LO_MASK) - cur = 1; - } - - if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON) - prev = 1; - - if (cur != prev) { - if (cur) - mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON; - else - mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON; - - device_printf(sc->sc_dev, - "status of RF switch is changed to %s\n", - cur ? "ON" : "OFF"); - if (cur != mac->mac_phy.rf_on) { - if (cur) - bwn_rf_turnon(mac); - else - bwn_rf_turnoff(mac); - } - } - - callout_schedule(&sc->sc_rfswitch_ch, hz); -} - -static void -bwn_sysctl_node(struct bwn_softc *sc) -{ - device_t dev = sc->sc_dev; - struct bwn_mac *mac; - struct bwn_stats *stats; - - /* XXX assume that count of MAC is only 1. */ - - if ((mac = sc->sc_curmac) == NULL) - return; - stats = &mac->mac_stats; - - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, - "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, - "rts", CTLFLAG_RW, &stats->rts, 0, "RTS"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, - "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send"); - -#ifdef BWN_DEBUG - SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, - "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags"); -#endif -} - -static device_method_t bwn_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, bwn_probe), - DEVMETHOD(device_attach, bwn_attach), - DEVMETHOD(device_detach, bwn_detach), - DEVMETHOD(device_suspend, bwn_suspend), - DEVMETHOD(device_resume, bwn_resume), - DEVMETHOD_END -}; -static driver_t bwn_driver = { - "bwn", - bwn_methods, - sizeof(struct bwn_softc) -}; -static devclass_t bwn_devclass; -DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0); -MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1); -MODULE_DEPEND(bwn, wlan, 1, 1, 1); /* 802.11 media layer */ -MODULE_DEPEND(bwn, firmware, 1, 1, 1); /* firmware support */ -MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1); -- cgit v1.1 From eb663acb54bc8677cc47448aa68f2e2393d5455b Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 5 May 2016 22:26:23 +0000 Subject: Native PCI-express HotPlug support. PCI-express HotPlug support is implemented via bits in the slot registers of the PCI-express capability of the downstream port along with an interrupt that triggers when bits in the slot status register change. This is implemented for FreeBSD by adding HotPlug support to the PCI-PCI bridge driver which attaches to the virtual PCI-PCI bridges representing downstream ports on HotPlug slots. The PCI-PCI bridge driver registers an interrupt handler to receive HotPlug events. It also uses the slot registers to determine the current HotPlug state and drive an internal HotPlug state machine. For simplicty of implementation, the PCI-PCI bridge device detaches and deletes the child PCI device when a card is removed from a slot and creates and attaches a PCI child device when a card is inserted into the slot. The PCI-PCI bridge driver provides a bus_child_present which claims that child devices are present on HotPlug-capable slots only when a card is inserted. Rather than requiring a timeout in the RC for config accesses to not-present children, the pcib_read/write_config methods fail all requests when a card is not present (or not yet ready). These changes include support for various optional HotPlug capabilities such as a power controller, mechanical latch, electro-mechanical interlock, indicators, and an attention button. It also includes support for devices which require waiting for command completion events before initiating a subsequent HotPlug command. However, it has only been tested on ExpressCard systems which support surprise removal and have none of these optional capabilities. PCI-express HotPlug support is conditional on the PCI_HP option which is enabled by default on arm64, x86, and powerpc. Reviewed by: adrian, imp, vangyzen (older versions) Relnotes: yes Differential Revision: https://reviews.freebsd.org/D6136 --- sys/amd64/conf/GENERIC | 1 + sys/arm64/conf/GENERIC | 1 + sys/conf/NOTES | 1 + sys/conf/options | 1 + sys/dev/acpica/acpi_pcib_acpi.c | 7 + sys/dev/pci/pci_pci.c | 530 ++++++++++++++++++++++++++++++++++++++++ sys/dev/pci/pcib_private.h | 20 ++ sys/dev/pci/pcireg.h | 8 + sys/i386/conf/GENERIC | 1 + sys/powerpc/conf/GENERIC | 1 + sys/powerpc/conf/GENERIC64 | 1 + 11 files changed, 572 insertions(+) (limited to 'sys') diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 747acc5..2859de5 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -102,6 +102,7 @@ device cpufreq device acpi options ACPI_DMAR device pci +options PCI_HP # PCI-Express native HotPlug options PCI_IOV # PCI SR-IOV support # Floppy drives diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index 2b52196..9300e77 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -96,6 +96,7 @@ device vtnet # Bus drivers device pci +options PCI_HP # PCI-Express native HotPlug options PCI_IOV # PCI SR-IOV support # Ethernet NICs diff --git a/sys/conf/NOTES b/sys/conf/NOTES index f1553bf..51e81f1 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1411,6 +1411,7 @@ options MSGBUF_SIZE=40960 # PCI bus & PCI options: # device pci +options PCI_HP # PCI-Express native HotPlug options PCI_IOV # PCI SR-IOV support diff --git a/sys/conf/options b/sys/conf/options index 4d6ee66..61bbaa7 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -177,6 +177,7 @@ NO_SYSCTL_DESCR opt_global.h NSWBUF_MIN opt_swap.h MBUF_PACKET_ZONE_DISABLE opt_global.h PANIC_REBOOT_WAIT_TIME opt_panic.h +PCI_HP opt_pci.h PCI_IOV opt_global.h PPC_DEBUG opt_ppc.h PPC_PROBE_CHIPSET opt_ppc.h diff --git a/sys/dev/acpica/acpi_pcib_acpi.c b/sys/dev/acpica/acpi_pcib_acpi.c index e9bcbd1..506e267 100644 --- a/sys/dev/acpica/acpi_pcib_acpi.c +++ b/sys/dev/acpica/acpi_pcib_acpi.c @@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$"); #include "opt_acpi.h" +#include "opt_pci.h" + #include #include #include @@ -312,6 +314,11 @@ acpi_pcib_osc(struct acpi_hpcib_softc *sc) /* Control Field */ cap_set[2] = 0; +#ifdef PCI_HP + /* Control Field: PCI Express Native Hot Plug */ + cap_set[2] |= 0x1; +#endif + status = acpi_EvaluateOSC(sc->ap_handle, pci_host_bridge_uuid, 1, nitems(cap_set), cap_set, cap_set, false); if (ACPI_FAILURE(status)) { diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index 76643bc..e3539f5 100644 --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$"); * PCI:PCI bridge support. */ +#include "opt_pci.h" + #include #include #include @@ -43,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -67,6 +70,11 @@ static int pcib_try_enable_ari(device_t pcib, device_t dev); static int pcib_ari_enabled(device_t pcib); static void pcib_ari_decode_rid(device_t pcib, uint16_t rid, int *bus, int *slot, int *func); +#ifdef PCI_HP +static void pcib_pcie_ab_timeout(void *arg); +static void pcib_pcie_cc_timeout(void *arg); +static void pcib_pcie_dll_timeout(void *arg); +#endif static device_method_t pcib_methods[] = { /* Device interface */ @@ -78,6 +86,7 @@ static device_method_t pcib_methods[] = { DEVMETHOD(device_resume, pcib_resume), /* Bus interface */ + DEVMETHOD(bus_child_present, pcib_child_present), DEVMETHOD(bus_read_ivar, pcib_read_ivar), DEVMETHOD(bus_write_ivar, pcib_write_ivar), DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), @@ -839,6 +848,466 @@ pcib_set_mem_decode(struct pcib_softc *sc) } #endif +#ifdef PCI_HP +/* + * PCI-express HotPlug support. + */ +static void +pcib_probe_hotplug(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + if (pci_find_cap(dev, PCIY_EXPRESS, NULL) != 0) + return; + + if (!(pcie_read_config(dev, PCIER_FLAGS, 2) & PCIEM_FLAGS_SLOT)) + return; + + sc->pcie_link_cap = pcie_read_config(dev, PCIER_LINK_CAP, 4); + sc->pcie_slot_cap = pcie_read_config(dev, PCIER_SLOT_CAP, 4); + + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_HPC) + sc->flags |= PCIB_HOTPLUG; +} + +/* + * Send a HotPlug command to the slot control register. If this slot + * uses command completion interrupts, these updates will be buffered + * while a previous command is completing. + */ +static void +pcib_pcie_hotplug_command(struct pcib_softc *sc, uint16_t val, uint16_t mask) +{ + device_t dev; + uint16_t ctl, new; + + dev = sc->dev; + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS) { + ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); + new = (ctl & ~mask) | val; + if (new != ctl) + pcie_write_config(dev, PCIER_SLOT_CTL, new, 2); + return; + } + + if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) { + sc->pcie_pending_link_ctl_val &= ~mask; + sc->pcie_pending_link_ctl_val |= val; + sc->pcie_pending_link_ctl_mask |= mask; + } else { + ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); + new = (ctl & ~mask) | val; + if (new != ctl) { + pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2); + sc->flags |= PCIB_HOTPLUG_CMD_PENDING; + if (!cold) + callout_reset(&sc->pcie_cc_timer, hz, + pcib_pcie_cc_timeout, sc); + } + } +} + +static void +pcib_pcie_hotplug_command_completed(struct pcib_softc *sc) +{ + device_t dev; + uint16_t ctl, new; + + dev = sc->dev; + + if (bootverbose) + device_printf(dev, "Command Completed\n"); + if (!(sc->flags & PCIB_HOTPLUG_CMD_PENDING)) + return; + if (sc->pcie_pending_link_ctl_mask != 0) { + ctl = pcie_read_config(dev, PCIER_SLOT_CTL, 2); + new = ctl & ~sc->pcie_pending_link_ctl_mask; + new |= sc->pcie_pending_link_ctl_val; + if (new != ctl) { + pcie_write_config(dev, PCIER_SLOT_CTL, ctl, 2); + if (!cold) + callout_reset(&sc->pcie_cc_timer, hz, + pcib_pcie_cc_timeout, sc); + } else + sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING; + sc->pcie_pending_link_ctl_mask = 0; + sc->pcie_pending_link_ctl_val = 0; + } else { + callout_stop(&sc->pcie_cc_timer); + sc->flags &= ~PCIB_HOTPLUG_CMD_PENDING; + } +} + +/* + * Returns true if a card is fully inserted from the user's + * perspective. It may not yet be ready for access, but the driver + * can now start enabling access if necessary. + */ +static bool +pcib_hotplug_inserted(struct pcib_softc *sc) +{ + + /* Pretend the card isn't present if a detach is forced. */ + if (sc->flags & PCIB_DETACHING) + return (false); + + /* Card must be present in the slot. */ + if ((sc->pcie_slot_sta & PCIEM_SLOT_STA_PDS) == 0) + return (false); + + /* A power fault implicitly turns off power to the slot. */ + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_PFD) + return (false); + + /* If the MRL is disengaged, the slot is powered off. */ + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP && + (sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSS) != 0) + return (false); + + return (true); +} + +/* + * Returns -1 if the card is fully inserted, powered, and ready for + * access. Otherwise, returns 0. + */ +static int +pcib_hotplug_present(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + + /* Card must be inserted. */ + if (!pcib_hotplug_inserted(sc)) + return (0); + + /* + * Require the Electromechanical Interlock to be engaged if + * present. + */ + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_EIP && + (sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS) == 0) + return (0); + + /* Require the Data Link Layer to be active. */ + if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) { + if (!(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE)) + return (0); + } + + return (-1); +} + +static void +pcib_pcie_hotplug_update(struct pcib_softc *sc, uint16_t val, uint16_t mask, + bool schedule_task) +{ + bool card_inserted; + + /* Clear DETACHING if Present Detect has cleared. */ + if ((sc->pcie_slot_sta & (PCIEM_SLOT_STA_PDC | PCIEM_SLOT_STA_PDS)) == + PCIEM_SLOT_STA_PDC) + sc->flags &= ~PCIB_DETACHING; + + card_inserted = pcib_hotplug_inserted(sc); + + /* Turn the power indicator on if a card is inserted. */ + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PIP) { + mask |= PCIEM_SLOT_CTL_PIC; + if (card_inserted) + val |= PCIEM_SLOT_CTL_PI_ON; + else if (sc->flags & PCIB_DETACH_PENDING) + val |= PCIEM_SLOT_CTL_PI_BLINK; + else + val |= PCIEM_SLOT_CTL_PI_OFF; + } + + /* Turn the power on via the Power Controller if a card is inserted. */ + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PCP) { + mask |= PCIEM_SLOT_CTL_PCC; + if (card_inserted) + val |= PCIEM_SLOT_CTL_PC_ON; + else + val |= PCIEM_SLOT_CTL_PC_OFF; + } + + /* + * If a card is inserted, enable the Electromechanical + * Interlock. If a card is not inserted (or we are in the + * process of detaching), disable the Electromechanical + * Interlock. + */ + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_EIP) { + if (card_inserted != + !(sc->pcie_slot_sta & PCIEM_SLOT_STA_EIS)) { + mask |= PCIEM_SLOT_CTL_EIC; + val |= PCIEM_SLOT_CTL_EIC; + } + } + + /* + * Start a timer to see if the Data Link Layer times out. + * Note that we only start the timer if Presence Detect + * changed on this interrupt. Stop any scheduled timer if + * the Data Link Layer is active. + */ + if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) { + if (card_inserted && + !(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE) && + sc->pcie_slot_sta & PCIEM_SLOT_STA_PDC) { + if (cold) + device_printf(sc->dev, + "Data Link Layer inactive\n"); + else + callout_reset(&sc->pcie_dll_timer, hz, + pcib_pcie_dll_timeout, sc); + } else if (sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE) + callout_stop(&sc->pcie_dll_timer); + } + + pcib_pcie_hotplug_command(sc, val, mask); + + /* + * During attach the child "pci" device is added sychronously; + * otherwise, the task is scheduled to manage the child + * device. + */ + if (schedule_task && + (pcib_hotplug_present(sc) != 0) != (sc->child != NULL)) + taskqueue_enqueue(taskqueue_thread, &sc->pcie_hp_task); +} + +static void +pcib_pcie_intr(void *arg) +{ + struct pcib_softc *sc; + device_t dev; + + sc = arg; + dev = sc->dev; + sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); + + /* Clear the events just reported. */ + pcie_write_config(dev, PCIER_SLOT_STA, sc->pcie_slot_sta, 2); + + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_ABP) { + if (sc->flags & PCIB_DETACH_PENDING) { + device_printf(dev, + "Attention Button Pressed: Detach Cancelled\n"); + sc->flags &= ~PCIB_DETACH_PENDING; + callout_stop(&sc->pcie_ab_timer); + } else { + device_printf(dev, + "Attention Button Pressed: Detaching in 5 seconds\n"); + sc->flags |= PCIB_DETACH_PENDING; + callout_reset(&sc->pcie_ab_timer, 5 * hz, + pcib_pcie_ab_timeout, sc); + } + } + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_PFD) + device_printf(dev, "Power Fault Detected\n"); + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSC) + device_printf(dev, "MRL Sensor Changed to %s\n", + sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSS ? "open" : + "closed"); + if (bootverbose && sc->pcie_slot_sta & PCIEM_SLOT_STA_PDC) + device_printf(dev, "Present Detect Changed to %s\n", + sc->pcie_slot_sta & PCIEM_SLOT_STA_PDS ? "card present" : + "empty"); + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_CC) + pcib_pcie_hotplug_command_completed(sc); + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_DLLSC) { + sc->pcie_link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2); + if (bootverbose) + device_printf(dev, + "Data Link Layer State Changed to %s\n", + sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE ? + "active" : "inactive"); + } + + pcib_pcie_hotplug_update(sc, 0, 0, true); +} + +static void +pcib_pcie_hotplug_task(void *context, int pending) +{ + struct pcib_softc *sc; + device_t dev; + + sc = context; + mtx_lock(&Giant); + dev = sc->dev; + if (pcib_hotplug_present(sc) != 0) { + if (sc->child == NULL) { + sc->child = device_add_child(dev, "pci", -1); + bus_generic_attach(dev); + } + } else { + if (sc->child != NULL) { + if (device_delete_child(dev, sc->child) == 0) + sc->child = NULL; + } + } + mtx_unlock(&Giant); +} + +static void +pcib_pcie_ab_timeout(void *arg) +{ + struct pcib_softc *sc; + device_t dev; + + sc = arg; + dev = sc->dev; + mtx_assert(&Giant, MA_OWNED); + if (sc->flags & PCIB_DETACH_PENDING) { + sc->flags |= PCIB_DETACHING; + sc->flags &= ~PCIB_DETACH_PENDING; + pcib_pcie_hotplug_update(sc, 0, 0, true); + } +} + +static void +pcib_pcie_cc_timeout(void *arg) +{ + struct pcib_softc *sc; + device_t dev; + + sc = arg; + dev = sc->dev; + mtx_assert(&Giant, MA_OWNED); + if (sc->flags & PCIB_HOTPLUG_CMD_PENDING) { + device_printf(dev, + "Hotplug Command Timed Out - forcing detach\n"); + sc->flags &= ~(PCIB_HOTPLUG_CMD_PENDING | PCIB_DETACH_PENDING); + sc->flags |= PCIB_DETACHING; + pcib_pcie_hotplug_update(sc, 0, 0, true); + } +} + +static void +pcib_pcie_dll_timeout(void *arg) +{ + struct pcib_softc *sc; + device_t dev; + uint16_t sta; + + sc = arg; + dev = sc->dev; + mtx_assert(&Giant, MA_OWNED); + sta = pcie_read_config(dev, PCIER_LINK_STA, 2); + if (!(sta & PCIEM_LINK_STA_DL_ACTIVE)) { + device_printf(dev, + "Timed out waiting for Data Link Layer Active\n"); + sc->flags |= PCIB_DETACHING; + pcib_pcie_hotplug_update(sc, 0, 0, true); + } else if (sta != sc->pcie_link_sta) { + device_printf(dev, + "Missed HotPlug interrupt waiting for DLL Active\n"); + pcib_pcie_intr(sc); + } +} + +static int +pcib_alloc_pcie_irq(struct pcib_softc *sc) +{ + device_t dev; + int count, error, rid; + + rid = -1; + dev = sc->dev; + + /* + * For simplicity, only use MSI-X if there is a single message. + * To support a device with multiple messages we would have to + * use remap intr if the MSI number is not 0. + */ + count = pci_msix_count(dev); + if (count == 1) { + error = pci_alloc_msix(dev, &count); + if (error == 0) + rid = 1; + } + + if (rid < 0 && pci_msi_count(dev) > 0) { + count = 1; + error = pci_alloc_msi(dev, &count); + if (error == 0) + rid = 1; + } + + if (rid < 0) + rid = 0; + + sc->pcie_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->pcie_irq == NULL) { + device_printf(dev, + "Failed to allocate interrupt for PCI-e events\n"); + if (rid > 0) + pci_release_msi(dev); + return (ENXIO); + } + + error = bus_setup_intr(dev, sc->pcie_irq, INTR_TYPE_MISC, + NULL, pcib_pcie_intr, sc, &sc->pcie_ihand); + if (error) { + device_printf(dev, "Failed to setup PCI-e interrupt handler\n"); + bus_release_resource(dev, SYS_RES_IRQ, rid, sc->pcie_irq); + if (rid > 0) + pci_release_msi(dev); + return (error); + } + return (0); +} + +static void +pcib_setup_hotplug(struct pcib_softc *sc) +{ + device_t dev; + uint16_t mask, val; + + dev = sc->dev; + callout_init(&sc->pcie_ab_timer, 0); + callout_init(&sc->pcie_cc_timer, 0); + callout_init(&sc->pcie_dll_timer, 0); + TASK_INIT(&sc->pcie_hp_task, 0, pcib_pcie_hotplug_task, sc); + + /* Allocate IRQ. */ + if (pcib_alloc_pcie_irq(sc) != 0) + return; + + sc->pcie_link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2); + sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); + + /* Enable HotPlug events. */ + mask = PCIEM_SLOT_CTL_DLLSCE | PCIEM_SLOT_CTL_HPIE | + PCIEM_SLOT_CTL_CCIE | PCIEM_SLOT_CTL_PDCE | PCIEM_SLOT_CTL_MRLSCE | + PCIEM_SLOT_CTL_PFDE | PCIEM_SLOT_CTL_ABPE; + val = PCIEM_SLOT_CTL_PDCE | PCIEM_SLOT_CTL_HPIE; + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_APB) + val |= PCIEM_SLOT_CTL_ABPE; + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PCP) + val |= PCIEM_SLOT_CTL_PFDE; + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP) + val |= PCIEM_SLOT_CTL_MRLSCE; + if (!(sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS)) + val |= PCIEM_SLOT_CTL_CCIE; + if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) + val |= PCIEM_SLOT_CTL_DLLSCE; + + /* Turn the attention indicator off. */ + if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_AIP) { + mask |= PCIEM_SLOT_CTL_AIC; + val |= PCIEM_SLOT_CTL_AI_OFF; + } + + pcib_pcie_hotplug_update(sc, val, mask, false); +} +#endif + /* * Get current bridge configuration. */ @@ -1017,12 +1486,19 @@ pcib_attach_common(device_t dev) pci_read_config(dev, PCIR_PROGIF, 1) == PCIP_BRIDGE_PCI_SUBTRACTIVE) sc->flags |= PCIB_SUBTRACTIVE; +#ifdef PCI_HP + pcib_probe_hotplug(sc); +#endif #ifdef NEW_PCIB #ifdef PCI_RES_BUS pcib_setup_secbus(dev, &sc->bus, 1); #endif pcib_probe_windows(sc); #endif +#ifdef PCI_HP + if (sc->flags & PCIB_HOTPLUG) + pcib_setup_hotplug(sc); +#endif if (bootverbose) { device_printf(dev, " domain %d\n", sc->domain); device_printf(dev, " secondary bus %d\n", sc->bus.sec); @@ -1074,6 +1550,17 @@ pcib_attach_common(device_t dev) pci_enable_busmaster(dev); } +#ifdef PCI_HP +static int +pcib_present(struct pcib_softc *sc) +{ + + if (sc->flags & PCIB_HOTPLUG) + return (pcib_hotplug_present(sc) != 0); + return (1); +} +#endif + int pcib_attach_child(device_t dev) { @@ -1085,6 +1572,13 @@ pcib_attach_child(device_t dev) return(0); } +#ifdef PCI_HP + if (!pcib_present(sc)) { + /* An empty HotPlug slot, so don't add a PCI bus yet. */ + return (0); + } +#endif + sc->child = device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } @@ -1129,6 +1623,22 @@ pcib_bridge_init(device_t dev) } int +pcib_child_present(device_t dev, device_t child) +{ +#ifdef PCI_HP + struct pcib_softc *sc = device_get_softc(dev); + int retval; + + retval = bus_child_present(dev); + if (retval != 0 && sc->flags & PCIB_HOTPLUG) + retval = pcib_hotplug_present(sc); + return (retval); +#else + return (bus_child_present(dev)); +#endif +} + +int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct pcib_softc *sc = device_get_softc(dev); @@ -1909,7 +2419,21 @@ pcib_ari_decode_rid(device_t pcib, uint16_t rid, int *bus, int *slot, static uint32_t pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width) { +#ifdef PCI_HP + struct pcib_softc *sc; + sc = device_get_softc(dev); + if (!pcib_present(sc)) { + switch (width) { + case 2: + return (0xffff); + case 1: + return (0xff); + default: + return (0xffffffff); + } + } +#endif pcib_xlate_ari(dev, b, &s, &f); return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width)); @@ -1918,7 +2442,13 @@ pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width) static void pcib_write_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, uint32_t val, int width) { +#ifdef PCI_HP + struct pcib_softc *sc; + sc = device_get_softc(dev); + if (!pcib_present(sc)) + return; +#endif pcib_xlate_ari(dev, b, &s, &f); PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width); diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h index 93d9a71..c209162 100644 --- a/sys/dev/pci/pcib_private.h +++ b/sys/dev/pci/pcib_private.h @@ -33,6 +33,9 @@ #ifndef __PCIB_PRIVATE_H__ #define __PCIB_PRIVATE_H__ +#include +#include + #ifdef NEW_PCIB /* * Data structure and routines that Host to PCI bridge drivers can use @@ -107,6 +110,10 @@ struct pcib_softc #define PCIB_DISABLE_MSI 0x2 #define PCIB_DISABLE_MSIX 0x4 #define PCIB_ENABLE_ARI 0x8 +#define PCIB_HOTPLUG 0x10 +#define PCIB_HOTPLUG_CMD_PENDING 0x20 +#define PCIB_DETACH_PENDING 0x40 +#define PCIB_DETACHING 0x80 u_int domain; /* domain number */ u_int pribus; /* primary bus number */ struct pcib_secbus bus; /* secondary bus numbers */ @@ -123,6 +130,18 @@ struct pcib_softc uint32_t iolimit; /* topmost address of port window */ #endif uint16_t bridgectl; /* bridge control register */ + uint16_t pcie_link_sta; + uint16_t pcie_slot_sta; + uint32_t pcie_link_cap; + uint32_t pcie_slot_cap; + uint16_t pcie_pending_link_ctl_mask; + uint16_t pcie_pending_link_ctl_val; + struct resource *pcie_irq; + void *pcie_ihand; + struct task pcie_hp_task; + struct callout pcie_ab_timer; + struct callout pcie_cc_timer; + struct callout pcie_dll_timer; }; #define PCIB_SUPPORTED_ARI_VER 1 @@ -151,6 +170,7 @@ void pcib_bridge_init(device_t dev); #ifdef NEW_PCIB const char *pcib_child_name(device_t child); #endif +int pcib_child_present(device_t dev, device_t child); int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value); struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index 68b5378..d463b7a 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -850,8 +850,16 @@ #define PCIEM_SLOT_CTL_CCIE 0x0010 #define PCIEM_SLOT_CTL_HPIE 0x0020 #define PCIEM_SLOT_CTL_AIC 0x00c0 +#define PCIEM_SLOT_CTL_AI_ON 0x0040 +#define PCIEM_SLOT_CTL_AI_BLINK 0x0080 +#define PCIEM_SLOT_CTL_AI_OFF 0x00c0 #define PCIEM_SLOT_CTL_PIC 0x0300 +#define PCIEM_SLOT_CTL_PI_ON 0x0100 +#define PCIEM_SLOT_CTL_PI_BLINK 0x0200 +#define PCIEM_SLOT_CTL_PI_OFF 0x0300 #define PCIEM_SLOT_CTL_PCC 0x0400 +#define PCIEM_SLOT_CTL_PC_ON 0x0000 +#define PCIEM_SLOT_CTL_PC_OFF 0x0400 #define PCIEM_SLOT_CTL_EIC 0x0800 #define PCIEM_SLOT_CTL_DLLSCE 0x1000 #define PCIER_SLOT_STA 0x1a diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index ee2df93..aefc507 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -101,6 +101,7 @@ device cpufreq # Bus support. device acpi device pci +options PCI_HP # PCI-Express native HotPlug options PCI_IOV # PCI SR-IOV support # Floppy drives diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC index f67e5e5..d464ac7 100644 --- a/sys/powerpc/conf/GENERIC +++ b/sys/powerpc/conf/GENERIC @@ -102,6 +102,7 @@ device cpufreq # Standard busses device pci +options PCI_HP # PCI-Express native HotPlug device agp # ATA controllers diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64 index 847101f..88d4811 100644 --- a/sys/powerpc/conf/GENERIC64 +++ b/sys/powerpc/conf/GENERIC64 @@ -99,6 +99,7 @@ device cpufreq # Standard busses device pci +options PCI_HP # PCI-Express native HotPlug device agp # ATA controllers -- cgit v1.1 From 68fbe09129d96f8e34b094c984d94f154d42b9b5 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 01:49:46 +0000 Subject: sys/rpc: minor spelling fixes. No functional change. --- sys/rpc/clnt_bck.c | 2 +- sys/rpc/clnt_dg.c | 6 +++--- sys/rpc/clnt_vc.c | 6 +++--- sys/rpc/svc.c | 2 +- sys/rpc/svc.h | 4 ++-- sys/rpc/types.h | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) (limited to 'sys') diff --git a/sys/rpc/clnt_bck.c b/sys/rpc/clnt_bck.c index 477b276..f1c8dde 100644 --- a/sys/rpc/clnt_bck.c +++ b/sys/rpc/clnt_bck.c @@ -431,7 +431,7 @@ got_reply: } } /* end successful completion */ /* - * If unsuccesful AND error is an authentication error + * If unsuccessful AND error is an authentication error * then refresh credentials and try again, else break */ else if (stat == RPC_AUTHERROR) diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c index d9d5e41..1f181fd 100644 --- a/sys/rpc/clnt_dg.c +++ b/sys/rpc/clnt_dg.c @@ -742,7 +742,7 @@ got_reply: } } /* end successful completion */ /* - * If unsuccesful AND error is an authentication error + * If unsuccessful AND error is an authentication error * then refresh credentials and try again, else break */ else if (stat == RPC_AUTHERROR) @@ -882,7 +882,7 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info) /* * This RELIES on the information that, in the call body, * the version number field is the fifth field from the - * begining of the RPC header. MUST be changed if the + * beginning of the RPC header. MUST be changed if the * call_struct is changed */ *(uint32_t *)info = @@ -899,7 +899,7 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info) /* * This RELIES on the information that, in the call body, * the program number field is the fourth field from the - * begining of the RPC header. MUST be changed if the + * beginning of the RPC header. MUST be changed if the * call_struct is changed */ *(uint32_t *)info = diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c index 3899511..1bd6e1c 100644 --- a/sys/rpc/clnt_vc.c +++ b/sys/rpc/clnt_vc.c @@ -520,7 +520,7 @@ got_reply: } } /* end successful completion */ /* - * If unsuccesful AND error is an authentication error + * If unsuccessful AND error is an authentication error * then refresh credentials and try again, else break */ else if (stat == RPC_AUTHERROR) @@ -653,7 +653,7 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info) /* * This RELIES on the information that, in the call body, * the version number field is the fifth field from the - * begining of the RPC header. MUST be changed if the + * beginning of the RPC header. MUST be changed if the * call_struct is changed */ *(uint32_t *)info = @@ -671,7 +671,7 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info) /* * This RELIES on the information that, in the call body, * the program number field is the fourth field from the - * begining of the RPC header. MUST be changed if the + * beginning of the RPC header. MUST be changed if the * call_struct is changed */ *(uint32_t *)info = diff --git a/sys/rpc/svc.c b/sys/rpc/svc.c index b436c18..50ab93a 100644 --- a/sys/rpc/svc.c +++ b/sys/rpc/svc.c @@ -440,7 +440,7 @@ xprt_inactive(SVCXPRT *xprt) /* * Variant of xprt_inactive() for use only when sure that port is - * assigned to thread. For example, withing receive handlers. + * assigned to thread. For example, within receive handlers. */ void xprt_inactive_self(SVCXPRT *xprt) diff --git a/sys/rpc/svc.h b/sys/rpc/svc.h index 80285ec..22322ba 100644 --- a/sys/rpc/svc.h +++ b/sys/rpc/svc.h @@ -226,7 +226,7 @@ typedef struct __rpc_svcxprt_ext { * The services list * Each entry represents a set of procedures (an rpc program). * The dispatch routine takes request structs and runs the - * apropriate procedure. + * appropriate procedure. */ struct svc_callout { TAILQ_ENTRY(svc_callout) sc_link; @@ -240,7 +240,7 @@ TAILQ_HEAD(svc_callout_list, svc_callout); /* * The services connection loss list * The dispatch routine takes request structs and runs the - * apropriate procedure. + * appropriate procedure. */ struct svc_loss_callout { TAILQ_ENTRY(svc_loss_callout) slc_link; diff --git a/sys/rpc/types.h b/sys/rpc/types.h index dd51a8a..62b5aca 100644 --- a/sys/rpc/types.h +++ b/sys/rpc/types.h @@ -94,7 +94,7 @@ struct netbuf { }; /* - * The format of the addres and options arguments of the XTI t_bind call. + * The format of the address and options arguments of the XTI t_bind call. * Only provided for compatibility, it should not be used. */ -- cgit v1.1 From eb4486dee856baad533f5cf9ea2e0ea1923187dc Mon Sep 17 00:00:00 2001 From: ae Date: Fri, 6 May 2016 03:18:51 +0000 Subject: Change the type of objhash_cb_t callback function to be able return an error code. Use it to interrupt the loop in ipfw_objhash_foreach(). Obtained from: Yandex LLC Sponsored by: Yandex LLC --- sys/netpfil/ipfw/ip_fw_iface.c | 6 ++++-- sys/netpfil/ipfw/ip_fw_private.h | 4 ++-- sys/netpfil/ipfw/ip_fw_sockopt.c | 17 +++++++++++------ sys/netpfil/ipfw/ip_fw_table.c | 16 ++++++++++------ sys/netpfil/ipfw/ip_fw_table_algo.c | 10 ++++++---- sys/netpfil/ipfw/ip_fw_table_value.c | 12 +++++++----- 6 files changed, 40 insertions(+), 25 deletions(-) (limited to 'sys') diff --git a/sys/netpfil/ipfw/ip_fw_iface.c b/sys/netpfil/ipfw/ip_fw_iface.c index 07d24de..b2aa7d3 100644 --- a/sys/netpfil/ipfw/ip_fw_iface.c +++ b/sys/netpfil/ipfw/ip_fw_iface.c @@ -249,13 +249,14 @@ vnet_ipfw_iface_init(struct ip_fw_chain *ch) } } -static void +static int destroy_iface(struct namedobj_instance *ii, struct named_object *no, void *arg) { /* Assume all consumers have been already detached */ free(no, M_IPFW); + return (0); } /* @@ -460,7 +461,7 @@ struct dump_iface_args { struct sockopt_data *sd; }; -static void +static int export_iface_internal(struct namedobj_instance *ii, struct named_object *no, void *arg) { @@ -481,6 +482,7 @@ export_iface_internal(struct namedobj_instance *ii, struct named_object *no, i->ifindex = iif->ifindex; i->refcnt = iif->no.refcnt; i->gencnt = iif->gencnt; + return (0); } /* diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index 0a722bd..52e8a76 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -649,7 +649,7 @@ caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed); } while(0) struct namedobj_instance; -typedef void (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, +typedef int (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, void *arg); typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, const void *key, uint32_t kopt); @@ -675,7 +675,7 @@ int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no); void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no); uint32_t ipfw_objhash_count(struct namedobj_instance *ni); -void ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, +int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg); int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 72d40ca..2f41d23 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -3009,7 +3009,7 @@ ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) return (0); } -static void +static int export_objhash_ntlv_internal(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3019,8 +3019,9 @@ export_objhash_ntlv_internal(struct namedobj_instance *ni, sd = (struct sockopt_data *)arg; ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); if (ntlv == NULL) - return; + return (ENOMEM); ipfw_export_obj_ntlv(no, ntlv); + return (0); } /* @@ -4249,16 +4250,20 @@ ipfw_objhash_count(struct namedobj_instance *ni) * Runs @func for each found named object. * It is safe to delete objects from callback */ -void +int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, void *arg) { struct named_object *no, *no_tmp; - int i; + int i, ret; for (i = 0; i < ni->nn_size; i++) { - TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) - f(ni, no, arg); + TAILQ_FOREACH_SAFE(no, &ni->names[i], nn_next, no_tmp) { + ret = f(ni, no, arg); + if (ret != 0) + return (ret); + } } + return (0); } /* diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c index 060fd94..194be08 100644 --- a/sys/netpfil/ipfw/ip_fw_table.c +++ b/sys/netpfil/ipfw/ip_fw_table.c @@ -2119,7 +2119,7 @@ struct dump_table_args { struct sockopt_data *sd; }; -static void +static int export_table_internal(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -2132,6 +2132,7 @@ export_table_internal(struct namedobj_instance *ni, struct named_object *no, KASSERT(i != NULL, ("previously checked buffer is not enough")); export_table_info(dta->ch, (struct table_config *)no, i); + return (0); } /* @@ -3123,7 +3124,7 @@ struct swap_table_args { * Ensure we dispatch each table once by setting/checking ochange * fields. */ -static void +static int swap_table_set(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3134,10 +3135,10 @@ swap_table_set(struct namedobj_instance *ni, struct named_object *no, sta = (struct swap_table_args *)arg; if (no->set != sta->set && (no->set != sta->new_set || sta->mv != 0)) - return; + return (0); if (tc->ochanged != 0) - return; + return (0); tc->ochanged = 1; ipfw_objhash_del(ni, no); @@ -3146,12 +3147,13 @@ swap_table_set(struct namedobj_instance *ni, struct named_object *no, else no->set = sta->set; ipfw_objhash_add(ni, no); + return (0); } /* * Cleans up ochange field for all tables. */ -static void +static int clean_table_set_data(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3162,6 +3164,7 @@ clean_table_set_data(struct namedobj_instance *ni, struct named_object *no, sta = (struct swap_table_args *)arg; tc->ochanged = 0; + return (0); } /* @@ -3318,7 +3321,7 @@ static struct ipfw_sopt_handler scodes[] = { { IP_FW_TABLE_XGETSIZE, 0, HDIR_GET, get_table_size }, }; -static void +static int destroy_table_locked(struct namedobj_instance *ni, struct named_object *no, void *arg) { @@ -3328,6 +3331,7 @@ destroy_table_locked(struct namedobj_instance *ni, struct named_object *no, printf("Error unlinking kidx %d from table %s\n", no->kidx, no->name); free_table_config(ni, (struct table_config *)no); + return (0); } /* diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c index b0ad73d..bd6a54d 100644 --- a/sys/netpfil/ipfw/ip_fw_table_algo.c +++ b/sys/netpfil/ipfw/ip_fw_table_algo.c @@ -1941,7 +1941,7 @@ static int ta_lookup_ifidx(struct table_info *ti, void *key, uint32_t keylen, static int ta_init_ifidx(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, char *data, uint8_t tflags); static void ta_change_ti_ifidx(void *ta_state, struct table_info *ti); -static void destroy_ifidx_locked(struct namedobj_instance *ii, +static int destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no, void *arg); static void ta_destroy_ifidx(void *ta_state, struct table_info *ti); static void ta_dump_ifidx_tinfo(void *ta_state, struct table_info *ti, @@ -1969,7 +1969,7 @@ static int ta_dump_ifidx_tentry(void *ta_state, struct table_info *ti, void *e, ipfw_obj_tentry *tent); static int ta_find_ifidx_tentry(void *ta_state, struct table_info *ti, ipfw_obj_tentry *tent); -static void foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, +static int foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, void *arg); static void ta_foreach_ifidx(void *ta_state, struct table_info *ti, ta_foreach_f *f, void *arg); @@ -2126,7 +2126,7 @@ ta_change_ti_ifidx(void *ta_state, struct table_info *ti) icfg->ti = ti; } -static void +static int destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no, void *arg) { @@ -2139,6 +2139,7 @@ destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no, ipfw_iface_del_notify(ch, &ife->ic); ipfw_iface_unref(ch, &ife->ic); free(ife, M_IPFW_TBL); + return (0); } @@ -2560,7 +2561,7 @@ struct wa_ifidx { void *arg; }; -static void +static int foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, void *arg) { @@ -2571,6 +2572,7 @@ foreach_ifidx(struct namedobj_instance *ii, struct named_object *no, wa = (struct wa_ifidx *)arg; wa->f(ife, wa->arg); + return (0); } static void diff --git a/sys/netpfil/ipfw/ip_fw_table_value.c b/sys/netpfil/ipfw/ip_fw_table_value.c index 7ca316d..e92a5a9 100644 --- a/sys/netpfil/ipfw/ip_fw_table_value.c +++ b/sys/netpfil/ipfw/ip_fw_table_value.c @@ -147,7 +147,7 @@ get_value_ptrs(struct ip_fw_chain *ch, struct table_config *tc, int vshared, /* * Update pointers to real vaues after @pval change. */ -static void +static int update_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) { struct vdump_args *da; @@ -160,7 +160,7 @@ update_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) pval = da->pval; ptv->pval = &pval[ptv->no.kidx]; ptv->no.name = (char *)&pval[ptv->no.kidx]; - + return (0); } /* @@ -693,7 +693,7 @@ ipfw_export_table_value_v1(struct table_value *v, ipfw_table_value *piv) * Exports real value data into ipfw_table_value structure. * Utilizes "spare1" field to store kernel index. */ -static void +static int dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) { struct vdump_args *da; @@ -707,11 +707,12 @@ dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg) /* Out of memory, returning */ if (v == NULL) { da->error = ENOMEM; - return; + return (ENOMEM); } memcpy(v, ptv->pval, sizeof(*v)); v->spare1 = ptv->no.kidx; + return (0); } /* @@ -785,12 +786,13 @@ ipfw_table_value_init(struct ip_fw_chain *ch, int first) IPFW_ADD_SOPT_HANDLER(first, scodes); } -static void +static int destroy_value(struct namedobj_instance *ni, struct named_object *no, void *arg) { free(no, M_IPFW); + return (0); } void -- cgit v1.1 From b834a046349f1e7cf3f151c5cc8a2b60022cbaa1 Mon Sep 17 00:00:00 2001 From: sgalabov Date: Fri, 6 May 2016 05:22:25 +0000 Subject: mtk_gpio fixes Allow output pins to be read and input pins to be set. Fix bugs where we were trying to access the gpio softc before doing device_get_softc. Approved by: adrian (mentor) Sponsored by: Smartcom - Bulgaria AD Differential Revision: https://reviews.freebsd.org/D6222 --- sys/mips/mediatek/mtk_gpio_v1.c | 23 ++++++----------------- sys/mips/mediatek/mtk_gpio_v2.c | 31 ++++++++++--------------------- 2 files changed, 16 insertions(+), 38 deletions(-) (limited to 'sys') diff --git a/sys/mips/mediatek/mtk_gpio_v1.c b/sys/mips/mediatek/mtk_gpio_v1.c index ec56360..7ca3a12 100644 --- a/sys/mips/mediatek/mtk_gpio_v1.c +++ b/sys/mips/mediatek/mtk_gpio_v1.c @@ -290,7 +290,7 @@ mtk_gpio_attach(device_t dev) else sc->num_pins = MTK_GPIO_PINS; - for (i = 0; i < num_pins; i++) { + for (i = 0; i < sc->num_pins; i++) { sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | GPIO_PIN_INVOUT; sc->pins[i].intr_polarity = INTR_POLARITY_HIGH; @@ -444,18 +444,12 @@ mtk_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) return (EINVAL); MTK_GPIO_LOCK(sc); - if(!(sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT)) { - ret = EINVAL; - goto out; - } - if (value) MTK_WRITE_4(sc, GPIO_PIOSET, (1u << pin)); else MTK_WRITE_4(sc, GPIO_PIORESET, (1u << pin)); - -out: MTK_GPIO_UNLOCK(sc); + return (ret); } @@ -473,15 +467,10 @@ mtk_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) return (EINVAL); MTK_GPIO_LOCK(sc); - if(!(sc->pins[pin].pin_flags & GPIO_PIN_INPUT)) { - ret = EINVAL; - goto out; - } data = MTK_READ_4(sc, GPIO_PIODATA); *val = (data & (1u << pin)) ? 1 : 0; - -out: MTK_GPIO_UNLOCK(sc); + return (ret); } @@ -491,12 +480,12 @@ mtk_gpio_pin_toggle(device_t dev, uint32_t pin) struct mtk_gpio_softc *sc; int ret; - if (pin >= sc->num_pins) - return (EINVAL); - sc = device_get_softc(dev); ret = 0; + if (pin >= sc->num_pins) + return (EINVAL); + MTK_GPIO_LOCK(sc); if (!(sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT)) { ret = EINVAL; diff --git a/sys/mips/mediatek/mtk_gpio_v2.c b/sys/mips/mediatek/mtk_gpio_v2.c index 66236cc..75c7263 100644 --- a/sys/mips/mediatek/mtk_gpio_v2.c +++ b/sys/mips/mediatek/mtk_gpio_v2.c @@ -428,23 +428,17 @@ mtk_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) struct mtk_gpio_softc *sc; int ret; - if (pin >= sc->num_pins) - return (EINVAL); - sc = device_get_softc(dev); ret = 0; + if (pin >= sc->num_pins) + return (EINVAL); + MTK_GPIO_LOCK(sc); - if (!(sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT)) { - ret = EINVAL; - goto out; - } if (value) MTK_WRITE_4(sc, GPIO_PIOSET(sc), (1u << pin)); else MTK_WRITE_4(sc, GPIO_PIORESET(sc), (1u << pin)); - -out: MTK_GPIO_UNLOCK(sc); return (ret); @@ -457,22 +451,17 @@ mtk_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) uint32_t data; int ret; - if (pin >= sc->num_pins) - return (EINVAL); - sc = device_get_softc(dev); ret = 0; + if (pin >= sc->num_pins) + return (EINVAL); + MTK_GPIO_LOCK(sc); - if (!(sc->pins[pin].pin_flags & GPIO_PIN_INPUT)) { - ret = EINVAL; - goto out; - } data = MTK_READ_4(sc, GPIO_PIODATA(sc)); *val = (data & (1u << pin)) ? 1 : 0; - -out: MTK_GPIO_UNLOCK(sc); + return (ret); } @@ -483,12 +472,12 @@ mtk_gpio_pin_toggle(device_t dev, uint32_t pin) uint32_t val; int ret; - if (pin >= sc->num_pins) - return (EINVAL); - sc = device_get_softc(dev); ret = 0; + if (pin >= sc->num_pins) + return (EINVAL); + MTK_GPIO_LOCK(sc); if(!(sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT)) { ret = EINVAL; -- cgit v1.1 From ed879e9400e0f15b6720e4e3a0171a2fac670f4b Mon Sep 17 00:00:00 2001 From: sgalabov Date: Fri, 6 May 2016 05:24:10 +0000 Subject: mtk_spi cleanup commented printfs Approved by: adrian (mentor) Sponsored by: Smartcom - Bulgaria AD Differential Revision: https://reviews.freebsd.org/D6223 --- sys/mips/mediatek/mtk_spi_v1.c | 5 ----- sys/mips/mediatek/mtk_spi_v2.c | 6 ------ 2 files changed, 11 deletions(-) (limited to 'sys') diff --git a/sys/mips/mediatek/mtk_spi_v1.c b/sys/mips/mediatek/mtk_spi_v1.c index 1835b8e..9cf8faa 100644 --- a/sys/mips/mediatek/mtk_spi_v1.c +++ b/sys/mips/mediatek/mtk_spi_v1.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -//#include #include #include @@ -166,7 +165,6 @@ mtk_spi_detach(device_t dev) static void mtk_spi_chip_activate(struct mtk_spi_softc *sc) { -// printf("%s\n", __func__); mtk_spi_wait(sc); /* * Put all CSx to low @@ -177,7 +175,6 @@ mtk_spi_chip_activate(struct mtk_spi_softc *sc) static void mtk_spi_chip_deactivate(struct mtk_spi_softc *sc) { -// printf("%s\n", __func__); mtk_spi_wait(sc); /* * Put all CSx to high @@ -212,14 +209,12 @@ mtk_spi_txrx(struct mtk_spi_softc *sc, uint8_t *data, int write) if (write == MTK_SPI_WRITE) { SPI_WRITE(sc, MTK_SPIDATA, *data); SPI_SET_BITS(sc, MTK_SPICTL, START_WRITE); - //printf("%s(W:%d)\n", __func__, *data); } else {/* MTK_SPI_READ */ SPI_SET_BITS(sc, MTK_SPICTL, START_READ); if (mtk_spi_wait(sc)) return (EBUSY); *data = SPI_READ(sc, MTK_SPIDATA) & 0xff; - //printf("%s(R:%d)\n", __func__, *data); } return (0); } diff --git a/sys/mips/mediatek/mtk_spi_v2.c b/sys/mips/mediatek/mtk_spi_v2.c index 0ffd976..1f85ca3 100644 --- a/sys/mips/mediatek/mtk_spi_v2.c +++ b/sys/mips/mediatek/mtk_spi_v2.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include -//#include #include #include @@ -157,8 +156,6 @@ mtk_spi_detach(device_t dev) { struct mtk_spi_softc *sc = device_get_softc(dev); - //SPI_SET_BITS(sc, MTK_SPICTL, HIZSMOSI | CS_HIGH); - if (sc->sc_mem_res) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); @@ -168,7 +165,6 @@ mtk_spi_detach(device_t dev) static void mtk_spi_chip_activate(struct mtk_spi_softc *sc) { -// printf("%s\n", __func__); mtk_spi_wait(sc); /* * Put all CSx to low @@ -179,7 +175,6 @@ mtk_spi_chip_activate(struct mtk_spi_softc *sc) static void mtk_spi_chip_deactivate(struct mtk_spi_softc *sc) { -// printf("%s\n", __func__); mtk_spi_wait(sc); /* * Put all CSx to high @@ -197,7 +192,6 @@ mtk_spi_wait(struct mtk_spi_softc *sc) break; } if (i == 0) { - //printf("busy\n"); return (1); } -- cgit v1.1 From 8d92017b7d2c110feb22d3cf64dd96b54ab24a90 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 6 May 2016 08:54:00 +0000 Subject: Set correct size to the size member of struct intr_map_data when initialized. As the size member is not used at the present, it did not break anything. --- sys/kern/subr_intr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 366ccf9..98e8e38 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -511,7 +511,7 @@ intr_ddata_alloc(u_int extsize) mtx_unlock(&isrc_table_lock); ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size); - ddata->idd_data->size = size; + ddata->idd_data->size = extsize; return (ddata); } -- cgit v1.1 From 5320545e5dff23e76fee3f75a2c8ad14cac1bde5 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 6 May 2016 08:56:46 +0000 Subject: INTRNG - use gpio interrupt modes definitions added in r298738 and implement also GPIO_INTR_EDGE_BOTH mode. All reasonable interrupt modes are supported now. --- sys/arm/ti/ti_gpio.c | 86 ++++++++++++++++++++++++++-------------------------- sys/arm/ti/ti_gpio.h | 2 +- 2 files changed, 44 insertions(+), 44 deletions(-) (limited to 'sys') diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 70c1a33..510e2cc7 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -800,17 +800,13 @@ ti_gpio_detach(device_t dev) #ifdef INTRNG static inline void -ti_gpio_rwreg_set(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask) +ti_gpio_rwreg_modify(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask, + bool set_bits) { + uint32_t value; - ti_gpio_write_4(sc, reg, ti_gpio_read_4(sc, reg) | mask); -} - -static inline void -ti_gpio_rwreg_clr(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask) -{ - - ti_gpio_write_4(sc, reg, ti_gpio_read_4(sc, reg) & ~mask); + value = ti_gpio_read_4(sc, reg); + ti_gpio_write_4(sc, reg, set_bits ? value | mask : value & ~mask); } static inline void @@ -841,8 +837,8 @@ static inline bool ti_gpio_isrc_is_level(struct ti_gpio_irqsrc *tgi) { - return (tgi->tgi_cfgreg == TI_GPIO_LEVELDETECT0 || - tgi->tgi_cfgreg == TI_GPIO_LEVELDETECT1); + return (tgi->tgi_mode == GPIO_INTR_LEVEL_LOW || + tgi->tgi_mode == GPIO_INTR_LEVEL_HIGH); } static int @@ -889,7 +885,7 @@ ti_gpio_pic_attach(struct ti_gpio_softc *sc) for (irq = 0; irq < sc->sc_maxpin; irq++) { sc->sc_isrcs[irq].tgi_irq = irq; sc->sc_isrcs[irq].tgi_mask = TI_GPIO_MASK(irq); - sc->sc_isrcs[irq].tgi_cfgreg = 0; + sc->sc_isrcs[irq].tgi_mode = GPIO_INTR_CONFORM; error = intr_isrc_register(&sc->sc_isrcs[irq].tgi_isrc, sc->sc_dev, 0, "%s,%u", name, irq); @@ -913,6 +909,24 @@ ti_gpio_pic_detach(struct ti_gpio_softc *sc) } static void +ti_gpio_pic_config_intr(struct ti_gpio_softc *sc, struct ti_gpio_irqsrc *tgi, + uint32_t mode) +{ + + TI_GPIO_LOCK(sc); + ti_gpio_rwreg_modify(sc, TI_GPIO_RISINGDETECT, tgi->tgi_mask, + mode == GPIO_INTR_EDGE_RISING || mode == GPIO_INTR_EDGE_BOTH); + ti_gpio_rwreg_modify(sc, TI_GPIO_FALLINGDETECT, tgi->tgi_mask, + mode == GPIO_INTR_EDGE_FALLING || mode == GPIO_INTR_EDGE_BOTH); + ti_gpio_rwreg_modify(sc, TI_GPIO_LEVELDETECT1, tgi->tgi_mask, + mode == GPIO_INTR_LEVEL_HIGH); + ti_gpio_rwreg_modify(sc, TI_GPIO_LEVELDETECT0, tgi->tgi_mask, + mode == GPIO_INTR_LEVEL_LOW); + tgi->tgi_mode = mode; + TI_GPIO_UNLOCK(sc); +} + +static void ti_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) { struct ti_gpio_softc *sc = device_get_softc(dev); @@ -933,9 +947,9 @@ ti_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) static int ti_gpio_pic_map_fdt(struct ti_gpio_softc *sc, u_int ncells, pcell_t *cells, - u_int *irqp, uint32_t *regp) + u_int *irqp, uint32_t *modep) { - uint32_t reg; + uint32_t mode; /* * The first cell is the interrupt number. @@ -949,26 +963,23 @@ ti_gpio_pic_map_fdt(struct ti_gpio_softc *sc, u_int ncells, pcell_t *cells, if (ncells != 2 || cells[0] >= sc->sc_maxpin) return (EINVAL); - /* - * All interrupt types could be set for an interrupt at one moment. - * At least, the combination of 'low-to-high' and 'high-to-low' edge - * triggered interrupt types can make a sense. However, no combo is - * supported now. - */ + /* Only reasonable modes are supported. */ if (cells[1] == 1) - reg = TI_GPIO_RISINGDETECT; + mode = GPIO_INTR_EDGE_RISING; else if (cells[1] == 2) - reg = TI_GPIO_FALLINGDETECT; + mode = GPIO_INTR_EDGE_FALLING; + else if (cells[1] == 3) + mode = GPIO_INTR_EDGE_BOTH; else if (cells[1] == 4) - reg = TI_GPIO_LEVELDETECT1; + mode = GPIO_INTR_LEVEL_HIGH; else if (cells[1] == 8) - reg = TI_GPIO_LEVELDETECT0; + mode = GPIO_INTR_LEVEL_LOW; else return (EINVAL); *irqp = cells[0]; - if (regp != NULL) - *regp = reg; + if (modep != NULL) + *modep = mode; return (0); } @@ -1026,7 +1037,7 @@ ti_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { u_int irq; - uint32_t cfgreg; + uint32_t mode; struct ti_gpio_softc *sc; struct ti_gpio_irqsrc *tgi; struct intr_map_data_fdt *daf; @@ -1040,7 +1051,7 @@ ti_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, /* Get and check config for an interrupt. */ if (ti_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, - &cfgreg) != 0 || tgi->tgi_irq != irq) + &mode) != 0 || tgi->tgi_irq != irq) return (EINVAL); /* @@ -1048,16 +1059,9 @@ ti_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, * only check that its configuration match. */ if (isrc->isrc_handlers != 0) - return (tgi->tgi_cfgreg == cfgreg ? 0 : EINVAL); + return (tgi->tgi_mode == mode ? 0 : EINVAL); - TI_GPIO_LOCK(sc); - ti_gpio_rwreg_clr(sc, TI_GPIO_RISINGDETECT, tgi->tgi_mask); - ti_gpio_rwreg_clr(sc, TI_GPIO_FALLINGDETECT, tgi->tgi_mask); - ti_gpio_rwreg_clr(sc, TI_GPIO_LEVELDETECT1, tgi->tgi_mask); - ti_gpio_rwreg_clr(sc, TI_GPIO_LEVELDETECT0, tgi->tgi_mask); - tgi->tgi_cfgreg = cfgreg; - ti_gpio_rwreg_set(sc, cfgreg, tgi->tgi_mask); - TI_GPIO_UNLOCK(sc); + ti_gpio_pic_config_intr(sc, tgi, mode); return (0); } @@ -1068,12 +1072,8 @@ ti_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, struct ti_gpio_softc *sc = device_get_softc(dev); struct ti_gpio_irqsrc *tgi = (struct ti_gpio_irqsrc *)isrc; - if (isrc->isrc_handlers == 0) { - TI_GPIO_LOCK(sc); - ti_gpio_rwreg_clr(sc, tgi->tgi_cfgreg, tgi->tgi_mask); - tgi->tgi_cfgreg = 0; - TI_GPIO_UNLOCK(sc); - } + if (isrc->isrc_handlers == 0) + ti_gpio_pic_config_intr(sc, tgi, GPIO_INTR_CONFORM); return (0); } diff --git a/sys/arm/ti/ti_gpio.h b/sys/arm/ti/ti_gpio.h index 174dd62..c9785dd 100644 --- a/sys/arm/ti/ti_gpio.h +++ b/sys/arm/ti/ti_gpio.h @@ -49,7 +49,7 @@ struct ti_gpio_irqsrc { struct intr_irqsrc tgi_isrc; u_int tgi_irq; uint32_t tgi_mask; - uint32_t tgi_cfgreg; + uint32_t tgi_mode; }; #endif -- cgit v1.1 From 3bddc92a33fc35ae491a65414e6c97d0caebacf7 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 6 May 2016 08:59:25 +0000 Subject: INTRNG - support new interrupt mapping type INTR_MAP_DATA_GPIO introduced in r298738. --- sys/arm/ti/ti_gpio.c | 72 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 22 deletions(-) (limited to 'sys') diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 510e2cc7..830af3d 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -946,7 +946,7 @@ ti_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) } static int -ti_gpio_pic_map_fdt(struct ti_gpio_softc *sc, u_int ncells, pcell_t *cells, +ti_gpio_pic_map_fdt(struct ti_gpio_softc *sc, struct intr_map_data_fdt *daf, u_int *irqp, uint32_t *modep) { uint32_t mode; @@ -960,45 +960,76 @@ ti_gpio_pic_map_fdt(struct ti_gpio_softc *sc, u_int ncells, pcell_t *cells, * 4 = active high level-sensitive. * 8 = active low level-sensitive. */ - if (ncells != 2 || cells[0] >= sc->sc_maxpin) + if (daf->ncells != 2 || daf->cells[0] >= sc->sc_maxpin) return (EINVAL); /* Only reasonable modes are supported. */ - if (cells[1] == 1) + if (daf->cells[1] == 1) mode = GPIO_INTR_EDGE_RISING; - else if (cells[1] == 2) + else if (daf->cells[1] == 2) mode = GPIO_INTR_EDGE_FALLING; - else if (cells[1] == 3) + else if (daf->cells[1] == 3) mode = GPIO_INTR_EDGE_BOTH; - else if (cells[1] == 4) + else if (daf->cells[1] == 4) mode = GPIO_INTR_LEVEL_HIGH; - else if (cells[1] == 8) + else if (daf->cells[1] == 8) mode = GPIO_INTR_LEVEL_LOW; else return (EINVAL); - *irqp = cells[0]; + *irqp = daf->cells[0]; if (modep != NULL) *modep = mode; return (0); } static int +ti_gpio_pic_map_gpio(struct ti_gpio_softc *sc, struct intr_map_data_gpio *dag, + u_int *irqp, uint32_t *modep) +{ + uint32_t mode; + + if (dag->gpio_pin_num >= sc->sc_maxpin) + return (EINVAL); + + mode = dag->gpio_intr_mode; + if (mode != GPIO_INTR_LEVEL_LOW && mode != GPIO_INTR_LEVEL_HIGH && + mode != GPIO_INTR_EDGE_RISING && mode != GPIO_INTR_EDGE_FALLING && + mode != GPIO_INTR_EDGE_BOTH) + return (EINVAL); + + *irqp = dag->gpio_pin_num; + if (modep != NULL) + *modep = mode; + return (0); +} + +static int +ti_gpio_pic_map(struct ti_gpio_softc *sc, struct intr_map_data *data, + u_int *irqp, uint32_t *modep) +{ + + switch (data->type) { + case INTR_MAP_DATA_FDT: + return (ti_gpio_pic_map_fdt(sc, + (struct intr_map_data_fdt *)data, irqp, modep)); + case INTR_MAP_DATA_GPIO: + return (ti_gpio_pic_map_gpio(sc, + (struct intr_map_data_gpio *)data, irqp, modep)); + default: + return (ENOTSUP); + } +} + +static int ti_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) { int error; u_int irq; - struct ti_gpio_softc *sc; - struct intr_map_data_fdt *daf; - - if (data->type != INTR_MAP_DATA_FDT) - return (ENOTSUP); - - sc = device_get_softc(dev); - daf = (struct intr_map_data_fdt *)data; + struct ti_gpio_softc *sc = device_get_softc(dev); - error = ti_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, NULL); + error = ti_gpio_pic_map(sc, data, &irq, NULL); if (error == 0) *isrcp = &sc->sc_isrcs[irq].tgi_isrc; return (error); @@ -1040,18 +1071,15 @@ ti_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, uint32_t mode; struct ti_gpio_softc *sc; struct ti_gpio_irqsrc *tgi; - struct intr_map_data_fdt *daf; - if (data == NULL || data->type != INTR_MAP_DATA_FDT) + if (data == NULL) return (ENOTSUP); sc = device_get_softc(dev); tgi = (struct ti_gpio_irqsrc *)isrc; - daf = (struct intr_map_data_fdt *)data; /* Get and check config for an interrupt. */ - if (ti_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, - &mode) != 0 || tgi->tgi_irq != irq) + if (ti_gpio_pic_map(sc, data, &irq, &mode) != 0 || tgi->tgi_irq != irq) return (EINVAL); /* -- cgit v1.1 From a5193740b95ef87e9ab4864032a28f58cb60085a Mon Sep 17 00:00:00 2001 From: avos Date: Fri, 6 May 2016 11:41:49 +0000 Subject: net80211: restore 'iflladdr_event' event handler. Now 'ether' argument to ifconfig can be used as an alias to 'wlanaddr'. PR: 208933 --- sys/net80211/ieee80211_freebsd.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'sys') diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 690e123..373b053 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -851,6 +851,7 @@ ieee80211_load_module(const char *modname) } static eventhandler_tag wlan_bpfevent; +static eventhandler_tag wlan_ifllevent; static void bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) @@ -879,6 +880,21 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) } /* + * Change MAC address on the vap (if was not started). + */ +static void +wlan_iflladdr(void *arg __unused, struct ifnet *ifp) +{ + /* NB: identify vap's by if_init */ + if (ifp->if_init == ieee80211_init && + (ifp->if_flags & IFF_UP) == 0) { + struct ieee80211vap *vap = ifp->if_softc; + + IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp)); + } +} + +/* * Module glue. * * NB: the module name is "wlan" for compatibility with NetBSD. @@ -892,12 +908,15 @@ wlan_modevent(module_t mod, int type, void *unused) printf("wlan: <802.11 Link Layer>\n"); wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track, bpf_track, 0, EVENTHANDLER_PRI_ANY); + wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event, + wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY); wlan_cloner = if_clone_simple(wlanname, wlan_clone_create, wlan_clone_destroy, 0); return 0; case MOD_UNLOAD: if_clone_detach(wlan_cloner); EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent); + EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent); return 0; } return EINVAL; -- cgit v1.1 From c27a61b5e81ce1aed081b053384ec74e9f9b5c3c Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 15:09:21 +0000 Subject: dev/usb: unsigned some loop indexes. Although usually small, values produced by nitems() are unsigned. By unsigning the corresponding indexes we avoid signed vs unsigned comparisons. This may have some effect on performance, although given the small sizes the effect will not be perceivable, and it makes the code clearer. Respect the style of the changed files: one uses u_int while the other uses "unsigned int". Reviewed by: hselasky --- sys/dev/usb/wlan/if_run.c | 8 ++++---- sys/dev/usb/wlan/if_urtw.c | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'sys') diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 1a96776..c7d7712 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -5222,7 +5222,7 @@ run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain) static void run_rt5390_bbp_init(struct run_softc *sc) { - int i; + u_int i; uint8_t bbp; /* Apply maximum likelihood detection for 2 stream case. */ @@ -5332,7 +5332,7 @@ run_rt3070_rf_init(struct run_softc *sc) { uint32_t tmp; uint8_t bbp4, mingain, rf, target; - int i; + u_int i; run_rt3070_rf_read(sc, 30, &rf); /* toggle RF R30 bit 7 */ @@ -5476,7 +5476,7 @@ run_rt3593_rf_init(struct run_softc *sc) { uint32_t tmp; uint8_t rf; - int i; + u_int i; /* Disable the GPIO bits 4 and 7 for LNA PE control. */ run_read(sc, RT3070_GPIO_SWITCH, &tmp); @@ -5525,7 +5525,7 @@ run_rt5390_rf_init(struct run_softc *sc) { uint32_t tmp; uint8_t rf; - int i; + u_int i; /* Toggle RF R2 to initiate calibration. */ if (sc->mac_ver == 0x5390) { diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 8895705..4c6bc76 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -1910,7 +1910,7 @@ fail: static uint16_t urtw_rate2rtl(uint32_t rate) { - int i; + unsigned int i; for (i = 0; i < nitems(urtw_ratetable); i++) { if (rate == urtw_ratetable[i].reg) @@ -1923,7 +1923,7 @@ urtw_rate2rtl(uint32_t rate) static uint16_t urtw_rtl2rate(uint32_t rate) { - int i; + unsigned int i; for (i = 0; i < nitems(urtw_ratetable); i++) { if (rate == urtw_ratetable[i].val) @@ -2450,7 +2450,7 @@ fail: static usb_error_t urtw_8225_rf_init(struct urtw_softc *sc) { - int i; + unsigned int i; uint16_t data; usb_error_t error; @@ -2831,7 +2831,7 @@ fail: static usb_error_t urtw_8225v2_rf_init(struct urtw_softc *sc) { - int i; + unsigned int i; uint16_t data; uint32_t data32; usb_error_t error; @@ -3164,7 +3164,7 @@ static usb_error_t urtw_8225v2b_rf_init(struct urtw_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; - int i; + unsigned int i; uint8_t data8; usb_error_t error; -- cgit v1.1 From 8f67ce00492024115c24366ed01bc6c7c28eb567 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 15:13:44 +0000 Subject: sys/cam/scsi: unsigned some loop indexes. Although usually small, values produced by nitems() are unsigned. By unsigning the corresponding indexes we avoid signed vs unsigned comparisons. This may have some effect on performance, although given the small sizes the effect will not be perceivable and it makes the code clearer. --- sys/cam/scsi/scsi_all.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'sys') diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index 35aecb9..3b23ae0 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -957,7 +957,7 @@ static struct scsi_sense_quirk_entry sense_quirk_table[] = { } }; -const int sense_quirk_table_size = nitems(sense_quirk_table); +const u_int sense_quirk_table_size = nitems(sense_quirk_table); static struct asc_table_entry asc_table[] = { /* @@ -3193,7 +3193,7 @@ static struct asc_table_entry asc_table[] = { "Security conflict in translated device") } }; -const int asc_table_size = nitems(asc_table); +const u_int asc_table_size = nitems(asc_table); struct asc_key { @@ -4700,7 +4700,7 @@ scsi_sense_desc_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, struct scsi_inquiry_data *inq_data, struct scsi_sense_desc_header *header) { - int i; + u_int i; for (i = 0; i < nitems(scsi_sense_printers); i++) { struct scsi_sense_desc_printer *printer; @@ -5475,8 +5475,8 @@ static struct { u_int scsi_calc_syncsrate(u_int period_factor) { - int i; - int num_syncrates; + u_int i; + u_int num_syncrates; /* * It's a bug if period is zero, but if it is anyway, don't @@ -5511,8 +5511,8 @@ scsi_calc_syncsrate(u_int period_factor) u_int scsi_calc_syncparam(u_int period) { - int i; - int num_syncrates; + u_int i; + u_int num_syncrates; if (period == 0) return (~0); /* Async */ @@ -6545,7 +6545,8 @@ scsi_parse_transportid(char *transportid_str, { char *tmpstr; scsi_nv_status status; - int retval, num_proto_entries, table_entry; + u_int num_proto_entries; + int retval, table_entry; retval = 0; table_entry = 0; -- cgit v1.1 From 4d8fd4b25e204a8c24b88db2ec6cab8417175e85 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 15:16:13 +0000 Subject: ofed/drivers: minor spelling fixes. No functional change. Reviewed by: hselasky --- sys/ofed/drivers/infiniband/hw/mlx4/main.c | 2 +- sys/ofed/drivers/infiniband/hw/mlx4/mcg.c | 2 +- sys/ofed/drivers/infiniband/hw/mlx4/mr.c | 4 ++-- sys/ofed/drivers/infiniband/ulp/sdp/sdp.h | 6 +++--- sys/ofed/drivers/infiniband/ulp/sdp/sdp_tx.c | 2 +- sys/ofed/drivers/net/mlx4/en_rx.c | 2 +- sys/ofed/drivers/net/mlx4/fw.c | 2 +- sys/ofed/drivers/net/mlx4/main.c | 4 ++-- sys/ofed/drivers/net/mlx4/mlx4.h | 2 +- sys/ofed/drivers/net/mlx4/resource_tracker.c | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) (limited to 'sys') diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/main.c b/sys/ofed/drivers/infiniband/hw/mlx4/main.c index 41705ad..cff90cc 100644 --- a/sys/ofed/drivers/infiniband/hw/mlx4/main.c +++ b/sys/ofed/drivers/infiniband/hw/mlx4/main.c @@ -799,7 +799,7 @@ static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) unsigned long command = vma->vm_pgoff & MLX4_IB_MMAP_CMD_MASK; if (command < MLX4_IB_MMAP_GET_CONTIGUOUS_PAGES) { - /* compatability handling for commands 0 & 1*/ + /* compatibility handling for commands 0 & 1*/ if (vma->vm_end - vma->vm_start != PAGE_SIZE) return -EINVAL; } diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/mcg.c b/sys/ofed/drivers/infiniband/hw/mlx4/mcg.c index f2a8411..85199e7 100644 --- a/sys/ofed/drivers/infiniband/hw/mlx4/mcg.c +++ b/sys/ofed/drivers/infiniband/hw/mlx4/mcg.c @@ -689,7 +689,7 @@ static void mlx4_ib_mcg_work_handler(struct work_struct *work) cur_join_state = group->rec.scope_join_state & 7; if (method == IB_MGMT_METHOD_GET_RESP) { - /* successfull join */ + /* successful join */ if (!cur_join_state && resp_join_state) --rc; } else if (!resp_join_state) diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/mr.c b/sys/ofed/drivers/infiniband/hw/mlx4/mr.c index a13bee7..f531a03 100644 --- a/sys/ofed/drivers/infiniband/hw/mlx4/mr.c +++ b/sys/ofed/drivers/infiniband/hw/mlx4/mr.c @@ -341,8 +341,8 @@ int mlx4_ib_umem_calc_optimal_mtt_size(struct ib_umem *umem, address for the start of the MR. */ /* umem_get aligned the start_va to a page - boundry. Therefore, we need to align the - start va to the same boundry */ + boundary. Therefore, we need to align the + start va to the same boundary */ /* misalignment_bits is needed to handle the case of a single memory region. In this case, the rest of the logic will not reduce diff --git a/sys/ofed/drivers/infiniband/ulp/sdp/sdp.h b/sys/ofed/drivers/infiniband/ulp/sdp/sdp.h index 5c573d2..bd07d49 100644 --- a/sys/ofed/drivers/infiniband/ulp/sdp/sdp.h +++ b/sys/ofed/drivers/infiniband/ulp/sdp/sdp.h @@ -66,7 +66,7 @@ struct name { \ struct type *lh_first; /* first element */ \ } -/* Interval between sucessive polls in the Tx routine when polling is used +/* Interval between successive polls in the Tx routine when polling is used instead of interrupts (in per-core Tx rings) - should be power of 2 */ #define SDP_TX_POLL_MODER 16 #define SDP_TX_POLL_TIMEOUT (HZ / 20) @@ -424,8 +424,8 @@ struct sdp_sock { /* SDP slow start */ int recv_request_head; /* mark the rx_head when the resize request - was recieved */ - int recv_request; /* XXX flag if request to resize was recieved */ + was received */ + int recv_request; /* XXX flag if request to resize was received */ unsigned long tx_packets; unsigned long rx_packets; diff --git a/sys/ofed/drivers/infiniband/ulp/sdp/sdp_tx.c b/sys/ofed/drivers/infiniband/ulp/sdp/sdp_tx.c index 6f54331..8f2a2f0 100644 --- a/sys/ofed/drivers/infiniband/ulp/sdp/sdp_tx.c +++ b/sys/ofed/drivers/infiniband/ulp/sdp/sdp_tx.c @@ -328,7 +328,7 @@ sdp_poll_tx(struct sdp_sock *ssk) SDPSTATS_COUNTER_INC(tx_poll_hit); inflight = (u32) tx_ring_posted(ssk); - sdp_prf1(ssk->socket, NULL, "finished tx proccessing. inflight = %d", + sdp_prf1(ssk->socket, NULL, "finished tx processing. inflight = %d", inflight); /* If there are still packets in flight and the timer has not already diff --git a/sys/ofed/drivers/net/mlx4/en_rx.c b/sys/ofed/drivers/net/mlx4/en_rx.c index 235a9ab..f4425af 100644 --- a/sys/ofed/drivers/net/mlx4/en_rx.c +++ b/sys/ofed/drivers/net/mlx4/en_rx.c @@ -552,7 +552,7 @@ mlx4_en_rx_mb(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring, /* For cpu arch with cache line of 64B the performance is better when cqe size==64B * To enlarge cqe size from 32B to 64B --> 32B of garbage (i.e. 0xccccccc) * was added in the beginning of each cqe (the real data is in the corresponding 32B). - * The following calc ensures that when factor==1, it means we are alligned to 64B + * The following calc ensures that when factor==1, it means we are aligned to 64B * and we get the real cqe data*/ #define CQE_FACTOR_INDEX(index, factor) ((index << factor) + factor) int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget) diff --git a/sys/ofed/drivers/net/mlx4/fw.c b/sys/ofed/drivers/net/mlx4/fw.c index 93f7f71..a16ede6 100644 --- a/sys/ofed/drivers/net/mlx4/fw.c +++ b/sys/ofed/drivers/net/mlx4/fw.c @@ -1901,7 +1901,7 @@ void mlx4_opreq_action(struct work_struct *work) MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); if (err) { - mlx4_err(dev, "Failed to retreive required operation: %d\n", err); + mlx4_err(dev, "Failed to retrieve required operation: %d\n", err); return; } MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET); diff --git a/sys/ofed/drivers/net/mlx4/main.c b/sys/ofed/drivers/net/mlx4/main.c index 462e7c8..314a4ba 100644 --- a/sys/ofed/drivers/net/mlx4/main.c +++ b/sys/ofed/drivers/net/mlx4/main.c @@ -159,7 +159,7 @@ MODULE_PARM_DESC(high_rate_steer, "Enable steering mode for higher packet rate" static int fast_drop; module_param_named(fast_drop, fast_drop, int, 0444); MODULE_PARM_DESC(fast_drop, - "Enable fast packet drop when no recieve WQEs are posted"); + "Enable fast packet drop when no receive WQEs are posted"); int mlx4_enable_64b_cqe_eqe = 1; module_param_named(enable_64b_cqe_eqe, mlx4_enable_64b_cqe_eqe, int, 0644); @@ -2452,7 +2452,7 @@ EXPORT_SYMBOL_GPL(mlx4_counter_alloc); void __mlx4_counter_free(struct mlx4_dev *dev, int slave, int port, u32 idx) { - /* check if native or slave and deletes acordingly */ + /* check if native or slave and deletes accordingly */ struct mlx4_priv *priv = mlx4_priv(dev); struct counter_index *pf, *tmp_pf; struct counter_index *vf, *tmp_vf; diff --git a/sys/ofed/drivers/net/mlx4/mlx4.h b/sys/ofed/drivers/net/mlx4/mlx4.h index bef2e00..e23e461 100644 --- a/sys/ofed/drivers/net/mlx4/mlx4.h +++ b/sys/ofed/drivers/net/mlx4/mlx4.h @@ -164,7 +164,7 @@ enum mlx4_res_tracker_free_type { /* *Virtual HCR structures. - * mlx4_vhcr is the sw representation, in machine endianess + * mlx4_vhcr is the sw representation, in machine endianness * * mlx4_vhcr_cmd is the formalized structure, the one that is passed * to FW to go through communication channel. diff --git a/sys/ofed/drivers/net/mlx4/resource_tracker.c b/sys/ofed/drivers/net/mlx4/resource_tracker.c index 743c887..1bdab67 100644 --- a/sys/ofed/drivers/net/mlx4/resource_tracker.c +++ b/sys/ofed/drivers/net/mlx4/resource_tracker.c @@ -2916,7 +2916,7 @@ int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, /* Call the SW implementation of write_mtt: * - Prepare a dummy mtt struct - * - Translate inbox contents to simple addresses in host endianess */ + * - Translate inbox contents to simple addresses in host endianness */ mtt.offset = 0; /* TBD this is broken but I don't handle it since we don't really use it */ mtt.order = 0; -- cgit v1.1 From e8f92bd9a78b427e7fc915694568b6b3eab60328 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 15:36:25 +0000 Subject: sys/cam/scsi: unsigned some loop indexes. Although usually small, values produced by nitems() are unsigned. One more case where unsgining the index may be useful. --- sys/cam/scsi/scsi_cd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index f505d2d..42dd491 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -1264,7 +1264,7 @@ cdgetpage(struct cd_mode_params *mode_params) static int cdgetpagesize(int page_num) { - int i; + u_int i; for (i = 0; i < nitems(cd_page_size_table); i++) { if (cd_page_size_table[i].page == page_num) -- cgit v1.1 From 6d50fbd9f2d19d1313fa2e30b41982783d3b4894 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 15:37:06 +0000 Subject: sys/ofed: minor spelling fix. No functional change. Reviewed by: hselasky --- sys/ofed/include/linux/mlx4/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/ofed/include/linux/mlx4/device.h b/sys/ofed/include/linux/mlx4/device.h index aca4aef..7f545b1 100644 --- a/sys/ofed/include/linux/mlx4/device.h +++ b/sys/ofed/include/linux/mlx4/device.h @@ -106,7 +106,7 @@ enum { MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1) }; -/* Driver supports 3 diffrent device methods to manage traffic steering: +/* Driver supports 3 different device methods to manage traffic steering: * -device managed - High level API for ib and eth flow steering. FW is * managing flow steering tables. * - B0 steering mode - Common low level API for ib and (if supported) eth. -- cgit v1.1 From 21d823059f5fb0f7e7c4638a13112f9e40f8df2b Mon Sep 17 00:00:00 2001 From: sbruno Date: Fri, 6 May 2016 15:41:38 +0000 Subject: If ALTQ is defined in the kern conf, switch to Legacy Mode. PR: 208409 Submitted by: freebsd@mcwest.org MFC after: 2 weeks --- sys/dev/e1000/if_igb.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sys') diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h index a0c35be..a30fc99 100644 --- a/sys/dev/e1000/if_igb.h +++ b/sys/dev/e1000/if_igb.h @@ -35,6 +35,10 @@ #ifndef _IF_IGB_H_ #define _IF_IGB_H_ +#ifdef ALTQ +#define IGB_LEGACY_TX +#endif + #include #include #ifndef IGB_LEGACY_TX -- cgit v1.1 From 4bf5db0a14f80296b60c436d2e67bbba00f74d01 Mon Sep 17 00:00:00 2001 From: royger Date: Fri, 6 May 2016 16:41:23 +0000 Subject: bitset: introduce helpers to allocate a bitset at runtime Introduce some new helpers to declare and allocate a dynamic bitset, whose size is not a constant. Sponsored by: Citrix Systems R&D Reviewed by: kib jhb Differential revision: https://reviews.freebsd.org/D6226 --- sys/sys/_bitset.h | 8 ++++++++ sys/sys/bitset.h | 6 ++++++ 2 files changed, 14 insertions(+) (limited to 'sys') diff --git a/sys/sys/_bitset.h b/sys/sys/_bitset.h index 86cf539..2f5301d 100644 --- a/sys/sys/_bitset.h +++ b/sys/sys/_bitset.h @@ -47,4 +47,12 @@ struct t { \ long __bits[__bitset_words((_s))]; \ } +/* + * Helper to declare a bitset without it's size being a constant. + * + * Sadly we cannot declare a bitset struct with '__bits[]', because it's + * the only member of the struct and the compiler complains. + */ +#define BITSET_DEFINE_VAR(t) BITSET_DEFINE(t, 1) + #endif /* !_SYS__BITSET_H_ */ diff --git a/sys/sys/bitset.h b/sys/sys/bitset.h index f1c7bf8..723c39b 100644 --- a/sys/sys/bitset.h +++ b/sys/sys/bitset.h @@ -199,4 +199,10 @@ #define BITSET_FSET(n) \ [ 0 ... ((n) - 1) ] = (-1L) +/* + * Dynamically allocate a bitset. + */ +#define BITSET_ALLOC(_s, mt, mf) \ + malloc(__bitset_words(_s) * sizeof(long), mt, (mf)) + #endif /* !_SYS_BITSET_H_ */ -- cgit v1.1 From 8e9c8dae365208b4911902eff1563f9d3090cf96 Mon Sep 17 00:00:00 2001 From: royger Date: Fri, 6 May 2016 16:44:46 +0000 Subject: xen/privcmd: fix integer truncation in IOCTL_PRIVCMD_MMAPBATCH The size field in the XENMEM_add_to_physmap_range is an uint16_t, and the privcmd driver was doing an implicit truncation of an int into an uint16_t when filling the hypercall parameters. Fix this by adding a loop and making sure privcmd splits ioctl request into 2^16 chunks when issuing the hypercalls. Reported and tested by: Marcin Cieslak Sponsored by: Citrix Systems R&D --- sys/dev/xen/privcmd/privcmd.c | 96 ++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 38 deletions(-) (limited to 'sys') diff --git a/sys/dev/xen/privcmd/privcmd.c b/sys/dev/xen/privcmd/privcmd.c index 0bf9585..37a3dbf 100644 --- a/sys/dev/xen/privcmd/privcmd.c +++ b/sys/dev/xen/privcmd/privcmd.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -72,7 +73,7 @@ struct privcmd_map { int pseudo_phys_res_id; vm_paddr_t phys_base_addr; boolean_t mapped; - int *errs; + BITSET_DEFINE_VAR() *err; }; static d_ioctl_t privcmd_ioctl; @@ -138,7 +139,7 @@ retry: rm.gpfn = atop(map->phys_base_addr) + i; HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &rm); } - free(map->errs, M_PRIVCMD); + free(map->err, M_PRIVCMD); } error = xenmem_free(privcmd_dev, map->pseudo_phys_res_id, @@ -160,7 +161,7 @@ privcmd_pg_fault(vm_object_t object, vm_ooffset_t offset, return (VM_PAGER_FAIL); pidx = OFF_TO_IDX(offset); - if (pidx >= map->size || map->errs[pidx] != 0) + if (pidx >= map->size || BIT_ISSET(map->size, pidx, map->err)) return (VM_PAGER_FAIL); page = PHYS_TO_VM_PAGE(map->phys_base_addr + offset); @@ -249,14 +250,15 @@ privcmd_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, vm_map_t map; vm_map_entry_t entry; vm_object_t mem; - vm_pindex_t index; + vm_pindex_t pindex; vm_prot_t prot; boolean_t wired; struct xen_add_to_physmap_range add; xen_ulong_t *idxs; xen_pfn_t *gpfns; - int *errs; + int *errs, index; struct privcmd_map *umap; + uint16_t num; mmap = (struct ioctl_privcmd_mmapbatch *)arg; @@ -268,7 +270,7 @@ privcmd_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, map = &td->td_proc->p_vmspace->vm_map; error = vm_map_lookup(&map, mmap->addr, VM_PROT_NONE, &entry, - &mem, &index, &prot, &wired); + &mem, &pindex, &prot, &wired); if (error != KERN_SUCCESS) { error = EINVAL; break; @@ -289,54 +291,72 @@ privcmd_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, add.domid = DOMID_SELF; add.space = XENMAPSPACE_gmfn_foreign; - add.size = mmap->num; add.foreign_domid = mmap->dom; - idxs = malloc(sizeof(*idxs) * mmap->num, M_PRIVCMD, - M_WAITOK | M_ZERO); - gpfns = malloc(sizeof(*gpfns) * mmap->num, M_PRIVCMD, - M_WAITOK | M_ZERO); - errs = malloc(sizeof(*errs) * mmap->num, M_PRIVCMD, - M_WAITOK | M_ZERO); + /* + * The 'size' field in the xen_add_to_physmap_range only + * allows for UINT16_MAX mappings in a single hypercall. + */ + num = MIN(mmap->num, UINT16_MAX); + + idxs = malloc(sizeof(*idxs) * num, M_PRIVCMD, M_WAITOK); + gpfns = malloc(sizeof(*gpfns) * num, M_PRIVCMD, M_WAITOK); + errs = malloc(sizeof(*errs) * num, M_PRIVCMD, M_WAITOK); set_xen_guest_handle(add.idxs, idxs); set_xen_guest_handle(add.gpfns, gpfns); set_xen_guest_handle(add.errs, errs); - error = copyin(&mmap->arr[0], idxs, - sizeof(idxs[0]) * mmap->num); - if (error != 0) - goto mmap_out; - - for (i = 0; i < mmap->num; i++) - gpfns[i] = atop(umap->phys_base_addr + i * PAGE_SIZE); - - error = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &add); - if (error) { - error = xen_translate_error(error); - goto mmap_out; - } + /* Allocate a bitset to store broken page mappings. */ + umap->err = BITSET_ALLOC(mmap->num, M_PRIVCMD, + M_WAITOK | M_ZERO); - for (i = 0; i < mmap->num; i++) { - if (errs[i] != 0) - errs[i] = xen_translate_error(errs[i]); + for (index = 0; index < mmap->num; index += num) { + num = MIN(mmap->num - index, UINT16_MAX); + add.size = num; + + error = copyin(&mmap->arr[index], idxs, + sizeof(idxs[0]) * num); + if (error != 0) + goto mmap_out; + + for (i = 0; i < num; i++) + gpfns[i] = atop(umap->phys_base_addr + + (i + index) * PAGE_SIZE); + + bzero(errs, sizeof(*errs) * num); + + error = HYPERVISOR_memory_op( + XENMEM_add_to_physmap_range, &add); + if (error != 0) { + error = xen_translate_error(error); + goto mmap_out; + } + + for (i = 0; i < num; i++) { + if (errs[i] != 0) { + errs[i] = xen_translate_error(errs[i]); + + /* Mark the page as invalid. */ + BIT_SET(mmap->num, index + i, + umap->err); + } + } + + error = copyout(errs, &mmap->err[index], + sizeof(errs[0]) * num); + if (error != 0) + goto mmap_out; } - /* - * Save errs, so we know which pages have been - * successfully mapped. - */ - umap->errs = errs; umap->mapped = true; - error = copyout(errs, &mmap->err[0], - sizeof(errs[0]) * mmap->num); - mmap_out: free(idxs, M_PRIVCMD); free(gpfns, M_PRIVCMD); + free(errs, M_PRIVCMD); if (!umap->mapped) - free(errs, M_PRIVCMD); + free(umap->err, M_PRIVCMD); break; } -- cgit v1.1 From d8bfd0e5b10678e8d887e9bbb5e2473513fc16ad Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 16:51:56 +0000 Subject: cam/scsi: Remove mostly unused scsi_quirk_table_size. It was only being used only once and it can be directly replaced instead. --- sys/cam/scsi/scsi_xpt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 94441a9..30a9104 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -556,8 +556,6 @@ static struct scsi_quirk_entry scsi_quirk_table[] = }, }; -static const int scsi_quirk_table_size = nitems(scsi_quirk_table); - static cam_status proberegister(struct cam_periph *periph, void *arg); static void probeschedule(struct cam_periph *probe_periph); @@ -2365,7 +2363,7 @@ scsi_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) * Take the default quirk entry until we have inquiry * data and can determine a better quirk to use. */ - quirk = &scsi_quirk_table[scsi_quirk_table_size - 1]; + quirk = &scsi_quirk_table[nitems(scsi_quirk_table) - 1]; device->quirk = (void *)quirk; device->mintags = quirk->mintags; device->maxtags = quirk->maxtags; -- cgit v1.1 From 9d9aae4d8478988a66d4f765a2c2b32a43bf627f Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 16:59:04 +0000 Subject: sys/security: minor spelling fixes. No functional change. --- sys/security/mac/mac_cred.c | 2 +- sys/security/mac/mac_framework.c | 2 +- sys/security/mac_biba/mac_biba.h | 2 +- sys/security/mac_lomac/mac_lomac.c | 2 +- sys/security/mac_lomac/mac_lomac.h | 2 +- sys/security/mac_mls/mac_mls.c | 2 +- sys/security/mac_mls/mac_mls.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sys') diff --git a/sys/security/mac/mac_cred.c b/sys/security/mac/mac_cred.c index 372679b..48bd480 100644 --- a/sys/security/mac/mac_cred.c +++ b/sys/security/mac/mac_cred.c @@ -174,7 +174,7 @@ mac_cred_internalize_label(struct label *label, char *string) /* * When a new process is created, its label must be initialized. Generally, - * this involves inheritence from the parent process, modulo possible deltas. + * this involves inheritance from the parent process, modulo possible deltas. * This function allows that processing to take place. */ void diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index d76b280..f56627c 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -437,7 +437,7 @@ mac_policy_register(struct mac_policy_conf *mpc) * Per-policy initialization. Currently, this takes place under the * exclusive lock, so policies must not sleep in their init method. * In the future, we may want to separate "init" from "start", with - * "init" occuring without the lock held. Likewise, on tear-down, + * "init" occurring without the lock held. Likewise, on tear-down, * breaking out "stop" from "destroy". */ if (mpc->mpc_ops->mpo_init != NULL) diff --git a/sys/security/mac_biba/mac_biba.h b/sys/security/mac_biba/mac_biba.h index 05eefab..a97f29b 100644 --- a/sys/security/mac_biba/mac_biba.h +++ b/sys/security/mac_biba/mac_biba.h @@ -54,7 +54,7 @@ * MAC_BIBA_TYPE_LABEL. */ #define MAC_BIBA_TYPE_HIGH 3 /* Dominates any * MAC_BIBA_TYPE_LABEL. */ -#define MAC_BIBA_TYPE_EQUAL 4 /* Equivilent to any +#define MAC_BIBA_TYPE_EQUAL 4 /* Equivalent to any * MAC_BIBA_TYPE_LABEL. */ /* diff --git a/sys/security/mac_lomac/mac_lomac.c b/sys/security/mac_lomac/mac_lomac.c index 5607940..b7c6289 100644 --- a/sys/security/mac_lomac/mac_lomac.c +++ b/sys/security/mac_lomac/mac_lomac.c @@ -1472,7 +1472,7 @@ lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel) dest = SLOT(mlabel); - /* XXX: where is the label for the firewall really comming from? */ + /* XXX: where is the label for the firewall really coming from? */ lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); } diff --git a/sys/security/mac_lomac/mac_lomac.h b/sys/security/mac_lomac/mac_lomac.h index 9edba98..9e69f95 100644 --- a/sys/security/mac_lomac/mac_lomac.h +++ b/sys/security/mac_lomac/mac_lomac.h @@ -56,7 +56,7 @@ * MAC_LOMAC_TYPE_LABEL. */ #define MAC_LOMAC_TYPE_HIGH 3 /* Dominates any * MAC_LOMAC_TYPE_LABEL. */ -#define MAC_LOMAC_TYPE_EQUAL 4 /* Equivilent to any +#define MAC_LOMAC_TYPE_EQUAL 4 /* Equivalent to any * MAC_LOMAC_TYPE_LABEL. */ /* diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c index 6a074d0..935c159 100644 --- a/sys/security/mac_mls/mac_mls.c +++ b/sys/security/mac_mls/mac_mls.c @@ -1276,7 +1276,7 @@ mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel) dest = SLOT(mlabel); - /* XXX: where is the label for the firewall really comming from? */ + /* XXX: where is the label for the firewall really coming from? */ mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL); } diff --git a/sys/security/mac_mls/mac_mls.h b/sys/security/mac_mls/mac_mls.h index 7bed921..b1ba469 100644 --- a/sys/security/mac_mls/mac_mls.h +++ b/sys/security/mac_mls/mac_mls.h @@ -54,7 +54,7 @@ * MAC_MLS_TYPE_LABEL. */ #define MAC_MLS_TYPE_HIGH 3 /* Dominates any * MAC_MLS_TYPE_LABEL. */ -#define MAC_MLS_TYPE_EQUAL 4 /* Equivilent to any +#define MAC_MLS_TYPE_EQUAL 4 /* Equivalent to any * MAC_MLS_TYPE_LABEL. */ /* -- cgit v1.1 From e0f2b3bfc7142076f9c8dc1b3cc2bb7852053bed Mon Sep 17 00:00:00 2001 From: sbruno Date: Fri, 6 May 2016 17:00:45 +0000 Subject: Since igb_detach() cleans up all the data structures that will be free'd by the functions following its call, we can simply return instead of crashing and burning in the event of igb_detach() failing. PR: 197139 Submitted by: rupavath@juniper.net MFC after: 2 weeks --- sys/dev/e1000/if_igb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 965370d..34f1d89 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -659,7 +659,8 @@ igb_attach(device_t dev) return (0); err_late: - igb_detach(dev); + if (igb_detach(dev) == 0) /* igb_detach() already did the cleanup */ + return(error); igb_free_transmit_structures(adapter); igb_free_receive_structures(adapter); igb_release_hw_control(adapter); -- cgit v1.1 From 05dac67f853adbb295eaff5bb65b005d958317a1 Mon Sep 17 00:00:00 2001 From: avos Date: Fri, 6 May 2016 17:39:12 +0000 Subject: iwn: fix comments for iwn_read_eeprom_channels(). It's used for all channels (20MHz and 40MHz). --- sys/dev/iwn/if_iwn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index 5d7a1d1..9545fe3 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -2212,7 +2212,7 @@ iwn4965_read_eeprom(struct iwn_softc *sc) /* Read regulatory domain (4 ASCII characters). */ iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4); - /* Read the list of authorized channels (20MHz ones only). */ + /* Read the list of authorized channels (20MHz & 40MHz). */ for (i = 0; i < IWN_NBANDS - 1; i++) { addr = iwn4965_regulatory_bands[i]; iwn_read_eeprom_channels(sc, i, addr); @@ -2303,7 +2303,7 @@ iwn5000_read_eeprom(struct iwn_softc *sc) iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN, sc->eeprom_domain, 4); - /* Read the list of authorized channels (20MHz ones only). */ + /* Read the list of authorized channels (20MHz & 40MHz). */ for (i = 0; i < IWN_NBANDS - 1; i++) { addr = base + sc->base_params->regulatory_bands[i]; iwn_read_eeprom_channels(sc, i, addr); -- cgit v1.1 From e14805fa958f0ce97eb840f7c29bd7d1c9bc34df Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 20:28:28 +0000 Subject: Revert r298938: Change x/a to work similar to gdb. This badly breaks x/ia: ddb and gdb syntax are quite different and it is unclear if they can be reconciled. --- sys/ddb/db_examine.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'sys') diff --git a/sys/ddb/db_examine.c b/sys/ddb/db_examine.c index 3eff396..a41fcb5 100644 --- a/sys/ddb/db_examine.c +++ b/sys/ddb/db_examine.c @@ -89,6 +89,15 @@ db_examine(db_addr_t addr, char *fmt, int count) case 'g': size = 8; break; + case 'a': /* address */ + size = sizeof(void *); + /* always forces a new line */ + if (db_print_position() != 0) + db_printf("\n"); + db_prev = addr; + db_printsym(addr, DB_STGY_ANY); + db_printf(":\t"); + break; default: if (db_print_position() == 0) { /* Print the address. */ @@ -99,18 +108,6 @@ db_examine(db_addr_t addr, char *fmt, int count) width = size * 4; switch (c) { - case 'a': /* address */ - size = sizeof(void *); - value = db_get_value(addr, size, TRUE); - addr += size; - db_printsym(value, DB_STGY_ANY); - break; - case 'p': - size = sizeof(void *); - value = db_get_value(addr, size, TRUE); - addr += size; - db_printf("%p", (void *)value); - break; case 'r': /* signed, current radix */ value = db_get_value(addr, size, true); addr += size; @@ -176,7 +173,7 @@ db_examine(db_addr_t addr, char *fmt, int count) default: break; } - if (db_print_position() != 0 || c == 'a' || c == 'p') + if (db_print_position() != 0) db_end_line(1); break; } -- cgit v1.1 From 76759cc2cf85de38f7fa9a52daa6ae5526245262 Mon Sep 17 00:00:00 2001 From: sobomax Date: Fri, 6 May 2016 20:32:39 +0000 Subject: Add missing include "opt_geom.h" to make GEOM_UZIP_DEBUG option working, also rename enum member so it does not conflict with GEOM_UZIP option name. Submitted by: mizhka@gmail.com Differential Revision: https://reviews.freebsd.org/D6207 --- sys/geom/uzip/g_uzip.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'sys') diff --git a/sys/geom/uzip/g_uzip.c b/sys/geom/uzip/g_uzip.c index bbb31e4..bdbf723 100644 --- a/sys/geom/uzip/g_uzip.c +++ b/sys/geom/uzip/g_uzip.c @@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include "opt_geom.h" + MALLOC_DEFINE(M_GEOM_UZIP, "geom_uzip", "GEOM UZIP data structures"); FEATURE(geom_uzip, "GEOM read-only compressed disks support"); @@ -576,8 +578,8 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) struct g_provider *pp2; struct g_uzip_softc *sc; enum { - GEOM_UZIP = 1, - GEOM_ULZMA + G_UZIP = 1, + G_ULZMA } type; g_trace(G_T_TOPOLOGY, "%s(%s,%s)", __func__, mp->name, pp->name); @@ -621,7 +623,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) switch (header->magic[CLOOP_OFS_COMPR]) { case CLOOP_COMP_LZMA: case CLOOP_COMP_LZMA_DDP: - type = GEOM_ULZMA; + type = G_ULZMA; if (header->magic[CLOOP_OFS_VERSN] < CLOOP_MINVER_LZMA) { DPRINTF(GUZ_DBG_ERR, ("%s: image version too old\n", gp->name)); @@ -632,7 +634,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) break; case CLOOP_COMP_LIBZ: case CLOOP_COMP_LIBZ_DDP: - type = GEOM_UZIP; + type = G_UZIP; if (header->magic[CLOOP_OFS_VERSN] < CLOOP_MINVER_ZLIB) { DPRINTF(GUZ_DBG_ERR, ("%s: image version too old\n", gp->name)); @@ -728,7 +730,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags) sc->req_total = 0; sc->req_cached = 0; - if (type == GEOM_UZIP) { + if (type == G_UZIP) { sc->dcp = g_uzip_zlib_ctor(sc->blksz); } else { sc->dcp = g_uzip_lzma_ctor(sc->blksz); -- cgit v1.1 From 7384b6e034e6483a9374d4385e545a095b417b27 Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 6 May 2016 20:55:14 +0000 Subject: INTRNG - use gpio interrupt modes definitions added in r298738 and implement also GPIO_INTR_EDGE_BOTH mode. All reasonable interrupt modes are supported now. --- sys/arm/broadcom/bcm2835/bcm2835_gpio.c | 134 ++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 41 deletions(-) (limited to 'sys') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index 29b5f03..15ec5e8 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -88,7 +88,7 @@ struct bcm_gpio_sysctl { struct bcm_gpio_irqsrc { struct intr_irqsrc bgi_isrc; uint32_t bgi_irq; - uint32_t bgi_reg; + uint32_t bgi_mode; uint32_t bgi_mask; }; #endif @@ -894,6 +894,17 @@ bcm_gpio_detach(device_t dev) #ifdef INTRNG static inline void +bcm_gpio_modify(struct bcm_gpio_softc *sc, uint32_t reg, uint32_t mask, + bool set_bits) +{ + + if (set_bits) + BCM_GPIO_SET_BITS(sc, reg, mask); + else + BCM_GPIO_CLEAR_BITS(sc, reg, mask); +} + +static inline void bcm_gpio_isrc_eoi(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) { uint32_t bank; @@ -906,28 +917,64 @@ bcm_gpio_isrc_eoi(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) static inline bool bcm_gpio_isrc_is_level(struct bcm_gpio_irqsrc *bgi) { - uint32_t bank; - bank = BCM_GPIO_BANK(bgi->bgi_irq); - return (bgi->bgi_reg == BCM_GPIO_GPHEN(bank) || - bgi->bgi_reg == BCM_GPIO_GPLEN(bank)); + return (bgi->bgi_mode == GPIO_INTR_LEVEL_LOW || + bgi->bgi_mode == GPIO_INTR_LEVEL_HIGH); } static inline void bcm_gpio_isrc_mask(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) { + uint32_t bank; + bank = BCM_GPIO_BANK(bgi->bgi_irq); BCM_GPIO_LOCK(sc); - BCM_GPIO_CLEAR_BITS(sc, bgi->bgi_reg, bgi->bgi_mask); - BCM_GPIO_UNLOCK(bcm_gpio_sc); + switch (bgi->bgi_mode) { + case GPIO_INTR_LEVEL_LOW: + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_LEVEL_HIGH: + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_EDGE_RISING: + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_EDGE_FALLING: + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_EDGE_BOTH: + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask); + BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask); + break; + } + BCM_GPIO_UNLOCK(sc); } static inline void bcm_gpio_isrc_unmask(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi) { + uint32_t bank; + bank = BCM_GPIO_BANK(bgi->bgi_irq); BCM_GPIO_LOCK(sc); - BCM_GPIO_SET_BITS(sc, bgi->bgi_reg, bgi->bgi_mask); + switch (bgi->bgi_mode) { + case GPIO_INTR_LEVEL_LOW: + BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_LEVEL_HIGH: + BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_EDGE_RISING: + BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_EDGE_FALLING: + BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask); + break; + case GPIO_INTR_EDGE_BOTH: + BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask); + BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask); + break; + } BCM_GPIO_UNLOCK(sc); } @@ -983,7 +1030,7 @@ bcm_gpio_pic_attach(struct bcm_gpio_softc *sc) for (irq = 0; irq < BCM_GPIO_PINS; irq++) { sc->sc_isrcs[irq].bgi_irq = irq; sc->sc_isrcs[irq].bgi_mask = BCM_GPIO_MASK(irq); - sc->sc_isrcs[irq].bgi_reg = 0; + sc->sc_isrcs[irq].bgi_mode = GPIO_INTR_CONFORM; error = intr_isrc_register(&sc->sc_isrcs[irq].bgi_isrc, sc->sc_dev, 0, "%s,%u", name, irq); @@ -1007,6 +1054,26 @@ bcm_gpio_pic_detach(struct bcm_gpio_softc *sc) } static void +bcm_gpio_pic_config_intr(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi, + uint32_t mode) +{ + uint32_t bank; + + bank = BCM_GPIO_BANK(bgi->bgi_irq); + BCM_GPIO_LOCK(sc); + bcm_gpio_modify(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask, + mode == GPIO_INTR_EDGE_RISING || mode == GPIO_INTR_EDGE_BOTH); + bcm_gpio_modify(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask, + mode == GPIO_INTR_EDGE_FALLING || mode == GPIO_INTR_EDGE_BOTH); + bcm_gpio_modify(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask, + mode == GPIO_INTR_LEVEL_HIGH); + bcm_gpio_modify(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask, + mode == GPIO_INTR_LEVEL_LOW); + bgi->bgi_mode = mode; + BCM_GPIO_UNLOCK(sc); +} + +static void bcm_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc) { struct bcm_gpio_softc *sc = device_get_softc(dev); @@ -1027,10 +1094,10 @@ bcm_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) static int bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, u_int ncells, pcell_t *cells, - u_int *irqp, uint32_t *regp) + u_int *irqp, uint32_t *modep) { u_int irq; - uint32_t reg, bank; + uint32_t mode, bank; /* * The first cell is the interrupt number. @@ -1048,27 +1115,24 @@ bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, u_int ncells, pcell_t *cells, if (irq >= BCM_GPIO_PINS || bcm_gpio_pin_is_ro(sc, irq)) return (EINVAL); - /* - * All interrupt types could be set for an interrupt at one moment. - * At least, the combination of 'low-to-high' and 'high-to-low' edge - * triggered interrupt types can make a sense. However, no combo is - * supported now. - */ + /* Only reasonable modes are supported. */ bank = BCM_GPIO_BANK(irq); if (cells[1] == 1) - reg = BCM_GPIO_GPREN(bank); + mode = GPIO_INTR_EDGE_RISING; else if (cells[1] == 2) - reg = BCM_GPIO_GPFEN(bank); + mode = GPIO_INTR_EDGE_FALLING; + else if (cells[1] == 3) + mode = GPIO_INTR_EDGE_BOTH; else if (cells[1] == 4) - reg = BCM_GPIO_GPHEN(bank); + mode = GPIO_INTR_LEVEL_HIGH; else if (cells[1] == 8) - reg = BCM_GPIO_GPLEN(bank); + mode = GPIO_INTR_LEVEL_LOW; else return (EINVAL); *irqp = irq; - if (regp != NULL) - *regp = reg; + if (modep != NULL) + *modep = mode; return (0); } @@ -1126,7 +1190,7 @@ bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { u_int irq; - uint32_t bank, reg; + uint32_t mode; struct bcm_gpio_softc *sc; struct bcm_gpio_irqsrc *bgi; struct intr_map_data_fdt *daf; @@ -1140,7 +1204,7 @@ bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, /* Get and check config for an interrupt. */ if (bcm_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, - ®) != 0 || bgi->bgi_irq != irq) + &mode) != 0 || bgi->bgi_irq != irq) return (EINVAL); /* @@ -1148,17 +1212,9 @@ bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, * only check that its configuration match. */ if (isrc->isrc_handlers != 0) - return (bgi->bgi_reg == reg ? 0 : EINVAL); + return (bgi->bgi_mode == mode ? 0 : EINVAL); - bank = BCM_GPIO_BANK(irq); - BCM_GPIO_LOCK(sc); - BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask); - BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask); - BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask); - BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask); - bgi->bgi_reg = reg; - BCM_GPIO_SET_BITS(sc, reg, bgi->bgi_mask); - BCM_GPIO_UNLOCK(sc); + bcm_gpio_pic_config_intr(sc, bgi, mode); return (0); } @@ -1169,12 +1225,8 @@ bcm_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc, struct bcm_gpio_softc *sc = device_get_softc(dev); struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc; - if (isrc->isrc_handlers == 0) { - BCM_GPIO_LOCK(sc); - BCM_GPIO_CLEAR_BITS(sc, bgi->bgi_reg, bgi->bgi_mask); - bgi->bgi_reg = 0; - BCM_GPIO_UNLOCK(sc); - } + if (isrc->isrc_handlers == 0) + bcm_gpio_pic_config_intr(sc, bgi, GPIO_INTR_CONFORM); return (0); } -- cgit v1.1 From 17e4d8bd453a78461460de07b72b68016b843cef Mon Sep 17 00:00:00 2001 From: skra Date: Fri, 6 May 2016 20:57:41 +0000 Subject: INTRNG - support new interrupt mapping type INTR_MAP_DATA_GPIO introduced in r298738. --- sys/arm/broadcom/bcm2835/bcm2835_gpio.c | 74 +++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 22 deletions(-) (limited to 'sys') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index 15ec5e8..49a879c 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -1093,7 +1093,7 @@ bcm_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc) } static int -bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, u_int ncells, pcell_t *cells, +bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, struct intr_map_data_fdt *daf, u_int *irqp, uint32_t *modep) { u_int irq; @@ -1108,24 +1108,24 @@ bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, u_int ncells, pcell_t *cells, * 4 = active high level-sensitive. * 8 = active low level-sensitive. */ - if (ncells != 2) + if (daf->ncells != 2) return (EINVAL); - irq = cells[0]; + irq = daf->cells[0]; if (irq >= BCM_GPIO_PINS || bcm_gpio_pin_is_ro(sc, irq)) return (EINVAL); /* Only reasonable modes are supported. */ bank = BCM_GPIO_BANK(irq); - if (cells[1] == 1) + if (daf->cells[1] == 1) mode = GPIO_INTR_EDGE_RISING; - else if (cells[1] == 2) + else if (daf->cells[1] == 2) mode = GPIO_INTR_EDGE_FALLING; - else if (cells[1] == 3) + else if (daf->cells[1] == 3) mode = GPIO_INTR_EDGE_BOTH; - else if (cells[1] == 4) + else if (daf->cells[1] == 4) mode = GPIO_INTR_LEVEL_HIGH; - else if (cells[1] == 8) + else if (daf->cells[1] == 8) mode = GPIO_INTR_LEVEL_LOW; else return (EINVAL); @@ -1137,21 +1137,54 @@ bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, u_int ncells, pcell_t *cells, } static int -bcm_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, - struct intr_irqsrc **isrcp) +bcm_gpio_pic_map_gpio(struct bcm_gpio_softc *sc, struct intr_map_data_gpio *dag, + u_int *irqp, uint32_t *modep) { - int error; u_int irq; - struct intr_map_data_fdt *daf; - struct bcm_gpio_softc *sc; + uint32_t mode; + + irq = dag->gpio_pin_num; + if (irq >= BCM_GPIO_PINS || bcm_gpio_pin_is_ro(sc, irq)) + return (EINVAL); + + mode = dag->gpio_intr_mode; + if (mode != GPIO_INTR_LEVEL_LOW && mode != GPIO_INTR_LEVEL_HIGH && + mode != GPIO_INTR_EDGE_RISING && mode != GPIO_INTR_EDGE_FALLING && + mode != GPIO_INTR_EDGE_BOTH) + return (EINVAL); + + *irqp = irq; + if (modep != NULL) + *modep = mode; + return (0); +} + +static int +bcm_gpio_pic_map(struct bcm_gpio_softc *sc, struct intr_map_data *data, + u_int *irqp, uint32_t *modep) +{ - if (data->type != INTR_MAP_DATA_FDT) + switch (data->type) { + case INTR_MAP_DATA_FDT: + return (bcm_gpio_pic_map_fdt(sc, + (struct intr_map_data_fdt *)data, irqp, modep)); + case INTR_MAP_DATA_GPIO: + return (bcm_gpio_pic_map_gpio(sc, + (struct intr_map_data_gpio *)data, irqp, modep)); + default: return (ENOTSUP); + } +} - sc = device_get_softc(dev); - daf = (struct intr_map_data_fdt *)data; +static int +bcm_gpio_pic_map_intr(device_t dev, struct intr_map_data *data, + struct intr_irqsrc **isrcp) +{ + int error; + u_int irq; + struct bcm_gpio_softc *sc = device_get_softc(dev); - error = bcm_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, NULL); + error = bcm_gpio_pic_map(sc, data, &irq, NULL); if (error == 0) *isrcp = &sc->sc_isrcs[irq].bgi_isrc; return (error); @@ -1193,18 +1226,15 @@ bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc, uint32_t mode; struct bcm_gpio_softc *sc; struct bcm_gpio_irqsrc *bgi; - struct intr_map_data_fdt *daf; - if (data == NULL || data->type != INTR_MAP_DATA_FDT) + if (data == NULL) return (ENOTSUP); sc = device_get_softc(dev); bgi = (struct bcm_gpio_irqsrc *)isrc; - daf = (struct intr_map_data_fdt *)data; /* Get and check config for an interrupt. */ - if (bcm_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq, - &mode) != 0 || bgi->bgi_irq != irq) + if (bcm_gpio_pic_map(sc, data, &irq, &mode) != 0 || bgi->bgi_irq != irq) return (EINVAL); /* -- cgit v1.1 From f73a7179da3396b35ddef811a1d46d42a62596ee Mon Sep 17 00:00:00 2001 From: emaste Date: Fri, 6 May 2016 21:19:28 +0000 Subject: Add nid_namelen bounds check to nfssvc system call This is only allowed by root and only used by the nfs daemon, which should not provide an incorrect value. However, it's still good practice to validate data provided by userland. PR: 206626 Reported by: CTurt Reviewed by: rmacklem MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D6201 --- sys/fs/nfs/nfs_commonsubs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sys') diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 0d46d95..02b85e7 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -3174,6 +3174,10 @@ nfssvc_idname(struct nfsd_idargs *nidp) static int onethread = 0; static time_t lasttime = 0; + if (nidp->nid_namelen <= 0 || nidp->nid_namelen > MAXHOSTNAMELEN) { + error = EINVAL; + goto out; + } if (nidp->nid_flag & NFSID_INITIALIZE) { cp = malloc(nidp->nid_namelen + 1, M_NFSSTRING, M_WAITOK); error = copyin(CAST_USER_ADDR_T(nidp->nid_name), cp, -- cgit v1.1 From 467363bdd373b3e1264a102307c2478e228f3680 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 22:54:56 +0000 Subject: dev/e1000,ixgbe: minor spelling fixes. No functional change. Differential Revision: https://reviews.freebsd.org/D6177 --- sys/dev/e1000/e1000_82571.c | 2 +- sys/dev/e1000/e1000_mbx.c | 4 ++-- sys/dev/e1000/if_em.c | 8 ++++---- sys/dev/e1000/if_igb.c | 4 ++-- sys/dev/e1000/if_lem.c | 4 ++-- sys/dev/ixgbe/if_ixv.c | 6 +++--- sys/dev/ixgbe/ixgbe_api.c | 2 +- sys/dev/ixgbe/ixgbe_common.c | 2 +- sys/dev/ixgbe/ixgbe_mbx.c | 4 ++-- sys/dev/ixgbe/ixgbe_type.h | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) (limited to 'sys') diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c index a64ef56..5ff17f0 100644 --- a/sys/dev/e1000/e1000_82571.c +++ b/sys/dev/e1000/e1000_82571.c @@ -396,7 +396,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) } /* Ensure that the inter-port SWSM.SMBI lock bit is clear before - * first NVM or PHY acess. This should be done for single-port + * first NVM or PHY access. This should be done for single-port * devices, and for one port only on dual-port devices so that * for those devices we can still use the SMBI lock to synchronize * inter-port accesses to the PHY & NVM. diff --git a/sys/dev/e1000/e1000_mbx.c b/sys/dev/e1000/e1000_mbx.c index 1de19a4..34649bf 100644 --- a/sys/dev/e1000/e1000_mbx.c +++ b/sys/dev/e1000/e1000_mbx.c @@ -67,7 +67,7 @@ static s32 e1000_null_mbx_transact(struct e1000_hw E1000_UNUSEDARG *hw, * @size: Length of buffer * @mbx_id: id of mailbox to read * - * returns SUCCESS if it successfuly read message from buffer + * returns SUCCESS if it successfully read message from buffer **/ s32 e1000_read_mbx(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id) { @@ -493,7 +493,7 @@ out_no_write: * @size: Length of buffer * @mbx_id: id of mailbox to read * - * returns SUCCESS if it successfuly read message from buffer + * returns SUCCESS if it successfully read message from buffer **/ static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size, u16 E1000_UNUSEDARG mbx_id) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index a989cae..14f5463 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -582,7 +582,7 @@ em_attach(device_t dev) } /* ** In the new SPT device flash is not a - ** seperate BAR, rather it is also in BAR0, + ** separate BAR, rather it is also in BAR0, ** so use the same tag and an offset handle for the ** FLASH read/write macros in the shared code. */ @@ -1929,7 +1929,7 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) * so we firstly get a writable mbuf chain then coalesce ethernet/ * IP/TCP header into a single buffer to meet the requirement of * controller. This also simplifies IP/TCP/UDP checksum offloading - * which also has similiar restrictions. + * which also has similar restrictions. */ if (do_tso || m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) { if (do_tso || (m_head->m_next != NULL && @@ -2595,7 +2595,7 @@ em_allocate_legacy(struct adapter *adapter) * * Setup the MSIX Interrupt handlers * This is not really Multiqueue, rather - * its just seperate interrupt vectors + * its just separate interrupt vectors * for TX, RX, and Link. * **********************************************************************/ @@ -3083,7 +3083,7 @@ em_reset(struct adapter *adapter) * received after sending an XOFF. * - Low water mark works best when it is very near the high water mark. * This allows the receiver to restart by sending XON when it has - * drained a bit. Here we use an arbitary value of 1500 which will + * drained a bit. Here we use an arbitrary value of 1500 which will * restart after one full frame is pulled from the buffer. There * could be several smaller frames in the buffer and if so they will * not trigger the XON until their total number reduces the buffer diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 34f1d89..120111d 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -304,7 +304,7 @@ SYSCTL_INT(_hw_igb, OID_AUTO, buf_ring_size, CTLFLAG_RDTUN, /* ** Header split causes the packet header to -** be dma'd to a seperate mbuf from the payload. +** be dma'd to a separate mbuf from the payload. ** this can have memory alignment benefits. But ** another plus is that small packets often fit ** into the header and thus use no cluster. Its @@ -4483,7 +4483,7 @@ skip_head: ** Now set up the LRO interface, we ** also only do head split when LRO ** is enabled, since so often they - ** are undesireable in similar setups. + ** are undesirable in similar setups. */ if (ifp->if_capenable & IFCAP_LRO) { error = tcp_lro_init(lro); diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c index 864ed6b..50b2cb0 100644 --- a/sys/dev/e1000/if_lem.c +++ b/sys/dev/e1000/if_lem.c @@ -2412,7 +2412,7 @@ lem_hardware_init(struct adapter *adapter) * received after sending an XOFF. * - Low water mark works best when it is very near the high water mark. * This allows the receiver to restart by sending XON when it has - * drained a bit. Here we use an arbitary value of 1500 which will + * drained a bit. Here we use an arbitrary value of 1500 which will * restart after one full frame is pulled from the buffer. There * could be several smaller frames in the buffer and if so they will * not trigger the XON until their total number reduces the buffer @@ -3838,7 +3838,7 @@ discard: * copy ethernet header to the new mbuf. The new mbuf is prepended into the * existing mbuf chain. * - * Be aware, best performance of the 8254x is achived only when jumbo frame is + * Be aware, best performance of the 8254x is achieved only when jumbo frame is * not used at all on architectures with strict alignment. */ static int diff --git a/sys/dev/ixgbe/if_ixv.c b/sys/dev/ixgbe/if_ixv.c index 7b6e3d1..13c2bef 100644 --- a/sys/dev/ixgbe/if_ixv.c +++ b/sys/dev/ixgbe/if_ixv.c @@ -195,7 +195,7 @@ TUNABLE_INT("hw.ixv.flow_control", &ixv_flow_control); /* * Header split: this causes the hardware to DMA - * the header into a seperate mbuf from the payload, + * the header into a separate mbuf from the payload, * it can be a performance win in some workloads, but * in others it actually hurts, its off by default. */ @@ -1141,7 +1141,7 @@ ixv_local_timer(void *arg) } - /* Only truely watchdog if all queues show hung */ + /* Only truly watchdog if all queues show hung */ if (hung == adapter->num_queues) goto watchdog; else if (queues != 0) { /* Force an IRQ on queues with work */ @@ -1958,7 +1958,7 @@ ixv_handle_mbx(void *context, int pending) } /* -** The VF stats registers never have a truely virgin +** The VF stats registers never have a truly virgin ** starting point, so this routine tries to make an ** artificial one, marking ground zero on attach as ** it were. diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c index 0f4d973..894d0b2 100644 --- a/sys/dev/ixgbe/ixgbe_api.c +++ b/sys/dev/ixgbe/ixgbe_api.c @@ -879,7 +879,7 @@ s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw) * @vmdq: VMDq pool to assign * * Puts an ethernet address into a receive address register, or - * finds the rar that it is aleady in; adds to the pool list + * finds the rar that it is already in; adds to the pool list **/ s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index c302071..cad2a85 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -3610,7 +3610,7 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) * @vmdq: VMDq pool to assign * * Puts an ethernet address into a receive address register, or - * finds the rar that it is aleady in; adds to the pool list + * finds the rar that it is already in; adds to the pool list **/ s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) { diff --git a/sys/dev/ixgbe/ixgbe_mbx.c b/sys/dev/ixgbe/ixgbe_mbx.c index d8ba55a..3e9b78a 100644 --- a/sys/dev/ixgbe/ixgbe_mbx.c +++ b/sys/dev/ixgbe/ixgbe_mbx.c @@ -42,7 +42,7 @@ * @size: Length of buffer * @mbx_id: id of mailbox to read * - * returns SUCCESS if it successfuly read message from buffer + * returns SUCCESS if it successfully read message from buffer **/ s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) { @@ -462,7 +462,7 @@ out_no_write: * @size: Length of buffer * @mbx_id: id of mailbox to read * - * returns SUCCESS if it successfuly read message from buffer + * returns SUCCESS if it successfully read message from buffer **/ static s32 ixgbe_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h index da03f79..123c9d5 100644 --- a/sys/dev/ixgbe/ixgbe_type.h +++ b/sys/dev/ixgbe/ixgbe_type.h @@ -47,7 +47,7 @@ * * - IXGBE_ERROR_POLLING * This category is for errors related to polling/timeout issues and should be - * used in any case where the timeout occured, or a failure to obtain a lock, or + * used in any case where the timeout occurred, or a failure to obtain a lock, or * failure to receive data within the time limit. * * - IXGBE_ERROR_CAUTION @@ -2078,7 +2078,7 @@ enum { #define IXGBE_MACC_FS 0x00040000 #define IXGBE_MAC_RX2TX_LPBK 0x00000002 -/* Veto Bit definiton */ +/* Veto Bit definition */ #define IXGBE_MMNGC_MNG_VETO 0x00000001 /* LINKS Bit Masks */ -- cgit v1.1 From b53514c2e21574d3ab1196a1554ea217a384ce37 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Fri, 6 May 2016 23:26:17 +0000 Subject: Give mountd -S priority over outstanding RPC requests when suspending the nfsd. It was reported via email that under certain heavy RPC loads long delays before the exports would be updated was observed when using "mountd -S". This patch reverses the priority between the exclusive lock request to suspend the nfsd threads and the shared lock request for performing RPCs. As such, when mountd attempts to suspend the nfsd threads, it gets priority over outstanding RPC requests to do this. I suspect that the case reported was an artificial test load, but this patch did fix the problem for the reporter. Reported and Tested by: josephlai@qnap.com MFC after: 2 weeks --- sys/fs/nfsserver/nfs_nfsdkrpc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sys') diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c index 6dd0c32..dd78c7a 100644 --- a/sys/fs/nfsserver/nfs_nfsdkrpc.c +++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c @@ -231,10 +231,16 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) * Get a refcnt (shared lock) on nfsd_suspend_lock. * NFSSVC_SUSPENDNFSD will take an exclusive lock on * nfsd_suspend_lock to suspend these threads. + * The call to nfsv4_lock() that preceeds nfsv4_getref() + * ensures that the acquisition of the exclusive lock + * takes priority over acquisition of the shared lock by + * waiting for any exclusive lock request to complete. * This must be done here, before the check of * nfsv4root exports by nfsvno_v4rootexport(). */ NFSLOCKV4ROOTMUTEX(); + nfsv4_lock(&nfsd_suspend_lock, 0, NULL, NFSV4ROOTLOCKMUTEXPTR, + NULL); nfsv4_getref(&nfsd_suspend_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL); NFSUNLOCKV4ROOTMUTEX(); -- cgit v1.1 From 7ae65329772cd6a2fe31ff6f0e29ad2c62063626 Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 23:37:19 +0000 Subject: sys/opencrypto: minor spelling fixes. No functional change. Reviewed by: jmg --- sys/opencrypto/cast.c | 2 +- sys/opencrypto/crypto.c | 2 +- sys/opencrypto/gfmult.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/opencrypto/cast.c b/sys/opencrypto/cast.c index 7474b36..53fec76 100644 --- a/sys/opencrypto/cast.c +++ b/sys/opencrypto/cast.c @@ -127,7 +127,7 @@ u_int32_t t, l, r; } -/***** Key Schedual *****/ +/***** Key Schedule *****/ void cast_setkey(cast_key* key, u_int8_t* rawkey, int keybytes) { diff --git a/sys/opencrypto/crypto.c b/sys/opencrypto/crypto.c index d084b77..44fbdf8 100644 --- a/sys/opencrypto/crypto.c +++ b/sys/opencrypto/crypto.c @@ -911,7 +911,7 @@ again: } /* - * Dispatch an assymetric crypto request. + * Dispatch an asymmetric crypto request. */ static int crypto_kinvoke(struct cryptkop *krp, int crid) diff --git a/sys/opencrypto/gfmult.c b/sys/opencrypto/gfmult.c index 990a7ff..b34af26 100644 --- a/sys/opencrypto/gfmult.c +++ b/sys/opencrypto/gfmult.c @@ -40,7 +40,7 @@ static const uint8_t nib_rev[] = { 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, }; -/* calulate v * 2 */ +/* calculate v * 2 */ static inline struct gf128 gf128_mulalpha(struct gf128 v) { -- cgit v1.1 From 4f457bceb76b121d1a553c9eb8e432ecccaa547a Mon Sep 17 00:00:00 2001 From: pfg Date: Fri, 6 May 2016 23:40:37 +0000 Subject: nfsserver: minor spelling fix in comment. No functional change. --- sys/fs/nfsserver/nfs_nfsdkrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c index dd78c7a..e5ad4ab 100644 --- a/sys/fs/nfsserver/nfs_nfsdkrpc.c +++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c @@ -231,7 +231,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) * Get a refcnt (shared lock) on nfsd_suspend_lock. * NFSSVC_SUSPENDNFSD will take an exclusive lock on * nfsd_suspend_lock to suspend these threads. - * The call to nfsv4_lock() that preceeds nfsv4_getref() + * The call to nfsv4_lock() that precedes nfsv4_getref() * ensures that the acquisition of the exclusive lock * takes priority over acquisition of the shared lock by * waiting for any exclusive lock request to complete. -- cgit v1.1 From 2f6c86a8e7dbc2b4ec73522a0128b0fc665c3b51 Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 6 May 2016 23:46:35 +0000 Subject: Restore name=value format of PCI location strings. When devctl was added, the location string for PCI devices was changed to use the PCI "selector" that pciconf and devctl accept. However, devd assumes that location strings are formatted as a list of name=value pairs. As a result, devd is no longer parsing any of the values out of PCI device events. Restore the previous format of the PCI location strings to restore the location and slot keywords in case any devd scripts are using this. Add the "selector" as a new 'dbsf' location variable. Reviewed by: imp MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D6253 --- sys/dev/pci/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index d668bd7..3c998b4 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -5427,7 +5427,8 @@ pci_child_location_str_method(device_t dev, device_t child, char *buf, size_t buflen) { - snprintf(buf, buflen, "pci%d:%d:%d:%d", pci_get_domain(child), + snprintf(buf, buflen, "slot=%d function=%d dbsf=pci%d:%d:%d:%d", + pci_get_slot(child), pci_get_function(child), pci_get_domain(child), pci_get_bus(child), pci_get_slot(child), pci_get_function(child)); return (0); } -- cgit v1.1 From fb93838519f07d0407c85096b63d303d9361d3d6 Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 6 May 2016 23:49:10 +0000 Subject: Set the correct vnet in TOE event handlers. Differential Revision: https://reviews.freebsd.org/D6152 --- sys/dev/cxgbe/tom/t4_cpl_io.c | 4 ++++ sys/dev/cxgbe/tom/t4_listen.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'sys') diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c index 43e4d611..dd6d5b5 100644 --- a/sys/dev/cxgbe/tom/t4_cpl_io.c +++ b/sys/dev/cxgbe/tom/t4_cpl_io.c @@ -267,6 +267,7 @@ make_established(struct toepcb *toep, uint32_t snd_isn, uint32_t rcv_isn, uint16_t tcpopt = be16toh(opt); struct flowc_tx_params ftxp; + CURVNET_SET(so->so_vnet); INP_WLOCK_ASSERT(inp); KASSERT(tp->t_state == TCPS_SYN_SENT || tp->t_state == TCPS_SYN_RECEIVED, @@ -317,6 +318,7 @@ make_established(struct toepcb *toep, uint32_t snd_isn, uint32_t rcv_isn, send_flowc_wr(toep, &ftxp); soisconnected(so); + CURVNET_RESTORE(); } static int @@ -1429,6 +1431,7 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) } /* receive buffer autosize */ + CURVNET_SET(so->so_vnet); if (sb->sb_flags & SB_AUTOSIZE && V_tcp_do_autorcvbuf && sb->sb_hiwat < V_tcp_autorcvbuf_max && @@ -1517,6 +1520,7 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) SOCKBUF_UNLOCK_ASSERT(sb); INP_WUNLOCK(inp); + CURVNET_RESTORE(); return (0); } diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c index 36b53d3..9865cc4 100644 --- a/sys/dev/cxgbe/tom/t4_listen.c +++ b/sys/dev/cxgbe/tom/t4_listen.c @@ -1305,6 +1305,7 @@ found: REJECT_PASS_ACCEPT(); } so = inp->inp_socket; + CURVNET_SET(so->so_vnet); mtu_idx = find_best_mtu_idx(sc, &inc, be16toh(cpl->tcpopt.mss)); rscale = cpl->tcpopt.wsf && V_tcp_do_rfc1323 ? select_rcv_wscale() : 0; @@ -1351,6 +1352,7 @@ found: */ toe_syncache_add(&inc, &to, &th, inp, tod, synqe); INP_UNLOCK_ASSERT(inp); /* ok to assert, we have a ref on the inp */ + CURVNET_RESTORE(); /* * If we replied during syncache_add (synqe->wr has been consumed), -- cgit v1.1 From 5a10a1e2e64319d6a871cdd80d31104b5f16a0c8 Mon Sep 17 00:00:00 2001 From: jhb Date: Sat, 7 May 2016 00:33:35 +0000 Subject: Use DDP to implement zerocopy TCP receive with aio_read(). Chelsio's TCP offload engine supports direct DMA of received TCP payload into wired user buffers. This feature is known as Direct-Data Placement. However, to scale well the adapter needs to prepare buffers for DDP before data arrives. aio_read() is more amenable to this requirement than read() as applications often call read() only after data is available in the socket buffer. When DDP is enabled, TOE sockets use the recently added pru_aio_queue protocol hook to claim aio_read(2) requests instead of letting them use the default AIO socket logic. The DDP feature supports scheduling DMA to two buffers at a time so that the second buffer is ready for use after the first buffer is filled. The aio/DDP code optimizes the case of an application ping-ponging between two buffers (similar to the zero-copy bpf(4) code) by keeping the two most recently used AIO buffers wired. If a buffer is reused, the aio/DDP code is able to reuse the vm_page_t array as well as page pod mappings (a kind of MMU mapping the Chelsio NIC uses to describe user buffers). The generation of the vmspace of the calling process is used in conjunction with the user buffer's address and length to determine if a user buffer matches a previously used buffer. If an application queues a buffer for AIO that does not match a previously used buffer then the least recently used buffer is unwired before the new buffer is wired. This ensures that no more than two user buffers per socket are ever wired. Note that this feature is best suited to applications sending a steady stream of data vs short bursts of traffic. Discussed with: np Relnotes: yes Sponsored by: Chelsio Communications --- sys/dev/cxgbe/offload.h | 2 - sys/dev/cxgbe/t4_main.c | 9 - sys/dev/cxgbe/tom/t4_cpl_io.c | 119 ++- sys/dev/cxgbe/tom/t4_ddp.c | 1740 ++++++++++++++++++++++++++--------------- sys/dev/cxgbe/tom/t4_tom.c | 36 +- sys/dev/cxgbe/tom/t4_tom.h | 63 +- 6 files changed, 1269 insertions(+), 700 deletions(-) (limited to 'sys') diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h index d1363c4..22612d5 100644 --- a/sys/dev/cxgbe/offload.h +++ b/sys/dev/cxgbe/offload.h @@ -145,8 +145,6 @@ struct uld_info { struct tom_tunables { int sndbuf; int ddp; - int indsz; - int ddp_thres; int rx_coalesce; int tx_align; }; diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 1e86aa9..132d69e 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -4901,15 +4901,6 @@ t4_sysctls(struct adapter *sc) SYSCTL_ADD_INT(ctx, children, OID_AUTO, "ddp", CTLFLAG_RW, &sc->tt.ddp, 0, "DDP allowed"); - sc->tt.indsz = G_INDICATESIZE(t4_read_reg(sc, A_TP_PARA_REG5)); - SYSCTL_ADD_INT(ctx, children, OID_AUTO, "indsz", CTLFLAG_RW, - &sc->tt.indsz, 0, "DDP max indicate size allowed"); - - sc->tt.ddp_thres = - G_RXCOALESCESIZE(t4_read_reg(sc, A_TP_PARA_REG2)); - SYSCTL_ADD_INT(ctx, children, OID_AUTO, "ddp_thres", CTLFLAG_RW, - &sc->tt.ddp_thres, 0, "DDP threshold"); - sc->tt.rx_coalesce = 1; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "rx_coalesce", CTLFLAG_RW, &sc->tt.rx_coalesce, 0, "receive coalescing"); diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c index dd6d5b5..4710977 100644 --- a/sys/dev/cxgbe/tom/t4_cpl_io.c +++ b/sys/dev/cxgbe/tom/t4_cpl_io.c @@ -343,7 +343,7 @@ send_rx_credits(struct adapter *sc, struct toepcb *toep, int credits) } void -t4_rcvd(struct toedev *tod, struct tcpcb *tp) +t4_rcvd_locked(struct toedev *tod, struct tcpcb *tp) { struct adapter *sc = tod->tod_softc; struct inpcb *inp = tp->t_inpcb; @@ -354,7 +354,7 @@ t4_rcvd(struct toedev *tod, struct tcpcb *tp) INP_WLOCK_ASSERT(inp); - SOCKBUF_LOCK(sb); + SOCKBUF_LOCK_ASSERT(sb); KASSERT(toep->sb_cc >= sbused(sb), ("%s: sb %p has more data (%d) than last time (%d).", __func__, sb, sbused(sb), toep->sb_cc)); @@ -372,6 +372,17 @@ t4_rcvd(struct toedev *tod, struct tcpcb *tp) tp->rcv_wnd += credits; tp->rcv_adv += credits; } +} + +void +t4_rcvd(struct toedev *tod, struct tcpcb *tp) +{ + struct inpcb *inp = tp->t_inpcb; + struct socket *so = inp->inp_socket; + struct sockbuf *sb = &so->so_rcv; + + SOCKBUF_LOCK(sb); + t4_rcvd_locked(tod, tp); SOCKBUF_UNLOCK(sb); } @@ -1042,7 +1053,6 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) struct inpcb *inp = toep->inp; struct tcpcb *tp = NULL; struct socket *so; - struct sockbuf *sb; #ifdef INVARIANTS unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl))); #endif @@ -1088,12 +1098,14 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) tp->rcv_nxt++; /* FIN */ so = inp->inp_socket; - sb = &so->so_rcv; - SOCKBUF_LOCK(sb); - if (__predict_false(toep->ddp_flags & (DDP_BUF0_ACTIVE | DDP_BUF1_ACTIVE))) { - handle_ddp_close(toep, tp, sb, cpl->rcv_nxt); + if (toep->ulp_mode == ULP_MODE_TCPDDP) { + DDP_LOCK(toep); + if (__predict_false(toep->ddp_flags & + (DDP_BUF0_ACTIVE | DDP_BUF1_ACTIVE))) + handle_ddp_close(toep, tp, cpl->rcv_nxt); + DDP_UNLOCK(toep); } - socantrcvmore_locked(so); /* unlocks the sockbuf */ + socantrcvmore(so); if (toep->ulp_mode != ULP_MODE_RDMA) { KASSERT(tp->rcv_nxt == be32toh(cpl->rcv_nxt), @@ -1409,6 +1421,8 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) tp->rcv_wnd -= len; tp->t_rcvtime = ticks; + if (toep->ulp_mode == ULP_MODE_TCPDDP) + DDP_LOCK(toep); so = inp_inpcbtosocket(inp); sb = &so->so_rcv; SOCKBUF_LOCK(sb); @@ -1418,6 +1432,8 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) __func__, tid, len); m_freem(m); SOCKBUF_UNLOCK(sb); + if (toep->ulp_mode == ULP_MODE_TCPDDP) + DDP_UNLOCK(toep); INP_WUNLOCK(inp); INP_INFO_RLOCK(&V_tcbinfo); @@ -1446,6 +1462,10 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) toep->rx_credits += newsize - hiwat; } + if (toep->ddp_waiting_count != 0 || toep->ddp_active_count != 0) + CTR3(KTR_CXGBE, "%s: tid %u, non-ddp rx (%d bytes)", __func__, + tid, len); + if (toep->ulp_mode == ULP_MODE_TCPDDP) { int changed = !(toep->ddp_flags & DDP_ON) ^ cpl->ddp_off; @@ -1458,47 +1478,22 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) __func__)); /* Fell out of DDP mode */ - toep->ddp_flags &= ~(DDP_ON | DDP_BUF0_ACTIVE | - DDP_BUF1_ACTIVE); + toep->ddp_flags &= ~DDP_ON; + CTR1(KTR_CXGBE, "%s: fell out of DDP mode", + __func__); - if (ddp_placed) - insert_ddp_data(toep, ddp_placed); + insert_ddp_data(toep, ddp_placed); } } - if ((toep->ddp_flags & DDP_OK) == 0 && - time_uptime >= toep->ddp_disabled + DDP_RETRY_WAIT) { - toep->ddp_score = DDP_LOW_SCORE; - toep->ddp_flags |= DDP_OK; - CTR3(KTR_CXGBE, "%s: tid %u DDP_OK @ %u", - __func__, tid, time_uptime); - } - if (toep->ddp_flags & DDP_ON) { - /* - * CPL_RX_DATA with DDP on can only be an indicate. Ask - * soreceive to post a buffer or disable DDP. The - * payload that arrived in this indicate is appended to - * the socket buffer as usual. + * CPL_RX_DATA with DDP on can only be an indicate. + * Start posting queued AIO requests via DDP. The + * payload that arrived in this indicate is appended + * to the socket buffer as usual. */ - -#if 0 - CTR5(KTR_CXGBE, - "%s: tid %u (0x%x) DDP indicate (seq 0x%x, len %d)", - __func__, tid, toep->flags, be32toh(cpl->seq), len); -#endif - sb->sb_flags |= SB_DDP_INDICATE; - } else if ((toep->ddp_flags & (DDP_OK|DDP_SC_REQ)) == DDP_OK && - tp->rcv_wnd > DDP_RSVD_WIN && len >= sc->tt.ddp_thres) { - - /* - * DDP allowed but isn't on (and a request to switch it - * on isn't pending either), and conditions are ripe for - * it to work. Switch it on. - */ - - enable_ddp(sc, toep); + handle_ddp_indicate(toep); } } @@ -1516,8 +1511,16 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) tp->rcv_wnd += credits; tp->rcv_adv += credits; } + + if (toep->ddp_waiting_count > 0 && sbavail(sb) != 0) { + CTR2(KTR_CXGBE, "%s: tid %u queueing AIO task", __func__, + tid); + ddp_queue_toep(toep); + } sorwakeup_locked(so); SOCKBUF_UNLOCK_ASSERT(sb); + if (toep->ulp_mode == ULP_MODE_TCPDDP) + DDP_UNLOCK(toep); INP_WUNLOCK(inp); CURVNET_RESTORE(); @@ -1680,6 +1683,7 @@ do_set_tcb_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) struct adapter *sc = iq->adapter; const struct cpl_set_tcb_rpl *cpl = (const void *)(rss + 1); unsigned int tid = GET_TID(cpl); + struct toepcb *toep; #ifdef INVARIANTS unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl))); #endif @@ -1691,6 +1695,12 @@ do_set_tcb_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) if (is_ftid(sc, tid)) return (t4_filter_rpl(iq, rss, m)); /* TCB is a filter */ + toep = lookup_tid(sc, tid); + if (toep->ulp_mode == ULP_MODE_TCPDDP) { + handle_ddp_tcb_rpl(toep, cpl); + return (0); + } + /* * TOM and/or other ULPs don't request replies for CPL_SET_TCB or * CPL_SET_TCB_FIELD requests. This can easily change and when it does @@ -1732,6 +1742,31 @@ t4_set_tcb_field(struct adapter *sc, struct toepcb *toep, int ctrl, } void +t4_set_tcb_field_rpl(struct adapter *sc, struct toepcb *toep, int ctrl, + uint16_t word, uint64_t mask, uint64_t val, uint8_t cookie) +{ + struct wrqe *wr; + struct cpl_set_tcb_field *req; + + KASSERT((cookie & ~M_COOKIE) == 0, ("%s: invalid cookie %#x", __func__, + cookie)); + wr = alloc_wrqe(sizeof(*req), ctrl ? toep->ctrlq : toep->ofld_txq); + if (wr == NULL) { + /* XXX */ + panic("%s: allocation failure.", __func__); + } + req = wrtod(wr); + + INIT_TP_WR_MIT_CPL(req, CPL_SET_TCB_FIELD, toep->tid); + req->reply_ctrl = htobe16(V_QUEUENO(toep->ofld_rxq->iq.abs_id)); + req->word_cookie = htobe16(V_WORD(word) | V_COOKIE(cookie)); + req->mask = htobe64(mask); + req->val = htobe64(val); + + t4_wrq_tx(sc, wr); +} + +void t4_init_cpl_io_handlers(struct adapter *sc) { diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c index 2aa774d..8cba8ca 100644 --- a/sys/dev/cxgbe/tom/t4_ddp.c +++ b/sys/dev/cxgbe/tom/t4_ddp.c @@ -31,7 +31,8 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include -#include +#include +#include #include #include #include @@ -41,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -72,7 +74,10 @@ VNET_DECLARE(int, tcp_autorcvbuf_inc); VNET_DECLARE(int, tcp_autorcvbuf_max); #define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max) -static struct mbuf *get_ddp_mbuf(int len); +static void aio_ddp_requeue_task(void *context, int pending); +static void ddp_complete_all(struct toepcb *toep, int error); +static void t4_aio_cancel_active(struct kaiocb *job); +static void t4_aio_cancel_queued(struct kaiocb *job); #define PPOD_SZ(n) ((n) * sizeof(struct pagepod)) #define PPOD_SIZE (PPOD_SZ(1)) @@ -80,6 +85,10 @@ static struct mbuf *get_ddp_mbuf(int len); /* XXX: must match A_ULP_RX_TDDP_PSZ */ static int t4_ddp_pgsz[] = {4096, 4096 << 2, 4096 << 4, 4096 << 6}; +static TAILQ_HEAD(, pageset) ddp_orphan_pagesets; +static struct mtx ddp_orphan_pagesets_lock; +static struct task ddp_orphan_task; + #define MAX_DDP_BUFFER_SIZE (M_TCB_RX_DDP_BUF0_LEN) static int alloc_ppods(struct tom_data *td, int n, u_int *ppod_addr) @@ -112,33 +121,199 @@ pages_to_nppods(int npages, int ddp_pgsz) return (howmany(nsegs, PPOD_PAGES)); } +/* + * A page set holds information about a buffer used for DDP. The page + * set holds resources such as the VM pages backing the buffer (either + * held or wired) and the page pods associated with the buffer. + * Recently used page sets are cached to allow for efficient reuse of + * buffers (avoiding the need to re-fault in pages, hold them, etc.). + * Note that cached page sets keep the backing pages wired. The + * number of wired pages is capped by only allowing for two wired + * pagesets per connection. This is not a perfect cap, but is a + * trade-off for performance. + * + * If an application ping-pongs two buffers for a connection via + * aio_read(2) then those buffers should remain wired and expensive VM + * fault lookups should be avoided after each buffer has been used + * once. If an application uses more than two buffers then this will + * fall back to doing expensive VM fault lookups for each operation. + */ +static void +free_pageset(struct tom_data *td, struct pageset *ps) +{ + vm_page_t p; + int i; + + if (ps->nppods > 0) + free_ppods(td, ps->ppod_addr, ps->nppods); + + if (ps->flags & PS_WIRED) { + for (i = 0; i < ps->npages; i++) { + p = ps->pages[i]; + vm_page_lock(p); + vm_page_unwire(p, PQ_INACTIVE); + vm_page_unlock(p); + } + } else + vm_page_unhold_pages(ps->pages, ps->npages); + mtx_lock(&ddp_orphan_pagesets_lock); + TAILQ_INSERT_TAIL(&ddp_orphan_pagesets, ps, link); + taskqueue_enqueue(taskqueue_thread, &ddp_orphan_task); + mtx_unlock(&ddp_orphan_pagesets_lock); +} + +static void +ddp_free_orphan_pagesets(void *context, int pending) +{ + struct pageset *ps; + + mtx_lock(&ddp_orphan_pagesets_lock); + while (!TAILQ_EMPTY(&ddp_orphan_pagesets)) { + ps = TAILQ_FIRST(&ddp_orphan_pagesets); + TAILQ_REMOVE(&ddp_orphan_pagesets, ps, link); + mtx_unlock(&ddp_orphan_pagesets_lock); + if (ps->vm) + vmspace_free(ps->vm); + free(ps, M_CXGBE); + mtx_lock(&ddp_orphan_pagesets_lock); + } + mtx_unlock(&ddp_orphan_pagesets_lock); +} + +static void +recycle_pageset(struct toepcb *toep, struct pageset *ps) +{ + + DDP_ASSERT_LOCKED(toep); + if (!(toep->ddp_flags & DDP_DEAD) && ps->flags & PS_WIRED) { + KASSERT(toep->ddp_cached_count + toep->ddp_active_count < + nitems(toep->db), ("too many wired pagesets")); + TAILQ_INSERT_HEAD(&toep->ddp_cached_pagesets, ps, link); + toep->ddp_cached_count++; + } else + free_pageset(toep->td, ps); +} + +static void +ddp_complete_one(struct kaiocb *job, int error) +{ + long copied; + + /* + * If this job had copied data out of the socket buffer before + * it was cancelled, report it as a short read rather than an + * error. + */ + copied = job->uaiocb._aiocb_private.status; + if (copied != 0 || error == 0) + aio_complete(job, copied, 0); + else + aio_complete(job, -1, error); +} + static void free_ddp_buffer(struct tom_data *td, struct ddp_buffer *db) { - if (db == NULL) - return; + if (db->job) { + /* + * XXX: If we are un-offloading the socket then we + * should requeue these on the socket somehow. If we + * got a FIN from the remote end, then this completes + * any remaining requests with an EOF read. + */ + if (!aio_clear_cancel_function(db->job)) + ddp_complete_one(db->job, 0); + } + + if (db->ps) + free_pageset(td, db->ps); +} + +void +ddp_init_toep(struct toepcb *toep) +{ - if (db->pages) - free(db->pages, M_CXGBE); + TAILQ_INIT(&toep->ddp_aiojobq); + TASK_INIT(&toep->ddp_requeue_task, 0, aio_ddp_requeue_task, toep); + toep->ddp_active_id = -1; + mtx_init(&toep->ddp_lock, "t4 ddp", NULL, MTX_DEF); +} - if (db->nppods > 0) - free_ppods(td, db->ppod_addr, db->nppods); +void +ddp_uninit_toep(struct toepcb *toep) +{ - free(db, M_CXGBE); + mtx_destroy(&toep->ddp_lock); } void release_ddp_resources(struct toepcb *toep) { + struct pageset *ps; int i; + DDP_LOCK(toep); + toep->flags |= DDP_DEAD; for (i = 0; i < nitems(toep->db); i++) { - if (toep->db[i] != NULL) { - free_ddp_buffer(toep->td, toep->db[i]); - toep->db[i] = NULL; - } + free_ddp_buffer(toep->td, &toep->db[i]); + } + while ((ps = TAILQ_FIRST(&toep->ddp_cached_pagesets)) != NULL) { + TAILQ_REMOVE(&toep->ddp_cached_pagesets, ps, link); + free_pageset(toep->td, ps); + } + ddp_complete_all(toep, 0); + DDP_UNLOCK(toep); +} + +#ifdef INVARIANTS +void +ddp_assert_empty(struct toepcb *toep) +{ + int i; + + MPASS(!(toep->ddp_flags & DDP_TASK_ACTIVE)); + for (i = 0; i < nitems(toep->db); i++) { + MPASS(toep->db[i].job == NULL); + MPASS(toep->db[i].ps == NULL); + } + MPASS(TAILQ_EMPTY(&toep->ddp_cached_pagesets)); + MPASS(TAILQ_EMPTY(&toep->ddp_aiojobq)); +} +#endif + +static void +complete_ddp_buffer(struct toepcb *toep, struct ddp_buffer *db, + unsigned int db_idx) +{ + unsigned int db_flag; + + toep->ddp_active_count--; + if (toep->ddp_active_id == db_idx) { + if (toep->ddp_active_count == 0) { + KASSERT(toep->db[db_idx ^ 1].job == NULL, + ("%s: active_count mismatch", __func__)); + toep->ddp_active_id = -1; + } else + toep->ddp_active_id ^= 1; + CTR2(KTR_CXGBE, "%s: ddp_active_id = %d", __func__, + toep->ddp_active_id); + } else { + KASSERT(toep->ddp_active_count != 0 && + toep->ddp_active_id != -1, + ("%s: active count mismatch", __func__)); } + + db->cancel_pending = 0; + db->job = NULL; + recycle_pageset(toep, db->ps); + db->ps = NULL; + + db_flag = db_idx == 1 ? DDP_BUF1_ACTIVE : DDP_BUF0_ACTIVE; + KASSERT(toep->ddp_flags & db_flag, + ("%s: DDP buffer not active. toep %p, ddp_flags 0x%x", + __func__, toep, toep->ddp_flags)); + toep->ddp_flags &= ~db_flag; } /* XXX: handle_ddp_data code duplication */ @@ -147,28 +322,59 @@ insert_ddp_data(struct toepcb *toep, uint32_t n) { struct inpcb *inp = toep->inp; struct tcpcb *tp = intotcpcb(inp); - struct sockbuf *sb = &inp->inp_socket->so_rcv; - struct mbuf *m; + struct ddp_buffer *db; + struct kaiocb *job; + size_t placed; + long copied; + unsigned int db_flag, db_idx; INP_WLOCK_ASSERT(inp); - SOCKBUF_LOCK_ASSERT(sb); + DDP_ASSERT_LOCKED(toep); - m = get_ddp_mbuf(n); tp->rcv_nxt += n; #ifndef USE_DDP_RX_FLOW_CONTROL KASSERT(tp->rcv_wnd >= n, ("%s: negative window size", __func__)); tp->rcv_wnd -= n; #endif - - KASSERT(toep->sb_cc >= sbused(sb), - ("%s: sb %p has more data (%d) than last time (%d).", - __func__, sb, sbused(sb), toep->sb_cc)); - toep->rx_credits += toep->sb_cc - sbused(sb); -#ifdef USE_DDP_RX_FLOW_CONTROL - toep->rx_credits -= n; /* adjust for F_RX_FC_DDP */ +#ifndef USE_DDP_RX_FLOW_CONTROL + toep->rx_credits += n; #endif - sbappendstream_locked(sb, m, 0); - toep->sb_cc = sbused(sb); + CTR2(KTR_CXGBE, "%s: placed %u bytes before falling out of DDP", + __func__, n); + while (toep->ddp_active_count > 0) { + MPASS(toep->ddp_active_id != -1); + db_idx = toep->ddp_active_id; + db_flag = db_idx == 1 ? DDP_BUF1_ACTIVE : DDP_BUF0_ACTIVE; + MPASS((toep->ddp_flags & db_flag) != 0); + db = &toep->db[db_idx]; + job = db->job; + copied = job->uaiocb._aiocb_private.status; + placed = n; + if (placed > job->uaiocb.aio_nbytes - copied) + placed = job->uaiocb.aio_nbytes - copied; + if (!aio_clear_cancel_function(job)) { + /* + * Update the copied length for when + * t4_aio_cancel_active() completes this + * request. + */ + job->uaiocb._aiocb_private.status += placed; + } else if (copied + placed != 0) { + CTR4(KTR_CXGBE, + "%s: completing %p (copied %ld, placed %lu)", + __func__, job, copied, placed); + /* XXX: This always completes if there is some data. */ + aio_complete(job, copied + placed, 0); + } else if (aio_set_cancel_function(job, t4_aio_cancel_queued)) { + TAILQ_INSERT_HEAD(&toep->ddp_aiojobq, job, list); + toep->ddp_waiting_count++; + } else + aio_cancel(job); + n -= placed; + complete_ddp_buffer(toep, db, db_idx); + } + + MPASS(n == 0); } /* SET_TCB_FIELD sent as a ULP command looks like this */ @@ -236,42 +442,10 @@ mk_rx_data_ack_ulp(struct ulp_txpkt *ulpmc, struct toepcb *toep) return (ulpsc); } -static inline uint64_t -select_ddp_flags(struct socket *so, int flags, int db_idx) -{ - uint64_t ddp_flags = V_TF_DDP_INDICATE_OUT(0); - int waitall = flags & MSG_WAITALL; - int nb = so->so_state & SS_NBIO || flags & (MSG_DONTWAIT | MSG_NBIO); - - KASSERT(db_idx == 0 || db_idx == 1, - ("%s: bad DDP buffer index %d", __func__, db_idx)); - - if (db_idx == 0) { - ddp_flags |= V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_ACTIVE_BUF(0); - if (waitall) - ddp_flags |= V_TF_DDP_PUSH_DISABLE_0(1); - else if (nb) - ddp_flags |= V_TF_DDP_BUF0_FLUSH(1); - else - ddp_flags |= V_TF_DDP_BUF0_FLUSH(0); - } else { - ddp_flags |= V_TF_DDP_BUF1_VALID(1) | V_TF_DDP_ACTIVE_BUF(1); - if (waitall) - ddp_flags |= V_TF_DDP_PUSH_DISABLE_1(1); - else if (nb) - ddp_flags |= V_TF_DDP_BUF1_FLUSH(1); - else - ddp_flags |= V_TF_DDP_BUF1_FLUSH(0); - } - - return (ddp_flags); -} - static struct wrqe * mk_update_tcb_for_ddp(struct adapter *sc, struct toepcb *toep, int db_idx, - int offset, uint64_t ddp_flags) + struct pageset *ps, int offset, uint64_t ddp_flags, uint64_t ddp_flags_mask) { - struct ddp_buffer *db = toep->db[db_idx]; struct wrqe *wr; struct work_request_hdr *wrh; struct ulp_txpkt *ulpmc; @@ -302,7 +476,7 @@ mk_update_tcb_for_ddp(struct adapter *sc, struct toepcb *toep, int db_idx, ulpmc = mk_set_tcb_field_ulp(ulpmc, toep, W_TCB_RX_DDP_BUF0_TAG + db_idx, V_TCB_RX_DDP_BUF0_TAG(M_TCB_RX_DDP_BUF0_TAG), - V_TCB_RX_DDP_BUF0_TAG(db->tag)); + V_TCB_RX_DDP_BUF0_TAG(ps->tag)); /* Update the current offset in the DDP buffer and its total length */ if (db_idx == 0) @@ -311,21 +485,18 @@ mk_update_tcb_for_ddp(struct adapter *sc, struct toepcb *toep, int db_idx, V_TCB_RX_DDP_BUF0_OFFSET(M_TCB_RX_DDP_BUF0_OFFSET) | V_TCB_RX_DDP_BUF0_LEN(M_TCB_RX_DDP_BUF0_LEN), V_TCB_RX_DDP_BUF0_OFFSET(offset) | - V_TCB_RX_DDP_BUF0_LEN(db->len)); + V_TCB_RX_DDP_BUF0_LEN(ps->len)); else ulpmc = mk_set_tcb_field_ulp(ulpmc, toep, W_TCB_RX_DDP_BUF1_OFFSET, V_TCB_RX_DDP_BUF1_OFFSET(M_TCB_RX_DDP_BUF1_OFFSET) | V_TCB_RX_DDP_BUF1_LEN((u64)M_TCB_RX_DDP_BUF1_LEN << 32), V_TCB_RX_DDP_BUF1_OFFSET(offset) | - V_TCB_RX_DDP_BUF1_LEN((u64)db->len << 32)); + V_TCB_RX_DDP_BUF1_LEN((u64)ps->len << 32)); /* Update DDP flags */ ulpmc = mk_set_tcb_field_ulp(ulpmc, toep, W_TCB_RX_DDP_FLAGS, - V_TF_DDP_BUF0_FLUSH(1) | V_TF_DDP_BUF1_FLUSH(1) | - V_TF_DDP_PUSH_DISABLE_0(1) | V_TF_DDP_PUSH_DISABLE_1(1) | - V_TF_DDP_BUF0_VALID(1) | V_TF_DDP_BUF1_VALID(1) | - V_TF_DDP_ACTIVE_BUF(1) | V_TF_DDP_INDICATE_OUT(1), ddp_flags); + ddp_flags_mask, ddp_flags); /* Gratuitous RX_DATA_ACK with RX_MODULATE set to speed up delivery. */ ulpmc = mk_rx_data_ack_ulp(ulpmc, toep); @@ -333,30 +504,20 @@ mk_update_tcb_for_ddp(struct adapter *sc, struct toepcb *toep, int db_idx, return (wr); } -static void -discourage_ddp(struct toepcb *toep) -{ - - if (toep->ddp_score && --toep->ddp_score == 0) { - toep->ddp_flags &= ~DDP_OK; - toep->ddp_disabled = time_uptime; - CTR3(KTR_CXGBE, "%s: tid %u !DDP_OK @ %u", - __func__, toep->tid, time_uptime); - } -} - static int handle_ddp_data(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, int len) { uint32_t report = be32toh(ddp_report); - unsigned int db_flag; + unsigned int db_idx; struct inpcb *inp = toep->inp; + struct ddp_buffer *db; struct tcpcb *tp; struct socket *so; struct sockbuf *sb; - struct mbuf *m; + struct kaiocb *job; + long copied; - db_flag = report & F_DDP_BUF_IDX ? DDP_BUF1_ACTIVE : DDP_BUF0_ACTIVE; + db_idx = report & F_DDP_BUF_IDX ? 1 : 0; if (__predict_false(!(report & F_DDP_INV))) CXGBE_UNIMPLEMENTED("DDP buffer still valid"); @@ -364,19 +525,24 @@ handle_ddp_data(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, int len) INP_WLOCK(inp); so = inp_inpcbtosocket(inp); sb = &so->so_rcv; - if (__predict_false(inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT))) { + DDP_LOCK(toep); + KASSERT(toep->ddp_active_id == db_idx, + ("completed DDP buffer (%d) != active_id (%d) for tid %d", db_idx, + toep->ddp_active_id, toep->tid)); + db = &toep->db[db_idx]; + job = db->job; + + if (__predict_false(inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT))) { /* - * XXX: think a bit more. - * tcpcb probably gone, but socket should still be around - * because we always wait for DDP completion in soreceive no - * matter what. Just wake it up and let it clean up. + * This can happen due to an administrative tcpdrop(8). + * Just fail the request with ECONNRESET. */ - CTR5(KTR_CXGBE, "%s: tid %u, seq 0x%x, len %d, inp_flags 0x%x", __func__, toep->tid, be32toh(rcv_nxt), len, inp->inp_flags); - SOCKBUF_LOCK(sb); - goto wakeup; + if (aio_clear_cancel_function(job)) + ddp_complete_one(job, ECONNRESET); + goto completed; } tp = intotcpcb(inp); @@ -386,7 +552,7 @@ handle_ddp_data(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, int len) * sequence number of the next byte to receive. The length of * the data received for this message must be computed by * comparing the new and old values of rcv_nxt. - * + * * For RX_DATA_DDP, len might be non-zero, but it is only the * length of the most recent DMA. It does not include the * total length of the data received since the previous update @@ -400,15 +566,14 @@ handle_ddp_data(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, int len) KASSERT(tp->rcv_wnd >= len, ("%s: negative window size", __func__)); tp->rcv_wnd -= len; #endif - m = get_ddp_mbuf(len); - - SOCKBUF_LOCK(sb); - if (report & F_DDP_BUF_COMPLETE) - toep->ddp_score = DDP_HIGH_SCORE; - else - discourage_ddp(toep); +#ifdef VERBOSE_TRACES + CTR4(KTR_CXGBE, "%s: DDP[%d] placed %d bytes (%#x)", __func__, db_idx, + len, report); +#endif /* receive buffer autosize */ + CURVNET_SET(so->so_vnet); + SOCKBUF_LOCK(sb); if (sb->sb_flags & SB_AUTOSIZE && V_tcp_do_autorcvbuf && sb->sb_hiwat < V_tcp_autorcvbuf_max && @@ -422,57 +587,185 @@ handle_ddp_data(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, int len) else toep->rx_credits += newsize - hiwat; } + SOCKBUF_UNLOCK(sb); + CURVNET_RESTORE(); - KASSERT(toep->sb_cc >= sbused(sb), - ("%s: sb %p has more data (%d) than last time (%d).", - __func__, sb, sbused(sb), toep->sb_cc)); - toep->rx_credits += toep->sb_cc - sbused(sb); -#ifdef USE_DDP_RX_FLOW_CONTROL - toep->rx_credits -= len; /* adjust for F_RX_FC_DDP */ +#ifndef USE_DDP_RX_FLOW_CONTROL + toep->rx_credits += len; #endif - sbappendstream_locked(sb, m, 0); - toep->sb_cc = sbused(sb); -wakeup: - KASSERT(toep->ddp_flags & db_flag, - ("%s: DDP buffer not active. toep %p, ddp_flags 0x%x, report 0x%x", - __func__, toep, toep->ddp_flags, report)); - toep->ddp_flags &= ~db_flag; - sorwakeup_locked(so); - SOCKBUF_UNLOCK_ASSERT(sb); + if (db->cancel_pending) { + /* + * Update the job's length but defer completion to the + * TCB_RPL callback. + */ + job->uaiocb._aiocb_private.status += len; + goto out; + } else if (!aio_clear_cancel_function(job)) { + /* + * Update the copied length for when + * t4_aio_cancel_active() completes this request. + */ + job->uaiocb._aiocb_private.status += len; + } else { + copied = job->uaiocb._aiocb_private.status; +#ifdef VERBOSE_TRACES + CTR4(KTR_CXGBE, "%s: completing %p (copied %ld, placed %d)", + __func__, job, copied, len); +#endif + aio_complete(job, copied + len, 0); + t4_rcvd(&toep->td->tod, tp); + } + +completed: + complete_ddp_buffer(toep, db, db_idx); + if (toep->ddp_waiting_count > 0) + ddp_queue_toep(toep); +out: + DDP_UNLOCK(toep); INP_WUNLOCK(inp); + return (0); } void -handle_ddp_close(struct toepcb *toep, struct tcpcb *tp, struct sockbuf *sb, - __be32 rcv_nxt) +handle_ddp_indicate(struct toepcb *toep) { - struct mbuf *m; - int len; - SOCKBUF_LOCK_ASSERT(sb); + DDP_ASSERT_LOCKED(toep); + MPASS(toep->ddp_active_count == 0); + MPASS((toep->ddp_flags & (DDP_BUF0_ACTIVE | DDP_BUF1_ACTIVE)) == 0); + if (toep->ddp_waiting_count == 0) { + /* + * The pending requests that triggered the request for an + * an indicate were cancelled. Those cancels should have + * already disabled DDP. Just ignore this as the data is + * going into the socket buffer anyway. + */ + return; + } + CTR3(KTR_CXGBE, "%s: tid %d indicated (%d waiting)", __func__, + toep->tid, toep->ddp_waiting_count); + ddp_queue_toep(toep); +} + +enum { + DDP_BUF0_INVALIDATED = 0x2, + DDP_BUF1_INVALIDATED +}; + +void +handle_ddp_tcb_rpl(struct toepcb *toep, const struct cpl_set_tcb_rpl *cpl) +{ + unsigned int db_idx; + struct inpcb *inp = toep->inp; + struct ddp_buffer *db; + struct kaiocb *job; + long copied; + + if (cpl->status != CPL_ERR_NONE) + panic("XXX: tcp_rpl failed: %d", cpl->status); + + switch (cpl->cookie) { + case V_WORD(W_TCB_RX_DDP_FLAGS) | V_COOKIE(DDP_BUF0_INVALIDATED): + case V_WORD(W_TCB_RX_DDP_FLAGS) | V_COOKIE(DDP_BUF1_INVALIDATED): + /* + * XXX: This duplicates a lot of code with handle_ddp_data(). + */ + db_idx = G_COOKIE(cpl->cookie) - DDP_BUF0_INVALIDATED; + INP_WLOCK(inp); + DDP_LOCK(toep); + db = &toep->db[db_idx]; + + /* + * handle_ddp_data() should leave the job around until + * this callback runs once a cancel is pending. + */ + MPASS(db != NULL); + MPASS(db->job != NULL); + MPASS(db->cancel_pending); + + /* + * XXX: It's not clear what happens if there is data + * placed when the buffer is invalidated. I suspect we + * need to read the TCB to see how much data was placed. + * + * For now this just pretends like nothing was placed. + * + * XXX: Note that if we did check the PCB we would need to + * also take care of updating the tp, etc. + */ + job = db->job; + copied = job->uaiocb._aiocb_private.status; + if (copied == 0) { + CTR2(KTR_CXGBE, "%s: cancelling %p", __func__, job); + aio_cancel(job); + } else { + CTR3(KTR_CXGBE, "%s: completing %p (copied %ld)", + __func__, job, copied); + aio_complete(job, copied, 0); + t4_rcvd(&toep->td->tod, intotcpcb(inp)); + } + + complete_ddp_buffer(toep, db, db_idx); + if (toep->ddp_waiting_count > 0) + ddp_queue_toep(toep); + DDP_UNLOCK(toep); + INP_WUNLOCK(inp); + break; + default: + panic("XXX: unknown tcb_rpl offset %#x, cookie %#x", + G_WORD(cpl->cookie), G_COOKIE(cpl->cookie)); + } +} + +void +handle_ddp_close(struct toepcb *toep, struct tcpcb *tp, __be32 rcv_nxt) +{ + struct ddp_buffer *db; + struct kaiocb *job; + long copied; + unsigned int db_flag, db_idx; + int len, placed; + INP_WLOCK_ASSERT(toep->inp); + DDP_ASSERT_LOCKED(toep); len = be32toh(rcv_nxt) - tp->rcv_nxt; - /* Signal handle_ddp() to break out of its sleep loop. */ - toep->ddp_flags &= ~(DDP_BUF0_ACTIVE | DDP_BUF1_ACTIVE); - if (len == 0) - return; - tp->rcv_nxt += len; - KASSERT(toep->sb_cc >= sbused(sb), - ("%s: sb %p has more data (%d) than last time (%d).", - __func__, sb, sbused(sb), toep->sb_cc)); - toep->rx_credits += toep->sb_cc - sbused(sb); -#ifdef USE_DDP_RX_FLOW_CONTROL - toep->rx_credits -= len; /* adjust for F_RX_FC_DDP */ +#ifndef USE_DDP_RX_FLOW_CONTROL + toep->rx_credits += len; #endif - m = get_ddp_mbuf(len); + while (toep->ddp_active_count > 0) { + MPASS(toep->ddp_active_id != -1); + db_idx = toep->ddp_active_id; + db_flag = db_idx == 1 ? DDP_BUF1_ACTIVE : DDP_BUF0_ACTIVE; + MPASS((toep->ddp_flags & db_flag) != 0); + db = &toep->db[db_idx]; + job = db->job; + copied = job->uaiocb._aiocb_private.status; + placed = len; + if (placed > job->uaiocb.aio_nbytes - copied) + placed = job->uaiocb.aio_nbytes - copied; + if (!aio_clear_cancel_function(job)) { + /* + * Update the copied length for when + * t4_aio_cancel_active() completes this + * request. + */ + job->uaiocb._aiocb_private.status += placed; + } else { + CTR4(KTR_CXGBE, "%s: tid %d completed buf %d len %d", + __func__, toep->tid, db_idx, placed); + aio_complete(job, copied + placed, 0); + } + len -= placed; + complete_ddp_buffer(toep, db, db_idx); + } - sbappendstream_locked(sb, m, 0); - toep->sb_cc = sbused(sb); + MPASS(len == 0); + ddp_complete_all(toep, 0); } #define DDP_ERR (F_DDP_PPOD_MISMATCH | F_DDP_LLIMIT_ERR | F_DDP_ULIMIT_ERR |\ @@ -529,7 +822,7 @@ do_rx_ddp_complete(struct sge_iq *iq, const struct rss_header *rss, return (0); } -void +static void enable_ddp(struct adapter *sc, struct toepcb *toep) { @@ -540,6 +833,7 @@ enable_ddp(struct adapter *sc, struct toepcb *toep) CTR3(KTR_CXGBE, "%s: tid %u (time %u)", __func__, toep->tid, time_uptime); + DDP_ASSERT_LOCKED(toep); toep->ddp_flags |= DDP_SC_REQ; t4_set_tcb_field(sc, toep, 1, W_TCB_RX_DDP_FLAGS, V_TF_DDP_OFF(1) | V_TF_DDP_INDICATE_OUT(1) | @@ -550,81 +844,6 @@ enable_ddp(struct adapter *sc, struct toepcb *toep) V_TF_RCV_COALESCE_ENABLE(1), 0); } -static inline void -disable_ddp(struct adapter *sc, struct toepcb *toep) -{ - - KASSERT((toep->ddp_flags & (DDP_ON | DDP_SC_REQ)) == DDP_ON, - ("%s: toep %p has bad ddp_flags 0x%x", - __func__, toep, toep->ddp_flags)); - - CTR3(KTR_CXGBE, "%s: tid %u (time %u)", - __func__, toep->tid, time_uptime); - - toep->ddp_flags |= DDP_SC_REQ; - t4_set_tcb_field(sc, toep, 1, W_TCB_T_FLAGS, - V_TF_RCV_COALESCE_ENABLE(1), V_TF_RCV_COALESCE_ENABLE(1)); - t4_set_tcb_field(sc, toep, 1, W_TCB_RX_DDP_FLAGS, V_TF_DDP_OFF(1), - V_TF_DDP_OFF(1)); -} - -static int -hold_uio(struct uio *uio, vm_page_t **ppages, int *pnpages) -{ - struct vm_map *map; - struct iovec *iov; - vm_offset_t start, end; - vm_page_t *pp; - int n; - - KASSERT(uio->uio_iovcnt == 1, - ("%s: uio_iovcnt %d", __func__, uio->uio_iovcnt)); - KASSERT(uio->uio_td->td_proc == curproc, - ("%s: uio proc (%p) is not curproc (%p)", - __func__, uio->uio_td->td_proc, curproc)); - - map = &curproc->p_vmspace->vm_map; - iov = &uio->uio_iov[0]; - start = trunc_page((uintptr_t)iov->iov_base); - end = round_page((vm_offset_t)iov->iov_base + iov->iov_len); - n = howmany(end - start, PAGE_SIZE); - - if (end - start > MAX_DDP_BUFFER_SIZE) - return (E2BIG); - - pp = malloc(n * sizeof(vm_page_t), M_CXGBE, M_NOWAIT); - if (pp == NULL) - return (ENOMEM); - - if (vm_fault_quick_hold_pages(map, (vm_offset_t)iov->iov_base, - iov->iov_len, VM_PROT_WRITE, pp, n) < 0) { - free(pp, M_CXGBE); - return (EFAULT); - } - - *ppages = pp; - *pnpages = n; - - return (0); -} - -static int -bufcmp(struct ddp_buffer *db, vm_page_t *pages, int npages, int offset, int len) -{ - int i; - - if (db == NULL || db->npages != npages || db->offset != offset || - db->len != len) - return (1); - - for (i = 0; i < npages; i++) { - if (pages[i]->phys_addr != db->pages[i]->phys_addr) - return (1); - } - - return (0); -} - static int calculate_hcf(int n1, int n2) { @@ -647,12 +866,13 @@ calculate_hcf(int n1, int n2) return (b); } -static struct ddp_buffer * -alloc_ddp_buffer(struct tom_data *td, vm_page_t *pages, int npages, int offset, - int len) +static int +alloc_page_pods(struct tom_data *td, struct pageset *ps) { int i, hcf, seglen, idx, ppod, nppods; - struct ddp_buffer *db; + u_int ppod_addr; + + KASSERT(ps->nppods == 0, ("%s: page pods already allocated", __func__)); /* * The DDP page size is unrelated to the VM page size. We combine @@ -662,10 +882,11 @@ alloc_ddp_buffer(struct tom_data *td, vm_page_t *pages, int npages, int offset, * the page list. */ hcf = 0; - for (i = 0; i < npages; i++) { + for (i = 0; i < ps->npages; i++) { seglen = PAGE_SIZE; - while (i < npages - 1 && - pages[i]->phys_addr + PAGE_SIZE == pages[i + 1]->phys_addr) { + while (i < ps->npages - 1 && + ps->pages[i]->phys_addr + PAGE_SIZE == + ps->pages[i + 1]->phys_addr) { seglen += PAGE_SIZE; i++; } @@ -683,7 +904,7 @@ alloc_ddp_buffer(struct tom_data *td, vm_page_t *pages, int npages, int offset, ("%s: PAGE_SIZE %d, hcf %d", __func__, PAGE_SIZE, hcf)); CTR3(KTR_CXGBE, "%s: PAGE_SIZE %d, hcf %d", __func__, PAGE_SIZE, hcf); - return (NULL); + return (0); } for (idx = nitems(t4_ddp_pgsz) - 1; idx > 0; idx--) { @@ -693,40 +914,29 @@ alloc_ddp_buffer(struct tom_data *td, vm_page_t *pages, int npages, int offset, have_pgsz: MPASS(idx <= M_PPOD_PGSZ); - db = malloc(sizeof(*db), M_CXGBE, M_NOWAIT); - if (db == NULL) { - CTR1(KTR_CXGBE, "%s: malloc failed.", __func__); - return (NULL); - } - - nppods = pages_to_nppods(npages, t4_ddp_pgsz[idx]); - if (alloc_ppods(td, nppods, &db->ppod_addr) != 0) { - free(db, M_CXGBE); - CTR4(KTR_CXGBE, "%s: no pods, nppods %d, resid %d, pgsz %d", - __func__, nppods, len, t4_ddp_pgsz[idx]); - return (NULL); + nppods = pages_to_nppods(ps->npages, t4_ddp_pgsz[idx]); + if (alloc_ppods(td, nppods, &ppod_addr) != 0) { + CTR4(KTR_CXGBE, "%s: no pods, nppods %d, npages %d, pgsz %d", + __func__, nppods, ps->npages, t4_ddp_pgsz[idx]); + return (0); } - ppod = (db->ppod_addr - td->ppod_start) / PPOD_SIZE; - db->tag = V_PPOD_PGSZ(idx) | V_PPOD_TAG(ppod); - db->nppods = nppods; - db->npages = npages; - db->pages = pages; - db->offset = offset; - db->len = len; + ppod = (ppod_addr - td->ppod_start) / PPOD_SIZE; + ps->tag = V_PPOD_PGSZ(idx) | V_PPOD_TAG(ppod); + ps->ppod_addr = ppod_addr; + ps->nppods = nppods; - CTR6(KTR_CXGBE, "New DDP buffer. " - "ddp_pgsz %d, ppod 0x%x, npages %d, nppods %d, offset %d, len %d", - t4_ddp_pgsz[idx], ppod, db->npages, db->nppods, db->offset, - db->len); + CTR5(KTR_CXGBE, "New page pods. " + "ps %p, ddp_pgsz %d, ppod 0x%x, npages %d, nppods %d", + ps, t4_ddp_pgsz[idx], ppod, ps->npages, ps->nppods); - return (db); + return (1); } #define NUM_ULP_TX_SC_IMM_PPODS (256 / PPOD_SIZE) static int -write_page_pods(struct adapter *sc, struct toepcb *toep, struct ddp_buffer *db) +write_page_pods(struct adapter *sc, struct toepcb *toep, struct pageset *ps) { struct wrqe *wr; struct ulp_mem_io *ulpmc; @@ -736,17 +946,20 @@ write_page_pods(struct adapter *sc, struct toepcb *toep, struct ddp_buffer *db) u_int ppod_addr; uint32_t cmd; + KASSERT(!(ps->flags & PS_PPODS_WRITTEN), + ("%s: page pods already written", __func__)); + cmd = htobe32(V_ULPTX_CMD(ULP_TX_MEM_WRITE)); if (is_t4(sc)) cmd |= htobe32(F_ULP_MEMIO_ORDER); else cmd |= htobe32(F_T5_ULP_MEMIO_IMM); - ddp_pgsz = t4_ddp_pgsz[G_PPOD_PGSZ(db->tag)]; - ppod_addr = db->ppod_addr; - for (i = 0; i < db->nppods; ppod_addr += chunk) { + ddp_pgsz = t4_ddp_pgsz[G_PPOD_PGSZ(ps->tag)]; + ppod_addr = ps->ppod_addr; + for (i = 0; i < ps->nppods; ppod_addr += chunk) { /* How many page pods are we writing in this cycle */ - n = min(db->nppods - i, NUM_ULP_TX_SC_IMM_PPODS); + n = min(ps->nppods - i, NUM_ULP_TX_SC_IMM_PPODS); chunk = PPOD_SZ(n); len = roundup2(sizeof(*ulpmc) + sizeof(*ulpsc) + chunk, 16); @@ -768,15 +981,15 @@ write_page_pods(struct adapter *sc, struct toepcb *toep, struct ddp_buffer *db) ppod = (struct pagepod *)(ulpsc + 1); for (j = 0; j < n; i++, j++, ppod++) { ppod->vld_tid_pgsz_tag_color = htobe64(F_PPOD_VALID | - V_PPOD_TID(toep->tid) | db->tag); - ppod->len_offset = htobe64(V_PPOD_LEN(db->len) | - V_PPOD_OFST(db->offset)); + V_PPOD_TID(toep->tid) | ps->tag); + ppod->len_offset = htobe64(V_PPOD_LEN(ps->len) | + V_PPOD_OFST(ps->offset)); ppod->rsvd = 0; idx = i * PPOD_PAGES * (ddp_pgsz / PAGE_SIZE); for (k = 0; k < nitems(ppod->addr); k++) { - if (idx < db->npages) { + if (idx < ps->npages) { ppod->addr[k] = - htobe64(db->pages[idx]->phys_addr); + htobe64(ps->pages[idx]->phys_addr); idx += ddp_pgsz / PAGE_SIZE; } else ppod->addr[k] = 0; @@ -792,188 +1005,53 @@ write_page_pods(struct adapter *sc, struct toepcb *toep, struct ddp_buffer *db) t4_wrq_tx(sc, wr); } + ps->flags |= PS_PPODS_WRITTEN; return (0); } -/* - * Reuse, or allocate (and program the page pods for) a new DDP buffer. The - * "pages" array is handed over to this function and should not be used in any - * way by the caller after that. - */ -static int -select_ddp_buffer(struct adapter *sc, struct toepcb *toep, vm_page_t *pages, - int npages, int db_off, int db_len) -{ - struct ddp_buffer *db; - struct tom_data *td = sc->tom_softc; - int i, empty_slot = -1; - - /* Try to reuse */ - for (i = 0; i < nitems(toep->db); i++) { - if (bufcmp(toep->db[i], pages, npages, db_off, db_len) == 0) { - free(pages, M_CXGBE); - return (i); /* pages still held */ - } else if (toep->db[i] == NULL && empty_slot < 0) - empty_slot = i; - } - - /* Allocate new buffer, write its page pods. */ - db = alloc_ddp_buffer(td, pages, npages, db_off, db_len); - if (db == NULL) { - vm_page_unhold_pages(pages, npages); - free(pages, M_CXGBE); - return (-1); - } - if (write_page_pods(sc, toep, db) != 0) { - vm_page_unhold_pages(pages, npages); - free_ddp_buffer(td, db); - return (-1); - } - - i = empty_slot; - if (i < 0) { - i = arc4random() % nitems(toep->db); - free_ddp_buffer(td, toep->db[i]); - } - toep->db[i] = db; - - CTR5(KTR_CXGBE, "%s: tid %d, DDP buffer[%d] = %p (tag 0x%x)", - __func__, toep->tid, i, db, db->tag); - - return (i); -} - static void -wire_ddp_buffer(struct ddp_buffer *db) +wire_pageset(struct pageset *ps) { - int i; vm_page_t p; + int i; + + KASSERT(!(ps->flags & PS_WIRED), ("pageset already wired")); - for (i = 0; i < db->npages; i++) { - p = db->pages[i]; + for (i = 0; i < ps->npages; i++) { + p = ps->pages[i]; vm_page_lock(p); vm_page_wire(p); vm_page_unhold(p); vm_page_unlock(p); } + ps->flags |= PS_WIRED; } -static void -unwire_ddp_buffer(struct ddp_buffer *db) +/* + * Prepare a pageset for DDP. This wires the pageset and sets up page + * pods. + */ +static int +prep_pageset(struct adapter *sc, struct toepcb *toep, struct pageset *ps) { - int i; - vm_page_t p; + struct tom_data *td = sc->tom_softc; - for (i = 0; i < db->npages; i++) { - p = db->pages[i]; - vm_page_lock(p); - vm_page_unwire(p, PQ_INACTIVE); - vm_page_unlock(p); + if (!(ps->flags & PS_WIRED)) + wire_pageset(ps); + if (ps->nppods == 0 && !alloc_page_pods(td, ps)) { + return (0); } + if (!(ps->flags & PS_PPODS_WRITTEN) && + write_page_pods(sc, toep, ps) != 0) { + return (0); + } + + return (1); } -static int -handle_ddp(struct socket *so, struct uio *uio, int flags, int error) -{ - struct sockbuf *sb = &so->so_rcv; - struct tcpcb *tp = so_sototcpcb(so); - struct toepcb *toep = tp->t_toe; - struct adapter *sc = td_adapter(toep->td); - vm_page_t *pages; - int npages, db_idx, rc, buf_flag; - struct ddp_buffer *db; - struct wrqe *wr; - uint64_t ddp_flags; - - SOCKBUF_LOCK_ASSERT(sb); - -#if 0 - if (sbused(sb) + sc->tt.ddp_thres > uio->uio_resid) { - CTR4(KTR_CXGBE, "%s: sb_cc %d, threshold %d, resid %d", - __func__, sbused(sb), sc->tt.ddp_thres, uio->uio_resid); - } -#endif - - /* XXX: too eager to disable DDP, could handle NBIO better than this. */ - if (sbused(sb) >= uio->uio_resid || uio->uio_resid < sc->tt.ddp_thres || - uio->uio_resid > MAX_DDP_BUFFER_SIZE || uio->uio_iovcnt > 1 || - so->so_state & SS_NBIO || flags & (MSG_DONTWAIT | MSG_NBIO) || - error || so->so_error || sb->sb_state & SBS_CANTRCVMORE) - goto no_ddp; - - /* - * Fault in and then hold the pages of the uio buffers. We'll wire them - * a bit later if everything else works out. - */ - SOCKBUF_UNLOCK(sb); - if (hold_uio(uio, &pages, &npages) != 0) { - SOCKBUF_LOCK(sb); - goto no_ddp; - } - SOCKBUF_LOCK(sb); - if (__predict_false(so->so_error || sb->sb_state & SBS_CANTRCVMORE)) { - vm_page_unhold_pages(pages, npages); - free(pages, M_CXGBE); - goto no_ddp; - } - - /* - * Figure out which one of the two DDP buffers to use this time. - */ - db_idx = select_ddp_buffer(sc, toep, pages, npages, - (uintptr_t)uio->uio_iov->iov_base & PAGE_MASK, uio->uio_resid); - pages = NULL; /* handed off to select_ddp_buffer */ - if (db_idx < 0) - goto no_ddp; - db = toep->db[db_idx]; - buf_flag = db_idx == 0 ? DDP_BUF0_ACTIVE : DDP_BUF1_ACTIVE; - - /* - * Build the compound work request that tells the chip where to DMA the - * payload. - */ - ddp_flags = select_ddp_flags(so, flags, db_idx); - wr = mk_update_tcb_for_ddp(sc, toep, db_idx, sbused(sb), ddp_flags); - if (wr == NULL) { - /* - * Just unhold the pages. The DDP buffer's software state is - * left as-is in the toep. The page pods were written - * successfully and we may have an opportunity to use it in the - * future. - */ - vm_page_unhold_pages(db->pages, db->npages); - goto no_ddp; - } - - /* Wire (and then unhold) the pages, and give the chip the go-ahead. */ - wire_ddp_buffer(db); - t4_wrq_tx(sc, wr); - sb->sb_flags &= ~SB_DDP_INDICATE; - toep->ddp_flags |= buf_flag; - - /* - * Wait for the DDP operation to complete and then unwire the pages. - * The return code from the sbwait will be the final return code of this - * function. But we do need to wait for DDP no matter what. - */ - rc = sbwait(sb); - while (toep->ddp_flags & buf_flag) { - /* XXXGL: shouldn't here be sbwait() call? */ - sb->sb_flags |= SB_WAIT; - msleep(&sb->sb_acc, &sb->sb_mtx, PSOCK , "sbwait", 0); - } - unwire_ddp_buffer(db); - return (rc); -no_ddp: - disable_ddp(sc, toep); - discourage_ddp(toep); - sb->sb_flags &= ~SB_DDP_INDICATE; - return (0); -} - -void -t4_init_ddp(struct adapter *sc, struct tom_data *td) +void +t4_init_ddp(struct adapter *sc, struct tom_data *td) { td->ppod_start = sc->vres.ddp.start; @@ -994,287 +1072,689 @@ t4_uninit_ddp(struct adapter *sc __unused, struct tom_data *td) } } -#define VNET_SO_ASSERT(so) \ - VNET_ASSERT(curvnet != NULL, \ - ("%s:%d curvnet is NULL, so=%p", __func__, __LINE__, (so))); -#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? 0 : SBL_WAIT) static int -soreceive_rcvoob(struct socket *so, struct uio *uio, int flags) +pscmp(struct pageset *ps, struct vmspace *vm, vm_offset_t start, int npages, + int pgoff, int len) { - CXGBE_UNIMPLEMENTED(__func__); -} + if (ps->npages != npages || ps->offset != pgoff || ps->len != len) + return (1); -static char ddp_magic_str[] = "nothing to see here"; + return (ps->vm != vm || ps->vm_timestamp != vm->vm_map.timestamp); +} -static struct mbuf * -get_ddp_mbuf(int len) +static int +hold_aio(struct toepcb *toep, struct kaiocb *job, struct pageset **pps) { - struct mbuf *m; + struct vmspace *vm; + vm_map_t map; + vm_offset_t start, end, pgoff; + struct pageset *ps; + int n; - m = m_get(M_NOWAIT, MT_DATA); - if (m == NULL) - CXGBE_UNIMPLEMENTED("mbuf alloc failure"); - m->m_len = len; - m->m_data = &ddp_magic_str[0]; + DDP_ASSERT_LOCKED(toep); - return (m); -} - -static inline int -is_ddp_mbuf(struct mbuf *m) -{ + /* + * The AIO subsystem will cancel and drain all requests before + * permitting a process to exit or exec, so p_vmspace should + * be stable here. + */ + vm = job->userproc->p_vmspace; + map = &vm->vm_map; + start = (uintptr_t)job->uaiocb.aio_buf; + pgoff = start & PAGE_MASK; + end = round_page(start + job->uaiocb.aio_nbytes); + start = trunc_page(start); + + if (end - start > MAX_DDP_BUFFER_SIZE) { + /* + * Truncate the request to a short read. + * Alternatively, we could DDP in chunks to the larger + * buffer, but that would be quite a bit more work. + * + * When truncating, round the request down to avoid + * crossing a cache line on the final transaction. + */ + end = rounddown2(start + MAX_DDP_BUFFER_SIZE, CACHE_LINE_SIZE); +#ifdef VERBOSE_TRACES + CTR4(KTR_CXGBE, "%s: tid %d, truncating size from %lu to %lu", + __func__, toep->tid, (unsigned long)job->uaiocb.aio_nbytes, + (unsigned long)(end - (start + pgoff))); + job->uaiocb.aio_nbytes = end - (start + pgoff); +#endif + end = round_page(end); + } - return (m->m_data == &ddp_magic_str[0]); -} + n = atop(end - start); -/* - * Copy an mbuf chain into a uio limited by len if set. - */ -static int -m_mbuftouio_ddp(struct uio *uio, struct mbuf *m, int len) -{ - int error, length, total; - int progress = 0; + /* + * Try to reuse a cached pageset. + */ + TAILQ_FOREACH(ps, &toep->ddp_cached_pagesets, link) { + if (pscmp(ps, vm, start, n, pgoff, + job->uaiocb.aio_nbytes) == 0) { + TAILQ_REMOVE(&toep->ddp_cached_pagesets, ps, link); + toep->ddp_cached_count--; + *pps = ps; + return (0); + } + } - if (len > 0) - total = min(uio->uio_resid, len); - else - total = uio->uio_resid; + /* + * If there are too many cached pagesets to create a new one, + * free a pageset before creating a new one. + */ + KASSERT(toep->ddp_active_count + toep->ddp_cached_count <= + nitems(toep->db), ("%s: too many wired pagesets", __func__)); + if (toep->ddp_active_count + toep->ddp_cached_count == + nitems(toep->db)) { + KASSERT(toep->ddp_cached_count > 0, + ("no cached pageset to free")); + ps = TAILQ_LAST(&toep->ddp_cached_pagesets, pagesetq); + TAILQ_REMOVE(&toep->ddp_cached_pagesets, ps, link); + toep->ddp_cached_count--; + free_pageset(toep->td, ps); + } + DDP_UNLOCK(toep); + + /* Create a new pageset. */ + ps = malloc(sizeof(*ps) + n * sizeof(vm_page_t), M_CXGBE, M_WAITOK | + M_ZERO); + ps->pages = (vm_page_t *)(ps + 1); + ps->vm_timestamp = map->timestamp; + ps->npages = vm_fault_quick_hold_pages(map, start, end - start, + VM_PROT_WRITE, ps->pages, n); + + DDP_LOCK(toep); + if (ps->npages < 0) { + free(ps, M_CXGBE); + return (EFAULT); + } - /* Fill the uio with data from the mbufs. */ - for (; m != NULL; m = m->m_next) { - length = min(m->m_len, total - progress); + KASSERT(ps->npages == n, ("hold_aio: page count mismatch: %d vs %d", + ps->npages, n)); - if (is_ddp_mbuf(m)) { - enum uio_seg segflag = uio->uio_segflg; + ps->offset = pgoff; + ps->len = job->uaiocb.aio_nbytes; + atomic_add_int(&vm->vm_refcnt, 1); + ps->vm = vm; - uio->uio_segflg = UIO_NOCOPY; - error = uiomove(mtod(m, void *), length, uio); - uio->uio_segflg = segflag; - } else - error = uiomove(mtod(m, void *), length, uio); - if (error) - return (error); + CTR5(KTR_CXGBE, "%s: tid %d, new pageset %p for job %p, npages %d", + __func__, toep->tid, ps, job, ps->npages); + *pps = ps; + return (0); +} - progress += length; +static void +ddp_complete_all(struct toepcb *toep, int error) +{ + struct kaiocb *job; + + DDP_ASSERT_LOCKED(toep); + while (!TAILQ_EMPTY(&toep->ddp_aiojobq)) { + job = TAILQ_FIRST(&toep->ddp_aiojobq); + TAILQ_REMOVE(&toep->ddp_aiojobq, job, list); + toep->ddp_waiting_count--; + if (aio_clear_cancel_function(job)) + ddp_complete_one(job, error); } +} - return (0); +static void +aio_ddp_cancel_one(struct kaiocb *job) +{ + long copied; + + /* + * If this job had copied data out of the socket buffer before + * it was cancelled, report it as a short read rather than an + * error. + */ + copied = job->uaiocb._aiocb_private.status; + if (copied != 0) + aio_complete(job, copied, 0); + else + aio_cancel(job); } /* - * Based on soreceive_stream() in uipc_socket.c + * Called when the main loop wants to requeue a job to retry it later. + * Deals with the race of the job being cancelled while it was being + * examined. */ -int -t4_soreceive_ddp(struct socket *so, struct sockaddr **psa, struct uio *uio, - struct mbuf **mp0, struct mbuf **controlp, int *flagsp) +static void +aio_ddp_requeue_one(struct toepcb *toep, struct kaiocb *job) +{ + + DDP_ASSERT_LOCKED(toep); + if (!(toep->ddp_flags & DDP_DEAD) && + aio_set_cancel_function(job, t4_aio_cancel_queued)) { + TAILQ_INSERT_HEAD(&toep->ddp_aiojobq, job, list); + toep->ddp_waiting_count++; + } else + aio_ddp_cancel_one(job); +} + +static void +aio_ddp_requeue(struct toepcb *toep) { - int len = 0, error = 0, flags, oresid, ddp_handled = 0; + struct adapter *sc = td_adapter(toep->td); + struct socket *so; struct sockbuf *sb; - struct mbuf *m, *n = NULL; - - /* We only do stream sockets. */ - if (so->so_type != SOCK_STREAM) - return (EINVAL); - if (psa != NULL) - *psa = NULL; - if (controlp != NULL) - return (EINVAL); - if (flagsp != NULL) - flags = *flagsp &~ MSG_EOR; - else - flags = 0; - if (flags & MSG_OOB) - return (soreceive_rcvoob(so, uio, flags)); - if (mp0 != NULL) - *mp0 = NULL; + struct inpcb *inp; + struct kaiocb *job; + struct ddp_buffer *db; + size_t copied, offset, resid; + struct pageset *ps; + struct mbuf *m; + uint64_t ddp_flags, ddp_flags_mask; + struct wrqe *wr; + int buf_flag, db_idx, error; - sb = &so->so_rcv; + DDP_ASSERT_LOCKED(toep); - /* Prevent other readers from entering the socket. */ - error = sblock(sb, SBLOCKWAIT(flags)); - SOCKBUF_LOCK(sb); - if (error) - goto out; +restart: + if (toep->ddp_flags & DDP_DEAD) { + MPASS(toep->ddp_waiting_count == 0); + MPASS(toep->ddp_active_count == 0); + return; + } - /* Easy one, no space to copyout anything. */ - if (uio->uio_resid == 0) { - error = EINVAL; - goto out; + if (toep->ddp_waiting_count == 0 || + toep->ddp_active_count == nitems(toep->db)) { + return; } - oresid = uio->uio_resid; - /* We will never ever get anything unless we are or were connected. */ + job = TAILQ_FIRST(&toep->ddp_aiojobq); + so = job->fd_file->f_data; + sb = &so->so_rcv; + SOCKBUF_LOCK(sb); + + /* We will never get anything unless we are or were connected. */ if (!(so->so_state & (SS_ISCONNECTED|SS_ISDISCONNECTED))) { - error = ENOTCONN; - goto out; + SOCKBUF_UNLOCK(sb); + ddp_complete_all(toep, ENOTCONN); + return; } -restart: - SOCKBUF_LOCK_ASSERT(&so->so_rcv); + KASSERT(toep->ddp_active_count == 0 || sbavail(sb) == 0, + ("%s: pending sockbuf data and DDP is active", __func__)); - if (sb->sb_flags & SB_DDP_INDICATE && !ddp_handled) { + /* Abort if socket has reported problems. */ + /* XXX: Wait for any queued DDP's to finish and/or flush them? */ + if (so->so_error && sbavail(sb) == 0) { + toep->ddp_waiting_count--; + TAILQ_REMOVE(&toep->ddp_aiojobq, job, list); + if (!aio_clear_cancel_function(job)) { + SOCKBUF_UNLOCK(sb); + goto restart; + } - /* uio should be just as it was at entry */ - KASSERT(oresid == uio->uio_resid, - ("%s: oresid = %d, uio_resid = %zd, sbavail = %d", - __func__, oresid, uio->uio_resid, sbavail(sb))); + /* + * If this job has previously copied some data, report + * a short read and leave the error to be reported by + * a future request. + */ + copied = job->uaiocb._aiocb_private.status; + if (copied != 0) { + SOCKBUF_UNLOCK(sb); + aio_complete(job, copied, 0); + goto restart; + } + error = so->so_error; + so->so_error = 0; + SOCKBUF_UNLOCK(sb); + aio_complete(job, -1, error); + goto restart; + } - error = handle_ddp(so, uio, flags, 0); - ddp_handled = 1; - if (error) - goto out; + /* + * Door is closed. If there is pending data in the socket buffer, + * deliver it. If there are pending DDP requests, wait for those + * to complete. Once they have completed, return EOF reads. + */ + if (sb->sb_state & SBS_CANTRCVMORE && sbavail(sb) == 0) { + SOCKBUF_UNLOCK(sb); + if (toep->ddp_active_count != 0) + return; + ddp_complete_all(toep, 0); + return; } - /* Abort if socket has reported problems. */ - if (so->so_error) { - if (sbavail(sb)) - goto deliver; - if (oresid > uio->uio_resid) - goto out; - error = so->so_error; - if (!(flags & MSG_PEEK)) - so->so_error = 0; - goto out; + /* + * If DDP is not enabled and there is no pending socket buffer + * data, try to enable DDP. + */ + if (sbavail(sb) == 0 && (toep->ddp_flags & DDP_ON) == 0) { + SOCKBUF_UNLOCK(sb); + + /* + * Wait for the card to ACK that DDP is enabled before + * queueing any buffers. Currently this waits for an + * indicate to arrive. This could use a TCB_SET_FIELD_RPL + * message to know that DDP was enabled instead of waiting + * for the indicate which would avoid copying the indicate + * if no data is pending. + * + * XXX: Might want to limit the indicate size to the size + * of the first queued request. + */ + if ((toep->ddp_flags & DDP_SC_REQ) == 0) + enable_ddp(sc, toep); + return; } + SOCKBUF_UNLOCK(sb); - /* Door is closed. Deliver what is left, if any. */ - if (sb->sb_state & SBS_CANTRCVMORE) { - if (sbavail(sb)) - goto deliver; - else - goto out; + /* + * If another thread is queueing a buffer for DDP, let it + * drain any work and return. + */ + if (toep->ddp_queueing != NULL) + return; + + /* Take the next job to prep it for DDP. */ + toep->ddp_waiting_count--; + TAILQ_REMOVE(&toep->ddp_aiojobq, job, list); + if (!aio_clear_cancel_function(job)) + goto restart; + toep->ddp_queueing = job; + + /* NB: This drops DDP_LOCK while it holds the backing VM pages. */ + error = hold_aio(toep, job, &ps); + if (error != 0) { + ddp_complete_one(job, error); + toep->ddp_queueing = NULL; + goto restart; } - /* Socket buffer is empty and we shall not block. */ - if (sbavail(sb) == 0 && - ((so->so_state & SS_NBIO) || (flags & (MSG_DONTWAIT|MSG_NBIO)))) { - error = EAGAIN; - goto out; + SOCKBUF_LOCK(sb); + if (so->so_error && sbavail(sb) == 0) { + copied = job->uaiocb._aiocb_private.status; + if (copied != 0) { + SOCKBUF_UNLOCK(sb); + recycle_pageset(toep, ps); + aio_complete(job, copied, 0); + toep->ddp_queueing = NULL; + goto restart; + } + + error = so->so_error; + so->so_error = 0; + SOCKBUF_UNLOCK(sb); + recycle_pageset(toep, ps); + aio_complete(job, -1, error); + toep->ddp_queueing = NULL; + goto restart; } - /* Socket buffer got some data that we shall deliver now. */ - if (sbavail(sb) > 0 && !(flags & MSG_WAITALL) && - ((so->so_state & SS_NBIO) || - (flags & (MSG_DONTWAIT|MSG_NBIO)) || - sbavail(sb) >= sb->sb_lowat || - sbavail(sb) >= uio->uio_resid || - sbavail(sb) >= sb->sb_hiwat) ) { - goto deliver; + if (sb->sb_state & SBS_CANTRCVMORE && sbavail(sb) == 0) { + SOCKBUF_UNLOCK(sb); + recycle_pageset(toep, ps); + if (toep->ddp_active_count != 0) { + /* + * The door is closed, but there are still pending + * DDP buffers. Requeue. These jobs will all be + * completed once those buffers drain. + */ + aio_ddp_requeue_one(toep, job); + toep->ddp_queueing = NULL; + return; + } + ddp_complete_one(job, 0); + ddp_complete_all(toep, 0); + toep->ddp_queueing = NULL; + return; } - /* On MSG_WAITALL we must wait until all data or error arrives. */ - if ((flags & MSG_WAITALL) && - (sbavail(sb) >= uio->uio_resid || sbavail(sb) >= sb->sb_lowat)) - goto deliver; +sbcopy: + /* + * If the toep is dead, there shouldn't be any data in the socket + * buffer, so the above case should have handled this. + */ + MPASS(!(toep->ddp_flags & DDP_DEAD)); /* - * Wait and block until (more) data comes in. - * NB: Drops the sockbuf lock during wait. + * If there is pending data in the socket buffer (either + * from before the requests were queued or a DDP indicate), + * copy those mbufs out directly. */ - error = sbwait(sb); - if (error) { - if (sb->sb_flags & SB_DDP_INDICATE && !ddp_handled) { - (void) handle_ddp(so, uio, flags, 1); - ddp_handled = 1; + copied = 0; + offset = ps->offset + job->uaiocb._aiocb_private.status; + MPASS(job->uaiocb._aiocb_private.status <= job->uaiocb.aio_nbytes); + resid = job->uaiocb.aio_nbytes - job->uaiocb._aiocb_private.status; + m = sb->sb_mb; + KASSERT(m == NULL || toep->ddp_active_count == 0, + ("%s: sockbuf data with active DDP", __func__)); + while (m != NULL && resid > 0) { + struct iovec iov[1]; + struct uio uio; + int error; + + iov[0].iov_base = mtod(m, void *); + iov[0].iov_len = m->m_len; + if (iov[0].iov_len > resid) + iov[0].iov_len = resid; + uio.uio_iov = iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = iov[0].iov_len; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_WRITE; + error = uiomove_fromphys(ps->pages, offset + copied, + uio.uio_resid, &uio); + MPASS(error == 0 && uio.uio_resid == 0); + copied += uio.uio_offset; + resid -= uio.uio_offset; + m = m->m_next; + } + if (copied != 0) { + sbdrop_locked(sb, copied); + job->uaiocb._aiocb_private.status += copied; + copied = job->uaiocb._aiocb_private.status; + inp = sotoinpcb(so); + if (!INP_TRY_WLOCK(inp)) { + /* + * The reference on the socket file descriptor in + * the AIO job should keep 'sb' and 'inp' stable. + * Our caller has a reference on the 'toep' that + * keeps it stable. + */ + SOCKBUF_UNLOCK(sb); + DDP_UNLOCK(toep); + INP_WLOCK(inp); + DDP_LOCK(toep); + SOCKBUF_LOCK(sb); + + /* + * If the socket has been closed, we should detect + * that and complete this request if needed on + * the next trip around the loop. + */ } - goto out; + t4_rcvd_locked(&toep->td->tod, intotcpcb(inp)); + INP_WUNLOCK(inp); + if (resid == 0 || toep->ddp_flags & DDP_DEAD) { + /* + * We filled the entire buffer with socket + * data, DDP is not being used, or the socket + * is being shut down, so complete the + * request. + */ + SOCKBUF_UNLOCK(sb); + recycle_pageset(toep, ps); + aio_complete(job, copied, 0); + toep->ddp_queueing = NULL; + goto restart; + } + + /* + * If DDP is not enabled, requeue this request and restart. + * This will either enable DDP or wait for more data to + * arrive on the socket buffer. + */ + if ((toep->ddp_flags & (DDP_ON | DDP_SC_REQ)) != DDP_ON) { + SOCKBUF_UNLOCK(sb); + recycle_pageset(toep, ps); + aio_ddp_requeue_one(toep, job); + toep->ddp_queueing = NULL; + goto restart; + } + + /* + * An indicate might have arrived and been added to + * the socket buffer while it was unlocked after the + * copy to lock the INP. If so, restart the copy. + */ + if (sbavail(sb) != 0) + goto sbcopy; } - goto restart; + SOCKBUF_UNLOCK(sb); -deliver: - SOCKBUF_LOCK_ASSERT(&so->so_rcv); - KASSERT(sbavail(sb) > 0, ("%s: sockbuf empty", __func__)); - KASSERT(sb->sb_mb != NULL, ("%s: sb_mb == NULL", __func__)); + if (prep_pageset(sc, toep, ps) == 0) { + recycle_pageset(toep, ps); + aio_ddp_requeue_one(toep, job); + toep->ddp_queueing = NULL; - if (sb->sb_flags & SB_DDP_INDICATE && !ddp_handled) - goto restart; + /* + * XXX: Need to retry this later. Mostly need a trigger + * when page pods are freed up. + */ + printf("%s: prep_pageset failed\n", __func__); + return; + } - /* Statistics. */ - if (uio->uio_td) - uio->uio_td->td_ru.ru_msgrcv++; - - /* Fill uio until full or current end of socket buffer is reached. */ - len = min(uio->uio_resid, sbavail(sb)); - if (mp0 != NULL) { - /* Dequeue as many mbufs as possible. */ - if (!(flags & MSG_PEEK) && len >= sb->sb_mb->m_len) { - for (*mp0 = m = sb->sb_mb; - m != NULL && m->m_len <= len; - m = m->m_next) { - len -= m->m_len; - uio->uio_resid -= m->m_len; - sbfree(sb, m); - n = m; - } - sb->sb_mb = m; - if (sb->sb_mb == NULL) - SB_EMPTY_FIXUP(sb); - n->m_next = NULL; - } - /* Copy the remainder. */ - if (len > 0) { - KASSERT(sb->sb_mb != NULL, - ("%s: len > 0 && sb->sb_mb empty", __func__)); - - m = m_copym(sb->sb_mb, 0, len, M_NOWAIT); - if (m == NULL) - len = 0; /* Don't flush data from sockbuf. */ - else - uio->uio_resid -= m->m_len; - if (*mp0 != NULL) - n->m_next = m; - else - *mp0 = m; - if (*mp0 == NULL) { - error = ENOBUFS; - goto out; - } - } + /* Determine which DDP buffer to use. */ + if (toep->db[0].job == NULL) { + db_idx = 0; } else { - /* NB: Must unlock socket buffer as uiomove may sleep. */ - SOCKBUF_UNLOCK(sb); - error = m_mbuftouio_ddp(uio, sb->sb_mb, len); - SOCKBUF_LOCK(sb); - if (error) - goto out; + MPASS(toep->db[1].job == NULL); + db_idx = 1; + } + + ddp_flags = 0; + ddp_flags_mask = 0; + if (db_idx == 0) { + ddp_flags |= V_TF_DDP_BUF0_VALID(1); + if (so->so_state & SS_NBIO) + ddp_flags |= V_TF_DDP_BUF0_FLUSH(1); + ddp_flags_mask |= V_TF_DDP_PSH_NO_INVALIDATE0(1) | + V_TF_DDP_PUSH_DISABLE_0(1) | V_TF_DDP_PSHF_ENABLE_0(1) | + V_TF_DDP_BUF0_FLUSH(1) | V_TF_DDP_BUF0_VALID(1); + buf_flag = DDP_BUF0_ACTIVE; + } else { + ddp_flags |= V_TF_DDP_BUF1_VALID(1); + if (so->so_state & SS_NBIO) + ddp_flags |= V_TF_DDP_BUF1_FLUSH(1); + ddp_flags_mask |= V_TF_DDP_PSH_NO_INVALIDATE1(1) | + V_TF_DDP_PUSH_DISABLE_1(1) | V_TF_DDP_PSHF_ENABLE_1(1) | + V_TF_DDP_BUF1_FLUSH(1) | V_TF_DDP_BUF1_VALID(1); + buf_flag = DDP_BUF1_ACTIVE; + } + MPASS((toep->ddp_flags & buf_flag) == 0); + if ((toep->ddp_flags & (DDP_BUF0_ACTIVE | DDP_BUF1_ACTIVE)) == 0) { + MPASS(db_idx == 0); + MPASS(toep->ddp_active_id == -1); + MPASS(toep->ddp_active_count == 0); + ddp_flags_mask |= V_TF_DDP_ACTIVE_BUF(1); } - SBLASTRECORDCHK(sb); - SBLASTMBUFCHK(sb); /* - * Remove the delivered data from the socket buffer unless we - * were only peeking. + * The TID for this connection should still be valid. If DDP_DEAD + * is set, SBS_CANTRCVMORE should be set, so we shouldn't be + * this far anyway. Even if the socket is closing on the other + * end, the AIO job holds a reference on this end of the socket + * which will keep it open and keep the TCP PCB attached until + * after the job is completed. */ - if (!(flags & MSG_PEEK)) { - if (len > 0) - sbdrop_locked(sb, len); - - /* Notify protocol that we drained some data. */ - if ((so->so_proto->pr_flags & PR_WANTRCVD) && - (((flags & MSG_WAITALL) && uio->uio_resid > 0) || - !(flags & MSG_SOCALLBCK))) { - SOCKBUF_UNLOCK(sb); - VNET_SO_ASSERT(so); - (*so->so_proto->pr_usrreqs->pru_rcvd)(so, flags); - SOCKBUF_LOCK(sb); + wr = mk_update_tcb_for_ddp(sc, toep, db_idx, ps, + job->uaiocb._aiocb_private.status, ddp_flags, ddp_flags_mask); + if (wr == NULL) { + recycle_pageset(toep, ps); + aio_ddp_requeue_one(toep, job); + toep->ddp_queueing = NULL; + + /* + * XXX: Need a way to kick a retry here. + * + * XXX: We know the fixed size needed and could + * preallocate this using a blocking request at the + * start of the task to avoid having to handle this + * edge case. + */ + printf("%s: mk_update_tcb_for_ddp failed\n", __func__); + return; + } + + if (!aio_set_cancel_function(job, t4_aio_cancel_active)) { + free_wrqe(wr); + recycle_pageset(toep, ps); + aio_ddp_cancel_one(job); + toep->ddp_queueing = NULL; + goto restart; + } + +#ifdef VERBOSE_TRACES + CTR5(KTR_CXGBE, "%s: scheduling %p for DDP[%d] (flags %#lx/%#lx)", + __func__, job, db_idx, ddp_flags, ddp_flags_mask); +#endif + /* Give the chip the go-ahead. */ + t4_wrq_tx(sc, wr); + db = &toep->db[db_idx]; + db->cancel_pending = 0; + db->job = job; + db->ps = ps; + toep->ddp_queueing = NULL; + toep->ddp_flags |= buf_flag; + toep->ddp_active_count++; + if (toep->ddp_active_count == 1) { + MPASS(toep->ddp_active_id == -1); + toep->ddp_active_id = db_idx; + CTR2(KTR_CXGBE, "%s: ddp_active_id = %d", __func__, + toep->ddp_active_id); + } + goto restart; +} + +void +ddp_queue_toep(struct toepcb *toep) +{ + + DDP_ASSERT_LOCKED(toep); + if (toep->ddp_flags & DDP_TASK_ACTIVE) + return; + toep->ddp_flags |= DDP_TASK_ACTIVE; + hold_toepcb(toep); + soaio_enqueue(&toep->ddp_requeue_task); +} + +static void +aio_ddp_requeue_task(void *context, int pending) +{ + struct toepcb *toep = context; + + DDP_LOCK(toep); + aio_ddp_requeue(toep); + toep->ddp_flags &= ~DDP_TASK_ACTIVE; + DDP_UNLOCK(toep); + + free_toepcb(toep); +} + +static void +t4_aio_cancel_active(struct kaiocb *job) +{ + struct socket *so = job->fd_file->f_data; + struct tcpcb *tp = so_sototcpcb(so); + struct toepcb *toep = tp->t_toe; + struct adapter *sc = td_adapter(toep->td); + uint64_t valid_flag; + int i; + + DDP_LOCK(toep); + if (aio_cancel_cleared(job)) { + DDP_UNLOCK(toep); + aio_ddp_cancel_one(job); + return; + } + + for (i = 0; i < nitems(toep->db); i++) { + if (toep->db[i].job == job) { + /* Should only ever get one cancel request for a job. */ + MPASS(toep->db[i].cancel_pending == 0); + + /* + * Invalidate this buffer. It will be + * cancelled or partially completed once the + * card ACKs the invalidate. + */ + valid_flag = i == 0 ? V_TF_DDP_BUF0_VALID(1) : + V_TF_DDP_BUF1_VALID(1); + t4_set_tcb_field_rpl(sc, toep, 1, W_TCB_RX_DDP_FLAGS, + valid_flag, 0, i + DDP_BUF0_INVALIDATED); + toep->db[i].cancel_pending = 1; + CTR2(KTR_CXGBE, "%s: request %p marked pending", + __func__, job); + break; } } + DDP_UNLOCK(toep); +} + +static void +t4_aio_cancel_queued(struct kaiocb *job) +{ + struct socket *so = job->fd_file->f_data; + struct tcpcb *tp = so_sototcpcb(so); + struct toepcb *toep = tp->t_toe; + + DDP_LOCK(toep); + if (!aio_cancel_cleared(job)) { + TAILQ_REMOVE(&toep->ddp_aiojobq, job, list); + toep->ddp_waiting_count--; + if (toep->ddp_waiting_count == 0) + ddp_queue_toep(toep); + } + CTR2(KTR_CXGBE, "%s: request %p cancelled", __func__, job); + DDP_UNLOCK(toep); + + aio_ddp_cancel_one(job); +} + +int +t4_aio_queue_ddp(struct socket *so, struct kaiocb *job) +{ + struct tcpcb *tp = so_sototcpcb(so); + struct toepcb *toep = tp->t_toe; + + + /* Ignore writes. */ + if (job->uaiocb.aio_lio_opcode != LIO_READ) + return (EOPNOTSUPP); + + DDP_LOCK(toep); /* - * For MSG_WAITALL we may have to loop again and wait for - * more data to come in. + * XXX: Think about possibly returning errors for ENOTCONN, + * etc. Perhaps the caller would only queue the request + * if it failed with EOPNOTSUPP? */ - if ((flags & MSG_WAITALL) && uio->uio_resid > 0) - goto restart; -out: - SOCKBUF_LOCK_ASSERT(sb); - SBLASTRECORDCHK(sb); - SBLASTMBUFCHK(sb); - SOCKBUF_UNLOCK(sb); - sbunlock(sb); - return (error); + +#ifdef VERBOSE_TRACES + CTR2(KTR_CXGBE, "%s: queueing %p", __func__, job); +#endif + if (!aio_set_cancel_function(job, t4_aio_cancel_queued)) + panic("new job was cancelled"); + TAILQ_INSERT_TAIL(&toep->ddp_aiojobq, job, list); + job->uaiocb._aiocb_private.status = 0; + toep->ddp_waiting_count++; + toep->ddp_flags |= DDP_OK; + + /* + * Try to handle this request synchronously. If this has + * to block because the task is running, it will just bail + * and let the task handle it instead. + */ + aio_ddp_requeue(toep); + DDP_UNLOCK(toep); + return (0); +} + +int +t4_ddp_mod_load(void) +{ + + TAILQ_INIT(&ddp_orphan_pagesets); + mtx_init(&ddp_orphan_pagesets_lock, "ddp orphans", NULL, MTX_DEF); + TASK_INIT(&ddp_orphan_task, 0, ddp_free_orphan_pagesets, NULL); + return (0); } +void +t4_ddp_mod_unload(void) +{ + + taskqueue_drain(taskqueue_thread, &ddp_orphan_task); + MPASS(TAILQ_EMPTY(&ddp_orphan_pagesets)); + mtx_destroy(&ddp_orphan_pagesets_lock); +} #endif diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c index fe7ec76..452c47e 100644 --- a/sys/dev/cxgbe/tom/t4_tom.c +++ b/sys/dev/cxgbe/tom/t4_tom.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -152,6 +153,7 @@ alloc_toepcb(struct vi_info *vi, int txqid, int rxqid, int flags) if (toep == NULL) return (NULL); + refcount_init(&toep->refcount, 1); toep->td = sc->tom_softc; toep->vi = vi; toep->tx_total = tx_credits; @@ -165,19 +167,32 @@ alloc_toepcb(struct vi_info *vi, int txqid, int rxqid, int flags) toep->txsd_avail = txsd_total; toep->txsd_pidx = 0; toep->txsd_cidx = 0; + ddp_init_toep(toep); return (toep); } +struct toepcb * +hold_toepcb(struct toepcb *toep) +{ + + refcount_acquire(&toep->refcount); + return (toep); +} + void free_toepcb(struct toepcb *toep) { + if (refcount_release(&toep->refcount) == 0) + return; + KASSERT(!(toep->flags & TPF_ATTACHED), ("%s: attached to an inpcb", __func__)); KASSERT(!(toep->flags & TPF_CPL_PENDING), ("%s: CPL pending", __func__)); + ddp_uninit_toep(toep); free(toep, M_CXGBE); } @@ -259,6 +274,8 @@ undo_offload_socket(struct socket *so) mtx_lock(&td->toep_list_lock); TAILQ_REMOVE(&td->toep_list, toep, link); mtx_unlock(&td->toep_list_lock); + + free_toepcb(toep); } static void @@ -283,9 +300,9 @@ release_offload_resources(struct toepcb *toep) */ MPASS(mbufq_len(&toep->ulp_pduq) == 0); MPASS(mbufq_len(&toep->ulp_pdu_reclaimq) == 0); - - if (toep->ulp_mode == ULP_MODE_TCPDDP) - release_ddp_resources(toep); +#ifdef INVARIANTS + ddp_assert_empty(toep); +#endif if (toep->l2te) t4_l2t_release(toep->l2te); @@ -389,6 +406,8 @@ final_cpl_received(struct toepcb *toep) CTR6(KTR_CXGBE, "%s: tid %d, toep %p (0x%x), inp %p (0x%x)", __func__, toep->tid, toep, toep->flags, inp, inp->inp_flags); + if (toep->ulp_mode == ULP_MODE_TCPDDP) + release_ddp_resources(toep); toep->inp = NULL; toep->flags &= ~TPF_CPL_PENDING; mbufq_drain(&toep->ulp_pdu_reclaimq); @@ -599,7 +618,6 @@ set_tcpddp_ulp_mode(struct toepcb *toep) toep->ulp_mode = ULP_MODE_TCPDDP; toep->ddp_flags = DDP_OK; - toep->ddp_score = DDP_LOW_SCORE; } int @@ -1109,12 +1127,16 @@ t4_tom_mod_load(void) int rc; struct protosw *tcp_protosw, *tcp6_protosw; + rc = t4_ddp_mod_load(); + if (rc != 0) + return (rc); + tcp_protosw = pffindproto(PF_INET, IPPROTO_TCP, SOCK_STREAM); if (tcp_protosw == NULL) return (ENOPROTOOPT); bcopy(tcp_protosw, &ddp_protosw, sizeof(ddp_protosw)); bcopy(tcp_protosw->pr_usrreqs, &ddp_usrreqs, sizeof(ddp_usrreqs)); - ddp_usrreqs.pru_soreceive = t4_soreceive_ddp; + ddp_usrreqs.pru_aio_queue = t4_aio_queue_ddp; ddp_protosw.pr_usrreqs = &ddp_usrreqs; tcp6_protosw = pffindproto(PF_INET6, IPPROTO_TCP, SOCK_STREAM); @@ -1122,7 +1144,7 @@ t4_tom_mod_load(void) return (ENOPROTOOPT); bcopy(tcp6_protosw, &ddp6_protosw, sizeof(ddp6_protosw)); bcopy(tcp6_protosw->pr_usrreqs, &ddp6_usrreqs, sizeof(ddp6_usrreqs)); - ddp6_usrreqs.pru_soreceive = t4_soreceive_ddp; + ddp6_usrreqs.pru_aio_queue = t4_aio_queue_ddp; ddp6_protosw.pr_usrreqs = &ddp6_usrreqs; TIMEOUT_TASK_INIT(taskqueue_thread, &clip_task, 0, t4_clip_task, NULL); @@ -1162,6 +1184,8 @@ t4_tom_mod_unload(void) taskqueue_cancel_timeout(taskqueue_thread, &clip_task, NULL); } + t4_ddp_mod_unload(); + return (0); } #endif /* TCP_OFFLOAD */ diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h index f61888d..09238a4 100644 --- a/sys/dev/cxgbe/tom/t4_tom.h +++ b/sys/dev/cxgbe/tom/t4_tom.h @@ -74,6 +74,8 @@ enum { DDP_ON = (1 << 2), /* DDP is turned on */ DDP_BUF0_ACTIVE = (1 << 3), /* buffer 0 in use (not invalidated) */ DDP_BUF1_ACTIVE = (1 << 4), /* buffer 1 in use (not invalidated) */ + DDP_TASK_ACTIVE = (1 << 5), /* requeue task is queued / running */ + DDP_DEAD = (1 << 6), /* toepcb is shutting down */ }; struct ofld_tx_sdesc { @@ -81,19 +83,36 @@ struct ofld_tx_sdesc { uint8_t tx_credits; /* firmware tx credits (unit is 16B) */ }; -struct ddp_buffer { - uint32_t tag; /* includes color, page pod addr, and DDP page size */ +struct pageset { + TAILQ_ENTRY(pageset) link; + vm_page_t *pages; + int npages; + int flags; u_int ppod_addr; int nppods; - int offset; + uint32_t tag; /* includes color, page pod addr, and DDP page size */ + int offset; /* offset in first page */ int len; - int npages; - vm_page_t *pages; + struct vmspace *vm; + u_int vm_timestamp; +}; + +TAILQ_HEAD(pagesetq, pageset); + +#define PS_WIRED 0x0001 /* Pages wired rather than held. */ +#define PS_PPODS_WRITTEN 0x0002 /* Page pods written to the card. */ + +struct ddp_buffer { + struct pageset *ps; + + struct kaiocb *job; + int cancel_pending; }; struct toepcb { TAILQ_ENTRY(toepcb) link; /* toep_list */ u_int flags; /* miscellaneous flags */ + int refcount; struct tom_data *td; struct inpcb *inp; /* backpointer to host stack's PCB */ struct vi_info *vi; /* virtual interface */ @@ -121,9 +140,16 @@ struct toepcb { struct mbufq ulp_pdu_reclaimq; u_int ddp_flags; - struct ddp_buffer *db[2]; - time_t ddp_disabled; - uint8_t ddp_score; + struct ddp_buffer db[2]; + TAILQ_HEAD(, pageset) ddp_cached_pagesets; + TAILQ_HEAD(, kaiocb) ddp_aiojobq; + u_int ddp_waiting_count; + u_int ddp_active_count; + u_int ddp_cached_count; + int ddp_active_id; /* the currently active DDP buffer */ + struct task ddp_requeue_task; + struct kaiocb *ddp_queueing; + struct mtx ddp_lock; /* Tx software descriptor */ uint8_t txsd_total; @@ -133,6 +159,10 @@ struct toepcb { struct ofld_tx_sdesc txsd[]; }; +#define DDP_LOCK(toep) mtx_lock(&(toep)->ddp_lock) +#define DDP_UNLOCK(toep) mtx_unlock(&(toep)->ddp_lock) +#define DDP_ASSERT_LOCKED(toep) mtx_assert(&(toep)->ddp_lock, MA_OWNED) + struct flowc_tx_params { uint32_t snd_nxt; uint32_t rcv_nxt; @@ -242,6 +272,7 @@ mbuf_ulp_submode(struct mbuf *m) /* t4_tom.c */ struct toepcb *alloc_toepcb(struct vi_info *, int, int, int); +struct toepcb *hold_toepcb(struct toepcb *); void free_toepcb(struct toepcb *); void offload_socket(struct socket *, struct toepcb *); void undo_offload_socket(struct socket *); @@ -289,11 +320,14 @@ void send_flowc_wr(struct toepcb *, struct flowc_tx_params *); void send_reset(struct adapter *, struct toepcb *, uint32_t); void make_established(struct toepcb *, uint32_t, uint32_t, uint16_t); void t4_rcvd(struct toedev *, struct tcpcb *); +void t4_rcvd_locked(struct toedev *, struct tcpcb *); int t4_tod_output(struct toedev *, struct tcpcb *); int t4_send_fin(struct toedev *, struct tcpcb *); int t4_send_rst(struct toedev *, struct tcpcb *); void t4_set_tcb_field(struct adapter *, struct toepcb *, int, uint16_t, uint64_t, uint64_t); +void t4_set_tcb_field_rpl(struct adapter *, struct toepcb *, int, uint16_t, + uint64_t, uint64_t, uint8_t); void t4_push_frames(struct adapter *sc, struct toepcb *toep, int drop); void t4_push_pdus(struct adapter *sc, struct toepcb *toep, int drop); @@ -302,10 +336,17 @@ void t4_init_ddp(struct adapter *, struct tom_data *); void t4_uninit_ddp(struct adapter *, struct tom_data *); int t4_soreceive_ddp(struct socket *, struct sockaddr **, struct uio *, struct mbuf **, struct mbuf **, int *); -void enable_ddp(struct adapter *, struct toepcb *toep); +int t4_aio_queue_ddp(struct socket *, struct kaiocb *); +int t4_ddp_mod_load(void); +void t4_ddp_mod_unload(void); +void ddp_assert_empty(struct toepcb *); +void ddp_init_toep(struct toepcb *); +void ddp_uninit_toep(struct toepcb *); +void ddp_queue_toep(struct toepcb *); void release_ddp_resources(struct toepcb *toep); -void handle_ddp_close(struct toepcb *, struct tcpcb *, struct sockbuf *, - uint32_t); +void handle_ddp_close(struct toepcb *, struct tcpcb *, uint32_t); +void handle_ddp_indicate(struct toepcb *); +void handle_ddp_tcb_rpl(struct toepcb *, const struct cpl_set_tcb_rpl *); void insert_ddp_data(struct toepcb *, uint32_t); #endif -- cgit v1.1 From 557551b31f6bd7ec0a7933a63a83e4b18fbe4a3d Mon Sep 17 00:00:00 2001 From: markj Date: Sat, 7 May 2016 03:32:29 +0000 Subject: Remove two useless local variables from prelist_update(). MFC after: 1 week --- sys/netinet6/nd6_rtr.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'sys') diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index f679c3f..cc4c7522 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -1081,7 +1081,6 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, struct ifnet *ifp = new->ndpr_ifp; struct nd_prefix *pr; int error = 0; - int newprefix = 0; int auth; struct in6_addrlifetime lt6_tmp; char ip6buf[INET6_ADDRSTRLEN]; @@ -1139,23 +1138,19 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, if (dr && pfxrtr_lookup(pr, dr) == NULL) pfxrtr_add(pr, dr); } else { - struct nd_prefix *newpr = NULL; - - newprefix = 1; - if (new->ndpr_vltime == 0) goto end; if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0) goto end; - error = nd6_prelist_add(new, dr, &newpr); - if (error != 0 || newpr == NULL) { + error = nd6_prelist_add(new, dr, &pr); + if (error != 0 || pr == NULL) { nd6log((LOG_NOTICE, "prelist_update: " "nd6_prelist_add failed for %s/%d on %s " "errno=%d, returnpr=%p\n", ip6_sprintf(ip6buf, &new->ndpr_prefix.sin6_addr), new->ndpr_plen, if_name(new->ndpr_ifp), - error, newpr)); + error, pr)); goto end; /* we should just give up in this case. */ } @@ -1166,13 +1161,11 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, * addresses. Thus, we explicitly make sure that the prefix * itself expires now. */ - if (newpr->ndpr_raf_onlink == 0) { - newpr->ndpr_vltime = 0; - newpr->ndpr_pltime = 0; - in6_init_prefix_ltimes(newpr); + if (pr->ndpr_raf_onlink == 0) { + pr->ndpr_vltime = 0; + pr->ndpr_pltime = 0; + in6_init_prefix_ltimes(pr); } - - pr = newpr; } /* -- cgit v1.1 From 94a1c2572532b60f69f86b39608742b65fdd2558 Mon Sep 17 00:00:00 2001 From: markj Date: Sat, 7 May 2016 03:41:29 +0000 Subject: Clean up callers of nd6_prelist_add(). nd6_prelist_add() sets *newp if and only if it is successful, so there's no need for code that handles the case where the return value is 0 and *newp == NULL. Fix some style bugs in nd6_prelist_add() while here. MFC after: 1 week --- sys/netinet6/in6.c | 8 -------- sys/netinet6/nd6_rtr.c | 19 ++++++++----------- 2 files changed, 8 insertions(+), 19 deletions(-) (limited to 'sys') diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index b6817da..902438e 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -669,14 +669,6 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, (*carp_detach_p)(&ia->ia_ifa); goto out; } - if (pr == NULL) { - if (carp_attached) - (*carp_detach_p)(&ia->ia_ifa); - log(LOG_ERR, "nd6_prelist_add succeeded but " - "no prefix\n"); - error = EINVAL; - goto out; - } } /* relate the address to the prefix */ diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index cc4c7522..988bf2b 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -993,11 +993,9 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, new->ndpr_flags = pr->ndpr_flags; if ((error = in6_init_prefix_ltimes(new)) != 0) { free(new, M_IP6NDP); - return(error); + return (error); } new->ndpr_lastupdate = time_uptime; - if (newp != NULL) - *newp = new; /* initialization */ LIST_INIT(&new->ndpr_advrtrs); @@ -1021,10 +1019,11 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr, } } - if (dr) + if (dr != NULL) pfxrtr_add(new, dr); - - return 0; + if (newp != NULL) + *newp = new; + return (0); } void @@ -1144,13 +1143,11 @@ prelist_update(struct nd_prefixctl *new, struct nd_defrouter *dr, goto end; error = nd6_prelist_add(new, dr, &pr); - if (error != 0 || pr == NULL) { + if (error != 0) { nd6log((LOG_NOTICE, "prelist_update: " - "nd6_prelist_add failed for %s/%d on %s " - "errno=%d, returnpr=%p\n", + "nd6_prelist_add failed for %s/%d on %s errno=%d\n", ip6_sprintf(ip6buf, &new->ndpr_prefix.sin6_addr), - new->ndpr_plen, if_name(new->ndpr_ifp), - error, pr)); + new->ndpr_plen, if_name(new->ndpr_ifp), error)); goto end; /* we should just give up in this case. */ } -- cgit v1.1 From 2f51e8d0c7f41c6ba51ff77fe97ab636e4683b2a Mon Sep 17 00:00:00 2001 From: rmacklem Date: Sat, 7 May 2016 22:45:08 +0000 Subject: Don't increment srvrpccnt[] for the NFSv4.1 operations. When support for NFSv4.1 was added to the NFS server, it broke the server rpc count stats, since newnfsstats.srvrpccnt[] doesn't have entries for the new NFSv4.1 operations. Without this patch, the code was incrementing bogus entries in newnfsstats for the new NFSv4.1 operations. This patch is an interim fix. The nfsstats structure needs to be updated and that will come in a future commit. Reported by: cem MFC after: 2 weeks --- sys/fs/nfsserver/nfs_nfsdsocket.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c index 4e995c1..e09116c 100644 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -771,7 +771,12 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag, } if (nfsv4_opflag[op].savereply) nd->nd_flag |= ND_SAVEREPLY; - NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); + /* + * For now, newnfsstats.srvrpccnt[] doesn't have entries + * for the NFSv4.1 operations. + */ + if (nd->nd_procnum < NFSV4OP_NOPS) + NFSINCRGLOBAL(newnfsstats.srvrpccnt[nd->nd_procnum]); switch (op) { case NFSV4OP_PUTFH: error = nfsrv_mtofh(nd, &fh); -- cgit v1.1 From 4376e44d3a1b68847c2e83ec9dd34a601e9dd791 Mon Sep 17 00:00:00 2001 From: mjg Date: Sun, 8 May 2016 03:26:12 +0000 Subject: fd: assert dropped filedesc lock in fdcloseexec --- sys/kern/kern_descrip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index bd8a934..a0b07d1 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -2307,7 +2307,7 @@ fdcloseexec(struct thread *td) FILEDESC_XLOCK(fdp); fdfree(fdp, i); (void) closefp(fdp, i, fp, td, 0); - /* closefp() drops the FILEDESC lock. */ + FILEDESC_UNLOCK_ASSERT(fdp); } } } -- cgit v1.1 From 48408bced42e63b7b022fa92604c053f5169a60d Mon Sep 17 00:00:00 2001 From: skra Date: Sun, 8 May 2016 08:57:50 +0000 Subject: INTRNG - update gpio pin capabilities according to r299166. Note that the updated comment is valid only for INTRNG. This should not be a problem as not INTRNG code is left in place for debugging reasons only and should not be used anymore. It's anticipated that this old code will be removed soon. --- sys/arm/ti/ti_gpio.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 830af3d..a67884e 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -290,7 +290,7 @@ ti_gpio_valid_pin(struct ti_gpio_softc *sc, int pin) } /** - * ti_gpio_pin_getcaps - Gets the capabilties of a given pin + * ti_gpio_pin_getcaps - Gets the capabilities of a given pin * @dev: gpio device handle * @pin: the number of the pin * @caps: pointer to a value that upon return will contain the capabilities @@ -300,6 +300,11 @@ ti_gpio_valid_pin(struct ti_gpio_softc *sc, int pin) * - GPIO_PIN_OUTPUT * - GPIO_PIN_PULLUP * - GPIO_PIN_PULLDOWN + * - GPIO_INTR_LEVEL_LOW + * - GPIO_INTR_LEVEL_HIGH + * - GPIO_INTR_EDGE_RISING + * - GPIO_INTR_EDGE_FALLING + * - GPIO_INTR_EDGE_BOTH * * LOCKING: * No locking required, returns static data. @@ -316,8 +321,15 @@ ti_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) if (ti_gpio_valid_pin(sc, pin) != 0) return (EINVAL); +#ifdef INTRNG + *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP | + GPIO_PIN_PULLDOWN | GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH | + GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING | + GPIO_INTR_EDGE_BOTH); +#else *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); +#endif return (0); } -- cgit v1.1 From a172d95fac235c55facc30336d520e2918021f8d Mon Sep 17 00:00:00 2001 From: skra Date: Sun, 8 May 2016 09:01:30 +0000 Subject: INTRNG - update gpio pin capabilities according to r299198. --- sys/arm/broadcom/bcm2835/bcm2835_gpio.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sys') diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index 49a879c..9619503 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -67,8 +67,16 @@ __FBSDID("$FreeBSD$"); #define BCM_GPIO_IRQS 4 #define BCM_GPIO_PINS 54 #define BCM_GPIO_PINS_PER_BANK 32 + +#ifdef INTRNG +#define BCM_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ + GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_INTR_LEVEL_LOW | \ + GPIO_INTR_LEVEL_HIGH | GPIO_INTR_EDGE_RISING | \ + GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH) +#else #define BCM_GPIO_DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) +#endif static struct resource_spec bcm_gpio_res_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, -- cgit v1.1 From c5cd1a68776cdb817d2dfdb81aebb7344a092598 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 8 May 2016 17:52:12 +0000 Subject: [bhnd] Replace is_hostb_device() with a more general find_hostb_device() This allows bus children to query for the host bridge device, rather than having to iterate over all attached devices. Submitted by: Landon Fuller Differential Revision: https://reviews.freebsd.org/D6193 --- sys/dev/bhnd/bcma/bcma.c | 9 +++++++++ sys/dev/bhnd/bcma/bcma_bhndb.c | 7 ++++++- sys/dev/bhnd/bcma/bcmavar.h | 1 + sys/dev/bhnd/bhnd.c | 3 +-- sys/dev/bhnd/bhnd.h | 14 ++++++-------- sys/dev/bhnd/bhnd_bus_if.m | 21 +++++++++----------- sys/dev/bhnd/bhnd_subr.c | 28 +++++++-------------------- sys/dev/bhnd/bhndb/bhndb.c | 44 +++++++++++++----------------------------- sys/dev/bhnd/bhndb/bhndb_if.m | 17 ++++++++++++++++ sys/dev/bhnd/siba/siba.c | 10 ++++++++++ sys/dev/bhnd/siba/siba_bhndb.c | 6 ++++++ sys/dev/bhnd/siba/sibavar.h | 1 + 12 files changed, 86 insertions(+), 75 deletions(-) (limited to 'sys') diff --git a/sys/dev/bhnd/bcma/bcma.c b/sys/dev/bhnd/bcma/bcma.c index 987eee2..b9a7c33 100644 --- a/sys/dev/bhnd/bcma/bcma.c +++ b/sys/dev/bhnd/bcma/bcma.c @@ -194,6 +194,14 @@ bcma_get_resource_list(device_t dev, device_t child) return (&dinfo->resources); } +static device_t +bcma_find_hostb_device(device_t dev) +{ + struct bcma_softc *sc = device_get_softc(dev); + + /* This is set (or not) by the concrete bcma driver subclass. */ + return (sc->hostb_dev); +} static int bcma_reset_core(device_t dev, device_t child, uint16_t flags) @@ -471,6 +479,7 @@ static device_method_t bcma_methods[] = { DEVMETHOD(bus_get_resource_list, bcma_get_resource_list), /* BHND interface */ + DEVMETHOD(bhnd_bus_find_hostb_device, bcma_find_hostb_device), DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core), DEVMETHOD(bhnd_bus_suspend_core, bcma_suspend_core), DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count), diff --git a/sys/dev/bhnd/bcma/bcma_bhndb.c b/sys/dev/bhnd/bcma/bcma_bhndb.c index ec8b647..88a5a28 100644 --- a/sys/dev/bhnd/bcma/bcma_bhndb.c +++ b/sys/dev/bhnd/bcma/bcma_bhndb.c @@ -65,14 +65,16 @@ bcma_bhndb_probe(device_t dev) static int bcma_bhndb_attach(device_t dev) { + struct bcma_softc *sc; const struct bhnd_chipid *cid; struct resource *erom_res; int error; int rid; - cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); + sc = device_get_softc(dev); /* Map the EROM resource and enumerate our children. */ + cid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); rid = 0; erom_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, cid->enum_addr, cid->enum_addr + BCMA_EROM_TABLE_SIZE, BCMA_EROM_TABLE_SIZE, @@ -95,6 +97,9 @@ bcma_bhndb_attach(device_t dev) if (error) return (error); + /* Ask our parent bridge to find the corresponding bridge core */ + sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev); + /* Call our superclass' implementation */ return (bcma_attach(dev)); } diff --git a/sys/dev/bhnd/bcma/bcmavar.h b/sys/dev/bhnd/bcma/bcmavar.h index 48a5307..359a2d1 100644 --- a/sys/dev/bhnd/bcma/bcmavar.h +++ b/sys/dev/bhnd/bcma/bcmavar.h @@ -144,6 +144,7 @@ struct bcma_devinfo { /** BMCA per-instance state */ struct bcma_softc { struct bhnd_softc bhnd_sc; /**< bhnd state */ + device_t hostb_dev; /**< host bridge core, or NULL */ }; #endif /* _BCMA_BCMAVAR_H_ */ \ No newline at end of file diff --git a/sys/dev/bhnd/bhnd.c b/sys/dev/bhnd/bhnd.c index 88b75ad..44c36ed 100644 --- a/sys/dev/bhnd/bhnd.c +++ b/sys/dev/bhnd/bhnd.c @@ -347,7 +347,7 @@ bhnd_generic_get_probe_order(device_t dev, device_t child) case BHND_DEVCLASS_EROM: case BHND_DEVCLASS_OTHER: case BHND_DEVCLASS_INVALID: - if (bhnd_is_hostb_device(child)) + if (bhnd_find_hostb_device(dev) == child) return (BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY); return (BHND_PROBE_DEFAULT); @@ -676,7 +676,6 @@ static device_method_t bhnd_methods[] = { DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), - DEVMETHOD(bhnd_bus_is_hostb_device, bhnd_bus_generic_is_hostb_device), DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), DEVMETHOD(bhnd_bus_read_nvram_var, bhnd_generic_read_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index 7589556..1b0cecf 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -335,8 +335,6 @@ void bhnd_set_custom_core_desc(device_t dev, void bhnd_set_default_core_desc(device_t dev); -bool bhnd_bus_generic_is_hostb_device(device_t dev, - device_t child); bool bhnd_bus_generic_is_hw_disabled(device_t dev, device_t child); bool bhnd_bus_generic_is_region_valid(device_t dev, @@ -364,14 +362,14 @@ int bhnd_bus_generic_deactivate_resource (device_t dev, /** - * Return true if @p dev is serving as a host bridge for its parent bhnd - * bus. + * Return the active host bridge core for the bhnd bus, if any, or NULL if + * not found. * - * @param dev A bhnd bus child device. + * @param dev A bhnd bus device. */ -static inline bool -bhnd_is_hostb_device(device_t dev) { - return (BHND_BUS_IS_HOSTB_DEVICE(device_get_parent(dev), dev)); +static inline device_t +bhnd_find_hostb_device(device_t dev) { + return (BHND_BUS_FIND_HOSTB_DEVICE(dev)); } /** diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m index 779dd89..fc0cd25 100644 --- a/sys/dev/bhnd/bhnd_bus_if.m +++ b/sys/dev/bhnd/bhnd_bus_if.m @@ -55,10 +55,10 @@ CODE { panic("bhnd_bus_get_chipid unimplemented"); } - static bool - bhnd_bus_null_is_hostb_device(device_t dev, device_t child) + static device_t + bhnd_bus_null_find_hostb_device(device_t dev) { - panic("bhnd_bus_is_hostb_device unimplemented"); + panic("bhnd_bus_find_hostb_device unimplemented"); } static bool @@ -105,19 +105,16 @@ CODE { } /** - * Returns true if @p child is serving as a host bridge for the bhnd - * bus. + * Return the active host bridge core for the bhnd bus, if any. * - * The default implementation will walk the parent device tree until - * the root node is hit, returning false. + * @param dev The bhnd bus device. * - * @param dev The device whose child is being examined. - * @param child The child device. + * @retval device_t if a hostb device exists + * @retval NULL if no hostb device is found. */ -METHOD bool is_hostb_device { +METHOD device_t find_hostb_device { device_t dev; - device_t child; -} DEFAULT bhnd_bus_null_is_hostb_device; +} DEFAULT bhnd_bus_null_find_hostb_device; /** * Return true if the hardware components required by @p child are unpopulated diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c index 5f92e9d..e9bad4f 100644 --- a/sys/dev/bhnd/bhnd_subr.c +++ b/sys/dev/bhnd/bhnd_subr.c @@ -486,7 +486,11 @@ const struct bhnd_device * bhnd_device_lookup(device_t dev, const struct bhnd_device *table, size_t entry_size) { - const struct bhnd_device *entry; + const struct bhnd_device *entry; + device_t hostb, parent; + + parent = device_get_parent(dev); + hostb = bhnd_find_hostb_device(parent); for (entry = table; entry->desc != NULL; entry = (const struct bhnd_device *) ((const char *) entry + entry_size)) @@ -496,8 +500,8 @@ bhnd_device_lookup(device_t dev, const struct bhnd_device *table, continue; /* match device flags */ - if (entry->device_flags & BHND_DF_HOSTB) { - if (!bhnd_is_hostb_device(dev)) + if (entry->device_flags & BHND_DF_HOSTB) { + if (dev != hostb) continue; } @@ -738,24 +742,6 @@ bhnd_set_default_core_desc(device_t dev) } /** - * Helper function for implementing BHND_BUS_IS_HOSTB_DEVICE(). - * - * If a parent device is available, this implementation delegates the - * request to the BHND_BUS_IS_HOSTB_DEVICE() method on the parent of @p dev. - * - * If no parent device is available (i.e. on a the bus root), false - * is returned. - */ -bool -bhnd_bus_generic_is_hostb_device(device_t dev, device_t child) { - if (device_get_parent(dev) != NULL) - return (BHND_BUS_IS_HOSTB_DEVICE(device_get_parent(dev), - child)); - - return (false); -} - -/** * Helper function for implementing BHND_BUS_IS_HW_DISABLED(). * * If a parent device is available, this implementation delegates the diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 434a324..6680938 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -589,18 +589,12 @@ bhndb_generic_init_full_config(device_t dev, device_t child, sc = device_get_softc(dev); hostb = NULL; - /* Fetch the full set of attached devices */ + /* Fetch the full set of bhnd-attached cores */ if ((error = device_get_children(sc->bus_dev, &devs, &ndevs))) return (error); /* Find our host bridge device */ - for (int i = 0; i < ndevs; i++) { - if (bhnd_is_hostb_device(devs[i])) { - hostb = devs[i]; - break; - } - } - + hostb = BHNDB_FIND_HOSTB_DEVICE(dev, child); if (hostb == NULL) { device_printf(sc->dev, "no host bridge core found\n"); error = ENODEV; @@ -950,13 +944,13 @@ bhndb_is_hw_disabled(device_t dev, device_t child) { /* Otherwise, we treat bridge-capable cores as unpopulated if they're * not the configured host bridge */ if (BHND_DEVCLASS_SUPPORTS_HOSTB(bhnd_core_class(&core))) - return (!BHND_BUS_IS_HOSTB_DEVICE(dev, child)); + return (BHNDB_FIND_HOSTB_DEVICE(dev, sc->bus_dev) != child); /* Otherwise, assume the core is populated */ return (false); } -/* ascending core index comparison used by bhndb_is_hostb_device() */ +/* ascending core index comparison used by bhndb_find_hostb_device() */ static int compare_core_index(const void *lhs, const void *rhs) { @@ -972,7 +966,7 @@ compare_core_index(const void *lhs, const void *rhs) } /** - * Default bhndb(4) implementation of BHND_BUS_IS_HOSTB_DEVICE(). + * Default bhndb(4) implementation of BHND_BUS_FIND_HOSTB_DEVICE(). * * This function uses a heuristic valid on all known PCI/PCIe/PCMCIA-bridged * bhnd(4) devices to determine the hostb core: @@ -982,27 +976,19 @@ compare_core_index(const void *lhs, const void *rhs) * - The core must be the first device on the bus with the bridged device * class. * - * @param sc The bridge device state. - * @param cores The table of bridge-enumerated cores. - * @param num_cores The length of @p cores. - * @param core The core to check. + * @param dev The bhndb device + * @param child The requesting bhnd bus. */ -static bool -bhndb_is_hostb_device(device_t dev, device_t child) +static device_t +bhndb_find_hostb_device(device_t dev, device_t child) { struct bhndb_softc *sc; struct bhnd_core_match md; device_t hostb_dev, *devlist; int devcnt, error; - sc = device_get_softc(dev); - /* Requestor must be attached to the bhnd bus */ - if (device_get_parent(child) != sc->bus_dev) - return (BHND_BUS_IS_HOSTB_DEVICE(device_get_parent(dev), - child)); - /* Determine required device class and set up a match descriptor. */ md = (struct bhnd_core_match) { .vendor = BHND_MFGID_BCM, @@ -1011,19 +997,15 @@ bhndb_is_hostb_device(device_t dev, device_t child) .class = sc->bridge_class, .unit = 0 }; - - /* Pre-screen the device before searching over the full device list. */ - if (!bhnd_device_matches(child, &md)) - return (false); /* Must be the absolute first matching device on the bus. */ - if ((error = device_get_children(sc->bus_dev, &devlist, &devcnt))) + if ((error = device_get_children(child, &devlist, &devcnt))) return (false); /* Sort by core index value, ascending */ qsort(devlist, devcnt, sizeof(*devlist), compare_core_index); - /* Find the actual hostb device */ + /* Find the hostb device */ hostb_dev = NULL; for (int i = 0; i < devcnt; i++) { if (bhnd_device_matches(devlist[i], &md)) { @@ -1035,7 +1017,7 @@ bhndb_is_hostb_device(device_t dev, device_t child) /* Clean up */ free(devlist, M_TEMP); - return (child == hostb_dev); + return (hostb_dev); } /** @@ -1922,12 +1904,12 @@ static device_method_t bhndb_methods[] = { /* BHNDB interface */ DEVMETHOD(bhndb_get_chipid, bhndb_get_chipid), DEVMETHOD(bhndb_init_full_config, bhndb_generic_init_full_config), + DEVMETHOD(bhndb_find_hostb_device, bhndb_find_hostb_device), DEVMETHOD(bhndb_suspend_resource, bhndb_suspend_resource), DEVMETHOD(bhndb_resume_resource, bhndb_resume_resource), /* BHND interface */ DEVMETHOD(bhnd_bus_is_hw_disabled, bhndb_is_hw_disabled), - DEVMETHOD(bhnd_bus_is_hostb_device, bhndb_is_hostb_device), DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), diff --git a/sys/dev/bhnd/bhndb/bhndb_if.m b/sys/dev/bhnd/bhndb/bhndb_if.m index 110925b..ce13a9e 100644 --- a/sys/dev/bhnd/bhndb/bhndb_if.m +++ b/sys/dev/bhnd/bhndb/bhndb_if.m @@ -62,6 +62,12 @@ CODE { panic("bhndb_init_full_config unimplemented"); } + static device_t + bhndb_null_find_hostb_device(device_t dev, device_t child) + { + panic("bhndb_find_hostb_device unimplemented"); + } + static void bhndb_null_suspend_resource(device_t dev, device_t child, int type, struct resource *r) @@ -120,6 +126,17 @@ METHOD int init_full_config { } DEFAULT bhndb_null_init_full_config; /** + * Locate the active host bridge core for the attached bhnd bus. + * + * @param dev The bridge device. + * @param child The bhnd bus device attached to @p dev. + */ +METHOD device_t find_hostb_device { + device_t dev; + device_t child; +} DEFAULT bhndb_null_find_hostb_device; + +/** * Mark a resource as 'suspended', gauranteeing to the bridge that no * further use of the resource will be made until BHNDB_RESUME_RESOURCE() * is called. diff --git a/sys/dev/bhnd/siba/siba.c b/sys/dev/bhnd/siba/siba.c index 4e0c34a..9fc87ff 100644 --- a/sys/dev/bhnd/siba/siba.c +++ b/sys/dev/bhnd/siba/siba.c @@ -216,6 +216,15 @@ siba_get_resource_list(device_t dev, device_t child) return (&dinfo->resources); } +static device_t +siba_find_hostb_device(device_t dev) +{ + struct siba_softc *sc = device_get_softc(dev); + + /* This is set (or not) by the concrete siba driver subclass. */ + return (sc->hostb_dev); +} + static int siba_reset_core(device_t dev, device_t child, uint16_t flags) { @@ -662,6 +671,7 @@ static device_method_t siba_methods[] = { DEVMETHOD(bus_get_resource_list, siba_get_resource_list), /* BHND interface */ + DEVMETHOD(bhnd_bus_find_hostb_device, siba_find_hostb_device), DEVMETHOD(bhnd_bus_reset_core, siba_reset_core), DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core), DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count), diff --git a/sys/dev/bhnd/siba/siba_bhndb.c b/sys/dev/bhnd/siba/siba_bhndb.c index 0e348b6..8a0e149 100644 --- a/sys/dev/bhnd/siba/siba_bhndb.c +++ b/sys/dev/bhnd/siba/siba_bhndb.c @@ -73,9 +73,12 @@ siba_bhndb_probe(device_t dev) static int siba_bhndb_attach(device_t dev) { + struct siba_softc *sc; const struct bhnd_chipid *chipid; int error; + sc = device_get_softc(dev); + /* Enumerate our children. */ chipid = BHNDB_GET_CHIPID(device_get_parent(dev), dev); if ((error = siba_add_children(dev, chipid))) @@ -87,6 +90,9 @@ siba_bhndb_attach(device_t dev) if (error) return (error); + /* Ask our parent bridge to find the corresponding bridge core */ + sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev); + /* Call our superclass' implementation */ return (siba_attach(dev)); } diff --git a/sys/dev/bhnd/siba/sibavar.h b/sys/dev/bhnd/siba/sibavar.h index 764ce23..f2b648a 100644 --- a/sys/dev/bhnd/siba/sibavar.h +++ b/sys/dev/bhnd/siba/sibavar.h @@ -145,6 +145,7 @@ struct siba_devinfo { /** siba(4) per-instance state */ struct siba_softc { struct bhnd_softc bhnd_sc; /**< bhnd state */ + device_t hostb_dev; /**< host bridge core, or NULL */ }; #endif /* _SIBA_SIBAVAR_H_ */ -- cgit v1.1 From 0fdbf5a8e1f07588912ef519c7f9b64cf33aae7a Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 8 May 2016 18:20:01 +0000 Subject: [bhnd] Add bhnd_resource support for the bus_(read|write)(_multi_)stream_* functions. This adds additional bhnd_resource shims used by the upcoming SPROM deltas. Submitted by: Landon Fuller Differential Revision: https://reviews.freebsd.org/D6194 --- sys/dev/bhnd/bhnd.c | 98 ++++++++++++++-------- sys/dev/bhnd/bhnd.h | 129 +++++++++++++++++++++++++++-- sys/dev/bhnd/bhnd_bus_if.m | 177 ++++++++++++++++++++++++++++++++++++++++ sys/dev/bhnd/bhndb/bhndb.c | 69 +++++++++++++--- sys/dev/bhnd/tools/bus_macro.sh | 10 +-- 5 files changed, 423 insertions(+), 60 deletions(-) (limited to 'sys') diff --git a/sys/dev/bhnd/bhnd.c b/sys/dev/bhnd/bhnd.c index 44c36ed..8b3c378 100644 --- a/sys/dev/bhnd/bhnd.c +++ b/sys/dev/bhnd/bhnd.c @@ -587,48 +587,53 @@ bhnd_generic_resume_child(device_t dev, device_t child) * non-bridged bus implementations, resources will never be marked as * indirect, and these methods should never be called. */ - -static uint8_t -bhnd_read_1(device_t dev, device_t child, struct bhnd_resource *r, - bus_size_t offset) -{ - return (BHND_BUS_READ_1(device_get_parent(dev), child, r, offset)); +#define BHND_IO_READ(_type, _name, _method) \ +static _type \ +bhnd_read_ ## _name (device_t dev, device_t child, \ + struct bhnd_resource *r, bus_size_t offset) \ +{ \ + return (BHND_BUS_READ_ ## _method( \ + device_get_parent(dev), child, r, offset)); \ } -static uint16_t -bhnd_read_2(device_t dev, device_t child, struct bhnd_resource *r, - bus_size_t offset) -{ - return (BHND_BUS_READ_2(device_get_parent(dev), child, r, offset)); +#define BHND_IO_WRITE(_type, _name, _method) \ +static void \ +bhnd_write_ ## _name (device_t dev, device_t child, \ + struct bhnd_resource *r, bus_size_t offset, _type value) \ +{ \ + return (BHND_BUS_WRITE_ ## _method( \ + device_get_parent(dev), child, r, offset, \ + value)); \ } -static uint32_t -bhnd_read_4(device_t dev, device_t child, struct bhnd_resource *r, - bus_size_t offset) -{ - return (BHND_BUS_READ_4(device_get_parent(dev), child, r, offset)); +#define BHND_IO_MULTI(_type, _rw, _name, _method) \ +static void \ +bhnd_ ## _rw ## _multi_ ## _name (device_t dev, device_t child, \ + struct bhnd_resource *r, bus_size_t offset, _type *datap, \ + bus_size_t count) \ +{ \ + BHND_BUS_ ## _method(device_get_parent(dev), child, r, \ + offset, datap, count); \ } -static void -bhnd_write_1(device_t dev, device_t child, struct bhnd_resource *r, - bus_size_t offset, uint8_t value) -{ - BHND_BUS_WRITE_1(device_get_parent(dev), child, r, offset, value); -} - -static void -bhnd_write_2(device_t dev, device_t child, struct bhnd_resource *r, - bus_size_t offset, uint16_t value) -{ - BHND_BUS_WRITE_2(device_get_parent(dev), child, r, offset, value); -} - -static void -bhnd_write_4(device_t dev, device_t child, struct bhnd_resource *r, - bus_size_t offset, uint32_t value) -{ - BHND_BUS_WRITE_4(device_get_parent(dev), child, r, offset, value); -} +#define BHND_IO_METHODS(_type, _size) \ + BHND_IO_READ(_type, _size, _size) \ + BHND_IO_WRITE(_type, _size, _size) \ + \ + BHND_IO_READ(_type, stream_ ## _size, STREAM_ ## _size) \ + BHND_IO_WRITE(_type, stream_ ## _size, STREAM_ ## _size) \ + \ + BHND_IO_MULTI(_type, read, _size, READ_MULTI_ ## _size) \ + BHND_IO_MULTI(_type, write, _size, WRITE_MULTI_ ## _size) \ + \ + BHND_IO_MULTI(_type, read, stream_ ## _size, \ + READ_MULTI_STREAM_ ## _size) \ + BHND_IO_MULTI(_type, write, stream_ ## _size, \ + WRITE_MULTI_STREAM_ ## _size) \ + +BHND_IO_METHODS(uint8_t, 1); +BHND_IO_METHODS(uint16_t, 2); +BHND_IO_METHODS(uint32_t, 4); static void bhnd_barrier(device_t dev, device_t child, struct bhnd_resource *r, @@ -684,6 +689,27 @@ static device_method_t bhnd_methods[] = { DEVMETHOD(bhnd_bus_write_1, bhnd_write_1), DEVMETHOD(bhnd_bus_write_2, bhnd_write_2), DEVMETHOD(bhnd_bus_write_4, bhnd_write_4), + DEVMETHOD(bhnd_bus_read_stream_1, bhnd_read_stream_1), + DEVMETHOD(bhnd_bus_read_stream_2, bhnd_read_stream_2), + DEVMETHOD(bhnd_bus_read_stream_4, bhnd_read_stream_4), + DEVMETHOD(bhnd_bus_write_stream_1, bhnd_write_stream_1), + DEVMETHOD(bhnd_bus_write_stream_2, bhnd_write_stream_2), + DEVMETHOD(bhnd_bus_write_stream_4, bhnd_write_stream_4), + + DEVMETHOD(bhnd_bus_read_multi_1, bhnd_read_multi_1), + DEVMETHOD(bhnd_bus_read_multi_2, bhnd_read_multi_2), + DEVMETHOD(bhnd_bus_read_multi_4, bhnd_read_multi_4), + DEVMETHOD(bhnd_bus_write_multi_1, bhnd_write_multi_1), + DEVMETHOD(bhnd_bus_write_multi_2, bhnd_write_multi_2), + DEVMETHOD(bhnd_bus_write_multi_4, bhnd_write_multi_4), + + DEVMETHOD(bhnd_bus_read_multi_stream_1, bhnd_read_multi_stream_1), + DEVMETHOD(bhnd_bus_read_multi_stream_2, bhnd_read_multi_stream_2), + DEVMETHOD(bhnd_bus_read_multi_stream_4, bhnd_read_multi_stream_4), + DEVMETHOD(bhnd_bus_write_multi_stream_1,bhnd_write_multi_stream_1), + DEVMETHOD(bhnd_bus_write_multi_stream_2,bhnd_write_multi_stream_2), + DEVMETHOD(bhnd_bus_write_multi_stream_4,bhnd_write_multi_stream_4), + DEVMETHOD(bhnd_bus_barrier, bhnd_barrier), DEVMETHOD_END diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index 1b0cecf..fdfe510 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -608,37 +608,152 @@ bhnd_get_region_addr(device_t dev, bhnd_port_type port_type, u_int port, #define bhnd_bus_barrier(r, o, l, f) \ ((r)->direct) ? \ bus_barrier((r)->res, (o), (l), (f)) : \ - BHND_BUS_BARRIER(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_BARRIER( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (l), (f)) #define bhnd_bus_read_1(r, o) \ ((r)->direct) ? \ bus_read_1((r)->res, (o)) : \ - BHND_BUS_READ_1(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_READ_1( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) +#define bhnd_bus_read_multi_1(r, o, d, c) \ + ((r)->direct) ? \ + bus_read_multi_1((r)->res, (o), (d), (c)) : \ + BHND_BUS_READ_MULTI_1( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_1(r, o, v) \ ((r)->direct) ? \ bus_write_1((r)->res, (o), (v)) : \ - BHND_BUS_WRITE_1(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_WRITE_1( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (v)) +#define bhnd_bus_write_multi_1(r, o, d, c) \ + ((r)->direct) ? \ + bus_write_multi_1((r)->res, (o), (d), (c)) : \ + BHND_BUS_WRITE_MULTI_1( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) +#define bhnd_bus_read_stream_1(r, o) \ + ((r)->direct) ? \ + bus_read_stream_1((r)->res, (o)) : \ + BHND_BUS_READ_STREAM_1( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o)) +#define bhnd_bus_read_multi_stream_1(r, o, d, c) \ + ((r)->direct) ? \ + bus_read_multi_stream_1((r)->res, (o), (d), (c)) : \ + BHND_BUS_READ_MULTI_STREAM_1( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) +#define bhnd_bus_write_stream_1(r, o, v) \ + ((r)->direct) ? \ + bus_write_stream_1((r)->res, (o), (v)) : \ + BHND_BUS_WRITE_STREAM_1( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) +#define bhnd_bus_write_multi_stream_1(r, o, d, c) \ + ((r)->direct) ? \ + bus_write_multi_stream_1((r)->res, (o), (d), (c)) : \ + BHND_BUS_WRITE_MULTI_STREAM_1( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_2(r, o) \ ((r)->direct) ? \ bus_read_2((r)->res, (o)) : \ - BHND_BUS_READ_2(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_READ_2( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) +#define bhnd_bus_read_multi_2(r, o, d, c) \ + ((r)->direct) ? \ + bus_read_multi_2((r)->res, (o), (d), (c)) : \ + BHND_BUS_READ_MULTI_2( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_2(r, o, v) \ ((r)->direct) ? \ bus_write_2((r)->res, (o), (v)) : \ - BHND_BUS_WRITE_2(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_WRITE_2( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (v)) +#define bhnd_bus_write_multi_2(r, o, d, c) \ + ((r)->direct) ? \ + bus_write_multi_2((r)->res, (o), (d), (c)) : \ + BHND_BUS_WRITE_MULTI_2( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) +#define bhnd_bus_read_stream_2(r, o) \ + ((r)->direct) ? \ + bus_read_stream_2((r)->res, (o)) : \ + BHND_BUS_READ_STREAM_2( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o)) +#define bhnd_bus_read_multi_stream_2(r, o, d, c) \ + ((r)->direct) ? \ + bus_read_multi_stream_2((r)->res, (o), (d), (c)) : \ + BHND_BUS_READ_MULTI_STREAM_2( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) +#define bhnd_bus_write_stream_2(r, o, v) \ + ((r)->direct) ? \ + bus_write_stream_2((r)->res, (o), (v)) : \ + BHND_BUS_WRITE_STREAM_2( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) +#define bhnd_bus_write_multi_stream_2(r, o, d, c) \ + ((r)->direct) ? \ + bus_write_multi_stream_2((r)->res, (o), (d), (c)) : \ + BHND_BUS_WRITE_MULTI_STREAM_2( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_read_4(r, o) \ ((r)->direct) ? \ bus_read_4((r)->res, (o)) : \ - BHND_BUS_READ_4(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_READ_4( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o)) +#define bhnd_bus_read_multi_4(r, o, d, c) \ + ((r)->direct) ? \ + bus_read_multi_4((r)->res, (o), (d), (c)) : \ + BHND_BUS_READ_MULTI_4( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) #define bhnd_bus_write_4(r, o, v) \ ((r)->direct) ? \ bus_write_4((r)->res, (o), (v)) : \ - BHND_BUS_WRITE_4(device_get_parent(rman_get_device((r)->res)), \ + BHND_BUS_WRITE_4( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (v)) +#define bhnd_bus_write_multi_4(r, o, d, c) \ + ((r)->direct) ? \ + bus_write_multi_4((r)->res, (o), (d), (c)) : \ + BHND_BUS_WRITE_MULTI_4( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) +#define bhnd_bus_read_stream_4(r, o) \ + ((r)->direct) ? \ + bus_read_stream_4((r)->res, (o)) : \ + BHND_BUS_READ_STREAM_4( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o)) +#define bhnd_bus_read_multi_stream_4(r, o, d, c) \ + ((r)->direct) ? \ + bus_read_multi_stream_4((r)->res, (o), (d), (c)) : \ + BHND_BUS_READ_MULTI_STREAM_4( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) +#define bhnd_bus_write_stream_4(r, o, v) \ + ((r)->direct) ? \ + bus_write_stream_4((r)->res, (o), (v)) : \ + BHND_BUS_WRITE_STREAM_4( \ + device_get_parent(rman_get_device((r)->res)), \ rman_get_device((r)->res), (r), (o), (v)) +#define bhnd_bus_write_multi_stream_4(r, o, d, c) \ + ((r)->direct) ? \ + bus_write_multi_stream_4((r)->res, (o), (d), (c)) : \ + BHND_BUS_WRITE_MULTI_STREAM_4( \ + device_get_parent(rman_get_device((r)->res)), \ + rman_get_device((r)->res), (r), (o), (d), (c)) #endif /* _BHND_BHND_H_ */ diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m index fc0cd25..2622524 100644 --- a/sys/dev/bhnd/bhnd_bus_if.m +++ b/sys/dev/bhnd/bhnd_bus_if.m @@ -463,6 +463,183 @@ METHOD void write_4 { uint32_t value; } +/** An implementation of bus_read_stream_1() compatible with bhnd_resource */ +METHOD uint8_t read_stream_1 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; +} + +/** An implementation of bus_read_stream_2() compatible with bhnd_resource */ +METHOD uint16_t read_stream_2 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; +} + +/** An implementation of bus_read_stream_4() compatible with bhnd_resource */ +METHOD uint32_t read_stream_4 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; +} + +/** An implementation of bus_write_stream_1() compatible with bhnd_resource */ +METHOD void write_stream_1 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint8_t value; +} + +/** An implementation of bus_write_stream_2() compatible with bhnd_resource */ +METHOD void write_stream_2 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint16_t value; +} + +/** An implementation of bus_write_stream_4() compatible with bhnd_resource */ +METHOD void write_stream_4 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint32_t value; +} + +/** An implementation of bus_read_multi_1() compatible with bhnd_resource */ +METHOD void read_multi_1 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint8_t *datap; + bus_size_t count; +} + +/** An implementation of bus_read_multi_2() compatible with bhnd_resource */ +METHOD void read_multi_2 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint16_t *datap; + bus_size_t count; +} + +/** An implementation of bus_read_multi_4() compatible with bhnd_resource */ +METHOD void read_multi_4 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint32_t *datap; + bus_size_t count; +} + +/** An implementation of bus_write_multi_1() compatible with bhnd_resource */ +METHOD void write_multi_1 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint8_t *datap; + bus_size_t count; +} + +/** An implementation of bus_write_multi_2() compatible with bhnd_resource */ +METHOD void write_multi_2 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint16_t *datap; + bus_size_t count; +} + +/** An implementation of bus_write_multi_4() compatible with bhnd_resource */ +METHOD void write_multi_4 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint32_t *datap; + bus_size_t count; +} + +/** An implementation of bus_read_multi_stream_1() compatible + * bhnd_resource */ +METHOD void read_multi_stream_1 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint8_t *datap; + bus_size_t count; +} + +/** An implementation of bus_read_multi_stream_2() compatible + * bhnd_resource */ +METHOD void read_multi_stream_2 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint16_t *datap; + bus_size_t count; +} + +/** An implementation of bus_read_multi_stream_4() compatible + * bhnd_resource */ +METHOD void read_multi_stream_4 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint32_t *datap; + bus_size_t count; +} + +/** An implementation of bus_write_multi_stream_1() compatible + * bhnd_resource */ +METHOD void write_multi_stream_1 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint8_t *datap; + bus_size_t count; +} + +/** An implementation of bus_write_multi_stream_2() compatible with + * bhnd_resource */ +METHOD void write_multi_stream_2 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint16_t *datap; + bus_size_t count; +} + +/** An implementation of bus_write_multi_stream_4() compatible with + * bhnd_resource */ +METHOD void write_multi_stream_4 { + device_t dev; + device_t child; + struct bhnd_resource *r; + bus_size_t offset; + uint32_t *datap; + bus_size_t count; +} + /** An implementation of bus_barrier() compatible with bhnd_resource */ METHOD void barrier { device_t dev; diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 6680938..6ca1efc 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -1737,37 +1737,60 @@ bhndb_io_resource(struct bhndb_softc *sc, bus_addr_t addr, bus_size_t size, BHNDB_UNLOCK(sc); /* Defines a bhndb_bus_read_* method implementation */ -#define BHNDB_IO_READ(_type, _size) \ +#define BHNDB_IO_READ(_type, _name) \ static _type \ -bhndb_bus_read_ ## _size (device_t dev, device_t child, \ +bhndb_bus_read_ ## _name (device_t dev, device_t child, \ struct bhnd_resource *r, bus_size_t offset) \ { \ _type v; \ BHNDB_IO_COMMON_SETUP(sizeof(_type)); \ - v = bus_read_ ## _size (io_res, io_offset); \ + v = bus_read_ ## _name (io_res, io_offset); \ BHNDB_IO_COMMON_TEARDOWN(); \ \ return (v); \ } /* Defines a bhndb_bus_write_* method implementation */ -#define BHNDB_IO_WRITE(_type, _size) \ +#define BHNDB_IO_WRITE(_type, _name) \ static void \ -bhndb_bus_write_ ## _size (device_t dev, device_t child, \ +bhndb_bus_write_ ## _name (device_t dev, device_t child, \ struct bhnd_resource *r, bus_size_t offset, _type value) \ { \ BHNDB_IO_COMMON_SETUP(sizeof(_type)); \ - bus_write_ ## _size (io_res, io_offset, value); \ + bus_write_ ## _name (io_res, io_offset, value); \ BHNDB_IO_COMMON_TEARDOWN(); \ } -BHNDB_IO_READ(uint8_t, 1); -BHNDB_IO_READ(uint16_t, 2); -BHNDB_IO_READ(uint32_t, 4); +/* Defines a bhndb_bus_(read|write)_multi_* method implementation */ +#define BHNDB_IO_MULTI(_type, _rw, _name) \ +static void \ +bhndb_bus_ ## _rw ## _multi_ ## _name (device_t dev, \ + device_t child, struct bhnd_resource *r, bus_size_t offset, \ + _type *datap, bus_size_t count) \ +{ \ + BHNDB_IO_COMMON_SETUP(sizeof(_type) * count); \ + bus_ ## _rw ## _multi_ ## _name (io_res, io_offset, \ + datap, count); \ + BHNDB_IO_COMMON_TEARDOWN(); \ +} -BHNDB_IO_WRITE(uint8_t, 1); -BHNDB_IO_WRITE(uint16_t, 2); -BHNDB_IO_WRITE(uint32_t, 4); +/* Defines a complete set of read/write methods */ +#define BHNDB_IO_METHODS(_type, _size) \ + BHNDB_IO_READ(_type, _size) \ + BHNDB_IO_WRITE(_type, _size) \ + \ + BHNDB_IO_READ(_type, stream_ ## _size) \ + BHNDB_IO_WRITE(_type, stream_ ## _size) \ + \ + BHNDB_IO_MULTI(_type, read, _size) \ + BHNDB_IO_MULTI(_type, write, _size) \ + \ + BHNDB_IO_MULTI(_type, read, stream_ ## _size) \ + BHNDB_IO_MULTI(_type, write, stream_ ## _size) + +BHNDB_IO_METHODS(uint8_t, 1); +BHNDB_IO_METHODS(uint16_t, 2); +BHNDB_IO_METHODS(uint32_t, 4); /** * Default bhndb(4) implementation of BHND_BUS_BARRIER(). @@ -1919,6 +1942,28 @@ static device_method_t bhndb_methods[] = { DEVMETHOD(bhnd_bus_write_1, bhndb_bus_write_1), DEVMETHOD(bhnd_bus_write_2, bhndb_bus_write_2), DEVMETHOD(bhnd_bus_write_4, bhndb_bus_write_4), + + DEVMETHOD(bhnd_bus_read_stream_1, bhndb_bus_read_stream_1), + DEVMETHOD(bhnd_bus_read_stream_2, bhndb_bus_read_stream_2), + DEVMETHOD(bhnd_bus_read_stream_4, bhndb_bus_read_stream_4), + DEVMETHOD(bhnd_bus_write_stream_1, bhndb_bus_write_stream_1), + DEVMETHOD(bhnd_bus_write_stream_2, bhndb_bus_write_stream_2), + DEVMETHOD(bhnd_bus_write_stream_4, bhndb_bus_write_stream_4), + + DEVMETHOD(bhnd_bus_read_multi_1, bhndb_bus_read_multi_1), + DEVMETHOD(bhnd_bus_read_multi_2, bhndb_bus_read_multi_2), + DEVMETHOD(bhnd_bus_read_multi_4, bhndb_bus_read_multi_4), + DEVMETHOD(bhnd_bus_write_multi_1, bhndb_bus_write_multi_1), + DEVMETHOD(bhnd_bus_write_multi_2, bhndb_bus_write_multi_2), + DEVMETHOD(bhnd_bus_write_multi_4, bhndb_bus_write_multi_4), + + DEVMETHOD(bhnd_bus_read_multi_stream_1, bhndb_bus_read_multi_stream_1), + DEVMETHOD(bhnd_bus_read_multi_stream_2, bhndb_bus_read_multi_stream_2), + DEVMETHOD(bhnd_bus_read_multi_stream_4, bhndb_bus_read_multi_stream_4), + DEVMETHOD(bhnd_bus_write_multi_stream_1,bhndb_bus_write_multi_stream_1), + DEVMETHOD(bhnd_bus_write_multi_stream_2,bhndb_bus_write_multi_stream_2), + DEVMETHOD(bhnd_bus_write_multi_stream_4,bhndb_bus_write_multi_stream_4), + DEVMETHOD(bhnd_bus_barrier, bhndb_bus_barrier), DEVMETHOD_END diff --git a/sys/dev/bhnd/tools/bus_macro.sh b/sys/dev/bhnd/tools/bus_macro.sh index de9e798..a11ed0c 100755 --- a/sys/dev/bhnd/tools/bus_macro.sh +++ b/sys/dev/bhnd/tools/bus_macro.sh @@ -50,8 +50,8 @@ macro () { echo -n ", (${i})" done echo ") : \\" - echo -n " BHND_BUS_${bus_n}(" - echo "device_get_parent(rman_get_device((r)->res)), \\" + echo " BHND_BUS_${bus_n}( \\" + echo " device_get_parent(rman_get_device((r)->res)), \\" echo -n " rman_get_device((r)->res), (r)" for i do @@ -70,15 +70,15 @@ do # macro copy_region_$w so dh do c # macro copy_region_stream_$w ? # macro peek_$w - for s in "" #stream_ + for s in "" stream_ do macro read_$s$w o -# macro read_multi_$s$w o d c + macro read_multi_$s$w o d c # macro read_region_$s$w o d c # macro set_multi_$s$w o v c # macro set_region_$s$w o v c macro write_$s$w o v -# macro write_multi_$s$w o d c + macro write_multi_$s$w o d c # macro write_region_$s$w o d c done done -- cgit v1.1 From e0239ae3fe12de3d01f6f9191e73a73af4ba3bf9 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 8 May 2016 18:30:08 +0000 Subject: [bhnd] Add support for matching on chip identifiers. This is used by the upcoming SPROM code to match on chipsets that require special handling of muxed SPROM pins. Submitted by: Landon Fuller Differential Revision: https://reviews.freebsd.org/D6195 --- sys/dev/bhnd/bhnd.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/bhnd/bhnd_subr.c | 57 ++++++++++++++++++++++++++++++++--- 2 files changed, 130 insertions(+), 4 deletions(-) (limited to 'sys') diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index fdfe510..55d2081 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -232,6 +232,65 @@ struct bhnd_core_match { .unit = -1 \ } +/** A chipset match descriptor. */ +struct bhnd_chip_match { + /** Select fields to be matched */ + uint8_t + match_id:1, + match_rev:1, + match_pkg:1, + match_flags_unused:5; + + uint16_t chip_id; /**< required chip id */ + struct bhnd_hwrev_match chip_rev; /**< matching chip revisions */ + uint8_t chip_pkg; /**< required package */ +}; + +#define BHND_CHIP_MATCH_ANY \ + { .match_id = 0, .match_rev = 0, .match_pkg = 0 } + +#define BHND_CHIP_MATCH_IS_ANY(_m) \ + ((_m)->match_id == 0 && (_m)->match_rev == 0 && (_m)->match_pkg == 0) + +/** Set the required chip ID within a bhnd_chip_match instance */ +#define BHND_CHIP_ID(_cid) \ + .match_id = 1, .chip_id = BHND_CHIPID_BCM ## _cid + +/** Set the required revision range within a bhnd_chip_match instance */ +#define BHND_CHIP_REV(_rev) \ + .match_rev = 1, .chip_rev = BHND_ ## _rev + +/** Set the required package ID within a bhnd_chip_match instance */ +#define BHND_CHIP_PKG(_pkg) \ + .match_pkg = 1, .chip_pkg = BHND_PKGID_BCM ## _pkg + +/** Set the required chip and package ID within a bhnd_chip_match instance */ +#define BHND_CHIP_IP(_cid, _pkg) \ + BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg) + +/** Set the required chip ID, package ID, and revision within a bhnd_chip_match + * instance */ +#define BHND_CHIP_IPR(_cid, _pkg, _rev) \ + BHND_CHIP_ID(_cid), BHND_CHIP_PKG(_pkg), BHND_CHIP_REV(_rev) + +/** Set the required chip ID and revision within a bhnd_chip_match + * instance */ +#define BHND_CHIP_IR(_cid, _rev) \ + BHND_CHIP_ID(_cid), BHND_CHIP_REV(_rev) + +/** + * Chipset quirk table descriptor. + */ +struct bhnd_chip_quirk { + const struct bhnd_chip_match chip; /**< chip match descriptor */ + uint32_t quirks; /**< quirk flags */ +}; + +#define BHND_CHIP_QUIRK_END { BHND_CHIP_MATCH_ANY, 0 } + +#define BHND_CHIP_QUIRK_IS_END(_q) \ + (BHND_CHIP_MATCH_IS_ANY(&(_q)->chip) && (_q)->quirks == 0) + /** * Device quirk table descriptor. */ @@ -297,9 +356,16 @@ bool bhnd_core_matches( const struct bhnd_core_info *core, const struct bhnd_core_match *desc); +bool bhnd_chip_matches( + const struct bhnd_chipid *chipid, + const struct bhnd_chip_match *desc); + bool bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc); +uint32_t bhnd_chip_quirks(device_t dev, + const struct bhnd_chip_quirk *table); + bool bhnd_device_matches(device_t dev, const struct bhnd_core_match *desc); @@ -389,6 +455,17 @@ bhnd_is_hw_disabled(device_t dev) { } /** + * Return the BHND chip identification info for the bhnd bus. + * + * @param dev A bhnd bus child device. + */ +static inline const struct bhnd_chipid * +bhnd_get_chipid(device_t dev) { + return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev)); +}; + + +/** * Allocate a resource from a device's parent bhnd(4) bus. * * @param dev The device requesting resource ownership. diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c index e9bad4f..ac8fb0d 100644 --- a/sys/dev/bhnd/bhnd_subr.c +++ b/sys/dev/bhnd/bhnd_subr.c @@ -415,10 +415,6 @@ bhnd_core_matches(const struct bhnd_core_info *core, if (!bhnd_hwrev_matches(core->hwrev, &desc->hwrev)) return (false); - - if (desc->hwrev.end != BHND_HWREV_INVALID && - desc->hwrev.end < core->hwrev) - return (false); if (desc->class != BHND_DEVCLASS_INVALID && desc->class != bhnd_core_class(core)) @@ -428,6 +424,32 @@ bhnd_core_matches(const struct bhnd_core_info *core, } /** + * Return true if the @p chip matches @p desc. + * + * @param chip A bhnd chip identifier. + * @param desc A match descriptor to compare against @p chip. + * + * @retval true if @p chip matches @p match + * @retval false if @p chip does not match @p match. + */ +bool +bhnd_chip_matches(const struct bhnd_chipid *chip, + const struct bhnd_chip_match *desc) +{ + if (desc->match_id && chip->chip_id != desc->chip_id) + return (false); + + if (desc->match_pkg && chip->chip_pkg != desc->chip_pkg) + return (false); + + if (desc->match_rev && + !bhnd_hwrev_matches(chip->chip_rev, &desc->chip_rev)) + return (false); + + return (true); +} + +/** * Return true if the @p hwrev matches @p desc. * * @param hwrev A bhnd hardware revision. @@ -514,6 +536,33 @@ bhnd_device_lookup(device_t dev, const struct bhnd_device *table, } /** + * Scan @p table for all quirk flags applicable to @p dev's chip identifier + * (as returned by bhnd_get_chipid). + * + * @param dev A bhnd device. + * @param table The chip quirk table to search. + * + * @return returns all matching quirk flags. + */ +uint32_t +bhnd_chip_quirks(device_t dev, const struct bhnd_chip_quirk *table) +{ + const struct bhnd_chipid *cid; + const struct bhnd_chip_quirk *qent; + uint32_t quirks; + + cid = bhnd_get_chipid(dev); + quirks = 0; + + for (qent = table; !BHND_CHIP_QUIRK_IS_END(qent); qent++) { + if (bhnd_chip_matches(cid, &qent->chip)) + quirks |= qent->quirks; + } + + return (quirks); +} + +/** * Scan @p table for all quirk flags applicable to @p dev. * * @param dev A bhnd device to match against @p table. -- cgit v1.1 From c04eb7cb4e5981671c560d331d66c9e841047112 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 8 May 2016 19:14:05 +0000 Subject: [bhnd] Initial bhnd(4) SPROM/NVRAM support. This adds support for the NVRAM handling and the basic SPROM hardware used on siba(4) and bcma(4) devices, including: * SPROM directly attached to the PCI core, accessible via PCI configuration space. * SPROM attached to later ChipCommon cores. * SPROM variables vended from the parent SoC bus (e.g. via a directly-attached flash device). Additional improvements to the NVRAM/SPROM interface will be required, but this changeset stands alone as working checkpoint. Submitted by: Landon Fuller Reviewed by: Michael Zhilin (Broadcom MIPS support) Differential Revision: https://reviews.freebsd.org/D6196 --- sys/conf/files | 13 + sys/conf/kmod.mk | 20 + sys/dev/bhnd/bcmsrom_fmt.h | 373 ------- sys/dev/bhnd/bcmsrom_tbl.h | 577 ----------- sys/dev/bhnd/bhnd.c | 51 +- sys/dev/bhnd/bhnd.h | 49 + sys/dev/bhnd/bhnd_bus_if.m | 6 +- sys/dev/bhnd/bhnd_ids.h | 3 +- sys/dev/bhnd/bhndb/bhndb.c | 32 +- sys/dev/bhnd/bhndb/bhndb_pci.c | 185 +++- sys/dev/bhnd/bhndb/bhndb_pci_sprom.c | 210 ++++ sys/dev/bhnd/bhndb/bhndb_pcireg.h | 18 +- sys/dev/bhnd/bhndb/bhndb_pcivar.h | 1 + sys/dev/bhnd/cores/chipc/chipc.c | 329 +++++-- sys/dev/bhnd/cores/chipc/chipcreg.h | 38 +- sys/dev/bhnd/cores/chipc/chipcvar.h | 76 +- sys/dev/bhnd/nvram/bhnd_nvram.h | 41 +- sys/dev/bhnd/nvram/bhnd_nvram_if.m | 38 +- sys/dev/bhnd/nvram/bhnd_sprom.c | 572 +++++++++++ sys/dev/bhnd/nvram/bhnd_spromreg.h | 63 ++ sys/dev/bhnd/nvram/bhnd_spromvar.h | 58 ++ sys/dev/bhnd/nvram/nvram_map | 1445 ++++++++++++++++++++++++++++ sys/dev/bhnd/nvram/nvram_subr.c | 149 +++ sys/dev/bhnd/nvram/nvramvar.h | 128 +++ sys/dev/bhnd/tools/bus_macro.sh | 0 sys/dev/bhnd/tools/nvram_map_gen.awk | 1162 ++++++++++++++++++++++ sys/dev/bhnd/tools/nvram_map_gen.sh | 12 + sys/dev/bwn/bwn_mac.c | 10 + sys/modules/bhnd/Makefile | 9 +- sys/modules/bhnd/bhndb/Makefile | 6 +- sys/modules/bhnd/bhndb_pci/Makefile | 4 +- sys/modules/bhnd/cores/bhnd_chipc/Makefile | 6 +- sys/modules/bhnd/nvram/Makefile | 10 - sys/modules/bwn_pci/Makefile | 4 +- 34 files changed, 4544 insertions(+), 1154 deletions(-) delete mode 100644 sys/dev/bhnd/bcmsrom_fmt.h delete mode 100644 sys/dev/bhnd/bcmsrom_tbl.h create mode 100644 sys/dev/bhnd/bhndb/bhndb_pci_sprom.c create mode 100644 sys/dev/bhnd/nvram/bhnd_sprom.c create mode 100644 sys/dev/bhnd/nvram/bhnd_spromreg.h create mode 100644 sys/dev/bhnd/nvram/bhnd_spromvar.h create mode 100644 sys/dev/bhnd/nvram/nvram_map create mode 100644 sys/dev/bhnd/nvram/nvram_subr.c create mode 100644 sys/dev/bhnd/nvram/nvramvar.h mode change 100755 => 100644 sys/dev/bhnd/tools/bus_macro.sh create mode 100755 sys/dev/bhnd/tools/nvram_map_gen.awk create mode 100755 sys/dev/bhnd/tools/nvram_map_gen.sh delete mode 100644 sys/modules/bhnd/nvram/Makefile (limited to 'sys') diff --git a/sys/conf/files b/sys/conf/files index 9105ae0..98ca4da 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -9,6 +9,16 @@ acpi_quirks.h optional acpi \ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" +bhnd_nvram_map.h optional bhndbus | bhnd \ + dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \ + compile-with "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -h" \ + no-obj no-implicit-rule before-depend \ + clean "bhnd_nvram_map.h" +bhnd_nvram_map_data.h optional bhndbus | bhnd \ + dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \ + compile-with "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -d" \ + no-obj no-implicit-rule before-depend \ + clean "bhnd_nvram_map_data.h" # # The 'fdt_dtb_file' target covers an actual DTB file name, which is derived # from the specified source (DTS) file: .dts -> .dtb @@ -1121,6 +1131,7 @@ dev/bhnd/bhndb/bhndb_hwdata.c optional bhndbus | bhndb dev/bhnd/bhndb/bhndb_if.m optional bhndbus | bhndb dev/bhnd/bhndb/bhndb_pci.c optional bhndbus pci | bhndb pci dev/bhnd/bhndb/bhndb_pci_hwdata.c optional bhndbus pci | bhndb pci +dev/bhnd/bhndb/bhndb_pci_sprom.c optional bhndbus pci | bhndb pci dev/bhnd/bhndb/bhndb_subr.c optional bhndbus pci | bhndb dev/bhnd/bcma/bcma.c optional bhndbus | bcma dev/bhnd/bcma/bcma_bhndb.c optional bhndbus | bcma bhndb @@ -1132,6 +1143,8 @@ dev/bhnd/cores/pci/bhnd_pci.c optional bhndbus pci | bhnd pci dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndbus pci | bhndb pci dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci dev/bhnd/nvram/bhnd_nvram_if.m optional bhndbus | bhnd +dev/bhnd/nvram/bhnd_sprom.c optional bhndbus | bhnd +dev/bhnd/nvram/nvram_subr.c optional bhndbus | bhnd dev/bhnd/siba/siba.c optional bhndbus | siba dev/bhnd/siba/siba_bhndb.c optional bhndbus | siba bhndb dev/bhnd/siba/siba_nexus.c optional siba_nexus siba diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 9e6b06c..2264ece 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -411,6 +411,26 @@ ${_i}devs.h: ${SYSDIR}/tools/${_i}devs2h.awk ${SYSDIR}/dev/${_i}/${_i}devs .endif .endfor # _i +.if !empty(SRCS:Mbhnd_nvram_map.h) +CLEANFILES+= bhnd_nvram_map.h +bhnd_nvram_map.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \ + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map +bhnd_nvram_map.h: + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map -h +.endif + +.if !empty(SRCS:Mbhnd_nvram_map_data.h) +CLEANFILES+= bhnd_nvram_map_data.h +bhnd_nvram_map_data.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \ + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map +bhnd_nvram_map_data.h: + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map -d +.endif + .if !empty(SRCS:Musbdevs.h) CLEANFILES+= usbdevs.h usbdevs.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs diff --git a/sys/dev/bhnd/bcmsrom_fmt.h b/sys/dev/bhnd/bcmsrom_fmt.h deleted file mode 100644 index 66c2b9d..0000000 --- a/sys/dev/bhnd/bcmsrom_fmt.h +++ /dev/null @@ -1,373 +0,0 @@ -/*- - * Copyright (c) 2010 Broadcom Corporation - * - * This file is derived from the bcmsrom.h header distributed with Broadcom's - * brcm80211 Linux driver release, as contributed to the Linux staging - * repository. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef _BHND_BCMSROM_FMT_H_ -#define _BHND_BCMSROM_FMT_H_ - -/* Maximum srom: 6 Kilobits == 768 bytes */ -#define SROM_MAX 768 -#define SROM_MAXW 384 -#define VARS_MAX 4096 - -/* PCI fields */ -#define PCI_F0DEVID 48 - -#define SROM_WORDS 64 - -#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ - -#define SROM_SSID 2 - -#define SROM_WL1LHMAXP 29 - -#define SROM_WL1LPAB0 30 -#define SROM_WL1LPAB1 31 -#define SROM_WL1LPAB2 32 - -#define SROM_WL1HPAB0 33 -#define SROM_WL1HPAB1 34 -#define SROM_WL1HPAB2 35 - -#define SROM_MACHI_IL0 36 -#define SROM_MACMID_IL0 37 -#define SROM_MACLO_IL0 38 -#define SROM_MACHI_ET0 39 -#define SROM_MACMID_ET0 40 -#define SROM_MACLO_ET0 41 -#define SROM_MACHI_ET1 42 -#define SROM_MACMID_ET1 43 -#define SROM_MACLO_ET1 44 -#define SROM3_MACHI 37 -#define SROM3_MACMID 38 -#define SROM3_MACLO 39 - -#define SROM_BXARSSI2G 40 -#define SROM_BXARSSI5G 41 - -#define SROM_TRI52G 42 -#define SROM_TRI5GHL 43 - -#define SROM_RXPO52G 45 - -#define SROM2_ENETPHY 45 - -#define SROM_AABREV 46 -/* Fields in AABREV */ -#define SROM_BR_MASK 0x00ff -#define SROM_CC_MASK 0x0f00 -#define SROM_CC_SHIFT 8 -#define SROM_AA0_MASK 0x3000 -#define SROM_AA0_SHIFT 12 -#define SROM_AA1_MASK 0xc000 -#define SROM_AA1_SHIFT 14 - -#define SROM_WL0PAB0 47 -#define SROM_WL0PAB1 48 -#define SROM_WL0PAB2 49 - -#define SROM_LEDBH10 50 -#define SROM_LEDBH32 51 - -#define SROM_WL10MAXP 52 - -#define SROM_WL1PAB0 53 -#define SROM_WL1PAB1 54 -#define SROM_WL1PAB2 55 - -#define SROM_ITT 56 - -#define SROM_BFL 57 -#define SROM_BFL2 28 -#define SROM3_BFL2 61 - -#define SROM_AG10 58 - -#define SROM_CCODE 59 - -#define SROM_OPO 60 - -#define SROM3_LEDDC 62 - -#define SROM_CRCREV 63 - -/* SROM Rev 4: Reallocate the software part of the srom to accommodate - * MIMO features. It assumes up to two PCIE functions and 440 bytes - * of useable srom i.e. the useable storage in chips with OTP that - * implements hardware redundancy. - */ - -#define SROM4_WORDS 220 - -#define SROM4_SIGN 32 -#define SROM4_SIGNATURE 0x5372 - -#define SROM4_BREV 33 - -#define SROM4_BFL0 34 -#define SROM4_BFL1 35 -#define SROM4_BFL2 36 -#define SROM4_BFL3 37 -#define SROM5_BFL0 37 -#define SROM5_BFL1 38 -#define SROM5_BFL2 39 -#define SROM5_BFL3 40 - -#define SROM4_MACHI 38 -#define SROM4_MACMID 39 -#define SROM4_MACLO 40 -#define SROM5_MACHI 41 -#define SROM5_MACMID 42 -#define SROM5_MACLO 43 - -#define SROM4_CCODE 41 -#define SROM4_REGREV 42 -#define SROM5_CCODE 34 -#define SROM5_REGREV 35 - -#define SROM4_LEDBH10 43 -#define SROM4_LEDBH32 44 -#define SROM5_LEDBH10 59 -#define SROM5_LEDBH32 60 - -#define SROM4_LEDDC 45 -#define SROM5_LEDDC 45 - -#define SROM4_AA 46 -#define SROM4_AA2G_MASK 0x00ff -#define SROM4_AA2G_SHIFT 0 -#define SROM4_AA5G_MASK 0xff00 -#define SROM4_AA5G_SHIFT 8 - -#define SROM4_AG10 47 -#define SROM4_AG32 48 - -#define SROM4_TXPID2G 49 -#define SROM4_TXPID5G 51 -#define SROM4_TXPID5GL 53 -#define SROM4_TXPID5GH 55 - -#define SROM4_TXRXC 61 -#define SROM4_TXCHAIN_MASK 0x000f -#define SROM4_TXCHAIN_SHIFT 0 -#define SROM4_RXCHAIN_MASK 0x00f0 -#define SROM4_RXCHAIN_SHIFT 4 -#define SROM4_SWITCH_MASK 0xff00 -#define SROM4_SWITCH_SHIFT 8 - -/* Per-path fields */ -#define MAX_PATH_SROM 4 -#define SROM4_PATH0 64 -#define SROM4_PATH1 87 -#define SROM4_PATH2 110 -#define SROM4_PATH3 133 - -#define SROM4_2G_ITT_MAXP 0 -#define SROM4_2G_PA 1 -#define SROM4_5G_ITT_MAXP 5 -#define SROM4_5GLH_MAXP 6 -#define SROM4_5G_PA 7 -#define SROM4_5GL_PA 11 -#define SROM4_5GH_PA 15 - -/* Fields in the ITT_MAXP and 5GLH_MAXP words */ -#define B2G_MAXP_MASK 0xff -#define B2G_ITT_SHIFT 8 -#define B5G_MAXP_MASK 0xff -#define B5G_ITT_SHIFT 8 -#define B5GH_MAXP_MASK 0xff -#define B5GL_MAXP_SHIFT 8 - -/* All the miriad power offsets */ -#define SROM4_2G_CCKPO 156 -#define SROM4_2G_OFDMPO 157 -#define SROM4_5G_OFDMPO 159 -#define SROM4_5GL_OFDMPO 161 -#define SROM4_5GH_OFDMPO 163 -#define SROM4_2G_MCSPO 165 -#define SROM4_5G_MCSPO 173 -#define SROM4_5GL_MCSPO 181 -#define SROM4_5GH_MCSPO 189 -#define SROM4_CDDPO 197 -#define SROM4_STBCPO 198 -#define SROM4_BW40PO 199 -#define SROM4_BWDUPPO 200 - -#define SROM4_CRCREV 219 - -/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. - * This is acombined srom for both MIMO and SISO boards, usable in - * the .130 4Kilobit OTP with hardware redundancy. - */ - -#define SROM8_SIGN 64 - -#define SROM8_BREV 65 - -#define SROM8_BFL0 66 -#define SROM8_BFL1 67 -#define SROM8_BFL2 68 -#define SROM8_BFL3 69 - -#define SROM8_MACHI 70 -#define SROM8_MACMID 71 -#define SROM8_MACLO 72 - -#define SROM8_CCODE 73 -#define SROM8_REGREV 74 - -#define SROM8_LEDBH10 75 -#define SROM8_LEDBH32 76 - -#define SROM8_LEDDC 77 - -#define SROM8_AA 78 - -#define SROM8_AG10 79 -#define SROM8_AG32 80 - -#define SROM8_TXRXC 81 - -#define SROM8_BXARSSI2G 82 -#define SROM8_BXARSSI5G 83 -#define SROM8_TRI52G 84 -#define SROM8_TRI5GHL 85 -#define SROM8_RXPO52G 86 - -#define SROM8_FEM2G 87 -#define SROM8_FEM5G 88 -#define SROM8_FEM_ANTSWLUT_MASK 0xf800 -#define SROM8_FEM_ANTSWLUT_SHIFT 11 -#define SROM8_FEM_TR_ISO_MASK 0x0700 -#define SROM8_FEM_TR_ISO_SHIFT 8 -#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 -#define SROM8_FEM_PDET_RANGE_SHIFT 3 -#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 -#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 -#define SROM8_FEM_TSSIPOS_MASK 0x0001 -#define SROM8_FEM_TSSIPOS_SHIFT 0 - -#define SROM8_THERMAL 89 - -/* Temp sense related entries */ -#define SROM8_MPWR_RAWTS 90 -#define SROM8_TS_SLP_OPT_CORRX 91 -/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */ -#define SROM8_FOC_HWIQ_IQSWP 92 - -/* Temperature delta for PHY calibration */ -#define SROM8_PHYCAL_TEMPDELTA 93 - -/* Per-path offsets & fields */ -#define SROM8_PATH0 96 -#define SROM8_PATH1 112 -#define SROM8_PATH2 128 -#define SROM8_PATH3 144 - -#define SROM8_2G_ITT_MAXP 0 -#define SROM8_2G_PA 1 -#define SROM8_5G_ITT_MAXP 4 -#define SROM8_5GLH_MAXP 5 -#define SROM8_5G_PA 6 -#define SROM8_5GL_PA 9 -#define SROM8_5GH_PA 12 - -/* All the miriad power offsets */ -#define SROM8_2G_CCKPO 160 - -#define SROM8_2G_OFDMPO 161 -#define SROM8_5G_OFDMPO 163 -#define SROM8_5GL_OFDMPO 165 -#define SROM8_5GH_OFDMPO 167 - -#define SROM8_2G_MCSPO 169 -#define SROM8_5G_MCSPO 177 -#define SROM8_5GL_MCSPO 185 -#define SROM8_5GH_MCSPO 193 - -#define SROM8_CDDPO 201 -#define SROM8_STBCPO 202 -#define SROM8_BW40PO 203 -#define SROM8_BWDUPPO 204 - -/* SISO PA parameters are in the path0 spaces */ -#define SROM8_SISO 96 - -/* Legacy names for SISO PA parameters */ -#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) -#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) -#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) -#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) -#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) -#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) -#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) -#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) -#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) -#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) -#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) -#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) -#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) -#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) -#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) - -#define SROM8_CRCREV 219 - -/* SROM REV 9 */ -#define SROM9_2GPO_CCKBW20 160 -#define SROM9_2GPO_CCKBW20UL 161 -#define SROM9_2GPO_LOFDMBW20 162 -#define SROM9_2GPO_LOFDMBW20UL 164 - -#define SROM9_5GLPO_LOFDMBW20 166 -#define SROM9_5GLPO_LOFDMBW20UL 168 -#define SROM9_5GMPO_LOFDMBW20 170 -#define SROM9_5GMPO_LOFDMBW20UL 172 -#define SROM9_5GHPO_LOFDMBW20 174 -#define SROM9_5GHPO_LOFDMBW20UL 176 - -#define SROM9_2GPO_MCSBW20 178 -#define SROM9_2GPO_MCSBW20UL 180 -#define SROM9_2GPO_MCSBW40 182 - -#define SROM9_5GLPO_MCSBW20 184 -#define SROM9_5GLPO_MCSBW20UL 186 -#define SROM9_5GLPO_MCSBW40 188 -#define SROM9_5GMPO_MCSBW20 190 -#define SROM9_5GMPO_MCSBW20UL 192 -#define SROM9_5GMPO_MCSBW40 194 -#define SROM9_5GHPO_MCSBW20 196 -#define SROM9_5GHPO_MCSBW20UL 198 -#define SROM9_5GHPO_MCSBW40 200 - -#define SROM9_PO_MCS32 202 -#define SROM9_PO_LOFDM40DUP 203 - -#define SROM9_REV_CRC 219 - -typedef struct { - u8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */ - u8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ - u8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */ - u8 triso; /* TR switch isolation */ - u8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */ -} srom_fem_t; - -#endif /* _BHND_BCMSROM_TBL_H_ */ diff --git a/sys/dev/bhnd/bcmsrom_tbl.h b/sys/dev/bhnd/bcmsrom_tbl.h deleted file mode 100644 index 1373f3f..0000000 --- a/sys/dev/bhnd/bcmsrom_tbl.h +++ /dev/null @@ -1,577 +0,0 @@ -/*- - * Copyright (c) 2010 Broadcom Corporation - * - * This file is derived from the bcmsrom.h header distributed with Broadcom's - * brcm80211 Linux driver release, as contributed to the Linux staging - * repository. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef _BHND_BCMSROM_TBL_H_ -#define _BHND_BCMSROM_TBL_H_ - -#include "bcmsrom_fmt.h" - -typedef struct { - const char *name; - u32 revmask; - u32 flags; - u16 off; - u16 mask; -} sromvar_t; - -#define SRFL_MORE 1 /* value continues as described by the next entry */ -#define SRFL_NOFFS 2 /* value bits can't be all one's */ -#define SRFL_PRHEX 4 /* value is in hexdecimal format */ -#define SRFL_PRSIGN 8 /* value is in signed decimal format */ -#define SRFL_CCODE 0x10 /* value is in country code format */ -#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ -#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ -#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */ - -/* Assumptions: - * - Ethernet address spans across 3 consective words - * - * Table rules: - * - Add multiple entries next to each other if a value spans across multiple words - * (even multiple fields in the same word) with each entry except the last having - * it's SRFL_MORE bit set. - * - Ethernet address entry does not follow above rule and must not have SRFL_MORE - * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. - * - The last entry's name field must be NULL to indicate the end of the table. Other - * entries must have non-NULL name. - */ - -static const sromvar_t pci_sromvars[] = { - {"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff}, - {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, - {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, - {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, - {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, - {"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, - {"", 0, 0, SROM_BFL2, 0xffff}, - {"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, - {"", 0, 0, SROM3_BFL2, 0xffff}, - {"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff}, - {"", 0, 0, SROM4_BFL1, 0xffff}, - {"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff}, - {"", 0, 0, SROM5_BFL1, 0xffff}, - {"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff}, - {"", 0, 0, SROM8_BFL1, 0xffff}, - {"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff}, - {"", 0, 0, SROM4_BFL3, 0xffff}, - {"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff}, - {"", 0, 0, SROM5_BFL3, 0xffff}, - {"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff}, - {"", 0, 0, SROM8_BFL3, 0xffff}, - {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, - {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, - {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, - {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, - {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, - {"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff}, - {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, - {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, - {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff}, - {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff}, - {"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff}, - {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, - {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, - {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, - {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, - {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, - {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, - {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, - {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, - {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, - {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, - {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, - {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, - {"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, - {"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, - {"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, - {"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, - {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, - {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, - {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, - {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff}, - {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, - {"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, - {"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, - {"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, - {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, - {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, - {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff}, - {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, - {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, - {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff}, - {"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff}, - {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, - {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, - {"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00}, - {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff}, - {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, - {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff}, - {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, - {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff}, - {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, - {"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff}, - {"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00}, - {"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff}, - {"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00}, - {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, - {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, - {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, - {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, - {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, - {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, - {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, - {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, - {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, - {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, - {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, - {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, - {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, - {"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, - {"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, - {"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, - {"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, - {"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, - {"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, - {"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, - {"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, - {"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, - {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, - {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, - {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, - {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, - {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, - {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, - {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, - {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, - {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, - {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, - {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, - {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, - {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, - {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, - {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, - {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, - {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, - {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, - {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, - {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, - {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff}, - {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, - {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, - {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, - {"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, - {"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00}, - {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, - {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, - {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, - {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, - {"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, - {"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, - {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, - {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, - {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, - {"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, - {"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, - {"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, - {"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK}, - {"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK}, - {"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK}, - {"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, - {"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK}, - {"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK}, - {"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK}, - {"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK}, - {"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, - {"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK}, - {"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00}, - {"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, - {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, - {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, - {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G+1, 0x00ff}, - {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G+1, 0xff00}, - {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, - {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, - {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G+1, 0x00ff}, - {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G+1, 0xff00}, - {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, - {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, - {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL+1, 0x00ff}, - {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL+1, 0xff00}, - {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, - {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, - {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH+1, 0x00ff}, - {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH+1, 0xff00}, - - {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, - {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, - {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, - {"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, - {"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, - {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, - {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, - {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, - {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, - {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, - {"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff}, - {"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff}, - {"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff}, - {"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff}, - {"rawtempsense",0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff}, - {"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00}, - {"tempsense_slope",0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff}, - {"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00}, - {"tempsense_option",0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300}, - {"freqoffset_corr",0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f}, - {"iqcal_swp_dis",0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010}, - {"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020}, - {"phycal_tempdelta",0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff}, - - {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, - {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, - {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_2G_OFDMPO+1, 0xffff}, - {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5G_OFDMPO+1, 0xffff}, - {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5GL_OFDMPO+1, 0xffff}, - {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5GH_OFDMPO+1, 0xffff}, - {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_2G_OFDMPO+1, 0xffff}, - {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5G_OFDMPO+1, 0xffff}, - {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5GL_OFDMPO+1, 0xffff}, - {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5GH_OFDMPO+1, 0xffff}, - - {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, - {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO+1, 0xffff}, - {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO+2, 0xffff}, - {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO+3, 0xffff}, - {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO+4, 0xffff}, - {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO+5, 0xffff}, - {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO+6, 0xffff}, - {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO+7, 0xffff}, - - {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, - {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO+1, 0xffff}, - {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO+2, 0xffff}, - {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO+3, 0xffff}, - {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO+4, 0xffff}, - {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO+5, 0xffff}, - {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO+6, 0xffff}, - {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO+7, 0xffff}, - - {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, - {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO+1, 0xffff}, - {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO+2, 0xffff}, - {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO+3, 0xffff}, - {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO+4, 0xffff}, - {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO+5, 0xffff}, - {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO+6, 0xffff}, - {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO+7, 0xffff}, - - {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, - {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO+1, 0xffff}, - {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO+2, 0xffff}, - {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO+3, 0xffff}, - {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO+4, 0xffff}, - {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO+5, 0xffff}, - {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO+6, 0xffff}, - {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO+7, 0xffff}, - - {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, - {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO+1, 0xffff}, - {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO+2, 0xffff}, - {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO+3, 0xffff}, - {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO+4, 0xffff}, - {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO+5, 0xffff}, - {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO+6, 0xffff}, - {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO+7, 0xffff}, - - {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, - {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO+1, 0xffff}, - {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO+2, 0xffff}, - {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO+3, 0xffff}, - {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO+4, 0xffff}, - {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO+5, 0xffff}, - {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO+6, 0xffff}, - {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO+7, 0xffff}, - - {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, - {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO+1, 0xffff}, - {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO+2, 0xffff}, - {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO+3, 0xffff}, - {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO+4, 0xffff}, - {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO+5, 0xffff}, - {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO+6, 0xffff}, - {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO+7, 0xffff}, - {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, - {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO+1, 0xffff}, - {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO+2, 0xffff}, - {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO+3, 0xffff}, - {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO+4, 0xffff}, - {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO+5, 0xffff}, - {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO+6, 0xffff}, - {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO+7, 0xffff}, - {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, - {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, - {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, - {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, - {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff}, - {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff}, - {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff}, - {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, - - /* power per rate from sromrev 9 */ - {"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, - {"cckbw20ul2gpo",0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, - {"legofdmbw202gpo",0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_2GPO_LOFDMBW20+1, 0xffff}, - {"legofdmbw20ul2gpo",0xfffffe00,SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff}, - {"", 0, 0, SROM9_2GPO_LOFDMBW20UL+1,0xffff}, - {"legofdmbw205glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_5GLPO_LOFDMBW20+1,0xffff}, - {"legofdmbw20ul5glpo",0xfffffe00,SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,0xffff}, - {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL+1,0xffff}, - {"legofdmbw205gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_5GMPO_LOFDMBW20+1,0xffff}, - {"legofdmbw20ul5gmpo",0xfffffe00,SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,0xffff}, - {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL+1,0xffff}, - {"legofdmbw205ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_5GHPO_LOFDMBW20+1,0xffff}, - {"legofdmbw20ul5ghpo",0xfffffe00,SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,0xffff}, - {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL+1,0xffff}, - {"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_2GPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul2gpo",0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_2GPO_MCSBW20UL+1, 0xffff}, - {"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_2GPO_MCSBW40+1, 0xffff}, - {"mcsbw205glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_5GLPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul5glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_5GLPO_MCSBW20UL+1,0xffff}, - {"mcsbw405glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_5GLPO_MCSBW40+1, 0xffff}, - {"mcsbw205gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_5GMPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul5gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_5GMPO_MCSBW20UL+1,0xffff}, - {"mcsbw405gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_5GMPO_MCSBW40+1, 0xffff}, - {"mcsbw205ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_5GHPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul5ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_5GHPO_MCSBW20UL+1,0xffff}, - {"mcsbw405ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_5GHPO_MCSBW40+1, 0xffff}, - {"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, - {"legofdm40duppo",0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, - - {NULL, 0, 0, 0, 0} -}; - -static const sromvar_t perpath_pci_sromvars[] = { - {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, - {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, - {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, - {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, - {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+1, 0xffff}, - {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+2, 0xffff}, - {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+3, 0xffff}, - {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, - {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, - {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, - {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, - {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+1, 0xffff}, - {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+2, 0xffff}, - {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+3, 0xffff}, - {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, - {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+1, 0xffff}, - {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+2, 0xffff}, - {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+3, 0xffff}, - {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, - {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+1, 0xffff}, - {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+2, 0xffff}, - {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+3, 0xffff}, - {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, - {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, - {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, - {"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, - {"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA+1, 0xffff}, - {"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA+2, 0xffff}, - {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, - {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, - {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, - {"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, - {"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA+1, 0xffff}, - {"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA+2, 0xffff}, - {"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, - {"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA+1, 0xffff}, - {"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA+2, 0xffff}, - {"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, - {"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA+1, 0xffff}, - {"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA+2, 0xffff}, - {NULL, 0, 0, 0, 0} -}; - -#if !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) -#define PHY_TYPE_N 4 /* N-Phy value */ -#define PHY_TYPE_LP 5 /* LP-Phy value */ -#endif /* !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */ -#if !defined(PHY_TYPE_NULL) -#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ -#endif /* !defined(PHY_TYPE_NULL) */ - -typedef struct { - u16 phy_type; - u16 bandrange; - u16 chain; - const char *vars; -} pavars_t; - -static const pavars_t pavars[] = { - /* NPHY */ - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, - /* LPPHY */ - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"}, - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"}, - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"}, - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"}, - {PHY_TYPE_NULL, 0, 0, ""} -}; - -typedef struct { - u16 phy_type; - u16 bandrange; - const char *vars; -} povars_t; - -static const povars_t povars[] = { - /* NPHY */ - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, - "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 " - "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, - "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 " - "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, - "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 " - "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, - "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 " - "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"}, - {PHY_TYPE_NULL, 0, ""} -}; - -typedef struct { - u8 tag; /* Broadcom subtag name */ - u8 len; /* Length field of the tuple, note that it includes the - * subtag name (1 byte): 1 + tuple content length - */ - const char *params; -} cis_tuple_t; - -#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */ -#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */ -#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */ -#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */ - -static const cis_tuple_t cis_hnbuvars[] = { - {OTP_RAW1, 0, ""}, /* special case */ - {OTP_VERS_1, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */ - {OTP_MANFID, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */ - {HNBU_SROMREV, 2, "1sromrev"}, - /* NOTE: subdevid is also written to boardtype. - * Need to write HNBU_BOARDTYPE to change it if it is different. - */ - {HNBU_CHIPID, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"}, - {HNBU_BOARDREV, 3, "2boardrev"}, - {HNBU_PAPARMS, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"}, - {HNBU_AA, 3, "1aa2g 1aa5g"}, - {HNBU_AA, 3, "1aa0 1aa1"}, /* backward compatibility */ - {HNBU_AG, 5, "1ag0 1ag1 1ag2 1ag3"}, - {HNBU_BOARDFLAGS, 9, "4boardflags 4boardflags2"}, - {HNBU_LEDS, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"}, - {HNBU_CCODE, 4, "2ccode 1cctl"}, - {HNBU_CCKPO, 3, "2cckpo"}, - {HNBU_OFDMPO, 5, "4ofdmpo"}, - {HNBU_RDLID, 3, "2rdlid"}, - {HNBU_RSSISMBXA2G, 3, "0rssismf2g 0rssismc2g 0rssisav2g 0bxa2g"}, /* special case */ - {HNBU_RSSISMBXA5G, 3, "0rssismf5g 0rssismc5g 0rssisav5g 0bxa5g"}, /* special case */ - {HNBU_XTALFREQ, 5, "4xtalfreq"}, - {HNBU_TRI2G, 2, "1tri2g"}, - {HNBU_TRI5G, 4, "1tri5gl 1tri5g 1tri5gh"}, - {HNBU_RXPO2G, 2, "1rxpo2g"}, - {HNBU_RXPO5G, 2, "1rxpo5g"}, - {HNBU_BOARDNUM, 3, "2boardnum"}, - {HNBU_MACADDR, 7, "6macaddr"}, /* special case */ - {HNBU_RDLSN, 3, "2rdlsn"}, - {HNBU_BOARDTYPE, 3, "2boardtype"}, - {HNBU_LEDDC, 3, "2leddc"}, - {HNBU_RDLRNDIS, 2, "1rdlndis"}, - {HNBU_CHAINSWITCH, 5, "1txchain 1rxchain 2antswitch"}, - {HNBU_REGREV, 2, "1regrev"}, - {HNBU_FEM, 5, "0antswctl2g, 0triso2g, 0pdetrange2g, 0extpagain2g, 0tssipos2g" "0antswctl5g, 0triso5g, 0pdetrange5g, 0extpagain5g, 0tssipos5g"}, /* special case */ - {HNBU_PAPARMS_C0, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 " - "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 " - "2pa5gw1a0 2pa5gw2a0 2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 " - "2pa5ghw1a0 2pa5ghw2a0"}, - {HNBU_PAPARMS_C1, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 " - "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 " - "2pa5gw1a1 2pa5gw2a1 2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 " - "2pa5ghw1a1 2pa5ghw2a1"}, - {HNBU_PO_CCKOFDM, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo " - "4ofdm5ghpo"}, - {HNBU_PO_MCS2G, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 " - "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"}, - {HNBU_PO_MCS5GM, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 " - "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"}, - {HNBU_PO_MCS5GLH, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 " - "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 " - "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 " - "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"}, - {HNBU_CCKFILTTYPE, 2, "1cckdigfilttype"}, - {HNBU_PO_CDD, 3, "2cddpo"}, - {HNBU_PO_STBC, 3, "2stbcpo"}, - {HNBU_PO_40M, 3, "2bw40po"}, - {HNBU_PO_40MDUP, 3, "2bwduppo"}, - {HNBU_RDLRWU, 2, "1rdlrwu"}, - {HNBU_WPS, 3, "1wpsgpio 1wpsled"}, - {HNBU_USBFS, 2, "1usbfs"}, - {HNBU_CUSTOM1, 5, "4customvar1"}, - {OTP_RAW, 0, ""}, /* special case */ - {HNBU_OFDMPO5G, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"}, - {HNBU_USBEPNUM, 3, "2usbepnum"}, - {0xFF, 0, ""} -}; - -#endif /* _BHND_BCMSROM_TBL_H_ */ diff --git a/sys/dev/bhnd/bhnd.c b/sys/dev/bhnd/bhnd.c index 8b3c378..3be15b2 100644 --- a/sys/dev/bhnd/bhnd.c +++ b/sys/dev/bhnd/bhnd.c @@ -58,11 +58,14 @@ __FBSDID("$FreeBSD$"); #include #include -#include "bhnd.h" -#include "bhndvar.h" +#include "nvram/bhnd_nvram.h" +#include "bhnd_chipc_if.h" #include "bhnd_nvram_if.h" +#include "bhnd.h" +#include "bhndvar.h" + MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures"); /** @@ -386,23 +389,27 @@ bhnd_generic_is_region_valid(device_t dev, device_t child, static device_t find_nvram_child(device_t dev) { - device_t chipc, nvram; + device_t chipc, nvram; /* Look for a directly-attached NVRAM child */ - nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass), - -1); - if (nvram == NULL) - return (NULL); + nvram = device_find_child(dev, "bhnd_nvram", 0); + if (nvram != NULL) + return (nvram); - /* Further checks require a bhnd(4) bus */ + /* Remaining checks are only applicable when searching a bhnd(4) + * bus. */ if (device_get_devclass(dev) != bhnd_devclass) return (NULL); - /* Look for a ChipCommon-attached OTP device */ + /* Look for a ChipCommon device */ if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) { - /* Recursively search the ChipCommon device */ - if ((nvram = find_nvram_child(chipc)) != NULL) - return (nvram); + bhnd_nvram_src_t src; + + /* Query the NVRAM source and determine whether it's + * accessible via the ChipCommon device */ + src = BHND_CHIPC_NVRAM_SRC(chipc); + if (BHND_NVRAM_SRC_CC(src)) + return (chipc); } /* Not found */ @@ -410,22 +417,26 @@ find_nvram_child(device_t dev) } /** - * Default bhnd(4) bus driver implementation of BHND_BUS_READ_NVRAM_VAR(). + * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR(). + * + * This implementation searches @p dev for a usable NVRAM child device: + * - The first child device implementing the bhnd_nvram devclass is + * returned, otherwise + * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an + * attached NVRAM source. * - * This implementation searches @p dev for a valid NVRAM device. If no NVRAM - * child device is found on @p dev, the request is delegated to the - * BHND_BUS_READ_NVRAM_VAR() method on the parent - * of @p dev. + * If no usable child device is found on @p dev, the request is delegated to + * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. */ static int -bhnd_generic_read_nvram_var(device_t dev, device_t child, const char *name, +bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size) { device_t nvram; /* Try to find an NVRAM device applicable to @p child */ if ((nvram = find_nvram_child(dev)) == NULL) - return (BHND_BUS_READ_NVRAM_VAR(device_get_parent(dev), child, + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, name, buf, size)); return BHND_NVRAM_GETVAR(nvram, name, buf, size); @@ -682,7 +693,7 @@ static device_method_t bhnd_methods[] = { DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), - DEVMETHOD(bhnd_bus_read_nvram_var, bhnd_generic_read_nvram_var), + DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index 55d2081..dca9867 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -464,6 +464,55 @@ bhnd_get_chipid(device_t dev) { return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev)); }; +/** + * Determine an NVRAM variable's expected size. + * + * @param dev A bhnd bus child device. + * @param name The variable name. + * @param[out] len On success, the variable's size, in bytes. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +static inline int +bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len) +{ + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, NULL, + len)); +} + +/** + * Read an NVRAM variable. + * + * @param dev A bhnd bus child device. + * @param name The NVRAM variable name. + * @param buf A buffer large enough to hold @p len bytes. On success, + * the requested value will be written to this buffer. + * @param len The required variable length. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval EINVAL If @p len does not match the actual variable size. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +static inline int +bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t len) +{ + size_t var_len; + int error; + + if ((error = bhnd_nvram_getvarlen(dev, name, &var_len))) + return (error); + + if (len != var_len) + return (EINVAL); + + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf, + &len)); +} /** * Allocate a resource from a device's parent bhnd(4) bus. diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m index 2622524..9762288 100644 --- a/sys/dev/bhnd/bhnd_bus_if.m +++ b/sys/dev/bhnd/bhnd_bus_if.m @@ -96,7 +96,7 @@ CODE { } static int - bhnd_bus_null_read_nvram_var(device_t dev, device_t child, + bhnd_bus_null_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size) { return (ENOENT); @@ -403,13 +403,13 @@ METHOD int get_region_addr { * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ -METHOD int read_nvram_var { +METHOD int get_nvram_var { device_t dev; device_t child; const char *name; void *buf; size_t *size; -} DEFAULT bhnd_bus_null_read_nvram_var; +} DEFAULT bhnd_bus_null_get_nvram_var; /** An implementation of bus_read_1() compatible with bhnd_resource */ diff --git a/sys/dev/bhnd/bhnd_ids.h b/sys/dev/bhnd/bhnd_ids.h index e28e53b..5000cf7 100644 --- a/sys/dev/bhnd/bhnd_ids.h +++ b/sys/dev/bhnd/bhnd_ids.h @@ -328,6 +328,7 @@ #define BHND_CHIPID_BCM43428 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43431 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43460 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ +#define BHND_CHIPID_BCM43462 0xA9C6 /* 43462 chipcommon chipid */ #define BHND_CHIPID_BCM4325 0x4325 /* 4325 chip id */ #define BHND_CHIPID_BCM4328 0x4328 /* 4328 chip id */ #define BHND_CHIPID_BCM4329 0x4329 /* 4329 chipcommon chipid */ @@ -345,6 +346,7 @@ #define BHND_CHIPID_BCM4334 0x4334 /* 4334 chipcommon chipid */ #define BHND_CHIPID_BCM4335 0x4335 /* 4335 chipcommon chipid */ #define BHND_CHIPID_BCM4360 0x4360 /* 4360 chipcommon chipid */ +#define BHND_CHIPID_BCM43602 0xaa52 /* 43602 chipcommon chipid */ #define BHND_CHIPID_BCM4352 0x4352 /* 4352 chipcommon chipid */ #define BHND_CHIPID_BCM43526 0xAA06 #define BHND_CHIPID_BCM43341 43341 /* 43341 chipcommon chipid */ @@ -433,7 +435,6 @@ #define BHND_PKGID_BCM4335_FCBGAD (0x3) /* FCBGA Debug Debug/Dev All if's. */ #define BHND_PKGID_PKG_MASK_BCM4335 (0x3) - /* Broadcom Core IDs */ #define BHND_COREID_INVALID 0x700 /* Invalid coreid */ #define BHND_COREID_CC 0x800 /* chipcommon core */ diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c index 6ca1efc..b75c04a 100644 --- a/sys/dev/bhnd/bhndb/bhndb.c +++ b/sys/dev/bhnd/bhndb/bhndb.c @@ -51,6 +51,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#include "bhnd_chipc_if.h" +#include "bhnd_nvram_if.h" #include "bhndbvar.h" #include "bhndb_bus_if.h" @@ -609,7 +613,7 @@ bhndb_generic_init_full_config(device_t dev, device_t child, goto cleanup; } - if (bootverbose) + if (bootverbose || BHNDB_DEBUG(PRIO)) device_printf(sc->dev, "%s resource configuration\n", hw->name); /* Release existing resource state */ @@ -1298,9 +1302,10 @@ bhndb_retain_dynamic_window(struct bhndb_softc *sc, struct resource *r) rman_get_size(r)); if (error) { device_printf(sc->dev, "dynamic window initialization " - "for 0x%llx-0x%llx failed\n", + "for 0x%llx-0x%llx failed: %d\n", (unsigned long long) r_start, - (unsigned long long) r_start + r_size - 1); + (unsigned long long) r_start + r_size - 1, + error); return (NULL); } @@ -1709,6 +1714,26 @@ bhndb_io_resource(struct bhndb_softc *sc, bus_addr_t addr, bus_size_t size, return (dwa); } +/** + * Default bhndb(4) implementation of BHND_BUS_GET_NVRAM_VAR(). + */ +static int +bhndb_get_nvram_var(device_t dev, device_t child, const char *name, + void *buf, size_t *size) +{ + device_t nvram; + + /* Look for a directly-attached NVRAM child */ + nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass), + 0); + if (nvram != NULL) + return (BHND_NVRAM_GETVAR(nvram, name, buf, size)); + + /* Otherwise, delegate to our parent */ + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, + name, buf, size)); +} + /* * BHND_BUS_(READ|WRITE_* implementations */ @@ -1936,6 +1961,7 @@ static device_method_t bhndb_methods[] = { DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), + DEVMETHOD(bhnd_bus_get_nvram_var, bhndb_get_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhndb_bus_read_1), DEVMETHOD(bhnd_bus_read_2, bhndb_bus_read_2), DEVMETHOD(bhnd_bus_read_4, bhndb_bus_read_4), diff --git a/sys/dev/bhnd/bhndb/bhndb_pci.c b/sys/dev/bhnd/bhndb/bhndb_pci.c index 9b3f260..33da141 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pci.c +++ b/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -61,15 +61,19 @@ __FBSDID("$FreeBSD$"); #include "bhndb_pcivar.h" #include "bhndb_private.h" -static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc); -static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc); +static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc); +static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc); -static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *, - const struct bhndb_regwin *, bhnd_addr_t); -static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *, - const struct bhndb_regwin *, bhnd_addr_t); +static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *, + const struct bhndb_regwin *, bhnd_addr_t); +static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *, + const struct bhndb_regwin *, bhnd_addr_t); -static void bhndb_init_sromless_pci_config(struct bhndb_pci_softc *sc); +static void bhndb_init_sromless_pci_config( + struct bhndb_pci_softc *sc); + +static bus_addr_t bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc); +static size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc); /** * Default bhndb_pci implementation of device_probe(). @@ -104,13 +108,14 @@ bhndb_pci_attach(device_t dev) sc = device_get_softc(dev); sc->dev = dev; + sc->parent = device_get_parent(dev); /* Enable PCI bus mastering */ - pci_enable_busmaster(device_get_parent(dev)); + pci_enable_busmaster(sc->parent); /* Determine our bridge device class */ sc->pci_devclass = BHND_DEVCLASS_PCI; - if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, ®) == 0) + if (pci_find_cap(sc->parent, PCIY_EXPRESS, ®) == 0) sc->pci_devclass = BHND_DEVCLASS_PCIE; /* Enable clocks (if supported by this hardware) */ @@ -142,6 +147,8 @@ bhndb_pci_init_full_config(device_t dev, device_t child, const struct bhndb_hw_priority *hw_prio_table) { struct bhndb_pci_softc *sc; + device_t nv_dev; + bus_size_t nv_sz; int error; sc = device_get_softc(dev); @@ -153,9 +160,126 @@ bhndb_pci_init_full_config(device_t dev, device_t child, /* Fix-up power on defaults for SROM-less devices. */ bhndb_init_sromless_pci_config(sc); + /* If SPROM is mapped directly into BAR0, add NVRAM device. */ + nv_sz = bhndb_pci_sprom_size(sc); + if (nv_sz > 0) { + struct bhndb_devinfo *dinfo; + const char *dname; + + if (bootverbose) { + device_printf(dev, "found SPROM (%zu bytes)\n", nv_sz); + } + + /* Add sprom device */ + dname = "bhnd_nvram"; + if ((nv_dev = BUS_ADD_CHILD(dev, 0, dname, -1)) == NULL) { + device_printf(dev, "failed to add sprom device\n"); + return (ENXIO); + } + + /* Initialize device address space and resource covering the + * BAR0 SPROM shadow. */ + dinfo = device_get_ivars(nv_dev); + dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE; + error = bus_set_resource(nv_dev, SYS_RES_MEMORY, 0, + bhndb_pci_sprom_addr(sc), nv_sz); + + if (error) { + device_printf(dev, + "failed to register sprom resources\n"); + return (error); + } + + /* Attach the device */ + if ((error = device_probe_and_attach(nv_dev))) { + device_printf(dev, "sprom attach failed\n"); + return (error); + } + } + return (0); } +static const struct bhndb_regwin * +bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc) +{ + struct bhndb_resources *bres; + const struct bhndb_hwcfg *cfg; + const struct bhndb_regwin *sprom_win; + + bres = sc->bhndb.bus_res; + cfg = bres->cfg; + + sprom_win = bhndb_regwin_find_type(cfg->register_windows, + BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE); + + return (sprom_win); +} + +static bus_addr_t +bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc) +{ + const struct bhndb_regwin *sprom_win; + struct resource *r; + + /* Fetch the SPROM register window */ + sprom_win = bhndb_pci_sprom_regwin(sc); + KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+")); + + /* Fetch the associated resource */ + r = bhndb_find_regwin_resource(sc->bhndb.bus_res, sprom_win); + KASSERT(r != NULL, ("missing resource for sprom window\n")); + + return (rman_get_start(r) + sprom_win->win_offset); +} + +static bus_size_t +bhndb_pci_sprom_size(struct bhndb_pci_softc *sc) +{ + const struct bhndb_regwin *sprom_win; + uint32_t sctl; + bus_size_t sprom_sz; + + sprom_win = bhndb_pci_sprom_regwin(sc); + + /* PCI_V2 and later devices map SPROM/OTP via ChipCommon */ + if (sprom_win == NULL) + return (0); + + /* Determine SPROM size */ + sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4); + if (sctl & BHNDB_PCI_SPROM_BLANK) + return (0); + + switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) { + case BHNDB_PCI_SPROM_SZ_1KB: + sprom_sz = (1 * 1024); + break; + + case BHNDB_PCI_SPROM_SZ_4KB: + sprom_sz = (4 * 1024); + break; + + case BHNDB_PCI_SPROM_SZ_16KB: + sprom_sz = (16 * 1024); + break; + + case BHNDB_PCI_SPROM_SZ_RESERVED: + default: + device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl); + return (0); + } + + if (sprom_sz > sprom_win->win_size) { + device_printf(sc->dev, + "PCI sprom size (0x%x) overruns defined register window\n", + sctl); + return (0); + } + + return (sprom_sz); +} + /* * On devices without a SROM, the PCI(e) cores will be initialized with * their Power-on-Reset defaults; this can leave two of the BAR0 PCI windows @@ -274,7 +398,7 @@ bhndb_pci_detach(device_t dev) return (error); /* Disable PCI bus mastering */ - pci_disable_busmaster(device_get_parent(dev)); + pci_disable_busmaster(sc->parent); return (0); } @@ -301,19 +425,18 @@ static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *sc, const struct bhndb_regwin *rw, bhnd_addr_t addr) { - device_t parent; int error; - - parent = sc->bhndb.parent_dev; + int reg; if (rw->win_type != BHNDB_REGWIN_T_DYN) return (ENODEV); + reg = rw->d.dyn.cfg_offset; for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) { if ((error = bhndb_pci_fast_setregwin(sc, rw, addr))) return (error); - if (pci_read_config(parent, rw->d.dyn.cfg_offset, 4) == addr) + if (pci_read_config(sc->parent, reg, 4) == addr) return (0); DELAY(10); @@ -330,8 +453,6 @@ static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc, const struct bhndb_regwin *rw, bhnd_addr_t addr) { - device_t parent = sc->bhndb.parent_dev; - /* The PCI bridge core only supports 32-bit addressing, regardless * of the bus' support for 64-bit addressing */ if (addr > UINT32_MAX) @@ -343,7 +464,7 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc, if (addr % rw->win_size != 0) return (EINVAL); - pci_write_config(parent, rw->d.dyn.cfg_offset, addr, 4); + pci_write_config(sc->parent, rw->d.dyn.cfg_offset, addr, 4); break; default: return (ENODEV); @@ -366,7 +487,6 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc, static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc) { - device_t pci_parent; uint32_t gpio_in, gpio_out, gpio_en; uint32_t gpio_flags; uint16_t pci_status; @@ -375,35 +495,33 @@ bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc) if (sc->pci_devclass != BHND_DEVCLASS_PCI) return (0); - pci_parent = device_get_parent(sc->dev); - /* Read state of XTAL pin */ - gpio_in = pci_read_config(pci_parent, BHNDB_PCI_GPIO_IN, 4); + gpio_in = pci_read_config(sc->parent, BHNDB_PCI_GPIO_IN, 4); if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON) return (0); /* already enabled */ /* Fetch current config */ - gpio_out = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUT, 4); - gpio_en = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, 4); + gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4); + gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4); /* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */ gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON); gpio_out |= gpio_flags; gpio_en |= gpio_flags; - pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); - pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); DELAY(1000); /* Reset PLL_OFF */ gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF; - pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); DELAY(5000); /* Clear any PCI 'sent target-abort' flag. */ - pci_status = pci_read_config(pci_parent, PCIR_STATUS, 2); + pci_status = pci_read_config(sc->parent, PCIR_STATUS, 2); pci_status &= ~PCIM_STATUS_STABORT; - pci_write_config(pci_parent, PCIR_STATUS, pci_status, 2); + pci_write_config(sc->parent, PCIR_STATUS, pci_status, 2); return (0); } @@ -416,31 +534,28 @@ bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc) static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc) { - device_t parent_dev; uint32_t gpio_out, gpio_en; /* Only supported and required on PCI devices */ if (sc->pci_devclass != BHND_DEVCLASS_PCI) return (0); - parent_dev = device_get_parent(sc->dev); - // TODO: Check board flags for BFL2_XTALBUFOUTEN? // TODO: Check PCI core revision? // TODO: Switch to 'slow' clock? /* Fetch current config */ - gpio_out = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUT, 4); - gpio_en = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, 4); + gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4); + gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4); /* Set PLL_OFF to HIGH, XTAL_ON to LOW. */ gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON; gpio_out |= BHNDB_PCI_GPIO_PLL_OFF; - pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); /* Enable both output pins */ gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON); - pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); return (0); } diff --git a/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c b/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c new file mode 100644 index 0000000..8f0ea56 --- /dev/null +++ b/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * BHNDB PCI SPROM driver. + * + * Provides support for early PCI bridge cores that vend SPROM CSRs + * via PCI configuration space. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "bhnd_nvram_if.h" +#include "bhndb_pcireg.h" +#include "bhndb_pcivar.h" + +struct bhndb_pci_sprom_softc { + device_t dev; + struct bhnd_resource *sprom_res; /**< SPROM resource */ + int sprom_rid; /**< SPROM RID */ + struct bhnd_sprom shadow; /**< SPROM shadow */ + struct mtx mtx; /**< SPROM shadow mutex */ +}; + +#define SPROM_LOCK_INIT(sc) \ + mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ + "BHND PCI SPROM lock", MTX_DEF) +#define SPROM_LOCK(sc) mtx_lock(&(sc)->mtx) +#define SPROM_UNLOCK(sc) mtx_unlock(&(sc)->mtx) +#define SPROM_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) +#define SPROM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) + +static int +bhndb_pci_sprom_probe(device_t dev) +{ + device_t bridge, bus; + + /* Our parent must be a PCI-BHND bridge with an attached bhnd bus */ + bridge = device_get_parent(dev); + if (device_get_driver(bridge) != &bhndb_pci_driver) + return (ENXIO); + + bus = device_find_child(bridge, devclass_get_name(bhnd_devclass), 0); + if (bus == NULL) + return (ENXIO); + + /* Found */ + device_set_desc(dev, "PCI-BHNDB SPROM/OTP"); + if (!bootverbose) + device_quiet(dev); + + /* Refuse wildcard attachments */ + return (BUS_PROBE_NOWILDCARD); +} + +static int +bhndb_pci_sprom_attach(device_t dev) +{ + struct bhndb_pci_sprom_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Allocate SPROM resource */ + sc->sprom_rid = 0; + sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->sprom_rid, RF_ACTIVE); + if (sc->sprom_res == NULL) { + device_printf(dev, "failed to allocate resources\n"); + return (ENXIO); + } + + /* Initialize SPROM shadow */ + if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) { + device_printf(dev, "unrecognized SPROM format\n"); + goto failed; + } + + /* Initialize mutex */ + SPROM_LOCK_INIT(sc); + + return (0); + +failed: + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, + sc->sprom_res); + return (error); +} + +static int +bhndb_pci_sprom_resume(device_t dev) +{ + return (0); +} + +static int +bhndb_pci_sprom_suspend(device_t dev) +{ + return (0); +} + +static int +bhndb_pci_sprom_detach(device_t dev) +{ + struct bhndb_pci_sprom_softc *sc; + + sc = device_get_softc(dev); + + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, + sc->sprom_res); + bhnd_sprom_fini(&sc->shadow); + SPROM_LOCK_DESTROY(sc); + + return (0); +} + +static int +bhndb_pci_sprom_getvar(device_t dev, const char *name, void *buf, size_t *len) +{ + struct bhndb_pci_sprom_softc *sc; + int error; + + sc = device_get_softc(dev); + + SPROM_LOCK(sc); + error = bhnd_sprom_getvar(&sc->shadow, name, buf, len); + SPROM_UNLOCK(sc); + + return (error); +} + +static int +bhndb_pci_sprom_setvar(device_t dev, const char *name, const void *buf, + size_t len) +{ + struct bhndb_pci_sprom_softc *sc; + int error; + + sc = device_get_softc(dev); + + SPROM_LOCK(sc); + error = bhnd_sprom_setvar(&sc->shadow, name, buf, len); + SPROM_UNLOCK(sc); + + return (error); +} + +static device_method_t bhndb_pci_sprom_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bhndb_pci_sprom_probe), + DEVMETHOD(device_attach, bhndb_pci_sprom_attach), + DEVMETHOD(device_resume, bhndb_pci_sprom_resume), + DEVMETHOD(device_suspend, bhndb_pci_sprom_suspend), + DEVMETHOD(device_detach, bhndb_pci_sprom_detach), + + /* NVRAM interface */ + DEVMETHOD(bhnd_nvram_getvar, bhndb_pci_sprom_getvar), + DEVMETHOD(bhnd_nvram_setvar, bhndb_pci_sprom_setvar), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(bhnd_nvram, bhndb_pci_sprom_driver, bhndb_pci_sprom_methods, sizeof(struct bhndb_pci_sprom_softc)); + +DRIVER_MODULE(bhndb_pci_sprom, bhndb, bhndb_pci_sprom_driver, bhnd_nvram_devclass, NULL, NULL); +MODULE_DEPEND(bhndb_pci_sprom, bhnd, 1, 1, 1); +MODULE_VERSION(bhndb_pci_sprom, 1); diff --git a/sys/dev/bhnd/bhndb/bhndb_pcireg.h b/sys/dev/bhnd/bhndb/bhndb_pcireg.h index 6f431ac..eb2dc66 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pcireg.h +++ b/sys/dev/bhnd/bhndb/bhndb_pcireg.h @@ -205,13 +205,17 @@ #define BHNDB_PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ /* BHNDB_PCI_SPROM_CONTROL */ -#define BHNDB_PCI_SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ -#define BHNDB_PCI_SPROM_LOCKED 0x08 /* SPROM Locked */ -#define BHNDB_PCI_SPROM_BLANK 0x04 /* indicating a blank SPROM */ -#define BHNDB_PCI_SPROM_WRITEEN 0x10 /* SPROM write enable */ -#define BHNDB_PCI_SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ -#define BHNDB_PCI_SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */ -#define BHNDB_PCI_SPROM_OTPIN_USE 0x80 /* device OTP In use */ +#define BHNDB_PCI_SPROM_SZ_MASK 0x03 /**< sprom size mask */ +#define BHNDB_PCI_SPROM_SZ_1KB 0x00 /**< 1KB sprom size */ +#define BHNDB_PCI_SPROM_SZ_4KB 0x01 /**< 4KB sprom size */ +#define BHNDB_PCI_SPROM_SZ_16KB 0x02 /**< 16KB sprom size */ +#define BHNDB_PCI_SPROM_SZ_RESERVED 0x03 /**< unsupported sprom size */ +#define BHNDB_PCI_SPROM_LOCKED 0x08 /**< sprom locked */ +#define BHNDB_PCI_SPROM_BLANK 0x04 /**< sprom blank */ +#define BHNDB_PCI_SPROM_WRITEEN 0x10 /**< sprom write enable */ +#define BHNDB_PCI_SPROM_BOOTROM_WE 0x20 /**< external bootrom write enable */ +#define BHNDB_PCI_SPROM_BACKPLANE_EN 0x40 /**< enable indirect backplane access (BHNDB_PCI_BACKPLANE_*) */ +#define BHNDB_PCI_SPROM_OTPIN_USE 0x80 /**< device OTP in use */ /* PCI (non-PCIe) BHNDB_PCI_GPIO_OUTEN */ diff --git a/sys/dev/bhnd/bhndb/bhndb_pcivar.h b/sys/dev/bhnd/bhndb/bhndb_pcivar.h index 021b393..7d7fcad 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pcivar.h +++ b/sys/dev/bhnd/bhndb/bhndb_pcivar.h @@ -51,6 +51,7 @@ typedef int (*bhndb_pci_set_regwin_t)(struct bhndb_pci_softc *sc, struct bhndb_pci_softc { struct bhndb_softc bhndb; /**< parent softc */ device_t dev; /**< bridge device */ + device_t parent; /**< parent PCI device */ bhnd_devclass_t pci_devclass; /**< PCI core's devclass */ bhndb_pci_set_regwin_t set_regwin; /**< regwin handler */ }; diff --git a/sys/dev/bhnd/cores/chipc/chipc.c b/sys/dev/bhnd/cores/chipc/chipc.c index eac1dcb..2f698ce 100644 --- a/sys/dev/bhnd/cores/chipc/chipc.c +++ b/sys/dev/bhnd/cores/chipc/chipc.c @@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$"); #include +#include "bhnd_nvram_if.h" + #include "chipcreg.h" #include "chipcvar.h" @@ -73,13 +75,44 @@ static const struct bhnd_device chipc_devices[] = { /* Device quirks table */ static struct bhnd_device_quirk chipc_quirks[] = { - { BHND_HWREV_RANGE (0, 21), CHIPC_QUIRK_ALWAYS_HAS_SPROM }, - { BHND_HWREV_EQ (22), CHIPC_QUIRK_SPROM_CHECK_CST_R22 }, - { BHND_HWREV_RANGE (23, 31), CHIPC_QUIRK_SPROM_CHECK_CST_R23 }, - { BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH }, + { BHND_HWREV_GTE (32), CHIPC_QUIRK_SUPPORTS_SPROM }, + { BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH }, BHND_DEVICE_QUIRK_END }; +/* Chip-specific quirks table */ +static struct bhnd_chip_quirk chipc_chip_quirks[] = { + /* 4331 12x9 packages */ + {{ BHND_CHIP_IP(4331, 4331TN) }, + CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM + }, + {{ BHND_CHIP_IP(4331, 4331TNA0) }, + CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM + }, + + /* 4331 12x12 packages */ + {{ BHND_CHIP_IPR(4331, 4331TT, HWREV_GTE(1)) }, + CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM + }, + + /* 4331 (all packages/revisions) */ + {{ BHND_CHIP_ID(4331) }, + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM + }, + + /* 4360 family (all revs <= 2) */ + {{ BHND_CHIP_IR(4352, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + {{ BHND_CHIP_IR(43460, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + {{ BHND_CHIP_IR(43462, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + {{ BHND_CHIP_IR(43602, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + + BHND_CHIP_QUIRK_END +}; + /* quirk and capability flag convenience macros */ #define CHIPC_QUIRK(_sc, _name) \ ((_sc)->quirks & CHIPC_QUIRK_ ## _name) @@ -91,7 +124,13 @@ static struct bhnd_device_quirk chipc_quirks[] = { KASSERT(CHIPC_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set")) #define CHIPC_ASSERT_CAP(_sc, name) \ - KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set")) + KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set")) + +static bhnd_nvram_src_t chipc_nvram_identify(struct chipc_softc *sc); +static int chipc_sprom_init(struct chipc_softc *); +static int chipc_enable_sprom_pins(struct chipc_softc *); +static int chipc_disable_sprom_pins(struct chipc_softc *); + static int chipc_probe(device_t dev) @@ -119,6 +158,9 @@ chipc_attach(device_t dev) sc->dev = dev; sc->quirks = bhnd_device_quirks(dev, chipc_devices, sizeof(chipc_devices[0])); + sc->quirks |= bhnd_chip_quirks(dev, chipc_chip_quirks); + + CHIPC_LOCK_INIT(sc); /* Allocate bus resources */ memcpy(sc->rspec, chipc_rspec, sizeof(sc->rspec)); @@ -152,22 +194,28 @@ chipc_attach(device_t dev) sc->caps = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES); sc->cst = bhnd_bus_read_4(sc->core, CHIPC_CHIPST); - // TODO - switch (bhnd_chipc_nvram_src(dev)) { - case BHND_NVRAM_SRC_CIS: - device_printf(dev, "NVRAM source: CIS\n"); - break; - case BHND_NVRAM_SRC_SPROM: - device_printf(dev, "NVRAM source: SPROM\n"); - break; + /* Identify NVRAM source */ + sc->nvram_src = chipc_nvram_identify(sc); + + /* Read NVRAM data */ + switch (sc->nvram_src) { case BHND_NVRAM_SRC_OTP: - device_printf(dev, "NVRAM source: OTP\n"); + // TODO (requires access to OTP hardware) + device_printf(sc->dev, "NVRAM-OTP unsupported\n"); break; + case BHND_NVRAM_SRC_NFLASH: - device_printf(dev, "NVRAM source: NFLASH\n"); + // TODO (requires access to NFLASH hardware) + device_printf(sc->dev, "NVRAM-NFLASH unsupported\n"); + break; + + case BHND_NVRAM_SRC_SPROM: + if ((error = chipc_sprom_init(sc))) + goto cleanup; break; - case BHND_NVRAM_SRC_NONE: - device_printf(dev, "NVRAM source: NONE\n"); + + case BHND_NVRAM_SRC_UNKNOWN: + /* Handled externally */ break; } @@ -175,6 +223,7 @@ chipc_attach(device_t dev) cleanup: bhnd_release_resources(dev, sc->rspec, sc->res); + CHIPC_LOCK_DESTROY(sc); return (error); } @@ -185,6 +234,9 @@ chipc_detach(device_t dev) sc = device_get_softc(dev); bhnd_release_resources(dev, sc->rspec, sc->res); + bhnd_sprom_fini(&sc->sprom); + + CHIPC_LOCK_DESTROY(sc); return (0); } @@ -202,68 +254,64 @@ chipc_resume(device_t dev) } /** - * Use device-specific ChipStatus flags to determine the preferred NVRAM - * data source. + * Initialize local SPROM shadow, if required. + * + * @param sc chipc driver state. */ -static bhnd_nvram_src_t -chipc_nvram_src_chipst(struct chipc_softc *sc) +static int +chipc_sprom_init(struct chipc_softc *sc) { - uint8_t nvram_sel; - - CHIPC_ASSERT_QUIRK(sc, SPROM_CHECK_CHIPST); - - if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R22)) { - // TODO: On these devices, the official driver code always - // assumes SPROM availability if CHIPC_CST_OTP_SEL is not - // set; we must review against the actual behavior of our - // BCM4312 hardware - nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R22); - } else if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R23)) { - nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R23); - } else { - panic("invalid CST OTP/SPROM chipc quirk flags"); - } - device_printf(sc->dev, "querying chipst for 0x%x, 0x%x\n", sc->ccid.chip_id, sc->cst); + int error; - switch (nvram_sel) { - case CHIPC_CST_DEFCIS_SEL: - return (BHND_NVRAM_SRC_CIS); + KASSERT(sc->nvram_src == BHND_NVRAM_SRC_SPROM, + ("non-SPROM source (%u)\n", sc->nvram_src)); - case CHIPC_CST_SPROM_SEL: - case CHIPC_CST_OTP_PWRDN: - return (BHND_NVRAM_SRC_SPROM); + /* Enable access to the SPROM */ + CHIPC_LOCK(sc); + if ((error = chipc_enable_sprom_pins(sc))) + goto failed; - case CHIPC_CST_OTP_SEL: - return (BHND_NVRAM_SRC_OTP); + /* Initialize SPROM parser */ + error = bhnd_sprom_init(&sc->sprom, sc->core, CHIPC_SPROM_OTP); + if (error) { + device_printf(sc->dev, "SPROM identification failed: %d\n", + error); - default: - device_printf(sc->dev, "unrecognized OTP/SPROM type 0x%hhx", - nvram_sel); - return (BHND_NVRAM_SRC_NONE); + chipc_disable_sprom_pins(sc); + goto failed; + } + + /* Drop access to the SPROM lines */ + if ((error = chipc_disable_sprom_pins(sc))) { + bhnd_sprom_fini(&sc->sprom); + goto failed; } + CHIPC_UNLOCK(sc); + + return (0); + +failed: + CHIPC_UNLOCK(sc); + return (error); } /** - * Determine the preferred NVRAM data source. + * Determine the NVRAM data source for this device. + * + * @param sc chipc driver state. */ static bhnd_nvram_src_t -chipc_nvram_src(device_t dev) +chipc_nvram_identify(struct chipc_softc *sc) { - struct chipc_softc *sc; uint32_t srom_ctrl; - sc = device_get_softc(dev); - - /* Very early devices always included a SPROM */ - if (CHIPC_QUIRK(sc, ALWAYS_HAS_SPROM)) - return (BHND_NVRAM_SRC_SPROM); - - /* Most other early devices require checking ChipStatus flags */ - if (CHIPC_QUIRK(sc, SPROM_CHECK_CHIPST)) - return (chipc_nvram_src_chipst(sc)); + /* Very early devices vend SPROM/OTP/CIS (if at all) via the + * host bridge interface instead of ChipCommon. */ + if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM)) + return (BHND_NVRAM_SRC_UNKNOWN); /* - * Later chipset revisions standardized the NVRAM capability flags and + * Later chipset revisions standardized the SPROM capability flags and * register interfaces. * * We check for hardware presence in order of precedence. For example, @@ -287,7 +335,158 @@ chipc_nvram_src(device_t dev) return (BHND_NVRAM_SRC_NFLASH); /* No NVRAM hardware capability declared */ - return (BHND_NVRAM_SRC_NONE); + return (BHND_NVRAM_SRC_UNKNOWN); +} + + +/** + * If required by this device, enable access to the SPROM. + * + * @param sc chipc driver state. + */ +static int +chipc_enable_sprom_pins(struct chipc_softc *sc) +{ + uint32_t cctrl; + + CHIPC_LOCK_ASSERT(sc, MA_OWNED); + + /* Nothing to do? */ + if (!CHIPC_QUIRK(sc, MUX_SPROM)) + return (0); + + cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); + + /* 4331 devices */ + if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) { + cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN; + + if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM)) + cctrl &= ~CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5; + + if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM)) + cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN2; + + bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); + return (0); + } + + /* 4360 devices */ + if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) { + /* Unimplemented */ + } + + /* Refuse to proceed on unsupported devices with muxed SPROM pins */ + device_printf(sc->dev, "muxed sprom lines on unrecognized device\n"); + return (ENXIO); +} + +/** + * If required by this device, revert any GPIO/pin configuration applied + * to allow SPROM access. + * + * @param sc chipc driver state. + */ +static int +chipc_disable_sprom_pins(struct chipc_softc *sc) +{ + uint32_t cctrl; + + CHIPC_LOCK_ASSERT(sc, MA_OWNED); + + /* Nothing to do? */ + if (!CHIPC_QUIRK(sc, MUX_SPROM)) + return (0); + + cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); + + /* 4331 devices */ + if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) { + cctrl |= CHIPC_CCTRL4331_EXTPA_EN; + + if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM)) + cctrl |= CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5; + + if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM)) + cctrl |= CHIPC_CCTRL4331_EXTPA_EN2; + + bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); + return (0); + } + + /* 4360 devices */ + if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) { + /* Unimplemented */ + } + + /* Refuse to proceed on unsupported devices with muxed SPROM pins */ + device_printf(sc->dev, "muxed sprom lines on unrecognized device\n"); + return (ENXIO); +} + +static bhnd_nvram_src_t +chipc_nvram_src(device_t dev) +{ + struct chipc_softc *sc = device_get_softc(dev); + return (sc->nvram_src); +} + +static int +chipc_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len) +{ + struct chipc_softc *sc; + int error; + + sc = device_get_softc(dev); + + switch (sc->nvram_src) { + case BHND_NVRAM_SRC_SPROM: + CHIPC_LOCK(sc); + error = bhnd_sprom_getvar(&sc->sprom, name, buf, len); + CHIPC_UNLOCK(sc); + return (error); + + case BHND_NVRAM_SRC_OTP: + case BHND_NVRAM_SRC_NFLASH: + /* Currently unsupported */ + return (ENXIO); + + case BHND_NVRAM_SRC_UNKNOWN: + return (ENODEV); + } + + /* Unknown NVRAM source */ + return (ENODEV); +} + +static int +chipc_nvram_setvar(device_t dev, const char *name, const void *buf, + size_t len) +{ + struct chipc_softc *sc; + int error; + + sc = device_get_softc(dev); + + switch (sc->nvram_src) { + case BHND_NVRAM_SRC_SPROM: + CHIPC_LOCK(sc); + error = bhnd_sprom_setvar(&sc->sprom, name, buf, len); + CHIPC_UNLOCK(sc); + return (error); + + case BHND_NVRAM_SRC_OTP: + case BHND_NVRAM_SRC_NFLASH: + /* Currently unsupported */ + return (ENXIO); + + case BHND_NVRAM_SRC_UNKNOWN: + default: + return (ENODEV); + } + + /* Unknown NVRAM source */ + return (ENODEV); } static device_method_t chipc_methods[] = { @@ -301,6 +500,10 @@ static device_method_t chipc_methods[] = { /* ChipCommon interface */ DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src), + /* NVRAM interface */ + DEVMETHOD(bhnd_nvram_getvar, chipc_nvram_getvar), + DEVMETHOD(bhnd_nvram_setvar, chipc_nvram_setvar), + DEVMETHOD_END }; diff --git a/sys/dev/bhnd/cores/chipc/chipcreg.h b/sys/dev/bhnd/cores/chipc/chipcreg.h index 5024684..b67eb34 100644 --- a/sys/dev/bhnd/cores/chipc/chipcreg.h +++ b/sys/dev/bhnd/cores/chipc/chipcreg.h @@ -36,26 +36,12 @@ #define CHIPC_GET_ATTR(_entry, _attr) \ ((_entry & CHIPC_ ## _attr ## _MASK) >> CHIPC_ ## _attr ## _SHIFT) -#define CHIPC_ID 0x0 -#define CHIPC_CAPABILITIES 0x04 -#define CHIPC_CHIPST 0x2c -#define CHIPC_EROMPTR 0xfc /**< 32-bit EROM base address - * on BCMA devices */ - -/** chipid */ -#define CHIPC_ID 0x0 /**< identification register */ -#define CHIPC_ID_CHIP_MASK 0x0000FFFF /**< chip id */ -#define CHIPC_ID_CHIP_SHIFT 0 -#define CHIPC_ID_REV_MASK 0x000F0000 /**< chip revision */ -#define CHIPC_ID_REV_SHIFT 16 -#define CHIPC_ID_PKG_MASK 0x00F00000 /**< physical package ID */ -#define CHIPC_ID_PKG_SHIFT 20 -#define CHIPC_ID_NUMCORE_MASK 0x0F000000 /**< number of cores on chip (rev >= 4) */ -#define CHIPC_ID_NUMCORE_SHIFT 24 -#define CHIPC_ID_BUS_MASK 0xF0000000 /**< chip/interconnect type (BHND_CHIPTYPE_*) */ -#define CHIPC_ID_BUS_SHIFT 28 +#define CHIPC_ID 0x0 +#define CHIPC_CAPABILITIES 0x04 #define CHIPC_OTPST 0x10 +#define CHIPC_CHIPCTRL 0x28 /**< chip control */ +#define CHIPC_CHIPST 0x2c /**< chip status */ #define CHIPC_JTAGCMD 0x30 #define CHIPC_JTAGIR 0x34 #define CHIPC_JTAGDR 0x38 @@ -76,6 +62,8 @@ #define CHIPC_CLKC_M3 0xa0 #define CHIPC_CLKDIV 0xa4 #define CHIPC_SYS_CLK_CTL 0xc0 +#define CHIPC_EROMPTR 0xfc /**< 32-bit EROM base address + * on BCMA devices */ #define CHIPC_SPROM_CTRL 0x190 /**< SPROM interface (rev >= 32) */ #define CHIPC_SPROM_ADDR 0x194 #define CHIPC_SPROM_DATA 0x198 @@ -95,6 +83,19 @@ #define CHIPC_PMU_PLL_CONTROL_DATA 0x664 #define CHIPC_SPROM_OTP 0x800 /* SPROM/OTP address space */ +/** chipid */ +#define CHIPC_ID 0x0 /**< identification register */ +#define CHIPC_ID_CHIP_MASK 0x0000FFFF /**< chip id */ +#define CHIPC_ID_CHIP_SHIFT 0 +#define CHIPC_ID_REV_MASK 0x000F0000 /**< chip revision */ +#define CHIPC_ID_REV_SHIFT 16 +#define CHIPC_ID_PKG_MASK 0x00F00000 /**< physical package ID */ +#define CHIPC_ID_PKG_SHIFT 20 +#define CHIPC_ID_NUMCORE_MASK 0x0F000000 /**< number of cores on chip (rev >= 4) */ +#define CHIPC_ID_NUMCORE_SHIFT 24 +#define CHIPC_ID_BUS_MASK 0xF0000000 /**< chip/interconnect type (BHND_CHIPTYPE_*) */ +#define CHIPC_ID_BUS_SHIFT 28 + /* capabilities */ #define CHIPC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ #define CHIPC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ @@ -1124,6 +1125,7 @@ enum { #define CHIPC_CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ #define CHIPC_CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ #define CHIPC_CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ +#define CHIPC_CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa2 disable, 1 ext pa2 enabled */ #define CHIPC_CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ #define CHIPC_CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ diff --git a/sys/dev/bhnd/cores/chipc/chipcvar.h b/sys/dev/bhnd/cores/chipc/chipcvar.h index 988224b..fe8dd0a 100644 --- a/sys/dev/bhnd/cores/chipc/chipcvar.h +++ b/sys/dev/bhnd/cores/chipc/chipcvar.h @@ -32,6 +32,8 @@ #ifndef _BHND_CORES_CHIPC_CHIPCVAR_H_ #define _BHND_CORES_CHIPC_CHIPCVAR_H_ +#include + #include "chipc.h" DECLARE_CLASS(bhnd_chipc); @@ -45,37 +47,64 @@ extern devclass_t bhnd_chipc_devclass; */ enum { /** No quirks */ - CHIPC_QUIRK_NONE = 0, + CHIPC_QUIRK_NONE = 0, /** - * The device always provides an external SROM. + * ChipCommon-controlled SPROM/OTP is supported, along with the + * CHIPC_CAP_SPROM capability flag. */ - CHIPC_QUIRK_ALWAYS_HAS_SPROM = (1<<1), - - + CHIPC_QUIRK_SUPPORTS_SPROM = (1<<1), + /** - * SROM availability must be determined through chip-specific - * ChipStatus flags. + * External NAND NVRAM is supported, along with the CHIPC_CAP_NFLASH + * capability flag. */ - CHIPC_QUIRK_SPROM_CHECK_CHIPST = (1<<3), + CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<2), /** - * Use the rev22 chipstatus register format when determining SPROM - * availability. + * The SPROM is attached via muxed pins. The pins must be switched + * to allow reading/writing. */ - CHIPC_QUIRK_SPROM_CHECK_CST_R22 = (1<<4)|CHIPC_QUIRK_SPROM_CHECK_CHIPST, + CHIPC_QUIRK_MUX_SPROM = (1<<3), /** - * Use the rev23 chipstatus register format when determining SPROM - * availability. + * Access to the SPROM uses pins shared with the 802.11a external PA. + * + * On modules using these 4331 packages, the CCTRL4331_EXTPA_EN flag + * must be cleared to allow SPROM access. */ - CHIPC_QUIRK_SPROM_CHECK_CST_R23 = (1<<5)|CHIPC_QUIRK_SPROM_CHECK_CHIPST, + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM = (1<<4) | + CHIPC_QUIRK_MUX_SPROM, /** - * External NAND NVRAM is supported, along with the CHIPC_CAP_NFLASH - * capability flag. + * Access to the SPROM uses pins shared with the 802.11a external PA. + * + * On modules using these 4331 chip packages, the external PA is + * attached via GPIO 2, 5, and sprom_dout pins. + * + * When enabling and disabling EXTPA to allow SPROM access, the + * CCTRL4331_EXTPA_ON_GPIO2_5 flag must also be set or cleared, + * respectively. + */ + CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM = (1<<5) | + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM, + + /** + * Access to the SPROM uses pins shared with two 802.11a external PAs. + * + * When enabling and disabling EXTPA, the CCTRL4331_EXTPA_EN2 must also + * be cleared to allow SPROM access. */ - CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<6), + CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM = (1<<6) | + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM, + + + /** + * SPROM pins are muxed with the FEM control lines on this 4360-family + * device. The muxed pins must be switched to allow reading/writing + * the SPROM. + */ + CHIPC_QUIRK_4360_FEM_MUX_SPROM = (1<<5) | CHIPC_QUIRK_MUX_SPROM }; struct chipc_softc { @@ -89,6 +118,19 @@ struct chipc_softc { uint32_t quirks; /**< CHIPC_QUIRK_* quirk flags */ uint32_t caps; /**< CHIPC_CAP_* capability register flags */ uint32_t cst; /**< CHIPC_CST* status register flags */ + bhnd_nvram_src_t nvram_src; /**< NVRAM source */ + + struct mtx mtx; /**< state mutex. */ + + struct bhnd_sprom sprom; /**< OTP/SPROM shadow, if any */ }; +#define CHIPC_LOCK_INIT(sc) \ + mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ + "BHND chipc driver lock", MTX_DEF) +#define CHIPC_LOCK(sc) mtx_lock(&(sc)->mtx) +#define CHIPC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) +#define CHIPC_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) +#define CHIPC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) + #endif /* _BHND_CORES_CHIPC_CHIPCVAR_H_ */ \ No newline at end of file diff --git a/sys/dev/bhnd/nvram/bhnd_nvram.h b/sys/dev/bhnd/nvram/bhnd_nvram.h index e2b6b0b..2c0c36b 100644 --- a/sys/dev/bhnd/nvram/bhnd_nvram.h +++ b/sys/dev/bhnd/nvram/bhnd_nvram.h @@ -36,10 +36,6 @@ * NVRAM data sources supported by bhnd(4) devices. */ typedef enum { - BHND_NVRAM_SRC_CIS, /**< Default CIS source; this may - * apply, for example, to PCMCIA cards - * vending Broadcom NVRAM data via - * their standard CIS table. */ BHND_NVRAM_SRC_OTP, /**< On-chip one-time-programmable * memory. */ @@ -51,15 +47,36 @@ typedef enum { * NVRAM. */ BHND_NVRAM_SRC_SPROM, /**< External serial EEPROM. */ - BHND_NVRAM_SRC_NONE /**< No NVRAM source is directly - * attached. This is used on devices - * attached via PCI(e) to BHND SoCs, - * where to avoid unnecessary flash - * hardware, NVRAM configuration for - * individual devices is provided by - * hardware attached to the SoC - * itself. + BHND_NVRAM_SRC_UNKNOWN /**< No NVRAM source is directly + * attached. + * + * This will be returned by ChipCommon + * revisions (rev <= 31) used in early + * chipsets that vend SPROM/OTP via the + * native host bridge interface. + * + * For example, PCMCIA cards may vend + * Broadcom NVRAM data via their standard CIS + * table, and earlier PCI(e) devices map + * SPROM statically into PCI BARs, and the + * control registers into PCI config space. + + * This will also be returned on later + * devices that are attached via PCI(e) to + * BHND SoCs, but do not include an attached + * SPROM, or programmed OTP. On such SoCs, + * NVRAM configuration for individual devices + * is provided by a common platform NVRAM + * device. */ } bhnd_nvram_src_t; +/** + * Evaluates to true if the given NVRAM data source is accessible via + * ChipCommon. + */ +#define BHND_NVRAM_SRC_CC(_src) \ + ((_src) == BHND_NVRAM_SRC_OTP || (_src) == BHND_NVRAM_SRC_SPROM) + + #endif /* _BHND_NVRAM_BHND_NVRAM_H_ */ \ No newline at end of file diff --git a/sys/dev/bhnd/nvram/bhnd_nvram_if.m b/sys/dev/bhnd/nvram/bhnd_nvram_if.m index c4baaec..2bb307b 100644 --- a/sys/dev/bhnd/nvram/bhnd_nvram_if.m +++ b/sys/dev/bhnd/nvram/bhnd_nvram_if.m @@ -46,13 +46,16 @@ INTERFACE bhnd_nvram; * @param[out] buf On success, the requested value will be written * to this buffer. This argment may be NULL if * the value is not desired. - * @param[in,out] size The capacity of @p buf. On success, will be set - * to the actual size of the requested value. + * @param[in,out] len The maximum capacity of @p buf. On success, + * will be set to the actual size of the requested + * value. * * @retval 0 success * @retval ENOENT The requested variable was not found. - * @retval ENOMEM If @p buf is non-NULL and a buffer of @p size is too + * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too * small to hold the requested value. + * @retval ENODEV If no supported NVRAM hardware is accessible via this + * device. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ @@ -60,5 +63,30 @@ METHOD int getvar { device_t dev; const char *name; void *buf; - size_t *size; -}; \ No newline at end of file + size_t *len; +}; + +/** + * Set an NVRAM variable's local value. + * + * No changes should be written to non-volatile storage. + * + * @param dev The NVRAM device. + * @param name The NVRAM variable name. + * @param buf The new value. + * @param len The size of @p buf. + * + * @retval 0 success + * @retval ENOENT The specified variable name is not recognized. + * @retval EINVAL If @p len does not match the expected variable size. + * @retval ENODEV If no supported NVRAM hardware is accessible via this + * device. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +METHOD int setvar { + device_t dev; + const char *name; + const void *buf; + size_t len; +}; diff --git a/sys/dev/bhnd/nvram/bhnd_sprom.c b/sys/dev/bhnd/nvram/bhnd_sprom.c new file mode 100644 index 0000000..54c1faa --- /dev/null +++ b/sys/dev/bhnd/nvram/bhnd_sprom.c @@ -0,0 +1,572 @@ +/*- + * Copyright (c) 2015 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "nvramvar.h" + +#include "bhnd_spromreg.h" +#include "bhnd_spromvar.h" + +/* + * BHND SPROM Parsing + * + * Provides identification and parsing of BHND SPROM data. + */ + +static int sprom_direct_read(struct bhnd_sprom *sc, size_t offset, + void *buf, size_t nbytes, uint8_t *crc); +static int sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size, + uint8_t *crc); +static int sprom_populate_shadow(struct bhnd_sprom *sc); + +static int sprom_var_defn(struct bhnd_sprom *sc, const char *name, + const struct bhnd_nvram_var **var, + const struct bhnd_sprom_var **sprom, size_t *size); + +/* SPROM revision is always located at the second-to-last byte */ +#define SPROM_REV(_sc) SPROM_READ_1((_sc), (_sc)->sp_size - 2) + +/* SPROM CRC is always located at the last byte */ +#define SPROM_CRC_OFF(_sc) SPROM_CRC_LEN(_sc) + +/* SPROM CRC covers all but the final CRC byte */ +#define SPROM_CRC_LEN(_sc) ((_sc)->sp_size - 1) + +/* SPROM shadow I/O (with byte-order translation) */ +#define SPROM_READ_1(_sc, _off) SPROM_READ_ENC_1(_sc, _off) +#define SPROM_READ_2(_sc, _off) le16toh(SPROM_READ_ENC_2(_sc, _off)) +#define SPROM_READ_4(_sc, _off) le32toh(SPROM_READ_ENC_4(_sc, _off)) + +#define SPROM_WRITE_1(_sc, _off, _v) SPROM_WRITE_ENC_1(_sc, _off, (_v)) +#define SPROM_WRITE_2(_sc, _off, _v) SPROM_WRITE_ENC_2(_sc, _off, \ + htole16(_v)) +#define SPROM_WRITE_4(_sc, _off, _v) SPROM_WRITE_ENC_4(_sc, _off, \ + htole32(_v)) + +/* SPROM shadow I/O (without byte-order translation) */ +#define SPROM_READ_ENC_1(_sc, _off) (*(uint8_t *)((_sc)->sp_shadow + _off)) +#define SPROM_READ_ENC_2(_sc, _off) (*(uint16_t *)((_sc)->sp_shadow + _off)) +#define SPROM_READ_ENC_4(_sc, _off) (*(uint32_t *)((_sc)->sp_shadow + _off)) + +#define SPROM_WRITE_ENC_1(_sc, _off, _v) \ + *((uint8_t *)((_sc)->sp_shadow + _off)) = (_v) +#define SPROM_WRITE_ENC_2(_sc, _off, _v) \ + *((uint16_t *)((_sc)->sp_shadow + _off)) = (_v) +#define SPROM_WRITE_ENC_4(_sc, _off, _v) \ + *((uint32_t *)((_sc)->sp_shadow + _off)) = (_v) + +/* Call @p _next macro with the C type, widened (signed or unsigned) C + * type, and width associated with @p _dtype */ +#define SPROM_SWITCH_TYPE(_dtype, _next, ...) \ +do { \ + switch (_dtype) { \ + case BHND_NVRAM_DT_UINT8: \ + _next (uint8_t, uint32_t, 1, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_UINT16: \ + _next (uint16_t, uint32_t, 2, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_UINT32: \ + _next (uint32_t, uint32_t, 4, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_INT8: \ + _next (int8_t, int32_t, 1, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_INT16: \ + _next (int16_t, int32_t, 2, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_INT32: \ + _next (int32_t, int32_t, 4, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_CHAR: \ + _next (uint8_t, uint32_t, 1, \ + ## __VA_ARGS__); \ + break; \ + } \ +} while (0) + +/* + * Table of supported SPROM image formats, sorted by image size, ascending. + */ +#define SPROM_FMT(_sz, _revmin, _revmax, _sig) \ + { SPROM_SZ_ ## _sz, _revmin, _revmax, \ + SPROM_SIG_ ## _sig ## _OFF, \ + SPROM_SIG_ ## _sig } + +static const struct sprom_fmt { + size_t size; + uint8_t rev_min; + uint8_t rev_max; + size_t sig_offset; + uint16_t sig_req; +} sprom_fmts[] = { + SPROM_FMT(R1_3, 1, 3, NONE), + SPROM_FMT(R4_8_9, 4, 4, R4), + SPROM_FMT(R4_8_9, 8, 9, R8_9), + SPROM_FMT(R10, 10, 10, R10), + SPROM_FMT(R11, 11, 11, R11) +}; + +/** + * Identify the SPROM format at @p offset within @p r, verify the CRC, + * and allocate a local shadow copy of the SPROM data. + * + * After successful initialization, @p r will not be accessed; any pin + * configuration required for SPROM access may be reset. + * + * @param[out] sprom On success, will be initialized with shadow of the SPROM + * data. + * @param r An active resource mapping the SPROM data. + * @param offset Offset of the SPROM data within @p resource. + */ +int +bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r, + bus_size_t offset) +{ + bus_size_t res_size; + int error; + + sprom->dev = rman_get_device(r->res); + sprom->sp_res = r; + sprom->sp_res_off = offset; + + /* Determine maximum possible SPROM image size */ + res_size = rman_get_size(r->res); + if (offset >= res_size) + return (EINVAL); + + sprom->sp_size_max = MIN(res_size - offset, SPROM_SZ_MAX); + + /* Allocate and populate SPROM shadow */ + sprom->sp_size = 0; + sprom->sp_capacity = sprom->sp_size_max; + sprom->sp_shadow = malloc(sprom->sp_capacity, M_BHND, M_NOWAIT); + if (sprom->sp_shadow == NULL) + return (ENOMEM); + + /* Read and identify SPROM image */ + if ((error = sprom_populate_shadow(sprom))) + return (error); + + return (0); +} + +/** + * Release all resources held by @p sprom. + * + * @param sprom A SPROM instance previously initialized via bhnd_sprom_init(). + */ +void +bhnd_sprom_fini(struct bhnd_sprom *sprom) +{ + free(sprom->sp_shadow, M_BHND); +} + +/* Perform a read using a SPROM offset descriptor, safely widening the + * result to its 32-bit representation before assigning it to @p _dest. */ +#define SPROM_GETVAR_READ(_type, _widen, _width, _sc, _off, _dest) \ +do { \ + _type _v = (_type)SPROM_READ_ ## _width(_sc, _off->offset); \ + if (_off->shift > 0) { \ + _v >>= _off->shift; \ + } else if (off->shift < 0) { \ + _v <<= -_off->shift; \ + } \ + _dest = ((uint32_t) (_widen) _v) & _off->mask; \ +} while(0) + +/* Emit a value read using a SPROM offset descriptor, narrowing the + * result output representation and, if necessary, OR'ing it with the + * previously read value from @p _buf. */ +#define SPROM_GETVAR_WRITE(_type, _widen, _width, _off, _src, _buf) \ +do { \ + _type _v = (_type) (_widen) _src; \ + if (_off->cont) \ + _v |= *((_type *)_buf); \ + *((_type *)_buf) = _v; \ +} while(0) + +/** + * Read a SPROM variable, performing conversion to host byte order. + * + * @param sc The SPROM parser state. + * @param name The SPROM variable name. + * @param[out] buf On success, the requested value will be written + * to this buffer. This argment may be NULL if + * the value is not desired. + * @param[in,out] len The capacity of @p buf. On success, will be set + * to the actual size of the requested value. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too + * small to hold the requested value. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +int +bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf, + size_t *len) +{ + const struct bhnd_nvram_var *nv; + const struct bhnd_sprom_var *sv; + size_t all1_offs; + size_t req_size; + int error; + + if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size))) + return (error); + + /* Provide required size */ + if (buf == NULL) { + *len = req_size; + return (0); + } + + /* Check (and update) target buffer len */ + if (*len < req_size) + return (ENOMEM); + else + *len = req_size; + + /* Read data */ + all1_offs = 0; + for (size_t i = 0; i < sv->num_offsets; i++) { + const struct bhnd_sprom_offset *off; + uint32_t val; + + off = &sv->offsets[i]; + KASSERT(!off->cont || i > 0, ("cont marked on first offset")); + + /* If not a continuation, advance the output buffer */ + if (i > 0 && !off->cont) { + buf = ((uint8_t *)buf) + + bhnd_nvram_type_width(sv->offsets[i-1].type); + } + + /* Read the value, widening to a common uint32 + * representation */ + SPROM_SWITCH_TYPE(off->type, SPROM_GETVAR_READ, sc, off, val); + + /* If IGNALL1, record whether value has all bits set. */ + if (nv->flags & BHND_NVRAM_VF_IGNALL1) { + uint32_t all1; + + all1 = off->mask; + if (off->shift > 0) + all1 >>= off->shift; + else if (off->shift < 0) + all1 <<= -off->shift; + + if ((val & all1) == all1) + all1_offs++; + } + + /* Write the value, narrowing to the appropriate output + * width. */ + SPROM_SWITCH_TYPE(nv->type, SPROM_GETVAR_WRITE, off, val, buf); + } + + /* Should value should be treated as uninitialized? */ + if (nv->flags & BHND_NVRAM_VF_IGNALL1 && all1_offs == sv->num_offsets) + return (ENOENT); + + return (0); +} + +/* Perform a read of a variable offset from _src, safely widening the result + * to its 32-bit representation before assigning it to @p + * _dest. */ +#define SPROM_SETVAR_READ(_type, _widen, _width, _off, _src, _dest) \ +do { \ + _type _v = *(const _type *)_src; \ + if (_off->shift > 0) { \ + _v <<= _off->shift; \ + } else if (off->shift < 0) { \ + _v >>= -_off->shift; \ + } \ + _dest = ((uint32_t) (_widen) _v) & _off->mask; \ +} while(0) + + +/* Emit a value read using a SPROM offset descriptor, narrowing the + * result output representation and, if necessary, OR'ing it with the + * previously read value from @p _buf. */ +#define SPROM_SETVAR_WRITE(_type, _widen, _width, _sc, _off, _src) \ +do { \ + _type _v = (_type) (_widen) _src; \ + if (_off->cont) \ + _v |= SPROM_READ_ ## _width(_sc, _off->offset); \ + SPROM_WRITE_ ## _width(_sc, _off->offset, _v); \ +} while(0) + +/** + * Set a local value for a SPROM variable, performing conversion to SPROM byte + * order. + * + * The new value will be written to the backing SPROM shadow. + * + * @param sc The SPROM parser state. + * @param name The SPROM variable name. + * @param[out] buf The new value. + * @param[in,out] len The size of @p buf. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval EINVAL If @p len does not match the expected variable size. + */ +int +bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, const void *buf, + size_t len) +{ + const struct bhnd_nvram_var *nv; + const struct bhnd_sprom_var *sv; + size_t req_size; + int error; + uint8_t crc; + + if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size))) + return (error); + + /* Provide required size */ + if (len != req_size) + return (EINVAL); + + /* Write data */ + for (size_t i = 0; i < sv->num_offsets; i++) { + const struct bhnd_sprom_offset *off; + uint32_t val; + + off = &sv->offsets[i]; + KASSERT(!off->cont || i > 0, ("cont marked on first offset")); + + /* If not a continuation, advance the input pointer */ + if (i > 0 && !off->cont) { + buf = ((const uint8_t *)buf) + + bhnd_nvram_type_width(sv->offsets[i-1].type); + } + + /* Read the value, widening to a common uint32 + * representation */ + SPROM_SWITCH_TYPE(nv->type, SPROM_SETVAR_READ, off, buf, val); + + /* Write the value, narrowing to the appropriate output + * width. */ + SPROM_SWITCH_TYPE(off->type, SPROM_SETVAR_WRITE, sc, off, val); + } + + /* Update CRC */ + crc = ~bhnd_nvram_crc8(sc->sp_shadow, SPROM_CRC_LEN(sc), + BHND_NVRAM_CRC8_INITIAL); + SPROM_WRITE_1(sc, SPROM_CRC_OFF(sc), crc); + + return (0); +} + +/* Read and identify the SPROM image by incrementally performing + * read + CRC of all supported image formats */ +static int +sprom_populate_shadow(struct bhnd_sprom *sc) +{ + const struct sprom_fmt *fmt; + int error; + uint16_t sig; + uint8_t srom_rev; + uint8_t crc; + + crc = BHND_NVRAM_CRC8_INITIAL; + + /* Identify the SPROM revision (and populate the SPROM shadow) */ + for (size_t i = 0; i < nitems(sprom_fmts); i++) { + fmt = &sprom_fmts[i]; + + /* Read image data and check CRC */ + if ((error = sprom_extend_shadow(sc, fmt->size, &crc))) + return (error); + + /* Skip on invalid CRC */ + if (crc != BHND_NVRAM_CRC8_VALID) + continue; + + /* Fetch SROM revision */ + srom_rev = SPROM_REV(sc); + + /* Early sromrev 1 devices (specifically some BCM440x enet + * cards) are reported to have been incorrectly programmed + * with a revision of 0x10. */ + if (fmt->size == SPROM_SZ_R1_3 && srom_rev == 0x10) + srom_rev = 0x1; + + /* Verify revision range */ + if (srom_rev < fmt->rev_min || srom_rev > fmt->rev_max) + continue; + + /* Verify signature (if any) */ + sig = SPROM_SIG_NONE; + if (fmt->sig_offset != SPROM_SIG_NONE_OFF) + sig = SPROM_READ_2(sc, fmt->sig_offset); + + if (sig != fmt->sig_req) { + device_printf(sc->dev, + "invalid sprom %hhu signature: 0x%hx " + "(expected 0x%hx)\n", + srom_rev, sig, fmt->sig_req); + return (EINVAL); + } + + /* Identified */ + sc->sp_rev = srom_rev; + return (0); + } + + /* identification failed */ + device_printf(sc->dev, "unrecognized sprom format\n"); + return (EINVAL); +} + +/* + * Extend the shadowed SPROM buffer to image_size, reading any required + * data from the backing SPROM resource and updating the CRC. + */ +static int +sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size, + uint8_t *crc) +{ + int error; + + KASSERT(image_size >= sc->sp_size, (("shadow truncation unsupported"))); + + /* Verify the request fits within our shadow buffer */ + if (image_size > sc->sp_capacity) + return (ENOSPC); + + /* Skip no-op requests */ + if (sc->sp_size == image_size) + return (0); + + /* Populate the extended range */ + error = sprom_direct_read(sc, sc->sp_size, sc->sp_shadow + sc->sp_size, + image_size - sc->sp_size, crc); + if (error) + return (error); + + sc->sp_size = image_size; + return (0); +} + +/** + * Read nbytes at the given offset from the backing SPROM resource, and + * update the CRC. + */ +static int +sprom_direct_read(struct bhnd_sprom *sc, size_t offset, void *buf, + size_t nbytes, uint8_t *crc) +{ + bus_size_t res_offset; + size_t nread; + uint16_t *p; + + KASSERT(nbytes % sizeof(uint16_t) == 0, ("unaligned sprom size")); + KASSERT(offset % sizeof(uint16_t) == 0, ("unaligned sprom offset")); + + /* Check for read overrun */ + if (offset >= sc->sp_size_max || sc->sp_size_max - offset < nbytes) { + device_printf(sc->dev, "requested SPROM read would overrun\n"); + return (EINVAL); + } + + p = (uint16_t *)buf; + res_offset = sc->sp_res_off + offset; + + /* Perform read */ + for (nread = 0; nread < nbytes; nread += 2) { + *p = bhnd_bus_read_stream_2(sc->sp_res, res_offset+nread); + *crc = bhnd_nvram_crc8(p, sizeof(*p), *crc); + p++; + }; + + return (0); +} + + +/** + * Locate the variable and SPROM revision-specific definitions + * for variable with @p name. + */ +static int +sprom_var_defn(struct bhnd_sprom *sc, const char *name, + const struct bhnd_nvram_var **var, + const struct bhnd_sprom_var **sprom, + size_t *size) +{ + /* Find variable definition */ + *var = bhnd_nvram_var_defn(name); + if (*var == NULL) + return (ENOENT); + + /* Find revision-specific SPROM definition */ + for (size_t i = 0; i < (*var)->num_sp_descs; i++) { + const struct bhnd_sprom_var *sp = &(*var)->sprom_descs[i]; + + if (sc->sp_rev < sp->compat.first) + continue; + + if (sc->sp_rev > sp->compat.last) + continue; + + /* Found */ + *sprom = sp; + + /* Calculate size in bytes */ + *size = bhnd_nvram_type_width((*var)->type) * sp->num_offsets; + return (0); + } + + /* Not supported by this SPROM revision */ + return (ENOENT); +} \ No newline at end of file diff --git a/sys/dev/bhnd/nvram/bhnd_spromreg.h b/sys/dev/bhnd/nvram/bhnd_spromreg.h new file mode 100644 index 0000000..2d5c237 --- /dev/null +++ b/sys/dev/bhnd/nvram/bhnd_spromreg.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_SPROMREG_H_ +#define _BHND_NVRAM_SPROMREG_H_ + +#define SPROM_SZ_R1_3 128 /**< SPROM image size (rev 1-3) */ +#define SPROM_SZ_R4_8_9 440 /**< SPROM image size (rev 4, 8-9) */ +#define SPROM_SZ_R10 460 /**< SPROM image size (rev 10) */ +#define SPROM_SZ_R11 468 /**< SPROM image size (rev 11) */ + +/** Maximum supported SPROM image size */ +#define SPROM_SZ_MAX SPROM_SZ_R11 + +#define SPROM_SIG_NONE 0x0 +#define SPROM_SIG_NONE_OFF 0x0 + +/** SPROM signature (rev 4) */ +#define SPROM_SIG_R4 0x5372 +#define SPROM_SIG_R4_OFF 64 /**< SPROM signature offset (rev 4) */ + +/** SPROM signature (rev 8, 9) */ +#define SPROM_SIG_R8_9 SPROM_SIG_R4 +#define SPROM_SIG_R8_9_OFF 128 /**< SPROM signature offset (rev 8-9) */ + +/** SPROM signature (rev 10) */ +#define SPROM_SIG_R10 SPROM_SIG_R4 +#define SPROM_SIG_R10_OFF 438 /**< SPROM signature offset (rev 10) */ + +/** SPROM signature (rev 11) */ +#define SPROM_SIG_R11 0x0634 +#define SPROM_SIG_R11_OFF 128 /**< SPROM signature offset (rev 11) */ + + +#endif /* _BHND_NVRAM_SPROMREG_H_ */ diff --git a/sys/dev/bhnd/nvram/bhnd_spromvar.h b/sys/dev/bhnd/nvram/bhnd_spromvar.h new file mode 100644 index 0000000..15cfa79 --- /dev/null +++ b/sys/dev/bhnd/nvram/bhnd_spromvar.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_BHND_SPROM_H_ +#define _BHND_NVRAM_BHND_SPROM_H_ + +struct bhnd_sprom { + device_t dev; /**< sprom parent device */ + + uint8_t sp_rev; /**< sprom revision */ + + struct bhnd_resource *sp_res; /**< sprom resource. */ + bus_size_t sp_res_off; /**< offset to sprom image */ + + uint8_t *sp_shadow; /**< sprom shadow */ + bus_size_t sp_size_max; /**< maximum possible sprom length */ + size_t sp_size; /**< shadow size */ + size_t sp_capacity; /**< shadow buffer capacity */ +}; + +int bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r, + bus_size_t offset); +void bhnd_sprom_fini(struct bhnd_sprom *sprom); + +int bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf, + size_t *len); +int bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, + const void *buf, size_t len); + +#endif /* _BHND_NVRAM_BHND_SPROM_H_ */ diff --git a/sys/dev/bhnd/nvram/nvram_map b/sys/dev/bhnd/nvram/nvram_map new file mode 100644 index 0000000..a716280 --- /dev/null +++ b/sys/dev/bhnd/nvram/nvram_map @@ -0,0 +1,1445 @@ +#- +# Copyright (c) 2015-2016 Landon Fuller +# Copyright (C) 2008-2015, Broadcom Corporation. +# All Rights Reserved. +# +# The contents of this file (variable names, descriptions, and offsets) were +# extracted or derived from Broadcom's ISC-licensed sources. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# $FreeBSD$ + +# +# NVRAM variable definitions and revision-specific SPROM offsets. +# +# Processed by nvram_map_gen.awk to produce bhnd_nvram_map.h +# +# NOTE: file was originally generated automatically by using libclang +# to analyze and extract format information and descriptions from Broadcom's +# available ISC-licensed CIS and SROM code and associated headers. +# + +# Antennas available +u8 aa2g { + srom 1-3 0x5C (&0x30, >>4) + srom 4-7 0x5D + srom 8-10 0x9D + srom >= 11 0xA1 +} +u8 aa5g { + srom 1-3 0x5C (&0xC0, >>6) + srom 4-7 0x5C + srom 8-10 0x9C + srom >= 11 0xA0 +} + +# ACPHY PA trimming parameters: 40 +u16[12] pa5gbw40a0 { + srom >= 11 0x110 +} + +# ACPHY PA trimming parameters: 80 +u16[12] pa5gbw80a0 { + srom >= 11 0x138 +} + +# ACPHY PA trimming parameters: 40/80 +u16[12] pa5gbw4080a0 { + srom >= 11 0x138 +} +u16[12] pa5gbw4080a1 { + srom >= 11 u16 0xB6, u16 0xBC, u16 0xCE, u16 0xD4, u16[8] 0x128 +} + +# ACPHY PA trimming parameters: CCK +u16[3] pa2gccka0 { + srom >= 11 0x102 +} + +# ACPHY Power-per-rate 2gpo +u16 dot11agofdmhrbw202gpo { + srom >= 11 0x15C +} +u16 ofdmlrbw202gpo { + srom >= 11 0x15E +} + +# ACPHY Power-per-rate 5gpo +u32 mcsbw805glpo { + srom >= 11 0x168 +} +u32 mcsbw805gmpo { + srom >= 11 0x178 +} +u32 mcsbw805ghpo { + srom >= 11 0x188 +} +u16 mcslr5glpo { + srom >= 11 0x190 (&0xFFF) +} +u16 mcslr5gmpo { + srom >= 11 0x192 +} +u16 mcslr5ghpo { + srom >= 11 0x194 +} + +# ACPHY Power-per-rate sbpo +u16 sb20in40hrpo { + srom >= 11 0x196 +} +u16 sb20in80and160hr5glpo { + srom >= 11 0x198 +} +u16 sb40and80hr5glpo { + srom >= 11 0x19A +} +u16 sb20in80and160hr5gmpo { + srom >= 11 0x19C +} +u16 sb40and80hr5gmpo { + srom >= 11 0x19E +} +u16 sb20in80and160hr5ghpo { + srom >= 11 0x1A0 +} +u16 sb40and80hr5ghpo { + srom >= 11 0x1A2 +} +u16 sb20in40lrpo { + srom >= 11 0x1A4 +} +u16 sb20in80and160lr5glpo { + srom >= 11 0x1A6 +} +u16 sb40and80lr5glpo { + srom >= 11 0x1A8 +} +u16 sb20in80and160lr5gmpo { + srom >= 11 0x1AA +} +u16 sb40and80lr5gmpo { + srom >= 11 0x1AC +} +u16 sb20in80and160lr5ghpo { + srom >= 11 0x1AE +} +u16 sb40and80lr5ghpo { + srom >= 11 0x1B0 +} +u16 dot11agduphrpo { + srom >= 11 0x1B2 +} +u16 dot11agduplrpo { + srom >= 11 0x1B4 +} + +# Antenna gain +u8 ag0 { + srom 1-3 0x75 + srom 4-7 0x5F + srom 8-10 0x9F +} +u8 ag1 { + srom 1-3 0x74 + srom 4-7 0x5E + srom 8-10 0x9E +} +u8 ag2 { + srom 4-7 0x61 + srom 8-10 0xA1 +} +u8 ag3 { + srom 4-7 0x60 + srom 8-10 0xA0 +} + +u8 agbg0 { + srom >= 11 0xA2 +} +u8 agbg1 { + srom >= 11 0xA3 +} +u8 agbg2 { + srom >= 11 0xA4 +} +u8 aga0 { + srom >= 11 0xA5 +} +u8 aga1 { + srom >= 11 0xA6 +} +u8 aga2 { + srom >= 11 0xA7 +} + +# board flags +u32 boardflags { + srom 1 u16 0x72 + srom 2 u16 0x72 | u16 0x38 (<<16) + srom 3 u16 0x72 | u16 0x7A (<<16) + srom 4 0x44 + srom 5-7 0x4A + srom >= 8 0x84 +} +u32 boardflags2 { + srom 4 0x48 + srom 5-7 0x4E + srom >= 8 0x88 +} +u32 boardflags3 { + srom >= 11 0x8C +} + +# board serial number, independent of mac addr +u16 boardnum { + srom 1-2 0x4C + srom 3 0x4E + srom 4 0x50 + srom 5-7 0x56 + srom 8-10 0x90 + srom >= 11 0x94 +} + +# One byte board revision +u16 boardrev { + srom 1-3 u8 0x5D + srom 4-7 0x42 + srom >= 8 0x82 +} + +# 2 bytes; boardtype +u16 boardtype { + srom >= 2 0x4 +} + +# Default country code (sromrev == 1) +u8 cc { + srom 1 0x5C (&0xF) +} + +# 2 bytes each +# CCK Power offsets for 20 MHz rates (11, 5.5, 2, 1Mbps) +# cckbw202gpo cckbw20ul2gpo +# +u16 cckbw202gpo { + srom 9-10 0x140 + srom >= 11 0x150 +} +u16 cckbw20ul2gpo { + srom 9-10 0x142 + srom >= 11 0x152 +} + +# Country code (2 bytes ascii + 1 byte cctl) +# in rev 2 +# +char[2] ccode { + sfmt ccode + srom 0-3 0x76 + srom 4 0x52 + srom 5-7 0x44 + srom 8-10 0x92 + srom >= 11 0x96 +} + +# 2 byte; txchain, rxchain +u8 txchain { + all1 ignore + srom 4-7 0x7B (&0xF) + srom 8-10 0xA3 (&0xF) + srom >= 11 0xA9 (&0xF) +} +u8 rxchain { + all1 ignore + srom 4-7 0x7B (&0xF0, >>4) + srom 8-10 0xA3 (&0xF0, >>4) + srom >= 11 0xA9 (&0xF0, >>4) +} +u16 antswitch { + all1 ignore + srom 4-7 u8 0x7A + srom 8-10 u8 0xA2 + srom >= 11 u8 0xA8 +} + +# PCI device id +private u16 devid { + srom >= 8 u16 0x60 +} + +u8 elna2g { + srom 8-10 0xBB +} + +u8 elna5g { + srom 8-10 0xBA +} + +# 11n front-end specification +u8 antswctl2g { + srom 8-10 0xAE (&0xF8, >>3) +} +u8 triso2g { + srom 8-10 0xAE (&0x7) +} +u8 pdetrange2g { + srom 8-10 0xAF (&0xF8, >>3) +} +u8 extpagain2g { + srom 8-10 0xAF (&0x6, >>1) +} +u8 tssipos2g { + srom 8-10 0xAF (&0x1) +} +u8 antswctl5g { + srom 8-10 0xB0 (&0xF8, >>3) +} +u8 triso5g { + srom 8-10 0xB0 (&0x7) +} +u8 pdetrange5g { + srom 8-10 0xB1 (&0xF8, >>3) +} +u8 extpagain5g { + srom 8-10 0xB1 (&0x6, >>1) +} +u8 tssipos5g { + srom 8-10 0xB1 (&0x1) +} + +# FEM config +u8 femctrl { + sfmt decimal + srom >= 11 0xAA (&0xF8, >>3) +} +u8 papdcap2g { + sfmt decimal + srom >= 11 0xAA (&0x4, >>2) +} +u8 tworangetssi2g { + sfmt decimal + srom >= 11 0xAA (&0x2, >>1) +} +u8 pdgain2g { + sfmt decimal + srom >= 11 u16 0xAA (&0x1F0, >>4) +} +u8 epagain2g { + sfmt decimal + srom >= 11 0xAB (&0xE, >>1) +} +u8 tssiposslope2g { + sfmt decimal + srom >= 11 0xAB (&0x1) +} +u8 gainctrlsph { + sfmt decimal + srom >= 11 0xAC (&0xF8, >>3) +} +u8 papdcap5g { + sfmt decimal + srom >= 11 0xAC (&0x4, >>2) +} +u8 tworangetssi5g { + sfmt decimal + srom >= 11 0xAC (&0x2, >>1) +} +u8 pdgain5g { + sfmt decimal + srom >= 11 u16 0xAC (&0x1F0, >>4) +} +u8 epagain5g { + sfmt decimal + srom >= 11 0xAD (&0xE, >>1) +} +u8 tssiposslope5g { + sfmt decimal + srom >= 11 0xAD (&0x1) +} + +# LED duty cycle +u8[2] leddc { + sfmt led_dc + all1 ignore + srom 3 0x7C + srom 4 0x5A + srom 5-7 0x5A + srom 8-10 0x9A + srom >= 11 0x9E +} + +# LED set +u8 ledbh0 { + all1 ignore + srom 1-3 0x65 + srom 4 0x57 + srom 5-7 0x77 + srom 8-10 0x97 + srom >= 11 0x9B +} +u8 ledbh1 { + all1 ignore + srom 1-3 0x64 + srom 4 0x56 + srom 5-7 0x76 + srom 8-10 0x96 + srom >= 11 0x9A +} +u8 ledbh2 { + all1 ignore + srom 1-3 0x67 + srom 4 0x59 + srom 5-7 0x79 + srom 8-10 0x99 + srom >= 11 0x9D +} +u8 ledbh3 { + all1 ignore + srom 1-3 0x66 + srom 4 0x58 + srom 5-7 0x78 + srom 8-10 0x98 + srom >= 11 0x9C +} + +# 2 bytes total +# Additional power offset for Legacy Dup40 transmissions. +# Applied in addition to legofdmbw20ulXpo, X=2g, 5gl, 5gm, or 5gh. +# LSB nibble: 2G band, MSB nibble: 5G band high subband. +# leg40dup5ghpo, leg40dup5gmpo, leg40dup5glpo, leg40dup2gpo +# +u16 legofdm40duppo { + srom 9-10 0x196 +} + +# 4 bytes each +# OFDM power offsets for 20 MHz Legacy rates +# (54, 48, 36, 24, 18, 12, 9, 6 Mbps) +# legofdmbw202gpo legofdmbw20ul2gpo +# +u32 legofdmbw202gpo { + srom 9-10 0x144 +} +u32 legofdmbw20ul2gpo { + srom 9-10 0x148 +} + +# 4 bytes each +# 5G band: OFDM power offsets for 20 MHz Legacy rates +# (54, 48, 36, 24, 18, 12, 9, 6 Mbps) +# low subband : legofdmbw205glpo legofdmbw20ul2glpo +# mid subband :legofdmbw205gmpo legofdmbw20ul2gmpo +# high subband :legofdmbw205ghpo legofdmbw20ul2ghpo +# +u32 legofdmbw205glpo { + srom 9-10 0x14C +} +u32 legofdmbw20ul5glpo { + srom 9-10 0x150 +} +u32 legofdmbw205gmpo { + srom 9-10 0x154 +} +u32 legofdmbw20ul5gmpo { + srom 9-10 0x158 +} +u32 legofdmbw205ghpo { + srom 9-10 0x15C +} +u32 legofdmbw20ul5ghpo { + srom 9-10 0x160 +} + +# mac addr override for the standard CIS LAN_NID +u8[6] macaddr { + sfmt macaddr + srom 3 u8 0x4B, u8 0x4A, u8 0x4D, u8 0x4C, u8 0x4F, u8 0x4E + srom 4 u8 0x4D, u8 0x4C, u8 0x4F, u8 0x4E, u8 0x51, u8 0x50 + srom 5-7 u8 0x53, u8 0x52, u8 0x55, u8 0x54, u8 0x57, u8 0x56 + srom 8-10 u8 0x8D, u8 0x8C, u8 0x8F, u8 0x8E, u8 0x91, u8 0x90 + srom >= 11 u8 0x91, u8 0x90, u8 0x93, u8 0x92, u8 0x95, u8 0x94 +} + +# 4 bytes each +# mcs 0-7 power-offset. LSB nibble: m0, MSB nibble: m7 +# mcsbw202gpo mcsbw20ul2gpo mcsbw402gpo +# +u32 mcsbw202gpo { + srom 9-10 0x164 + srom >= 11 0x154 +} +u32 mcsbw20ul2gpo { + srom 9-10 0x168 +} +u32 mcsbw402gpo { + srom 9-10 0x16C + srom >= 11 0x158 +} + +# 4 bytes each +# 5G high subband mcs 0-7 power-offset. +# LSB nibble: m0, MSB nibble: m7 +# mcsbw205ghpo mcsbw20ul5ghpo mcsbw405ghpo +# +u32 mcsbw205ghpo { + srom 9-10 0x188 + srom >= 11 0x180 +} +u32 mcsbw20ul5ghpo { + srom 9-10 0x18C +} +u32 mcsbw405ghpo { + srom 9-10 0x190 + srom >= 11 0x184 +} + +# 4 bytes each +# 5G low subband mcs 0-7 power-offset. +# LSB nibble: m0, MSB nibble: m7 +# mcsbw205glpo mcsbw20ul5glpo mcsbw405glpo +# +u32 mcsbw205glpo { + srom 9-10 0x170 + srom >= 11 0x160 +} +u32 mcsbw20ul5glpo { + srom 9-10 0x174 +} +u32 mcsbw405glpo { + srom 9-10 0x178 + srom >= 11 0x164 +} + +# 4 bytes each +# 5G mid subband mcs 0-7 power-offset. +# LSB nibble: m0, MSB nibble: m7 +# mcsbw205gmpo mcsbw20ul5gmpo mcsbw405gmpo +# +u32 mcsbw205gmpo { + srom 9-10 0x17C + srom >= 11 0x170 +} +u32 mcsbw20ul5gmpo { + srom 9-10 0x180 +} +u32 mcsbw405gmpo { + srom 9-10 0x184 + srom >= 11 0x174 +} + +# 2 bytes total +# mcs-32 power offset for each band/subband. +# LSB nibble: 2G band, MSB nibble: +# mcs322ghpo, mcs325gmpo, mcs325glpo, mcs322gpo +# +u16 mcs32po { + srom 9-10 0x194 +} + +u8 measpower { + srom 8-10 0xB4 (&0xFE, >>1) + srom >= 11 0xB0 (&0xFE, >>1) +} +u8 measpower1 { + srom 8-10 0xBF (&0x7F) + srom >= 11 0xBB (&0x7F) +} +u8 measpower2 { + srom 8-10 u16 0xBE (&0x3F80, >>7) + srom >= 11 u16 0xBA (&0x3F80, >>7) +} +u16 rawtempsense { + srom 8-10 0xB4 (&0x1FF) + srom >= 11 0xB0 (&0x1FF) +} + +u8 noiselvl2ga0 { + sfmt decimal + srom 8-10 0x1AB (&0x1F) + srom >= 11 0x1BD (&0x1F) +} +u8 noiselvl2ga1 { + sfmt decimal + srom 8-10 u16 0x1AA (&0x3E0, >>5) + srom >= 11 u16 0x1BC (&0x3E0, >>5) +} +u8 noiselvl2ga2 { + sfmt decimal + srom 8-10 0x1AA (&0x7C, >>2) + srom >= 11 0x1BC (&0x7C, >>2) +} +u8[4] noiselvl5ga0 { + sfmt decimal + srom >= 11 u8 0x1BF (&0x1F), u8 0x1C1 (&0x1F), u8 0x1C3 (&0x1F), u8 0x1C5 (&0x1F) +} +u8[4] noiselvl5ga1 { + sfmt decimal + srom >= 11 u16[4] 0x1BE (&0x3E0, >>5) +} +u8[4] noiselvl5ga2 { + sfmt decimal + srom >= 11 u8 0x1BE (&0x7C, >>2), u8 0x1C0 (&0x7C, >>2), u8 0x1C2 (&0x7C, >>2), u8 0x1C4 (&0x7C, >>2) +} + +# paparambwver +u8 paparambwver { + sfmt decimal + srom >= 11 0x190 (&0xF0, >>4) +} + +# PA parameters: 8 (sromrev == 1) +# or 9 (sromrev > 1) bytes +# +u16 pa0b0 { + sfmt decimal + srom 1-3 0x5E + srom 8-10 0xC2 +} +u16 pa0b1 { + sfmt decimal + srom 1-3 0x60 + srom 8-10 0xC4 +} +u16 pa0b2 { + sfmt decimal + srom 1-3 0x62 + srom 8-10 0xC6 +} +u8 pa0itssit { + sfmt decimal + srom 1-3 0x71 + srom 8-10 0xC0 +} +u8 pa0maxpwr { + sfmt decimal + srom 1-3 0x69 + srom 8-10 0xC1 +} +u8 opo { + srom 2-3 0x79 + srom 8-10 0x143 +} + +# 5G PA params +u16 pa1b0 { + sfmt decimal + srom 1-3 0x6A + srom 8-10 0xCC +} +u16 pa1b1 { + sfmt decimal + srom 1-3 0x6C + srom 8-10 0xCE +} +u16 pa1b2 { + sfmt decimal + srom 1-3 0x6E + srom 8-10 0xD0 +} +u16 pa1lob0 { + sfmt decimal + srom 2-3 0x3C + srom 8-10 0xD2 +} +u16 pa1lob1 { + sfmt decimal + srom 2-3 0x3E + srom 8-10 0xD4 +} +u16 pa1lob2 { + sfmt decimal + srom 2-3 0x40 + srom 8-10 0xD6 +} +u16 pa1hib0 { + sfmt decimal + srom 2-3 0x42 + srom 8-10 0xD8 +} +u16 pa1hib1 { + sfmt decimal + srom 2-3 0x44 + srom 8-10 0xDA +} +u16 pa1hib2 { + sfmt decimal + srom 2-3 0x46 + srom 8-10 0xDC +} +u8 pa1itssit { + sfmt decimal + srom 1-3 0x70 + srom 8-10 0xC8 +} +u8 pa1maxpwr { + sfmt decimal + srom 1-3 0x68 + srom 8-10 0xC9 +} +u8 pa1lomaxpwr { + sfmt decimal + srom 2-3 0x3A + srom 8-10 0xCA +} +u8 pa1himaxpwr { + sfmt decimal + srom 2-3 0x3B + srom 8-10 0xCB +} + +u16 pdoffset40ma0 { + srom >= 11 0xCA +} +u16 pdoffset40ma1 { + srom >= 11 0xCC +} +u16 pdoffset40ma2 { + srom >= 11 0xCE +} +u16 pdoffset80ma0 { + srom >= 11 0xD0 +} +u16 pdoffset80ma1 { + srom >= 11 0xD2 +} +u16 pdoffset80ma2 { + srom >= 11 0xD4 +} + +u8 pdoffset2g40ma0 { + srom >= 11 0xC9 (&0xF) +} +u8 pdoffset2g40ma1 { + srom >= 11 0xC9 (&0xF0, >>4) +} +u8 pdoffset2g40ma2 { + srom >= 11 0xC8 (&0xF) +} +u8 pdoffset2g40mvalid { + srom >= 11 0xC8 (&0x80, >>7) +} + +# 40Mhz channel 2g/5g power offset +u16 bw40po { + srom 4-7 0x18E + srom 8 0x196 +} + +# 40Mhz channel dup 2g/5g power offset +u16 bwduppo { + srom 4-7 0x190 + srom 8 0x198 +} + +# cck2g/ofdm2g/ofdm5g power offset +u16 cck2gpo { + srom 4-7 0x138 + srom 8 0x140 +} +u32 ofdm2gpo { + srom 4-7 0x13A + srom 8 0x142 +} +u32 ofdm5gpo { + srom 4-7 0x13E + srom 8 0x146 +} +u32 ofdm5glpo { + srom 4-7 0x142 + srom 8 0x14A +} +u32 ofdm5ghpo { + srom 4-7 0x146 + srom 8 0x14E +} + +# cdd2g/5g power offset +u16 cddpo { + srom 4-7 0x18A + srom 8 0x192 +} + +# mcs2g power offset +u16 mcs2gpo0 { + srom 4-7 0x14A + srom 8 0x152 +} +u16 mcs2gpo1 { + srom 4-7 0x14C + srom 8 0x154 +} +u16 mcs2gpo2 { + srom 4-7 0x14E + srom 8 0x156 +} +u16 mcs2gpo3 { + srom 4-7 0x150 + srom 8 0x158 +} +u16 mcs2gpo4 { + srom 4-7 0x152 + srom 8 0x15A +} +u16 mcs2gpo5 { + srom 4-7 0x154 + srom 8 0x15C +} +u16 mcs2gpo6 { + srom 4-7 0x156 + srom 8 0x15E +} +u16 mcs2gpo7 { + srom 4-7 0x158 + srom 8 0x160 +} + +# mcs5g low-high band power offset +u16 mcs5glpo0 { + srom 4-7 0x16A + srom 8 0x172 +} +u16 mcs5glpo1 { + srom 4-7 0x16C + srom 8 0x174 +} +u16 mcs5glpo2 { + srom 4-7 0x16E + srom 8 0x176 +} +u16 mcs5glpo3 { + srom 4-7 0x170 + srom 8 0x178 +} +u16 mcs5glpo4 { + srom 4-7 0x172 + srom 8 0x17A +} +u16 mcs5glpo5 { + srom 4-7 0x174 + srom 8 0x17C +} +u16 mcs5glpo6 { + srom 4-7 0x176 + srom 8 0x17E +} +u16 mcs5glpo7 { + srom 4-7 0x178 + srom 8 0x180 +} +u16 mcs5ghpo0 { + srom 4-7 0x17A + srom 8 0x182 +} +u16 mcs5ghpo1 { + srom 4-7 0x17C + srom 8 0x184 +} +u16 mcs5ghpo2 { + srom 4-7 0x17E + srom 8 0x186 +} +u16 mcs5ghpo3 { + srom 4-7 0x180 + srom 8 0x188 +} +u16 mcs5ghpo4 { + srom 4-7 0x182 + srom 8 0x18A +} +u16 mcs5ghpo5 { + srom 4-7 0x184 + srom 8 0x18C +} +u16 mcs5ghpo6 { + srom 4-7 0x186 + srom 8 0x18E +} +u16 mcs5ghpo7 { + srom 4-7 0x188 + srom 8 0x190 +} + +# mcs5g mid band power offset +u16 mcs5gpo0 { + srom 4-7 0x15A + srom 8 0x162 +} +u16 mcs5gpo1 { + srom 4-7 0x15C + srom 8 0x164 +} +u16 mcs5gpo2 { + srom 4-7 0x15E + srom 8 0x166 +} +u16 mcs5gpo3 { + srom 4-7 0x160 + srom 8 0x168 +} +u16 mcs5gpo4 { + srom 4-7 0x162 + srom 8 0x16A +} +u16 mcs5gpo5 { + srom 4-7 0x164 + srom 8 0x16C +} +u16 mcs5gpo6 { + srom 4-7 0x166 + srom 8 0x16E +} +u16 mcs5gpo7 { + srom 4-7 0x168 + srom 8 0x170 +} + +# stbc2g/5g power offset +u16 stbcpo { + srom 4-7 0x18C + srom 8 0x194 +} + +u8 regrev { + srom 3 0x78 + srom 4 0x55 + srom 5-7 0x47 + srom 8-10 0x95 + srom >= 11 0x99 +} + +# 4328 2G RSSI mid pt sel & board switch arch, +# 2 bytes, rev 3. +# +u8 rssismf2g { + srom 3 0x51 (&0xF) + srom 8-10 0xA5 (&0xF) +} +u8 rssismc2g { + srom 3 0x51 (&0xF0, >>4) + srom 8-10 0xA5 (&0xF0, >>4) +} +u8 rssisav2g { + srom 3 0x50 (&0x7) + srom 8-10 0xA4 (&0x7) +} +u8 bxa2g { + srom 3 0x50 (&0x18, >>3) + srom 8-10 0xA4 (&0x18, >>3) +} + +# 4328 5G RSSI mid pt sel & board switch arch, +# 2 bytes, rev 3. +# +u8 rssismf5g { + srom 3 0x53 (&0xF) + srom 8-10 0xA7 (&0xF) +} +u8 rssismc5g { + srom 3 0x53 (&0xF0, >>4) + srom 8-10 0xA7 (&0xF0, >>4) +} +u8 rssisav5g { + srom 3 0x52 (&0x7) + srom 8-10 0xA6 (&0x7) +} +u8 bxa5g { + srom 3 0x52 (&0x18, >>3) + srom 8-10 0xA6 (&0x18, >>3) +} + +u8 rxgainerr2ga0 { + srom 8-10 0x19B (&0x3F) + srom >= 11 0x1C7 (&0x3F) +} +u8 rxgainerr2ga1 { + srom 8-10 u16 0x19A (&0x7C0, >>6) + srom >= 11 u16 0x1C6 (&0x7C0, >>6) +} +u8 rxgainerr2ga2 { + srom 8-10 0x19A (&0xF8, >>3) + srom >= 11 0x1C6 (&0xF8, >>3) +} +u8[4] rxgainerr5ga0 { + srom >= 11 u8 0x1C9 (&0x3F), u8 0x1CB (&0x3F), u8 0x1CD (&0x3F), u8 0x1CF (&0x3F) +} +u8[4] rxgainerr5ga1 { + srom >= 11 u16[4] 0x1C8 (&0x7C0, >>6) +} +u8[4] rxgainerr5ga2 { + srom >= 11 u8 0x1C8 (&0xF8, >>3), u8 0x1CA (&0xF8, >>3), u8 0x1CC (&0xF8, >>3), u8 0x1CE (&0xF8, >>3) +} +u8 rxgainerr5gha0 { + srom 8-10 0x1A1 (&0x3F) +} +u8 rxgainerr5gha1 { + srom 8-10 u16 0x1A0 (&0x7C0, >>6) +} +u8 rxgainerr5gha2 { + srom 8-10 0x1A0 (&0xF8, >>3) +} +u8 rxgainerr5gla0 { + srom 8-10 0x19D (&0x3F) +} +u8 rxgainerr5gla1 { + srom 8-10 u16 0x19C (&0x7C0, >>6) +} +u8 rxgainerr5gla2 { + srom 8-10 0x19C (&0xF8, >>3) +} +u8 rxgainerr5gma0 { + srom 8-10 0x19F (&0x3F) +} +u8 rxgainerr5gma1 { + srom 8-10 u16 0x19E (&0x7C0, >>6) +} +u8 rxgainerr5gma2 { + srom 8-10 0x19E (&0xF8, >>3) +} +u8 rxgainerr5gua0 { + srom 8-10 0x1A3 (&0x3F) +} +u8 rxgainerr5gua1 { + srom 8-10 u16 0x1A2 (&0x7C0, >>6) +} +u8 rxgainerr5gua2 { + srom 8-10 0x1A2 (&0xF8, >>3) +} + +# 4328 2G RX power offset +i8 rxpo2g { + sfmt decimal + srom 3 0x5B + srom 8-10 0xAD +} + +# 4328 5G RX power offset +i8 rxpo5g { + sfmt decimal + srom 3 0x5A + srom 8-10 0xAC +} + +u16 subband5gver { + srom 8-10 u8 0x1A5 (&0x7) + srom >= 11 0xD6 +} + +# 2 bytes +# byte1 tempthresh +# byte2 period(msb 4 bits) | hysterisis(lsb 4 bits) +# +u8 tempthresh { + srom 8-10 0xB2 + srom >= 11 0xAE +} +u8 temps_period { + sfmt decimal + srom 8-10 0xBC (&0xF) + srom >= 11 0xB8 (&0xF) +} +u8 temps_hysteresis { + sfmt decimal + srom 8-10 0xBC (&0xF0, >>4) + srom >= 11 0xB8 (&0xF0, >>4) +} +u8 tempoffset { + sfmt decimal + srom 8-10 0xB3 + srom >= 11 0xAF +} +u8 tempsense_slope { + srom 8-10 0xB7 + srom >= 11 0xB3 +} +u8 tempcorrx { + srom 8-10 0xB6 (&0xFC, >>2) + srom >= 11 0xB2 (&0xFC, >>2) +} +u8 tempsense_option { + srom 8-10 0xB6 (&0x3) + srom >= 11 0xB2 (&0x3) +} +u8 phycal_tempdelta { + sfmt decimal + srom 8-10 0xBD + srom >= 11 0xB9 +} + +# 4328 2G TR isolation, 1 byte +u8 tri2g { + srom 3 0x55 + srom 8-10 0xA9 +} + +# 4328 5G TR isolation, 3 bytes +u8 tri5gl { + srom 3 0x57 + srom 8-10 0xAB +} +u8 tri5g { + srom 3 0x54 + srom 8-10 0xA8 +} +u8 tri5gh { + srom 3 0x56 + srom 8-10 0xAA +} + +# phy txbf rpcalvars +u16 rpcal2g { + srom >= 11 0x16C +} +u16 rpcal5gb0 { + srom >= 11 0x16E +} +u16 rpcal5gb1 { + srom >= 11 0x17C +} +u16 rpcal5gb2 { + srom >= 11 0x17E +} +u16 rpcal5gb3 { + srom >= 11 0x18C +} + +# Crystal frequency in kilohertz +u32 xtalfreq { + sfmt decimal + srom >= 11 u16 0xB4 +} + +# N-PHY tx power workaround +u8 txpid2ga0 { + srom 4-7 0x63 +} +u8 txpid2ga1 { + srom 4-7 0x62 +} +u8 txpid2ga2 { + srom 4-7 0x65 +} +u8 txpid2ga3 { + srom 4-7 0x64 +} +u8 txpid5ga0 { + srom 4-7 0x67 +} +u8 txpid5ga1 { + srom 4-7 0x66 +} +u8 txpid5ga2 { + srom 4-7 0x69 +} +u8 txpid5ga3 { + srom 4-7 0x68 +} +u8 txpid5gha0 { + srom 4-7 0x6F +} +u8 txpid5gha1 { + srom 4-7 0x6E +} +u8 txpid5gha2 { + srom 4-7 0x71 +} +u8 txpid5gha3 { + srom 4-7 0x70 +} +u8 txpid5gla0 { + srom 4-7 0x6B +} +u8 txpid5gla1 { + srom 4-7 0x6A +} +u8 txpid5gla2 { + srom 4-7 0x6D +} +u8 txpid5gla3 { + srom 4-7 0x6C +} + +u16 cckPwrOffset { + srom 10 0x1B4 +} +u8[6] et1macaddr { + sfmt macaddr + srom 0-2 u8 0x55, u8 0x54, u8 0x57, u8 0x56, u8 0x59, u8 0x58 +} +u8 eu_edthresh2g { + srom 8 0x1A9 + srom 9 0x199 + srom 10 0x199 + srom 11 0x1D1 +} +u8 eu_edthresh5g { + srom 8 0x1A8 + srom 9 0x198 + srom 10 0x198 + srom 11 0x1D0 +} +u8 freqoffset_corr { + srom 8-10 0xB9 (&0xF) +} +u8 hw_iqcal_en { + srom 8-10 0xB9 (&0x20, >>5) +} +u8[6] il0macaddr { + sfmt macaddr + srom 0-2 u8 0x49, u8 0x48, u8 0x51, u8 0x50, u8 0x53, u8 0x52 +} +u8 iqcal_swp_dis { + srom 8-10 0xB9 (&0x10, >>4) +} + +u8 noisecaloffset { + srom 8-9 0x1B5 +} +u8 noisecaloffset5g { + srom 8-9 0x1B4 +} +u8 noiselvl5gha0 { + srom 8-10 0x1B1 (&0x1F) +} +u8 noiselvl5gha1 { + srom 8-10 u16 0x1B0 (&0x3E0, >>5) +} +u8 noiselvl5gha2 { + srom 8-10 0x1B0 (&0x7C, >>2) +} +u8 noiselvl5gla0 { + srom 8-10 0x1AD (&0x1F) +} +u8 noiselvl5gla1 { + srom 8-10 u16 0x1AC (&0x3E0, >>5) +} +u8 noiselvl5gla2 { + srom 8-10 0x1AC (&0x7C, >>2) +} +u8 noiselvl5gma0 { + srom 8-10 0x1AF (&0x1F) +} +u8 noiselvl5gma1 { + srom 8-10 u16 0x1AE (&0x3E0, >>5) +} +u8 noiselvl5gma2 { + srom 8-10 0x1AE (&0x7C, >>2) +} +u8 noiselvl5gua0 { + srom 8-10 0x1B3 (&0x1F) +} +u8 noiselvl5gua1 { + srom 8-10 u16 0x1B2 (&0x3E0, >>5) +} +u8 noiselvl5gua2 { + srom 8-10 0x1B2 (&0x7C, >>2) +} + +u8 pcieingress_war { + srom 8-10 0x1A7 (&0xF) +} + +u8 pdoffsetcckma0 { + srom >= 11 0x18F (&0xF) +} +u8 pdoffsetcckma1 { + srom >= 11 0x18F (&0xF0, >>4) +} +u8 pdoffsetcckma2 { + srom >= 11 0x18E (&0xF) +} + +u8 sar2g { + srom 9-10 0x1A9 + srom >= 11 0x1BB +} +u8 sar5g { + srom 9-10 0x1A8 + srom >= 11 0x1BA +} + +u16 subvid { + srom >= 2 0x6 +} + +u32[5] swctrlmap_2g { + srom 10 u32[4] 0x1B8, u16 0x1C8 +} + +u16 tssifloor2g { + srom >= 11 0xBE (&0x3FF) +} +u16[4] tssifloor5g { + srom >= 11 0xC0 (&0x3FF) +} + +u8 txidxcap2g { + srom >= 11 u16 0x1A8 (&0xFF0, >>4) +} +u8 txidxcap5g { + srom >= 11 u16 0x1AC (&0xFF0, >>4) +} + +# +# Any variables defined within a `struct` block will be interpreted relative to +# the provided array of SPROM base addresses; this is used to define +# a common layout defined at the given base addresses. +# +# To produce SPROM variable names matching those used in the Broadcom HND +# ASCII 'key=value\0' NVRAM, the index number of the variable's +# struct instance will be appended (e.g., given a variable of noiselvl5ga, the +# generated variable instances will be named noiselvl5ga0, noiselvl5ga1, +# noiselvl5ga2, noiselvl5ga3 ...) +# + +# PHY chain[0-4] parameters +struct phy_chains[] { + srom 4-7 [0x080, 0x0AE, 0x0DC, 0x10A] + srom 8-10 [0x0C0, 0x0E0, 0x100, 0x120] + srom >= 11 [0x0D8, 0x100, 0x128] + + # AC-PHY PA parameters + u8[4] maxp5ga { + srom 4-7 u8 0xB + srom 8-10 u8 0x9 + srom >= 11 u8 0xD, u8 0xC, u8 0xF, u8 0xE + } + u16[3] pa2ga { + srom >= 11 0x2 + } + u8 maxp2ga { + srom 4-7 0x1 + srom 8-10 0x1 + srom >= 11 0x1 + } + u16[12] pa5ga { + srom >= 11 0x10 + } + + # AC-PHY rxgains + u8 rxgains5ghtrelnabypa { + srom >= 11 0x8 (&0x80, >>7) + } + u8 rxgains5ghelnagaina { + srom >= 11 0x8 (&0x7) + } + u8 rxgains5gelnagaina { + srom >= 11 0xA (&0x7) + } + u8 rxgains5gmtrelnabypa { + srom >= 11 0x9 (&0x80, >>7) + } + u8 rxgains2gtrelnabypa { + srom >= 11 0xB (&0x80, >>7) + } + u8 rxgains5gmtrisoa { + srom >= 11 0x9 (&0x78, >>3) + } + u8 rxgains5gmelnagaina { + srom >= 11 0x9 (&0x7) + } + u8 rxgains2gelnagaina { + srom >= 11 0xB (&0x7) + } + u8 rxgains5gtrisoa { + srom >= 11 0xA (&0x78, >>3) + } + u8 rxgains5gtrelnabypa { + srom >= 11 0xA (&0x80, >>7) + } + u8 rxgains2gtrisoa { + srom >= 11 0xB (&0x78, >>3) + } + u8 rxgains5ghtrisoa { + srom >= 11 0x8 (&0x78, >>3) + } + + # 11n PA parameters + u16 pa5gw2a { + srom 4-7 0x12 + srom 8-10 0x10 + } + u16 pa5ghw1a { + srom 4-7 0x20 + srom 8-10 0x1A + } + u16 pa5glw3a { + srom 4-7 0x1C + } + u16 pa5glw1a { + srom 4-7 0x18 + srom 8-10 0x14 + } + u16 pa5gw1a { + srom 4-7 0x10 + srom 8-10 0xE + } + u16 pa5glw0a { + srom 4-7 0x16 + srom 8-10 0x12 + } + u16 pa5gw3a { + srom 4-7 0x14 + } + u16 pa5glw2a { + srom 4-7 0x1A + srom 8-10 0x16 + } + u16 pa5ghw3a { + srom 4-7 0x24 + } + u16 pa5gw0a { + srom 4-7 0xE + srom 8-10 0xC + } + u8 maxp5gha { + srom 4-7 0xD + srom 8-10 0xB + } + u16 pa5ghw2a { + srom 4-7 0x22 + srom 8-10 0x1C + } + u16 pa5ghw0a { + srom 4-7 0x1E + srom 8-10 0x18 + } + u16 pa2gw3a { + srom 4-7 0x8 + } + u16 pa2gw2a { + srom 4-7 0x6 + srom 8-10 0x6 + } + u16 pa2gw1a { + srom 4-7 0x4 + srom 8-10 0x4 + } + u16 pa2gw0a { + srom 4-7 0x2 + srom 8-10 0x2 + } + u8 maxp5gla { + srom 4-7 0xC + srom 8-10 0xA + } + u8 itt5ga { + srom 4-7 0xA + srom 8-10 0x8 + } + u8 itt2ga { + srom 4-7 0x0 + srom 8-10 0x0 + } +} diff --git a/sys/dev/bhnd/nvram/nvram_subr.c b/sys/dev/bhnd/nvram/nvram_subr.c new file mode 100644 index 0000000..8465af8 --- /dev/null +++ b/sys/dev/bhnd/nvram/nvram_subr.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "bhnd_nvram_map_data.h" + +/* + * CRC-8 lookup table used to checksum SPROM and NVRAM data via + * bhnd_nvram_crc8(). + * + * Generated with following parameters: + * polynomial: CRC-8 (x^8 + x^7 + x^6 + x^4 + x^2 + 1) + * reflected bits: false + * reversed: true + */ +const uint8_t bhnd_nvram_crc8_tab[] = { + 0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3, + 0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, + 0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f, + 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b, + 0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, + 0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09, + 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91, + 0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01, + 0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38, + 0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, + 0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f, + 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5, + 0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, + 0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82, + 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1, + 0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5, + 0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3, + 0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, + 0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1, + 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5, + 0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, + 0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49, + 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1, + 0x26, 0x68, 0x9f +}; + + +/** + * Return the size of type @p dt. + * + * @param dt NVRAM data type. + * @result the byte width of @p dt. + */ +size_t +bhnd_nvram_type_width(bhnd_nvram_dt dt) +{ + switch (dt) { + case BHND_NVRAM_DT_INT8: + case BHND_NVRAM_DT_UINT8: + case BHND_NVRAM_DT_CHAR: + return (sizeof(uint8_t)); + + case BHND_NVRAM_DT_INT16: + case BHND_NVRAM_DT_UINT16: + return (sizeof(uint16_t)); + + case BHND_NVRAM_DT_INT32: + case BHND_NVRAM_DT_UINT32: + return (sizeof(uint32_t)); + } + + /* Quiesce gcc4.2 */ + panic("bhnd nvram data type %u unknown", dt); +} + + +/** + * Return the variable definition for @p varname, if any. + * + * @param varname variable name + * + * @retval bhnd_nvram_var If a valid definition for @p varname is found. + * @retval NULL If no definition for @p varname is found. + */ +const struct bhnd_nvram_var * +bhnd_nvram_var_defn(const char *varname) +{ + size_t min, mid, max; + int order; + + /* + * Locate the requested variable using a binary search. + * + * The variable table is guaranteed to be sorted in lexicographical + * order (using the 'C' locale for collation rules) + */ + min = 0; + mid = 0; + max = nitems(bhnd_nvram_vars) - 1; + + while (max >= min) { + /* Select midpoint */ + mid = (min + max) / 2; + + /* Determine which side of the partition to search */ + order = strcmp(bhnd_nvram_vars[mid].name, varname); + if (order < 0) { + /* Search upper partition */ + min = mid + 1; + } else if (order > 0) { + /* Search lower partition */ + max = mid - 1; + } else if (order == 0) { + /* Match found */ + return (&bhnd_nvram_vars[mid]); + } + } + + /* Not found */ + return (NULL); +} diff --git a/sys/dev/bhnd/nvram/nvramvar.h b/sys/dev/bhnd/nvram/nvramvar.h new file mode 100644 index 0000000..969cb50 --- /dev/null +++ b/sys/dev/bhnd/nvram/nvramvar.h @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_BHND_NVRAMVAR_H_ +#define _BHND_NVRAM_BHND_NVRAMVAR_H_ + +/** NVRAM Primitive data types */ +typedef enum { + BHND_NVRAM_DT_UINT8 = 0, /**< unsigned 8-bit integer */ + BHND_NVRAM_DT_UINT16 = 1, /**< unsigned 16-bit integer */ + BHND_NVRAM_DT_UINT32 = 2, /**< unsigned 32-bit integer */ + BHND_NVRAM_DT_INT8 = 3, /**< signed 8-bit integer */ + BHND_NVRAM_DT_INT16 = 4, /**< signed 16-bit integer */ + BHND_NVRAM_DT_INT32 = 5, /**< signed 32-bit integer */ + BHND_NVRAM_DT_CHAR = 6, /**< ASCII char */ +} bhnd_nvram_dt; + +/** NVRAM data type string representations */ +typedef enum { + BHND_NVRAM_VFMT_HEX = 1, /**< hex format */ + BHND_NVRAM_VFMT_DEC = 2, /**< decimal format */ + BHND_NVRAM_VFMT_MACADDR = 3, /**< mac address (canonical form, hex octets, + separated with ':') */ + BHND_NVRAM_VFMT_LEDDC = 4, /**< LED PWM duty-cycle (2 bytes -- on/off) */ + BHND_NVRAM_VFMT_CCODE = 5 /**< count code format (2-3 ASCII chars, or hex string) */ +} bhnd_nvram_fmt; + +/** NVRAM variable flags */ +enum { + BHND_NVRAM_VF_ARRAY = (1<<0), /**< variable is an array */ + BHND_NVRAM_VF_MFGINT = (1<<1), /**< mfg-internal variable; should not be externally visible */ + BHND_NVRAM_VF_IGNALL1 = (1<<2) /**< hide variable if its value has all bits set. */ +}; + +#define BHND_SPROMREV_MAX UINT8_MAX /**< maximum supported SPROM revision */ + +/** SPROM revision compatibility declaration */ +struct bhnd_sprom_compat { + uint8_t first; /**< first compatible SPROM revision */ + uint8_t last; /**< last compatible SPROM revision, or BHND_SPROMREV_MAX */ +}; + +/** SPROM value descriptor */ +struct bhnd_sprom_offset { + uint16_t offset; /**< byte offset within SPROM */ + bool cont:1; /**< value should be bitwise OR'd with the + * previous offset descriptor */ + bhnd_nvram_dt type:7; /**< data type */ + int8_t shift; /**< shift to be applied to the value */ + uint32_t mask; /**< mask to be applied to the value(s) */ +}; + +/** SPROM-specific variable definition */ +struct bhnd_sprom_var { + struct bhnd_sprom_compat compat; /**< sprom compatibility declaration */ + const struct bhnd_sprom_offset *offsets; /**< offset descriptors */ + size_t num_offsets; /**< number of offset descriptors */ +}; + +/** NVRAM variable definition */ +struct bhnd_nvram_var { + const char *name; /**< variable name */ + bhnd_nvram_dt type; /**< base data type */ + bhnd_nvram_fmt fmt; /**< string format */ + uint32_t flags; /**< BHND_NVRAM_VF_* flags */ + + const struct bhnd_sprom_var *sprom_descs; /**< SPROM-specific variable descriptors */ + size_t num_sp_descs; /**< number of sprom descriptors */ +}; + +size_t bhnd_nvram_type_width(bhnd_nvram_dt dt); +const struct bhnd_nvram_var *bhnd_nvram_var_defn(const char *varname); + +/** Initial bhnd_nvram_crc8 value */ +#define BHND_NVRAM_CRC8_INITIAL 0xFF + +/** Valid CRC-8 checksum */ +#define BHND_NVRAM_CRC8_VALID 0x9F + +extern const uint8_t bhnd_nvram_crc8_tab[]; + +/** + * Calculate CRC-8 over @p buf. + * + * @param buf input buffer + * @param size buffer size + * @param crc last computed crc, or BHND_NVRAM_CRC8_INITIAL + */ +static inline uint8_t +bhnd_nvram_crc8(const void *buf, size_t size, uint8_t crc) +{ + const uint8_t *p = (const uint8_t *)buf; + while (size--) + crc = bhnd_nvram_crc8_tab[(crc ^ *p++)]; + + return (crc); +} + + +#endif /* _BHND_NVRAM_BHND_NVRAMVAR_H_ */ \ No newline at end of file diff --git a/sys/dev/bhnd/tools/bus_macro.sh b/sys/dev/bhnd/tools/bus_macro.sh old mode 100755 new mode 100644 diff --git a/sys/dev/bhnd/tools/nvram_map_gen.awk b/sys/dev/bhnd/tools/nvram_map_gen.awk new file mode 100755 index 0000000..52e3a4d --- /dev/null +++ b/sys/dev/bhnd/tools/nvram_map_gen.awk @@ -0,0 +1,1162 @@ +#!/usr/bin/awk -f + +#- +# Copyright (c) 2015-2016 Landon Fuller +# 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, +# without modification. +# 2. Redistributions in binary form must reproduce at minimum a disclaimer +# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any +# redistribution must be conditioned upon including a substantially +# similar Disclaimer requirement for further binary redistribution. +# +# NO WARRANTY +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. +# +# $FreeBSD$ + +BEGIN { + RS="\n" + + depth = 0 + symbols[depth,"_file"] = FILENAME + num_output_vars = 0 + OUTPUT_FILE = null + + # Seed rand() + srand() + + # Output type + OUT_T = null + OUT_T_HEADER = "HEADER" + OUT_T_DATA = "DATA" + + # Enable debug output + DEBUG = 0 + + # Maximum revision + REV_MAX = 255 + + # Parse arguments + if (ARGC < 2) + usage() + + for (i = 1; i < ARGC; i++) { + if (ARGV[i] == "--debug") { + DEBUG = 1 + } else if (ARGV[i] == "-d" && OUT_T == null) { + OUT_T = OUT_T_DATA + } else if (ARGV[i] == "-h" && OUT_T == null) { + OUT_T = OUT_T_HEADER + } else if (ARGV[i] == "-o") { + i++ + if (i >= ARGC) + usage() + + OUTPUT_FILE = ARGV[i] + } else if (ARGV[i] == "--") { + i++ + break + } else if (ARGV[i] !~ /^-/) { + FILENAME = ARGV[i] + } else { + print "unknown option " ARGV[i] + usage() + } + } + + ARGC=2 + + if (OUT_T == null) { + print("error: one of -d or -h required") + usage() + } + + if (FILENAME == null) { + print("error: no input file specified") + usage() + } + + if (OUTPUT_FILE == "-") { + OUTPUT_FILE = "/dev/stdout" + } else if (OUTPUT_FILE == null) { + _bi = split(FILENAME, _paths, "/") + OUTPUT_FILE = _paths[_bi] + + if (OUTPUT_FILE !~ /^bhnd_/) + OUTPUT_FILE = "bhnd_" OUTPUT_FILE + + if (OUT_T == OUT_T_HEADER) + OUTPUT_FILE = OUTPUT_FILE ".h" + else + OUTPUT_FILE = OUTPUT_FILE "_data.h" + } + + # Format Constants + FMT["hex"] = "BHND_NVRAM_VFMT_HEX" + FMT["decimal"] = "BHND_NVRAM_VFMT_DEC" + FMT["ccode"] = "BHND_NVRAM_VFMT_CCODE" + FMT["macaddr"] = "BHND_NVRAM_VFMT_MACADDR" + FMT["led_dc"] = "BHND_NVRAM_VFMT_LEDDC" + + # Data Type Constants + DTYPE["u8"] = "BHND_NVRAM_DT_UINT8" + DTYPE["u16"] = "BHND_NVRAM_DT_UINT16" + DTYPE["u32"] = "BHND_NVRAM_DT_UINT32" + DTYPE["i8"] = "BHND_NVRAM_DT_INT8" + DTYPE["i16"] = "BHND_NVRAM_DT_INT16" + DTYPE["i32"] = "BHND_NVRAM_DT_INT32" + DTYPE["char"] = "BHND_NVRAM_DT_CHAR" + + # Default masking for standard types + TMASK["u8"] = "0x000000FF" + TMASK["u16"] = "0x0000FFFF" + TMASK["u32"] = "0xFFFFFFFF" + TMASK["i8"] = TMASK["u8"] + TMASK["i16"] = TMASK["u16"] + TMASK["i32"] = TMASK["u32"] + TMASK["char"] = TMASK["u8"] + + # Byte sizes for standard types + TSIZE["u8"] = "1" + TSIZE["u16"] = "2" + TSIZE["u32"] = "4" + TSIZE["i8"] = TSIZE["u8"] + TSIZE["i16"] = TSIZE["u8"] + TSIZE["i32"] = TSIZE["u8"] + TSIZE["char"] = "1" + + # Common Regexs + INT_REGEX = "^(0|[1-9][0-9]*),?$" + HEX_REGEX = "^0x[A-Fa-f0-9]+,?$" + + ARRAY_REGEX = "\\[(0|[1-9][0-9]*)\\]" + TYPES_REGEX = "^(((u|i)(8|16|32))|char)("ARRAY_REGEX")?,?$" + + IDENT_REGEX = "^[A-Za-z_][A-Za-z0-9_]*,?$" + SROM_OFF_REGEX = "("TYPES_REGEX"|"HEX_REGEX")" + + # Parser states types + ST_STRUCT_BLOCK = "struct" # struct block + ST_VAR_BLOCK = "var" # variable block + ST_SROM_DEFN = "srom" # srom offset defn + ST_NONE = "NONE" # default state + + # Property types + PROP_T_SFMT = "sfmt" + PROP_T_ALL1 = "all1" + + # Internal variables used for parser state + # tracking + STATE_TYPE = "_state_type" + STATE_IDENT = "_state_block_name" + STATE_LINENO = "_state_first_line" + STATE_ISBLOCK = "_state_is_block" + + # Common array keys + DEF_LINE = "def_line" + NUM_REVS = "num_revs" + REV = "rev" + + # Revision array keys + REV_START = "rev_start" + REV_END = "rev_end" + REV_DESC = "rev_decl" + REV_NUM_OFFS = "num_offs" + + # Offset array keys + OFF = "off" + OFF_NUM_SEGS = "off_num_segs" + OFF_SEG = "off_seg" + + # Segment array keys + SEG_ADDR = "seg_addr" + SEG_COUNT = "seg_count" + SEG_TYPE = "seg_type" + SEG_MASK = "seg_mask" + SEG_SHIFT = "seg_shift" + + # Variable array keys + VAR_NAME = "v_name" + VAR_TYPE = "v_type" + VAR_BASE_TYPE = "v_base_type" + VAR_FMT = "v_fmt" + VAR_STRUCT = "v_parent_struct" + VAR_PRIVATE = "v_private" + VAR_ARRAY = "v_array" + VAR_IGNALL1 = "v_ignall1" +} + +# return the flag definition for variable `v` +function gen_var_flags (v) +{ + _num_flags = 0; + if (vars[v,VAR_ARRAY]) + _flags[_num_flags++] = "BHND_NVRAM_VF_ARRAY" + + if (vars[v,VAR_PRIVATE]) + _flags[_num_flags++] = "BHND_NVRAM_VF_MFGINT" + + if (vars[v,VAR_IGNALL1]) + _flags[_num_flags++] = "BHND_NVRAM_VF_IGNALL1" + + if (_num_flags == 0) + _flags[_num_flags++] = "0" + + return (join(_flags, "|", _num_flags)) +} + +# emit the bhnd_sprom_offsets for a given variable revision key +function emit_var_sprom_offsets (v, revk) +{ + emit(sprintf("{{%u, %u}, (struct bhnd_sprom_offset[]) {\n", + vars[revk,REV_START], + vars[revk,REV_END])) + output_depth++ + + num_offs = vars[revk,REV_NUM_OFFS] + num_offs_written = 0 + elem_count = 0 + for (offset = 0; offset < num_offs; offset++) { + offk = subkey(revk, OFF, offset"") + num_segs = vars[offk,OFF_NUM_SEGS] + + for (seg = 0; seg < num_segs; seg++) { + segk = subkey(offk, OFF_SEG, seg"") + + for (seg_n = 0; seg_n < vars[segk,SEG_COUNT]; seg_n++) { + seg_addr = vars[segk,SEG_ADDR] + seg_addr += TSIZE[vars[segk,SEG_TYPE]] * seg_n + + emit(sprintf("{%s, %s, %s, %s, %s},\n", + seg_addr, + (seg > 0) ? "true" : "false", + DTYPE[vars[segk,SEG_TYPE]], + vars[segk,SEG_SHIFT], + vars[segk,SEG_MASK])) + + num_offs_written++ + } + } + } + + output_depth-- + emit("}, " num_offs_written "},\n") +} + +# emit the bhnd_nvram_var definition for variable name `v` +function emit_var_defn (v) +{ + emit(sprintf("{\"%s\", %s, %s, %s, (struct bhnd_sprom_var[]) {\n", + v suffix, + DTYPE[vars[v,VAR_BASE_TYPE]], + FMT[vars[v,VAR_FMT]], + gen_var_flags(v))) + output_depth++ + + for (rev = 0; rev < vars[v,NUM_REVS]; rev++) { + revk = subkey(v, REV, rev"") + emit_var_sprom_offsets(v, revk) + } + + output_depth-- + emit("}, " vars[v,NUM_REVS] "},\n") +} + +# emit a header name #define for variable `v` +function emit_var_namedef (v) +{ + emit("#define\tBHND_NVAR_" toupper(v) "\t\"" v "\"\n") +} + +# generate a set of var offset definitions for struct variable `st_vid` +function gen_struct_var_offsets (vid, revk, st_vid, st_revk, base_addr) +{ + # Copy all offsets to the new variable + for (offset = 0; offset < vars[v,REV_NUM_OFFS]; offset++) { + st_offk = subkey(st_revk, OFF, offset"") + offk = subkey(revk, OFF, offset"") + + # Copy all segments to the new variable, applying base + # address adjustment + num_segs = vars[st_offk,OFF_NUM_SEGS] + vars[offk,OFF_NUM_SEGS] = num_segs + + for (seg = 0; seg < num_segs; seg++) { + st_segk = subkey(st_offk, OFF_SEG, seg"") + segk = subkey(offk, OFF_SEG, seg"") + + vars[segk,SEG_ADDR] = vars[st_segk,SEG_ADDR] + \ + base_addr"" + vars[segk,SEG_COUNT] = vars[st_segk,SEG_COUNT] + vars[segk,SEG_TYPE] = vars[st_segk,SEG_TYPE] + vars[segk,SEG_MASK] = vars[st_segk,SEG_MASK] + vars[segk,SEG_SHIFT] = vars[st_segk,SEG_SHIFT] + } + } +} + +# generate a complete set of variable definitions for struct variable `st_vid`. +function gen_struct_vars (st_vid) +{ + st = vars[st_vid,VAR_STRUCT] + st_max_off = 0 + + # determine the total number of variables to generate + for (st_rev = 0; st_rev < structs[st,NUM_REVS]; st_rev++) { + srevk = subkey(st, REV, st_rev"") + for (off = 0; off < structs[srevk,REV_NUM_OFFS]; off++) { + if (off > st_max_off) + st_max_off = off + } + } + + # generate variable records for each defined struct offset + for (off = 0; off < st_max_off; off++) { + # Construct basic variable definition + v = st_vid off"" + vars[v,VAR_TYPE] = vars[st_vid,VAR_TYPE] + vars[v,VAR_BASE_TYPE] = vars[st_vid,VAR_BASE_TYPE] + vars[v,VAR_FMT] = vars[st_vid,VAR_FMT] + vars[v,VAR_PRIVATE] = vars[st_vid,VAR_PRIVATE] + vars[v,VAR_ARRAY] = vars[st_vid,VAR_ARRAY] + vars[v,VAR_IGNALL1] = vars[st_vid,VAR_IGNALL1] + vars[v,NUM_REVS] = 0 + + # Add to output variable list + output_vars[num_output_vars++] = v + + # Construct revision / offset entries + for (srev = 0; srev < structs[st,NUM_REVS]; srev++) { + # Struct revision key + st_revk = subkey(st, REV, srev"") + + # Skip offsets not defined for this revision + if (off > structs[st_revk,REV_NUM_OFFS]) + continue + + # Strut offset key and associated base address */ + offk = subkey(st_revk, OFF, off"") + base_addr = structs[offk,SEG_ADDR] + + for (vrev = 0; vrev < vars[st_vid,NUM_REVS]; vrev++) { + st_var_revk = subkey(st_vid, REV, vrev"") + v_start = vars[st_var_revk,REV_START] + v_end = vars[st_var_revk,REV_END] + s_start = structs[st_revk,REV_START] + s_end = structs[st_revk,REV_END] + + # We don't support computing the union + # of partially overlapping ranges + if ((v_start < s_start && v_end >= s_start) || + (v_start <= s_end && v_end > s_end)) + { + errorx("partially overlapping " \ + "revision ranges are not supported") + } + + # skip variables revs that are not within + # the struct offset's compatibility range + if (v_start < s_start || v_start > s_end || + v_end < s_start || v_end > s_end) + continue + + # Generate the new revision record + rev = vars[v,NUM_REVS] "" + revk = subkey(v, REV, rev) + vars[v,NUM_REVS]++ + + vars[revk,DEF_LINE] = vars[st_revk,DEF_LINE] + vars[revk,REV_START] = v_start + vars[revk,REV_END] = v_end + vars[revk,REV_NUM_OFFS] = \ + vars[st_var_revk,REV_NUM_OFFS] + + gen_struct_var_offsets(v, revk, st_vid, st_revk, + base_addr) + } + } + } +} + + +END { + # Skip completion handling if exiting from an error + if (_EARLY_EXIT) + exit 1 + + # Check for complete block closure + if (depth > 0) { + block_start = g(STATE_LINENO) + errorx("missing '}' for block opened on line " block_start "") + } + + # Generate concrete variable definitions for all struct variables + for (v in var_names) { + if (vars[v,VAR_STRUCT] != null) { + gen_struct_vars(v) + } else { + output_vars[num_output_vars++] = v + } + } + + # Apply lexicographical sorting. To support more effecient table + # searching, we guarantee a stable sort order (using C collation). + sort(output_vars) + + # Truncate output file and write common header + printf("") > OUTPUT_FILE + emit("/*\n") + emit(" * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.\n") + emit(" *\n") + emit(" * generated from nvram map: " FILENAME "\n") + emit(" */\n") + emit("\n") + + # Emit all variable definitions + if (OUT_T == OUT_T_DATA) { + emit("#include \n") + emit("static const struct bhnd_nvram_var bhnd_nvram_vars[] = "\ + "{\n") + output_depth++ + for (i = 0; i < num_output_vars; i++) + emit_var_defn(output_vars[i]) + output_depth-- + emit("};\n") + } else if (OUT_T == OUT_T_HEADER) { + for (i = 0; i < num_output_vars; i++) + emit_var_namedef(output_vars[i]) + } + + printf("%u variable records written to %s\n", num_output_vars, + OUTPUT_FILE) >> "/dev/stderr" +} + + +# +# Print usage +# +function usage () +{ + print "usage: bhnd_nvram_map.awk [-hd] [-o output file]" + _EARLY_EXIT = 1 + exit 1 +} + +# +# Join all array elements with the given separator +# +function join (array, sep, count) +{ + if (count == 0) + return ("") + + _result = array[0] + for (_ji = 1; _ji < count; _ji++) + _result = _result sep array[_ji] + + return (_result) +} + +# +# Sort a contiguous integer-indexed array, using standard awk comparison +# operators over its values. +# +function sort (array) { + # determine array size + _sort_alen = 0 + + for (_ssort_key in array) + _sort_alen++ + + if (_sort_alen <= 1) + return + + # perform sort + _qsort(array, 0, _sort_alen-1) +} + +function _qsort (array, first, last) +{ + if (first >= last) + return + + # select pivot element + _qpivot = int(first + int((last-first+1) * rand())) + _qleft = first + _qright = last + + _qpivot_val = array[_qpivot] + + # partition + while (_qleft <= _qright) { + while (array[_qleft] < _qpivot_val) + _qleft++ + + while (array[_qright] > _qpivot_val) + _qright-- + + # swap + if (_qleft <= _qright) { + _qleft_val = array[_qleft] + _qright_val = array[_qright] + + array[_qleft] = _qright_val + array[_qright] = _qleft_val + + _qleft++ + _qright-- + } + } + + # sort the partitions + _qsort(array, first, _qright) + _qsort(array, _qleft, last) +} + +# +# Print msg to output file, without indentation +# +function emit_ni (msg) +{ + printf("%s", msg) >> OUTPUT_FILE +} + +# +# Print msg to output file, indented for the current `output_depth` +# +function emit (msg) +{ + for (_ind = 0; _ind < output_depth; _ind++) + emit_ni("\t") + + emit_ni(msg) +} + +# +# Print a warning to stderr +# +function warn (msg) +{ + print "warning:", msg, "at", FILENAME, "line", NR > "/dev/stderr" +} + +# +# Print a compiler error to stderr +# +function error (msg) +{ + errorx(msg " at " FILENAME " line " NR ":\n\t" $0) +} + +# +# Print an error message without including the source line information +# +function errorx (msg) +{ + print "error:", msg > "/dev/stderr" + _EARLY_EXIT=1 + exit 1 +} + +# +# Print a debug output message +# +function debug (msg) +{ + if (!DEBUG) + return + for (_di = 0; _di < depth; _di++) + printf("\t") > "/dev/stderr" + print msg > "/dev/stderr" +} + +# +# Return an array key composed of the given (parent, selector, child) +# tuple. +# The child argument is optional and may be omitted. +# +function subkey (parent, selector, child) +{ + if (child != null) + return (parent SUBSEP selector SUBSEP child) + else + return (parent SUBSEP selector) +} + +# +# Advance to the next non-comment input record +# +function next_line () +{ + do { + _result = getline + } while (_result > 0 && $0 ~ /^[ \t]*#.*/) # skip comment lines + return (_result) +} + +# +# Advance to the next input record and verify that it matches @p regex +# +function getline_matching (regex) +{ + _result = next_line() + if (_result <= 0) + return (_result) + + if ($0 ~ regex) + return (1) + + return (-1) +} + +# +# Shift the current fields left by `n`. +# +# If all fields are consumed and the optional do_getline argument is true, +# read the next line. +# +function shiftf (n, do_getline) +{ + if (n > NF) error("shift past end of line") + for (_si = 1; _si <= NF-n; _si++) { + $(_si) = $(_si+n) + } + NF = NF - n + + if (NF == 0 && do_getline) + next_line() +} + +# +# Parse a revision descriptor from the current line. +# +function parse_revdesc (result) +{ + _rstart = 0 + _rend = 0 + + if ($2 ~ "[0-9]*-[0-9*]") { + split($2, _revrange, "[ \t]*-[ \t]*") + _rstart = _revrange[1] + _rend = _revrange[2] + } else if ($2 ~ "(>|>=|<|<=)" && $3 ~ "[1-9][0-9]*") { + if ($2 == ">") { + _rstart = int($3)+1 + _rend = REV_MAX + } else if ($2 == ">=") { + _rstart = int($3) + _rend = REV_MAX + } else if ($2 == "<" && int($3) > 0) { + _rstart = 0 + _rend = int($3)-1 + } else if ($2 == "<=") { + _rstart = 0 + _rend = int($3)-1 + } else { + error("invalid revision descriptor") + } + } else if ($2 ~ "[1-9][0-9]*") { + _rstart = int($2) + _rend = int($2) + } else { + error("invalid revision descriptor") + } + + result[REV_START] = _rstart + result[REV_END] = _rend +} + +# +# Push a new parser state. +# +# The name may be null, in which case the STATE_IDENT variable will not be +# defined in this scope +# +function push_state (type, name, block) { + depth++ + push(STATE_LINENO, NR) + if (name != null) + push(STATE_IDENT, name) + push(STATE_TYPE, type) + push(STATE_ISBLOCK, block) +} + +# +# Pop the top of the parser state stack. +# +function pop_state () { + # drop all symbols defined at this depth + for (s in symbols) { + if (s ~ "^"depth"[^0-9]") + delete symbols[s] + } + depth-- +} + +# +# Find opening brace and push a new parser state for a brace-delimited block. +# +# The name may be null, in which case the STATE_IDENT variable will not be +# defined in this scope +# +function open_block (type, name) +{ + if ($0 ~ "{" || getline_matching("^[ \t]*{") > 0) { + push_state(type, name, 1) + sub("^[^{]+{", "", $0) + return + } + + error("found '"$1 "' instead of expected '{' for '" name "'") +} + +# +# Find closing brace and pop parser states until the first +# brace-delimited block is discarded. +# +function close_block () +{ + if ($0 !~ "}") + error("internal error - no closing brace") + + # pop states until we exit the first enclosing block + do { + _closed_block = g(STATE_ISBLOCK) + pop_state() + } while (!_closed_block) + + # strip everything prior to the block closure + sub("^[^}]*}", "", $0) +} + +# Internal symbol table lookup function. Returns the symbol depth if +# name is found at or above scope; if scope is null, it defauls to 0 +function _find_sym (name, scope) +{ + if (scope == null) + scope = 0; + + for (i = scope; i < depth; i++) { + if ((depth-i,name) in symbols) + return (depth-i) + } + + return (-1) +} + +# +# Look up a variable in the symbol table with `name` and return its value. +# +# If `scope` is not null, the variable search will start at the provided +# scope level -- 0 is the current scope, 1 is the parent's scope, etc. +# +function g (name, scope) +{ + _g_depth = _find_sym(name, scope) + if (_g_depth < 0) + error("'" name "' is undefined") + + return (symbols[_g_depth,name]) +} + +function is_defined (name, scope) +{ + return (_find_sym(name, scope) >= 0) +} + +# Define a new variable in the symbol table's current scope, +# with the given value +function push (name, value) +{ + symbols[depth,name] = value +} + +# Set an existing variable's value in the symbol table; if not yet defined, +# will trigger an error +function set (name, value, scope) +{ + for (i = 0; i < depth; i++) { + if ((depth-i,name) in symbols) { + symbols[depth-i,name] = value + return + } + } + # No existing value, cannot define + error("'" name "' is undefined") +} + +# Evaluates to true if immediately within a block scope of the given type +function in_state (type) +{ + if (!is_defined(STATE_TYPE)) + return (type == ST_NONE) + + return (type == g(STATE_TYPE)) +} + +# Evaluates to true if within an immediate or non-immediate block scope of the +# given type +function in_nested_state (type) +{ + for (i = 0; i < depth; i++) { + if ((depth-i,STATE_TYPE) in symbols) { + if (symbols[depth-i,STATE_TYPE] == type) + return (1) + } + } + return (0) +} + +# Evaluates to true if definitions of the given type are permitted within +# the current scope +function allow_def (type) +{ + if (type == ST_VAR_BLOCK) { + return (in_state(ST_NONE) || in_state(ST_STRUCT_BLOCK)) + } else if (type == ST_STRUCT_BLOCK) { + return (in_state(ST_NONE)) + } else if (type == ST_SROM_DEFN) { + return (in_state(ST_VAR_BLOCK) || in_state(ST_STRUCT_BLOCK)) + } + + error("unknown type '" type "'") +} + +# struct definition +$1 == ST_STRUCT_BLOCK && allow_def($1) { + name = $2 + + # Remove array[] specifier + if (sub(/\[\]$/, "", name) == 0) + error("expected '" name "[]', not '" name "'") + + if (name !~ IDENT_REGEX || name ~ TYPES_REGEX) + error("invalid identifier '" name "'") + + # Add top-level struct entry + if ((name,DEF_LINE) in structs) + error("struct identifier '" name "' previously defined on " \ + "line " structs[name,DEF_LINE]) + structs[name,DEF_LINE] = NR + structs[name,NUM_REVS] = 0 + + # Open the block + debug("struct " name " {") + open_block(ST_STRUCT_BLOCK, name) +} + +# struct srom descriptor +$1 == ST_SROM_DEFN && allow_def(ST_SROM_DEFN) && in_state(ST_STRUCT_BLOCK) { + sid = g(STATE_IDENT) + + # parse revision descriptor + rev_desc[REV_START] = 0 + parse_revdesc(rev_desc) + + # assign revision id + rev = structs[sid,NUM_REVS] "" + revk = subkey(sid, REV, rev) + structs[sid,NUM_REVS]++ + + # init basic revision state + structs[revk,REV_START] = rev_desc[REV_START] + structs[revk,REV_END] = rev_desc[REV_END] + + if (match($0, "\\[[^]]*\\]") <= 0) + error("expected base address array") + + addrs_str = substr($0, RSTART+1, RLENGTH-2) + num_offs = split(addrs_str, addrs, ",[ \t]*") + structs[revk, REV_NUM_OFFS] = num_offs + for (i = 1; i <= num_offs; i++) { + offk = subkey(revk, OFF, (i-1) "") + + if (addrs[i] !~ HEX_REGEX) + error("invalid base address '" addrs[i] "'") + + structs[offk,SEG_ADDR] = addrs[i] + } + + debug("struct_srom " structs[revk,REV_START] "... [" addrs_str "]") + next +} + +# close any previous srom revision descriptor +$1 == ST_SROM_DEFN && in_state(ST_SROM_DEFN) { + pop_state() +} + +# open a new srom revision descriptor +$1 == ST_SROM_DEFN && allow_def(ST_SROM_DEFN) { + # parse revision descriptor + parse_revdesc(rev_desc) + + # assign revision id + vid = g(STATE_IDENT) + rev = vars[vid,NUM_REVS] "" + revk = subkey(vid, REV, rev) + vars[vid,NUM_REVS]++ + + # vend scoped rev/revk variables for use in the + # revision offset block + push("rev_id", rev) + push("rev_key", revk) + + # init basic revision state + vars[revk,DEF_LINE] = NR + vars[revk,REV_START] = rev_desc[REV_START] + vars[revk,REV_END] = rev_desc[REV_END] + vars[revk,REV_NUM_OFFS] = 0 + + debug("srom " rev_desc[REV_START] "-" rev_desc[REV_END] " {") + push_state(ST_SROM_DEFN, null, 0) + + # seek to the first offset definition + do { + shiftf(1) + } while ($1 !~ SROM_OFF_REGEX && NF > 0) +} + +# +# Extract and return the array length from the given type string. +# Returns -1 if the type is not an array. +# +function type_array_len (type) +{ + # extract byte count[] and width + if (match(type, ARRAY_REGEX"$") > 0) { + return (substr(type, RSTART+1, RLENGTH-2)) + } else { + return (-1) + } +} + +# +# Parse an offset declaration from the current line. +# +function parse_offset_segment (revk, offk) +{ + vid = g(STATE_IDENT) + + # use explicit type if specified, otherwise use the variable's + # common type + if ($1 !~ HEX_REGEX) { + type = $1 + if (type !~ TYPES_REGEX) + error("unknown field type '" type "'") + + shiftf(1) + } else { + type = vars[vid,VAR_TYPE] + } + + # read offset value + offset = $1 + if (offset !~ HEX_REGEX) + error("invalid offset value '" offset "'") + + # extract byte count[], base type, and width + if (match(type, ARRAY_REGEX"$") > 0) { + count = int(substr(type, RSTART+1, RLENGTH-2)) + type = substr(type, 1, RSTART-1) + } else { + count = 1 + } + width = TSIZE[type] + + # seek to attributes or end of the offset expr + sub("^[^,(|){}]+", "", $0) + + # parse attributes + mask=TMASK[type] + shift=0 + + if ($1 ~ "^\\(") { + # extract attribute list + if (match($0, "\\([^|\(\)]*\\)") <= 0) + error("expected attribute list") + attr_str = substr($0, RSTART+1, RLENGTH-2) + + # drop from input line + $0 = substr($0, RSTART+RLENGTH, length($0) - RSTART+RLENGTH) + + # parse attributes + num_attr = split(attr_str, attrs, ",[ \t]*") + for (i = 1; i <= num_attr; i++) { + attr = attrs[i] + if (sub("^&[ \t]*", "", attr) > 0) { + mask = attr + } else if (sub("^<<[ \t]*", "", attr) > 0) { + shift = "-"attr + } else if (sub("^>>[ \t]*", "", attr) > 0) { + shift = attr + } else { + error("unknown attribute '" attr "'") + } + } + } + + # assign segment id + seg = vars[offk,OFF_NUM_SEGS] "" + segk = subkey(offk, OFF_SEG, seg) + vars[offk,OFF_NUM_SEGS]++ + + vars[segk,SEG_ADDR] = offset + (width * _oi) + vars[segk,SEG_COUNT] = count + vars[segk,SEG_TYPE] = type + vars[segk,SEG_MASK] = mask + vars[segk,SEG_SHIFT] = shift + + debug("{"vars[segk,SEG_ADDR]", "type", "mask", "shift"}" \ + _comma) +} + +# revision offset definition +$1 ~ SROM_OFF_REGEX && in_state(ST_SROM_DEFN) { + vid = g(STATE_IDENT) + + # fetch rev id/key defined by our parent block + rev = g("rev_id") + revk = g("rev_key") + + # parse all offsets + do { + # assign offset id + off = vars[revk,REV_NUM_OFFS] "" + offk = subkey(revk, OFF, off) + vars[revk,REV_NUM_OFFS]++ + + # initialize segment count + vars[offk,DEF_LINE] = NR + vars[offk,OFF_NUM_SEGS] = 0 + + debug("[") + # parse all segments + do { + parse_offset_segment(revk, offk) + _more_seg = ($1 == "|") + if (_more_seg) + shiftf(1, 1) + } while (_more_seg) + debug("],") + _more_vals = ($1 == ",") + if (_more_vals) + shiftf(1, 1) + } while (_more_vals) +} + +# variable definition +(($1 == "private" && $2 ~ TYPES_REGEX) || $1 ~ TYPES_REGEX) && + allow_def(ST_VAR_BLOCK) \ +{ + # check for 'private' flag + if ($1 == "private") { + private = 1 + shiftf(1) + } else { + private = 0 + } + + type = $1 + name = $2 + array = 0 + debug(type " " name " {") + + # Check for and remove any array[] specifier + base_type = type + if (sub(ARRAY_REGEX"$", "", base_type) > 0) + array = 1 + + # verify type + if (!base_type in DTYPE) + error("unknown type '" $1 "'") + + # Add top-level variable entry + if (name in var_names) + error("variable identifier '" name "' previously defined on " \ + "line " vars[name,DEF_LINE]) + + var_names[name] = 0 + vars[name,VAR_NAME] = name + vars[name,DEF_LINE] = NR + vars[name,VAR_TYPE] = type + vars[name,VAR_BASE_TYPE] = base_type + vars[name,NUM_REVS] = 0 + vars[name,VAR_PRIVATE] = private + vars[name,VAR_ARRAY] = array + vars[name,VAR_FMT] = "hex" # default if not specified + + open_block(ST_VAR_BLOCK, name) + + debug("type=" DTYPE[base_type]) + + if (in_nested_state(ST_STRUCT_BLOCK)) { + # Fetch the enclosing struct's name + sid = g(STATE_IDENT, 1) + + # Mark as a struct-based variable + vars[name,VAR_STRUCT] = sid + } +} + +# variable parameters +$1 ~ IDENT_REGEX && $2 ~ IDENT_REGEX && in_state(ST_VAR_BLOCK) { + vid = g(STATE_IDENT) + if ($1 == PROP_T_SFMT) { + if (!$2 in FMT) + error("invalid fmt '" $2 "'") + + vars[vid,VAR_FMT] = $2 + debug($1 "=" FMT[$2]) + } else if ($1 == PROP_T_ALL1 && $2 == "ignore") { + vars[vid,VAR_IGNALL1] = 1 + } else { + error("unknown parameter " $1) + } + next +} + +# Skip comments and blank lines +/^[ \t]*#/ || /^$/ { + next +} + +# Close blocks +/}/ && !in_state(ST_NONE) { + while (!in_state(ST_NONE) && $0 ~ "}") { + close_block(); + debug("}") + } + next +} + +# Report unbalanced '}' +/}/ && in_state(ST_NONE) { + error("extra '}'") +} + +# Invalid variable type +$1 && allow_def(ST_VAR_BLOCK) { + error("unknown type '" $1 "'") +} + +# Generic parse failure +{ + error("unrecognized statement") +} diff --git a/sys/dev/bhnd/tools/nvram_map_gen.sh b/sys/dev/bhnd/tools/nvram_map_gen.sh new file mode 100755 index 0000000..d2b981a --- /dev/null +++ b/sys/dev/bhnd/tools/nvram_map_gen.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Use C locale to ensure AWK string comparisons always produce +# a stable sort order. + +# $FreeBSD$ + +BHND_TOOLDIR="$(dirname $0)/" + +LC_ALL=C; export LC_ALL + +"$BHND_TOOLDIR/nvram_map_gen.awk" $@ diff --git a/sys/dev/bwn/bwn_mac.c b/sys/dev/bwn/bwn_mac.c index d1cfbfd..8b2e962 100644 --- a/sys/dev/bwn/bwn_mac.c +++ b/sys/dev/bwn/bwn_mac.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include "bhnd_nvram_map.h" + static const struct resource_spec bwn_rspec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { -1, -1, 0 } @@ -97,6 +99,14 @@ bwn_attach(device_t dev) r = sc->res[0]; device_printf(dev, "got rid=%d res=%p\n", sc->rspec[0].rid, r); + uint8_t macaddr[6]; + error = bhnd_nvram_getvar(dev, BHND_NVAR_MACADDR, macaddr, + sizeof(macaddr)); + if (error) + return (error); + + device_printf(dev, "got macaddr %6D\n", macaddr, ":"); + return (0); } diff --git a/sys/modules/bhnd/Makefile b/sys/modules/bhnd/Makefile index 862b56d..9ef9d13 100644 --- a/sys/modules/bhnd/Makefile +++ b/sys/modules/bhnd/Makefile @@ -1,10 +1,16 @@ # $FreeBSD$ .PATH: ${.CURDIR}/../../dev/bhnd +.PATH: ${.CURDIR}/../../dev/bhnd/nvram KMOD= bhnd SRCS= bhnd.c bhnd_subr.c \ - bhnd_bus_if.c bhnd_bus_if.h bhnd_nvram_if.h + bhnd_sprom.c nvram_subr.c \ + bhnd_nvram_map.h bhnd_nvram_map_data.h + +SRCS+= bhnd_bus_if.c bhnd_bus_if.h \ + bhnd_chipc_if.c bhnd_chipc_if.h \ + bhnd_nvram_if.c bhnd_nvram_if.h SRCS+= device_if.h bus_if.h @@ -13,7 +19,6 @@ SUBDIR= bcma \ bhndb \ bhndb_pci \ cores \ - nvram \ siba \ siba_bhndb diff --git a/sys/modules/bhnd/bhndb/Makefile b/sys/modules/bhnd/bhndb/Makefile index 46aa6bd..7188009 100644 --- a/sys/modules/bhnd/bhndb/Makefile +++ b/sys/modules/bhnd/bhndb/Makefile @@ -5,8 +5,10 @@ KMOD= bhndb SRCS= bhndb.c bhndb_subr.c bhndb_hwdata.c \ bhndb_bus_if.c bhndb_bus_if.h \ - bhndb_if.c bhndb_if.h \ - bhnd_bus_if.h + bhndb_if.c bhndb_if.h +SRCS+= bhnd_bus_if.h \ + bhnd_chipc_if.h \ + bhnd_nvram_if.h SRCS+= device_if.h bus_if.h pci_if.h diff --git a/sys/modules/bhnd/bhndb_pci/Makefile b/sys/modules/bhnd/bhndb_pci/Makefile index 75621c5..f10845a 100644 --- a/sys/modules/bhnd/bhndb_pci/Makefile +++ b/sys/modules/bhnd/bhndb_pci/Makefile @@ -3,8 +3,10 @@ .PATH: ${.CURDIR}/../../../dev/bhnd/bhndb KMOD= bhndb_pci -SRCS= bhndb_pci.c bhndb_pci_hwdata.c +SRCS= bhndb_pci.c bhndb_pci_hwdata.c \ + bhndb_pci_sprom.c SRCS+= bhnd_bus_if.h bhndb_bus_if.h bhndb_if.h +SRCS+= bhnd_nvram_if.h SRCS+= device_if.h bus_if.h pci_if.h diff --git a/sys/modules/bhnd/cores/bhnd_chipc/Makefile b/sys/modules/bhnd/cores/bhnd_chipc/Makefile index d35409d..bb75aad 100644 --- a/sys/modules/bhnd/cores/bhnd_chipc/Makefile +++ b/sys/modules/bhnd/cores/bhnd_chipc/Makefile @@ -3,8 +3,8 @@ .PATH: ${.CURDIR}/../../../../dev/bhnd/cores/chipc KMOD= bhnd_chipc -SRCS= chipc.c \ - bhnd_chipc_if.c bhnd_chipc_if.h -SRCS+= device_if.h bus_if.h bhnd_bus_if.h +SRCS= chipc.c +SRCS+= device_if.h bus_if.h bhnd_bus_if.h \ + bhnd_chipc_if.h bhnd_nvram_if.h .include diff --git a/sys/modules/bhnd/nvram/Makefile b/sys/modules/bhnd/nvram/Makefile deleted file mode 100644 index 6c6d203..0000000 --- a/sys/modules/bhnd/nvram/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../../dev/bhnd/nvram - -KMOD= bhnd_nvram -SRCS= bhnd_nvram_if.c bhnd_nvram_if.h bhnd_bus_if.h - -SRCS+= device_if.h bus_if.h - -.include diff --git a/sys/modules/bwn_pci/Makefile b/sys/modules/bwn_pci/Makefile index 5e3a9db..355bc2a 100644 --- a/sys/modules/bwn_pci/Makefile +++ b/sys/modules/bwn_pci/Makefile @@ -4,8 +4,8 @@ KMOD= if_bwn_pci SRCS= if_bwn_pci.c bwn_mac.c +SRCS+= bhnd_bus_if.h bhndb_bus_if.h \ + bhndb_if.h bhnd_nvram_map.h SRCS+= device_if.h bus_if.h pci_if.h \ - bhnd_bus_if.h bhndb_bus_if.h \ - bhndb_if.h .include -- cgit v1.1 From b669afdf26f9714fa45044129bf86e3128c8281e Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 9 May 2016 05:59:21 +0000 Subject: [bwn] add opt_bwi.h and BWN_DEBUG. It isn't used yet in the bwn(4) code; that'll come next. --- sys/conf/options | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sys') diff --git a/sys/conf/options b/sys/conf/options index 61bbaa7..5356171 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -853,6 +853,9 @@ AH_AR5416_INTERRUPT_MITIGATION opt_ah.h BWI_DEBUG opt_bwi.h BWI_DEBUG_VERBOSE opt_bwi.h +# options for the Brodacom BCM43xx driver (bwn) +BWI_DEBUG opt_bwn.h + # options for the Marvell 8335 wireless driver MALO_DEBUG opt_malo.h MALO_TXBUF opt_malo.h -- cgit v1.1 From 67d3ece19cf5588e649a2f4e002cc461d1b5a512 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 9 May 2016 06:02:57 +0000 Subject: [bwn] oops. typo. --- sys/conf/options | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/conf/options b/sys/conf/options index 5356171..6dd51d7 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -854,7 +854,7 @@ BWI_DEBUG opt_bwi.h BWI_DEBUG_VERBOSE opt_bwi.h # options for the Brodacom BCM43xx driver (bwn) -BWI_DEBUG opt_bwn.h +BWN_DEBUG opt_bwn.h # options for the Marvell 8335 wireless driver MALO_DEBUG opt_malo.h -- cgit v1.1 From 9a4c3dcddc58da3a57d3b1ffa923bf05abf8efb2 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 9 May 2016 06:05:23 +0000 Subject: [siba] add FEM variables from the r8 SPROM layout. This will eventually be used the bwn(4) N-PHY code that I'm (slowly) writing. Obtained from: Linux b43 --- sys/dev/siba/sibareg.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sys') diff --git a/sys/dev/siba/sibareg.h b/sys/dev/siba/sibareg.h index c2a4fdb..7869850 100644 --- a/sys/dev/siba/sibareg.h +++ b/sys/dev/siba/sibareg.h @@ -414,6 +414,13 @@ #define SIBA_SPROM8_RXPO 0x10ac #define SIBA_SPROM8_RXPO2G 0x00ff #define SIBA_SPROM8_RXPO5G 0xff00 +#define SIBA_SPROM8_FEM2G 0x00AE +#define SIBA_SPROM8_FEM5G 0x00B0 +#define SSB_SROM8_FEM_TSSIPOS 0x0001 +#define SSB_SROM8_FEM_EXTPA_GAIN 0x0006 +#define SSB_SROM8_FEM_PDET_RANGE 0x00F8 +#define SSB_SROM8_FEM_TR_ISO 0x0700 +#define SSB_SROM8_FEM_ANTSWLUT 0xF800 #define SIBA_SPROM8_MAXP_BG 0x10c0 #define SIBA_SPROM8_MAXP_BG_MASK 0x00ff #define SIBA_SPROM8_TSSI_BG 0xff00 -- cgit v1.1 From b816032a05e1faaf4762b2b69357c3ab822794b8 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 9 May 2016 06:30:00 +0000 Subject: [siba] add 2GHz/5GHz FEM parameter fetching and accessor methods. This is used by the bwn(4) PHY-N code that I'm working on. --- sys/dev/siba/siba_core.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/siba/sibavar.h | 35 +++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/siba/siba_core.c b/sys/dev/siba/siba_core.c index 92c54d2..623bfc1 100644 --- a/sys/dev/siba/siba_core.c +++ b/sys/dev/siba/siba_core.c @@ -1689,6 +1689,29 @@ siba_sprom_r8(struct siba_sprom *out, const uint16_t *in) SIBA_SHIFTOUT(again.ghz24.a2, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN2); SIBA_SHIFTOUT(again.ghz24.a3, SIBA_SPROM8_AGAIN23, SIBA_SPROM8_AGAIN3); bcopy(&out->again.ghz24, &out->again.ghz5, sizeof(out->again.ghz5)); + + /* FEM */ + SIBA_SHIFTOUT(fem.ghz2.tssipos, SIBA_SPROM8_FEM2G, + SSB_SROM8_FEM_TSSIPOS); + SIBA_SHIFTOUT(fem.ghz2.extpa_gain, SIBA_SPROM8_FEM2G, + SSB_SROM8_FEM_EXTPA_GAIN); + SIBA_SHIFTOUT(fem.ghz2.pdet_range, SIBA_SPROM8_FEM2G, + SSB_SROM8_FEM_PDET_RANGE); + SIBA_SHIFTOUT(fem.ghz2.tr_iso, SIBA_SPROM8_FEM2G, + SSB_SROM8_FEM_TR_ISO); + SIBA_SHIFTOUT(fem.ghz2.antswlut, SIBA_SPROM8_FEM2G, + SSB_SROM8_FEM_ANTSWLUT); + + SIBA_SHIFTOUT(fem.ghz5.tssipos, SIBA_SPROM8_FEM5G, + SSB_SROM8_FEM_TSSIPOS); + SIBA_SHIFTOUT(fem.ghz5.extpa_gain, SIBA_SPROM8_FEM5G, + SSB_SROM8_FEM_EXTPA_GAIN); + SIBA_SHIFTOUT(fem.ghz5.pdet_range, SIBA_SPROM8_FEM5G, + SSB_SROM8_FEM_PDET_RANGE); + SIBA_SHIFTOUT(fem.ghz5.tr_iso, SIBA_SPROM8_FEM5G, + SSB_SROM8_FEM_TR_ISO); + SIBA_SHIFTOUT(fem.ghz5.antswlut, SIBA_SPROM8_FEM5G, + SSB_SROM8_FEM_ANTSWLUT); } static int8_t @@ -2338,6 +2361,36 @@ siba_read_sprom(device_t dev, device_t child, int which, uintptr_t *result) case SIBA_SPROMVAR_BF2_HI: *result = siba->siba_sprom.bf2_hi; break; + case SIBA_SPROMVAR_FEM_2GHZ_TSSIPOS: + *result = siba->siba_sprom.fem.ghz2.tssipos; + break; + case SIBA_SPROMVAR_FEM_2GHZ_EXTPAGAIN: + *result = siba->siba_sprom.fem.ghz2.extpa_gain; + break; + case SIBA_SPROMVAR_FEM_2GHZ_PDET_RANGE: + *result = siba->siba_sprom.fem.ghz2.pdet_range; + break; + case SIBA_SPROMVAR_FEM_2GHZ_TR_ISO: + *result = siba->siba_sprom.fem.ghz2.tr_iso; + break; + case SIBA_SPROMVAR_FEM_2GHZ_ANTSWLUT: + *result = siba->siba_sprom.fem.ghz2.antswlut; + break; + case SIBA_SPROMVAR_FEM_5GHZ_TSSIPOS: + *result = siba->siba_sprom.fem.ghz5.tssipos; + break; + case SIBA_SPROMVAR_FEM_5GHZ_EXTPAGAIN: + *result = siba->siba_sprom.fem.ghz5.extpa_gain; + break; + case SIBA_SPROMVAR_FEM_5GHZ_PDET_RANGE: + *result = siba->siba_sprom.fem.ghz5.pdet_range; + break; + case SIBA_SPROMVAR_FEM_5GHZ_TR_ISO: + *result = siba->siba_sprom.fem.ghz5.tr_iso; + break; + case SIBA_SPROMVAR_FEM_5GHZ_ANTSWLUT: + *result = siba->siba_sprom.fem.ghz5.antswlut; + break; default: return (ENOENT); } diff --git a/sys/dev/siba/sibavar.h b/sys/dev/siba/sibavar.h index 9b82310..14e0b14 100644 --- a/sys/dev/siba/sibavar.h +++ b/sys/dev/siba/sibavar.h @@ -278,7 +278,17 @@ enum siba_sprom_vars { SIBA_SPROMVAR_BF_LO, SIBA_SPROMVAR_BF_HI, SIBA_SPROMVAR_BF2_LO, - SIBA_SPROMVAR_BF2_HI + SIBA_SPROMVAR_BF2_HI, + SIBA_SPROMVAR_FEM_2GHZ_TSSIPOS, + SIBA_SPROMVAR_FEM_2GHZ_EXTPAGAIN, + SIBA_SPROMVAR_FEM_2GHZ_PDET_RANGE, + SIBA_SPROMVAR_FEM_2GHZ_TR_ISO, + SIBA_SPROMVAR_FEM_2GHZ_ANTSWLUT, + SIBA_SPROMVAR_FEM_5GHZ_TSSIPOS, + SIBA_SPROMVAR_FEM_5GHZ_EXTPAGAIN, + SIBA_SPROMVAR_FEM_5GHZ_PDET_RANGE, + SIBA_SPROMVAR_FEM_5GHZ_TR_ISO, + SIBA_SPROMVAR_FEM_5GHZ_ANTSWLUT, }; int siba_read_sprom(device_t, device_t, int, uintptr_t *); @@ -364,6 +374,18 @@ SIBA_SPROM_ACCESSOR(bf_lo, BF_LO, uint16_t); SIBA_SPROM_ACCESSOR(bf_hi, BF_HI, uint16_t); SIBA_SPROM_ACCESSOR(bf2_lo, BF2_LO, uint16_t); SIBA_SPROM_ACCESSOR(bf2_hi, BF2_HI, uint16_t); +/* 2GHz FEM */ +SIBA_SPROM_ACCESSOR(fem_2ghz_tssipos, FEM_2GHZ_TSSIPOS, uint8_t); +SIBA_SPROM_ACCESSOR(fem_2ghz_extpa_gain, FEM_2GHZ_EXTPAGAIN, uint8_t); +SIBA_SPROM_ACCESSOR(fem_2ghz_pdet_range, FEM_2GHZ_PDET_RANGE, uint8_t); +SIBA_SPROM_ACCESSOR(fem_2ghz_tr_iso, FEM_2GHZ_TR_ISO, uint8_t); +SIBA_SPROM_ACCESSOR(fem_2ghz_antswlut, FEM_2GHZ_ANTSWLUT, uint8_t); +/* 5GHz FEM */ +SIBA_SPROM_ACCESSOR(fem_5ghz_tssipos, FEM_5GHZ_TSSIPOS, uint8_t); +SIBA_SPROM_ACCESSOR(fem_5ghz_extpa_gain, FEM_5GHZ_EXTPAGAIN, uint8_t); +SIBA_SPROM_ACCESSOR(fem_5ghz_pdet_range, FEM_5GHZ_PDET_RANGE, uint8_t); +SIBA_SPROM_ACCESSOR(fem_5ghz_tr_iso, FEM_5GHZ_TR_ISO, uint8_t); +SIBA_SPROM_ACCESSOR(fem_5ghz_antswlut, FEM_5GHZ_ANTSWLUT, uint8_t); #undef SIBA_SPROM_ACCESSOR @@ -434,6 +456,17 @@ struct siba_sprom { int8_t a0, a1, a2, a3; } ghz5; } again; /* antenna gain */ + + struct { + struct { + uint8_t tssipos, extpa_gain, pdet_range, tr_iso; + uint8_t antswlut; + } ghz2; + struct { + uint8_t tssipos, extpa_gain, pdet_range, tr_iso; + uint8_t antswlut; + } ghz5; + } fem; }; #define SIBA_LDO_PAREF 0 -- cgit v1.1 From c62a8ee2d0de9c8b81ce15aca10928ad9780c175 Mon Sep 17 00:00:00 2001 From: dchagin Date: Mon, 9 May 2016 07:38:47 +0000 Subject: Add a forgotten in r283424 .eh_frame section with CFI & FDE records to allow stack unwinding through signal handler. Reported by: Dmitry Sivachenko MFC after: 2 weeks --- sys/amd64/linux/linux_locore.s | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'sys') diff --git a/sys/amd64/linux/linux_locore.s b/sys/amd64/linux/linux_locore.s index 5dcc09a..1bcf05b 100644 --- a/sys/amd64/linux/linux_locore.s +++ b/sys/amd64/linux/linux_locore.s @@ -29,6 +29,7 @@ NON_GPROF_ENTRY(linux_rt_sigcode) movq $LINUX_SYS_linux_rt_sigreturn,%rax /* linux_rt_sigreturn() */ syscall /* enter kernel with args */ hlt +.endrtsigcode: 0: jmp 0b NON_GPROF_ENTRY(__vdso_clock_gettime) @@ -74,3 +75,34 @@ NON_GPROF_ENTRY(__vdso_getcpu) .balign 4 .previous #endif + + .section .eh_frame,"a",@progbits +.LSTARTFRAMEDLSI0: + .long .LENDCIEDLSI0-.LSTARTCIEDLSI0 +.LSTARTCIEDLSI0: + .long 0 /* CIE ID */ + .byte 1 /* Version number */ + .string "zR" /* NULL-terminated + * augmentation string + */ + .uleb128 1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 8 /* Return address register column */ + .uleb128 1 /* Augmentation value length */ + .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */ + .byte 0x0c /* DW_CFA_def_cfa */ + .uleb128 4 + .uleb128 4 + .byte 0x88 /* DW_CFA_offset, column 0x8 */ + .uleb128 1 + .align 4 +.LENDCIEDLSI0: + .long .LENDFDEDLSI0-.LSTARTFDEDLSI0 /* Length FDE */ +.LSTARTFDEDLSI0: + .long .LSTARTFDEDLSI0-.LSTARTFRAMEDLSI0 /* CIE pointer */ + .long .startrtsigcode-. /* PC-relative start address */ + .long .endrtsigcode-.startrtsigcode + .uleb128 0 + .align 4 +.LENDFDEDLSI0: + .previous -- cgit v1.1 From 3bdf68fe5dc3c8bfb40dc399fa681ca207ab11e9 Mon Sep 17 00:00:00 2001 From: arybchik Date: Mon, 9 May 2016 08:28:52 +0000 Subject: sfxge(4): remove unused efx_nic_pcie_extended_sync() Submitted by: Andy Moreton Sponsored by: Solarflare Communications, Inc. MFC after: 1 week --- sys/dev/sfxge/common/efx.h | 4 ---- sys/dev/sfxge/common/efx_nic.c | 16 ---------------- sys/dev/sfxge/common/siena_impl.h | 8 -------- sys/dev/sfxge/common/siena_nic.c | 22 ---------------------- 4 files changed, 50 deletions(-) (limited to 'sys') diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 14374cf..6788913 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -155,10 +155,6 @@ efx_nic_pcie_tune( __in efx_nic_t *enp, unsigned int nlanes); -extern __checkReturn efx_rc_t -efx_nic_pcie_extended_sync( - __in efx_nic_t *enp); - #endif /* EFSYS_OPT_PCIE_TUNE */ extern __checkReturn efx_rc_t diff --git a/sys/dev/sfxge/common/efx_nic.c b/sys/dev/sfxge/common/efx_nic.c index 149cd23..0cefd39 100644 --- a/sys/dev/sfxge/common/efx_nic.c +++ b/sys/dev/sfxge/common/efx_nic.c @@ -485,22 +485,6 @@ efx_nic_pcie_tune( return (ENOTSUP); } - __checkReturn efx_rc_t -efx_nic_pcie_extended_sync( - __in efx_nic_t *enp) -{ - EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); - EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); - EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); - -#if EFSYS_OPT_SIENA - if (enp->en_family == EFX_FAMILY_SIENA) - return (siena_nic_pcie_extended_sync(enp)); -#endif - - return (ENOTSUP); -} - #endif /* EFSYS_OPT_PCIE_TUNE */ __checkReturn efx_rc_t diff --git a/sys/dev/sfxge/common/siena_impl.h b/sys/dev/sfxge/common/siena_impl.h index 4c80cd6..f9efe58 100644 --- a/sys/dev/sfxge/common/siena_impl.h +++ b/sys/dev/sfxge/common/siena_impl.h @@ -59,14 +59,6 @@ extern __checkReturn efx_rc_t siena_nic_probe( __in efx_nic_t *enp); -#if EFSYS_OPT_PCIE_TUNE - -extern __checkReturn efx_rc_t -siena_nic_pcie_extended_sync( - __in efx_nic_t *enp); - -#endif - extern __checkReturn efx_rc_t siena_nic_reset( __in efx_nic_t *enp); diff --git a/sys/dev/sfxge/common/siena_nic.c b/sys/dev/sfxge/common/siena_nic.c index 59e1283..f49914b 100644 --- a/sys/dev/sfxge/common/siena_nic.c +++ b/sys/dev/sfxge/common/siena_nic.c @@ -78,28 +78,6 @@ fail1: return (rc); } -#if EFSYS_OPT_PCIE_TUNE - - __checkReturn efx_rc_t -siena_nic_pcie_extended_sync( - __in efx_nic_t *enp) -{ - efx_rc_t rc; - - if ((rc = efx_mcdi_set_workaround(enp, MC_CMD_WORKAROUND_BUG17230, - B_TRUE, NULL) != 0)) - goto fail1; - - return (0); - -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - -#endif /* EFSYS_OPT_PCIE_TUNE */ - static __checkReturn efx_rc_t siena_board_cfg( __in efx_nic_t *enp) -- cgit v1.1 From 661ea3b03f1efc1b2cd29da58b0e58a425d8c154 Mon Sep 17 00:00:00 2001 From: arybchik Date: Mon, 9 May 2016 08:32:49 +0000 Subject: sfxge(4): Siena no longer supports EFSYS_OPT_PCIE_TUNE Submitted by: Andy Moreton Sponsored by: Solarflare Communications, Inc. MFC after: 1 week --- sys/dev/sfxge/common/efx_check.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/sfxge/common/efx_check.h b/sys/dev/sfxge/common/efx_check.h index d6b7cf4..cd54b72 100644 --- a/sys/dev/sfxge/common/efx_check.h +++ b/sys/dev/sfxge/common/efx_check.h @@ -254,8 +254,8 @@ /* Support PCIe interface tuning */ #if EFSYS_OPT_PCIE_TUNE -# if !(EFSYS_OPT_FALCON || EFSYS_OPT_SIENA) -# error "PCIE_TUNE requires FALCON or SIENA" +# if !EFSYS_OPT_FALCON +# error "PCIE_TUNE requires FALCON" # endif #endif /* EFSYS_OPT_PCIE_TUNE */ -- cgit v1.1 From 305da6d5f2c1a4fd41af2f77dc7d1d0dedb69f9a Mon Sep 17 00:00:00 2001 From: arybchik Date: Mon, 9 May 2016 08:35:08 +0000 Subject: sfxge(4): cleanup: fix obsolete EFSYS_OPT_PHY_BIST option Submitted by: Andy Moreton Sponsored by: Solarflare Communications, Inc. MFC after: 1 week --- sys/dev/sfxge/common/efsys.h | 1 - sys/dev/sfxge/common/efx_check.h | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'sys') diff --git a/sys/dev/sfxge/common/efsys.h b/sys/dev/sfxge/common/efsys.h index b44daca..07d5bbe 100644 --- a/sys/dev/sfxge/common/efsys.h +++ b/sys/dev/sfxge/common/efsys.h @@ -271,7 +271,6 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map, #define EFSYS_OPT_PHY_QT2025C 0 #define EFSYS_OPT_PHY_STATS 1 #define EFSYS_OPT_PHY_PROPS 0 -#define EFSYS_OPT_PHY_BIST 0 #define EFSYS_OPT_BIST 1 #define EFSYS_OPT_PHY_LED_CONTROL 1 #define EFSYS_OPT_PHY_FLAGS 0 diff --git a/sys/dev/sfxge/common/efx_check.h b/sys/dev/sfxge/common/efx_check.h index cd54b72..effe6d7 100644 --- a/sys/dev/sfxge/common/efx_check.h +++ b/sys/dev/sfxge/common/efx_check.h @@ -260,9 +260,9 @@ #endif /* EFSYS_OPT_PCIE_TUNE */ /* Obsolete option */ -#if EFSYS_OPT_PHY_BIST -# error "PHY_BIST is obsolete (replaced by BIST)." -#endif /* EFSYS_OPT_PHY_BIST */ +#ifdef EFSYS_OPT_PHY_BIST +# error "PHY_BIST is obsolete (replaced by BIST)." +#endif /* Support PHY flags */ #if EFSYS_OPT_PHY_FLAGS -- cgit v1.1 From a2834821fe76818b62c16dca63cedf08fe2c520f Mon Sep 17 00:00:00 2001 From: arybchik Date: Mon, 9 May 2016 08:37:42 +0000 Subject: sfxge(4): disable common code support for Falcon This patch ensures that client code will fail to build with Falcon support. Following patches remove Falcon support code entirely. sfxge(4) has never supported Falcon. Submitted by: Andy Moreton Sponsored by: Solarflare Communications, Inc. MFC after: 1 week --- sys/dev/sfxge/common/efsys.h | 17 ----------------- sys/dev/sfxge/common/efx.h | 1 + sys/dev/sfxge/common/efx_check.h | 28 ++++++++++++++++++++++++++++ sys/dev/sfxge/common/efx_impl.h | 3 +-- 4 files changed, 30 insertions(+), 19 deletions(-) (limited to 'sys') diff --git a/sys/dev/sfxge/common/efsys.h b/sys/dev/sfxge/common/efsys.h index 07d5bbe..f019139 100644 --- a/sys/dev/sfxge/common/efsys.h +++ b/sys/dev/sfxge/common/efsys.h @@ -236,8 +236,6 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map, #define EFSYS_OPT_NAMES 1 -#define EFSYS_OPT_FALCON 0 -#define EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE 0 #define EFSYS_OPT_SIENA 1 #define EFSYS_OPT_HUNTINGTON 1 #define EFSYS_OPT_MEDFORD 0 @@ -251,24 +249,13 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map, #define EFSYS_OPT_MCDI_LOGGING 0 #define EFSYS_OPT_MCDI_PROXY_AUTH 0 -#define EFSYS_OPT_MAC_FALCON_GMAC 0 -#define EFSYS_OPT_MAC_FALCON_XMAC 0 #define EFSYS_OPT_MAC_STATS 1 #define EFSYS_OPT_LOOPBACK 0 -#define EFSYS_OPT_MON_NULL 0 -#define EFSYS_OPT_MON_LM87 0 -#define EFSYS_OPT_MON_MAX6647 0 #define EFSYS_OPT_MON_MCDI 0 #define EFSYS_OPT_MON_STATS 0 -#define EFSYS_OPT_PHY_NULL 0 -#define EFSYS_OPT_PHY_QT2022C2 0 -#define EFSYS_OPT_PHY_SFX7101 0 -#define EFSYS_OPT_PHY_TXC43128 0 -#define EFSYS_OPT_PHY_SFT9001 0 -#define EFSYS_OPT_PHY_QT2025C 0 #define EFSYS_OPT_PHY_STATS 1 #define EFSYS_OPT_PHY_PROPS 0 #define EFSYS_OPT_BIST 1 @@ -277,12 +264,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map, #define EFSYS_OPT_VPD 1 #define EFSYS_OPT_NVRAM 1 -#define EFSYS_OPT_NVRAM_FALCON_BOOTROM 0 -#define EFSYS_OPT_NVRAM_SFT9001 0 -#define EFSYS_OPT_NVRAM_SFX7101 0 #define EFSYS_OPT_BOOTCFG 0 -#define EFSYS_OPT_PCIE_TUNE 0 #define EFSYS_OPT_DIAG 0 #define EFSYS_OPT_WOL 1 #define EFSYS_OPT_RX_SCALE 1 diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 6788913..70be977 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -34,6 +34,7 @@ #define _SYS_EFX_H #include "efsys.h" +#include "efx_check.h" #include "efx_phy_ids.h" #ifdef __cplusplus diff --git a/sys/dev/sfxge/common/efx_check.h b/sys/dev/sfxge/common/efx_check.h index effe6d7..e5c7c2e 100644 --- a/sys/dev/sfxge/common/efx_check.h +++ b/sys/dev/sfxge/common/efx_check.h @@ -43,6 +43,34 @@ * from client code (and do not reappear in merges from other branches). */ +#ifdef EFSYS_OPT_FALCON +# error "FALCON is obsolete and is not supported." +#else +/* FIXME: remove this after Falcon support has been removed */ +#define EFSYS_OPT_FALCON (0) +#define EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE (0) + +#define EFSYS_OPT_MAC_FALCON_GMAC (0) +#define EFSYS_OPT_MAC_FALCON_XMAC (0) + +#define EFSYS_OPT_MON_LM87 (0) +#define EFSYS_OPT_MON_MAX6647 (0) +#define EFSYS_OPT_MON_NULL (0) + +#define EFSYS_OPT_NVRAM_FALCON_BOOTROM (0) +#define EFSYS_OPT_NVRAM_SFT9001 (0) +#define EFSYS_OPT_NVRAM_SFX7101 (0) + +#define EFSYS_OPT_PCIE_TUNE (0) + +#define EFSYS_OPT_PHY_NULL (0) +#define EFSYS_OPT_PHY_QT2022C2 (0) +#define EFSYS_OPT_PHY_QT2025C (0) +#define EFSYS_OPT_PHY_SFT9001 (0) +#define EFSYS_OPT_PHY_SFX7101 (0) +#define EFSYS_OPT_PHY_TXC43128 (0) +#endif + /* Support NVRAM based boot config */ #if EFSYS_OPT_BOOTCFG # if !EFSYS_OPT_NVRAM diff --git a/sys/dev/sfxge/common/efx_impl.h b/sys/dev/sfxge/common/efx_impl.h index 5495b15..9e831c7 100644 --- a/sys/dev/sfxge/common/efx_impl.h +++ b/sys/dev/sfxge/common/efx_impl.h @@ -34,6 +34,7 @@ #define _SYS_EFX_IMPL_H #include "efsys.h" +#include "efx_check.h" #include "efx.h" #include "efx_regs.h" #include "efx_regs_ef10.h" @@ -43,8 +44,6 @@ #define ESE_DZ_EV_CODE_DRV_GEN_EV FSE_AZ_EV_CODE_DRV_GEN_EV #endif -#include "efx_check.h" - #if EFSYS_OPT_FALCON #include "falcon_impl.h" -- cgit v1.1 From 8ae63dd8bfb1cd7ce62c9fc3b04535766204e694 Mon Sep 17 00:00:00 2001 From: arybchik Date: Mon, 9 May 2016 08:38:56 +0000 Subject: sfxge(4): remove EFSYS_OPT_PCIE_TUNE With the removal of Falcon support, this is now dead code. Submitted by: Andy Moreton Sponsored by: Solarflare Communications, Inc. MFC after: 1 week --- sys/dev/sfxge/common/efx.h | 9 --------- sys/dev/sfxge/common/efx_check.h | 11 +++-------- sys/dev/sfxge/common/efx_impl.h | 3 --- sys/dev/sfxge/common/efx_nic.c | 20 -------------------- 4 files changed, 3 insertions(+), 40 deletions(-) (limited to 'sys') diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h index 70be977..3b67471 100644 --- a/sys/dev/sfxge/common/efx.h +++ b/sys/dev/sfxge/common/efx.h @@ -149,15 +149,6 @@ extern __checkReturn efx_rc_t efx_nic_probe( __in efx_nic_t *enp); -#if EFSYS_OPT_PCIE_TUNE - -extern __checkReturn efx_rc_t -efx_nic_pcie_tune( - __in efx_nic_t *enp, - unsigned int nlanes); - -#endif /* EFSYS_OPT_PCIE_TUNE */ - extern __checkReturn efx_rc_t efx_nic_init( __in efx_nic_t *enp); diff --git a/sys/dev/sfxge/common/efx_check.h b/sys/dev/sfxge/common/efx_check.h index e5c7c2e..1abed3e 100644 --- a/sys/dev/sfxge/common/efx_check.h +++ b/sys/dev/sfxge/common/efx_check.h @@ -61,8 +61,6 @@ #define EFSYS_OPT_NVRAM_SFT9001 (0) #define EFSYS_OPT_NVRAM_SFX7101 (0) -#define EFSYS_OPT_PCIE_TUNE (0) - #define EFSYS_OPT_PHY_NULL (0) #define EFSYS_OPT_PHY_QT2022C2 (0) #define EFSYS_OPT_PHY_QT2025C (0) @@ -280,12 +278,9 @@ # endif #endif /* EFSYS_OPT_NVRAM_SFX7101 */ -/* Support PCIe interface tuning */ -#if EFSYS_OPT_PCIE_TUNE -# if !EFSYS_OPT_FALCON -# error "PCIE_TUNE requires FALCON" -# endif -#endif /* EFSYS_OPT_PCIE_TUNE */ +#ifdef EFSYS_OPT_PCIE_TUNE +# error "PCIE_TUNE is obsolete and is not supported." +#endif /* Obsolete option */ #ifdef EFSYS_OPT_PHY_BIST diff --git a/sys/dev/sfxge/common/efx_impl.h b/sys/dev/sfxge/common/efx_impl.h index 9e831c7..f917ba1 100644 --- a/sys/dev/sfxge/common/efx_impl.h +++ b/sys/dev/sfxge/common/efx_impl.h @@ -667,9 +667,6 @@ struct efx_nic_s { const uint8_t *enu_forced_cfg; #endif /* EFSYS_OPT_FALCON_NIC_CFG_OVERRIDE */ uint8_t enu_mon_devid; -#if EFSYS_OPT_PCIE_TUNE - unsigned int enu_nlanes; -#endif /* EFSYS_OPT_PCIE_TUNE */ uint16_t enu_board_rev; boolean_t enu_internal_sram; uint8_t enu_sram_num_bank; diff --git a/sys/dev/sfxge/common/efx_nic.c b/sys/dev/sfxge/common/efx_nic.c index 0cefd39..35cd8eb 100644 --- a/sys/dev/sfxge/common/efx_nic.c +++ b/sys/dev/sfxge/common/efx_nic.c @@ -467,26 +467,6 @@ fail1: return (rc); } -#if EFSYS_OPT_PCIE_TUNE - - __checkReturn efx_rc_t -efx_nic_pcie_tune( - __in efx_nic_t *enp, - unsigned int nlanes) -{ - EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); - EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); - EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC)); - -#if EFSYS_OPT_FALCON - if (enp->en_family == EFX_FAMILY_FALCON) - return (falcon_nic_pcie_tune(enp, nlanes)); -#endif - return (ENOTSUP); -} - -#endif /* EFSYS_OPT_PCIE_TUNE */ - __checkReturn efx_rc_t efx_nic_set_drv_limits( __inout efx_nic_t *enp, -- cgit v1.1 From 2b976847f9d887e4b61c6bda5cfb9182ada6cdb4 Mon Sep 17 00:00:00 2001 From: hselasky Date: Mon, 9 May 2016 11:52:57 +0000 Subject: Fix file polling bug. Ensure the actual poll result is returned by the "linux_file_poll()" function instead of zero which means no data is available. MFC after: 3 days Sponsored by: Mellanox Technologies --- sys/compat/linuxkpi/common/src/linux_compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index d85d4ad..9273a24 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -671,7 +671,7 @@ linux_file_poll(struct file *file, int events, struct ucred *active_cred, else revents = 0; - return (0); + return (revents); } static int -- cgit v1.1 From ce5d941306ff7153dd0ef63bf4970f522db7b305 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 9 May 2016 12:24:39 +0000 Subject: Check malloc succeeded in pic_create, with M_NOWAIT it may return NULL. Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation --- sys/kern/subr_intr.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sys') diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 98e8e38..9b92e73 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -871,6 +871,10 @@ pic_create(device_t dev, intptr_t xref) return (pic); } pic = malloc(sizeof(*pic), M_INTRNG, M_NOWAIT | M_ZERO); + if (pic == NULL) { + mtx_unlock(&pic_list_lock); + return (NULL); + } pic->pic_xref = xref; pic->pic_dev = dev; SLIST_INSERT_HEAD(&pic_list, pic, pic_next); -- cgit v1.1 From b6372f21593ce505e7c59568e2f3440f50d91a27 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:12:32 +0000 Subject: Update MPI headers to version 42. Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6096 --- sys/dev/mpr/mpi/mpi2.h | 79 ++++++++++++++--- sys/dev/mpr/mpi/mpi2_cnfg.h | 181 +++++++++++++++++++++++++++++++++------ sys/dev/mpr/mpi/mpi2_hbd.h | 8 +- sys/dev/mpr/mpi/mpi2_history.txt | 153 ++++++++++++++++++++++++++------- sys/dev/mpr/mpi/mpi2_init.h | 44 +++++++--- sys/dev/mpr/mpi/mpi2_ioc.h | 158 +++++++++++++++++++++++++++++++--- sys/dev/mpr/mpi/mpi2_ra.h | 8 +- sys/dev/mpr/mpi/mpi2_raid.h | 8 +- sys/dev/mpr/mpi/mpi2_sas.h | 13 ++- sys/dev/mpr/mpi/mpi2_targ.h | 21 +++-- sys/dev/mpr/mpi/mpi2_tool.h | 10 ++- sys/dev/mpr/mpi/mpi2_type.h | 8 +- 12 files changed, 578 insertions(+), 113 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpi/mpi2.h b/sys/dev/mpr/mpi/mpi2.h index 42fdec2..7084a85 100644 --- a/sys/dev/mpr/mpi/mpi2.h +++ b/sys/dev/mpr/mpi/mpi2.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,7 +34,8 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2.h @@ -43,7 +44,7 @@ * scatter/gather formats. * Creation Date: June 21, 2006 * - * mpi2.h Version: 02.00.33 + * mpi2.h Version: 02.00.42 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -125,6 +126,22 @@ * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT. * 08-19-13 02.00.32 Bumped MPI2_HEADER_VERSION_UNIT. * 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT. + * 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT. + * 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT. + * 11-18-14 02.00.36 Updated copyright information. + * Bumped MPI2_HEADER_VERSION_UNIT. + * 03-16-15 02.00.37 Updated for MPI v2.6. + * Bumped MPI2_HEADER_VERSION_UNIT. + * Added Scratchpad registers to + * MPI2_SYSTEM_INTERFACE_REGS. + * Added MPI2_DIAG_SBR_RELOAD. + * Added MPI2_IOCSTATUS_INSUFFICIENT_POWER. + * 03-19-15 02.00.38 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-25-15 02.00.39 Bumped MPI2_HEADER_VERSION_UNIT + * 08-25-15 02.00.40 Bumped MPI2_HEADER_VERSION_UNIT. + * Added V7 HostDiagnostic register defines + * 12-15-15 02.00.41 Bumped MPI_HEADER_VERSION_UNIT + * 01-01-16 02.00.42 Bumped MPI_HEADER_VERSION_UNIT * -------------------------------------------------------------------------- */ @@ -160,8 +177,15 @@ #define MPI2_VERSION_02_05 (0x0205) +/* minor version for MPI v2.6 compatible products */ +#define MPI26_VERSION_MINOR (0x06) +#define MPI26_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ + MPI26_VERSION_MINOR) +#define MPI2_VERSION_02_06 (0x0206) + + /* Unit and Dev versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x21) +#define MPI2_HEADER_VERSION_UNIT (0x2A) #define MPI2_HEADER_VERSION_DEV (0x00) #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) @@ -217,7 +241,8 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS U32 HCBSize; /* 0x74 */ U32 HCBAddressLow; /* 0x78 */ U32 HCBAddressHigh; /* 0x7C */ - U32 Reserved6[16]; /* 0x80 */ + U32 Reserved6[12]; /* 0x80 */ + U32 Scratchpad[4]; /* 0xB0 */ U32 RequestDescriptorPostLow; /* 0xC0 */ U32 RequestDescriptorPostHigh; /* 0xC4 */ U32 Reserved7[14]; /* 0xC8 */ @@ -261,10 +286,17 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS */ #define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008) +#define MPI2_DIAG_SBR_RELOAD (0x00002000) + #define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800) #define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000) #define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800) +/* Defines for V7A/V7R HostDiagnostic Register */ +#define MPI26_DIAG_BOOT_DEVICE_SELECT_FLASH64 (0x00000000) +#define MPI26_DIAG_BOOT_DEVICE_SELECT_HCDW64 (0x00000800) +#define MPI26_DIAG_BOOT_DEVICE_SELECT_FLASH32 (0x00001000) +#define MPI26_DIAG_BOOT_DEVICE_SELECT_HCDW32 (0x00001800) #define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) #define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200) #define MPI2_DIAG_HCB_MODE (0x00000100) @@ -335,7 +367,15 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS #define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C) /* - * Offsets for the Request Queue + * Offsets for the Scratchpad registers + */ +#define MPI26_SCRATCHPAD0_OFFSET (0x000000B0) +#define MPI26_SCRATCHPAD1_OFFSET (0x000000B4) +#define MPI26_SCRATCHPAD2_OFFSET (0x000000B8) +#define MPI26_SCRATCHPAD3_OFFSET (0x000000BC) + +/* + * Offsets for the Request Descriptor Post Queue */ #define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0) #define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4) @@ -367,7 +407,8 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t; /* defines for the RequestFlags field */ -#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) +#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x1E) +#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_RSHIFT (1) /* use carefully; values below are pre-shifted left */ #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) @@ -455,6 +496,10 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t; + +/* for the RequestFlags field, use the same defines as MPI2_DEFAULT_REQUEST_DESCRIPTOR */ + + /* Reply Descriptors */ /* Default Reply Descriptor */ @@ -603,7 +648,8 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION #define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */ #define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */ #define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */ -#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */ +#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */ /* for MPI v2.5 and earlier */ +#define MPI2_FUNCTION_IO_UNIT_CONTROL (0x1B) /* IO Unit Control */ /* for MPI v2.6 and later */ #define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */ #define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */ #define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */ @@ -646,6 +692,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION #define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) #define MPI2_IOCSTATUS_INVALID_STATE (0x0008) #define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) +#define MPI2_IOCSTATUS_INSUFFICIENT_POWER (0x000A) /* MPI v2.6 and later */ /**************************************************************************** * Config IOCStatus values @@ -1123,7 +1170,7 @@ typedef union _MPI2_IEEE_SGE_CHAIN_UNION } MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION, Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t; -/* MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */ +/* MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 and later */ typedef struct _MPI25_IEEE_SGE_CHAIN64 { U64 Address; @@ -1181,16 +1228,23 @@ typedef union _MPI25_SGE_IO_UNION #define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00) #define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) +/* Next Segment Format */ + +#define MPI26_IEEE_SGE_FLAGS_NSF_MASK (0x1C) +#define MPI26_IEEE_SGE_FLAGS_NSF_MPI_IEEE (0x00) + /* Data Location Address Space */ #define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) /* for MPI v2.0, use in IEEE Simple Element only; for MPI v2.5, use in IEEE Simple or Chain element */ +#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) /* for MPI v2.0, use in IEEE Simple Element only; for MPI v2.5 and later, use in IEEE Simple or Chain element */ #define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) /* use in IEEE Simple Element only */ #define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) #define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) /* for MPI v2.0, use in IEEE Simple Element only; for MPI v2.5, use in IEEE Simple or Chain element */ #define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03) /* use in MPI v2.0 IEEE Chain Element only */ #define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) /* typo in name */ +#define MPI26_IEEE_SGE_FLAGS_IOCCTL_ADDR (0x02) /* for MPI v2.6 only */ + /**************************************************************************** * IEEE SGE operation Macros ****************************************************************************/ @@ -1246,8 +1300,9 @@ typedef union _MPI2_SGE_IO_UNION #define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C) #define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00) #define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04) -#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) -#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) +#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) /* only for MPI v2.5 and earlier */ +#define MPI26_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) /* only for MPI v2.6 */ +#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) /* only for MPI v2.5 and earlier */ /* values for SGL Type subfield */ #define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03) #define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00) diff --git a/sys/dev/mpr/mpi/mpi2_cnfg.h b/sys/dev/mpr/mpi/mpi2_cnfg.h index 3b0eb63..fb968b6 100644 --- a/sys/dev/mpr/mpi/mpi2_cnfg.h +++ b/sys/dev/mpr/mpi/mpi2_cnfg.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_cnfg.h * Title: MPI Configuration messages and pages * Creation Date: November 10, 2006 * - * mpi2_cnfg.h Version: 02.00.27 + * mpi2_cnfg.h Version: 02.00.35 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -210,6 +211,21 @@ * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. * Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. + * 01-08-14 02.00.28 Added more defines for the BiosOptions field of + * MPI2_CONFIG_PAGE_BIOS_1. + * 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and + * more defines for the BiosOptions field. + * 11-18-14 02.00.30 Updated copyright information. + * Added MPI2_BIOSPAGE1_OPTIONS_ADVANCED_CONFIG. + * Added AdapterOrderAux fields to BIOS Page 3. + * 03-16-15 02.00.31 Updated for MPI v2.6. + * Added BoardPowerRequirement, PCISlotPowerAllocation, and + * Flags field to IO Unit Page 7. + * Added IO Unit Page 11. + * Added new SAS Phy Event codes + * 05-25-15 02.00.33 Added more defines for the BiosOptions field of + * MPI2_CONFIG_PAGE_BIOS_1. + * 12-18-15 02.00.35 Added SATADeviceWaitTime to SAS IO Unit Page 4. * -------------------------------------------------------------------------- */ @@ -387,7 +403,6 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION #define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF) - /**************************************************************************** * Configuration messages ****************************************************************************/ @@ -491,8 +506,17 @@ typedef struct _MPI2_CONFIG_REPLY #define MPI25_MFGPAGE_DEVID_SAS3108_5 (0x0094) #define MPI25_MFGPAGE_DEVID_SAS3108_6 (0x0095) - - +/* MPI v2.6 SAS Products */ +#define MPI26_MFGPAGE_DEVID_SAS3216 (0x00C9) +#define MPI26_MFGPAGE_DEVID_SAS3224 (0x00C4) +#define MPI26_MFGPAGE_DEVID_SAS3316_1 (0x00C5) +#define MPI26_MFGPAGE_DEVID_SAS3316_2 (0x00C6) +#define MPI26_MFGPAGE_DEVID_SAS3316_3 (0x00C7) +#define MPI26_MFGPAGE_DEVID_SAS3316_4 (0x00C8) +#define MPI26_MFGPAGE_DEVID_SAS3324_1 (0x00C0) +#define MPI26_MFGPAGE_DEVID_SAS3324_2 (0x00C1) +#define MPI26_MFGPAGE_DEVID_SAS3324_3 (0x00C2) +#define MPI26_MFGPAGE_DEVID_SAS3324_4 (0x00C3) /* Manufacturing Page 0 */ @@ -962,14 +986,16 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 U16 BoardTemperature; /* 0x14 */ U8 BoardTemperatureUnits; /* 0x16 */ U8 Reserved3; /* 0x17 */ - U32 Reserved4; /* 0x18 */ - U32 Reserved5; /* 0x1C */ - U32 Reserved6; /* 0x20 */ - U32 Reserved7; /* 0x24 */ + U32 BoardPowerRequirement; /* 0x18 */ /* reserved prior to MPI v2.6 */ + U32 PCISlotPowerAllocation; /* 0x1C */ /* reserved prior to MPI v2.6 */ + U8 Flags; /* 0x20 */ /* reserved prior to MPI v2.6 */ + U8 Reserved6; /* 0x21 */ + U16 Reserved7; /* 0x22 */ + U32 Reserved8; /* 0x24 */ } MPI2_CONFIG_PAGE_IO_UNIT_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, Mpi2IOUnitPage7_t, MPI2_POINTER pMpi2IOUnitPage7_t; -#define MPI2_IOUNITPAGE7_PAGEVERSION (0x04) +#define MPI2_IOUNITPAGE7_PAGEVERSION (0x05) /* defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */ #define MPI25_IOUNITPAGE7_PM_INIT_MASK (0xC0) @@ -1050,6 +1076,8 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 #define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01) #define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02) +/* defines for IO Unit Page 7 Flags field */ +#define MPI2_IOUNITPAGE7_FLAG_CABLE_POWER_EXC (0x01) /* IO Unit Page 8 */ @@ -1168,6 +1196,61 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 #define MPI2_IOUNITPAGE10_PAGEVERSION (0x01) +/* IO Unit Page 11 (for MPI v2.6 and later) */ + +typedef struct _MPI26_IOUNIT11_SPINUP_GROUP +{ + U8 MaxTargetSpinup; /* 0x00 */ + U8 SpinupDelay; /* 0x01 */ + U8 SpinupFlags; /* 0x02 */ + U8 Reserved1; /* 0x03 */ +} MPI26_IOUNIT11_SPINUP_GROUP, MPI2_POINTER PTR_MPI26_IOUNIT11_SPINUP_GROUP, + Mpi26IOUnit11SpinupGroup_t, MPI2_POINTER pMpi26IOUnit11SpinupGroup_t; + +/* defines for IO Unit Page 11 SpinupFlags */ +#define MPI26_IOUNITPAGE11_SPINUP_DISABLE_FLAG (0x01) + + +/* + * Host code (drivers, BIOS, utilities, etc.) should leave this define set to + * four and check the value returned for NumPhys at runtime. + */ +#ifndef MPI26_IOUNITPAGE11_PHY_MAX +#define MPI26_IOUNITPAGE11_PHY_MAX (4) +#endif + +typedef struct _MPI26_CONFIG_PAGE_IO_UNIT_11 +{ + MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved1; /* 0x04 */ + MPI26_IOUNIT11_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */ + U32 Reserved2; /* 0x18 */ + U32 Reserved3; /* 0x1C */ + U32 Reserved4; /* 0x20 */ + U8 BootDeviceWaitTime; /* 0x24 */ + U8 Reserved5; /* 0x25 */ + U16 Reserved6; /* 0x26 */ + U8 NumPhys; /* 0x28 */ + U8 PEInitialSpinupDelay; /* 0x29 */ + U8 PEReplyDelay; /* 0x2A */ + U8 Flags; /* 0x2B */ + U8 PHY[MPI26_IOUNITPAGE11_PHY_MAX];/* 0x2C */ +} MPI26_CONFIG_PAGE_IO_UNIT_11, + MPI2_POINTER PTR_MPI26_CONFIG_PAGE_IO_UNIT_11, + Mpi26IOUnitPage11_t, MPI2_POINTER pMpi26IOUnitPage11_t; + +#define MPI26_IOUNITPAGE11_PAGEVERSION (0x00) + +/* defines for Flags field */ +#define MPI26_IOUNITPAGE11_FLAGS_AUTO_PORTENABLE (0x01) + +/* defines for PHY field */ +#define MPI26_IOUNITPAGE11_PHY_SPINUP_GROUP_MASK (0x03) + + + + + /**************************************************************************** * IOC Config Pages @@ -1331,7 +1414,9 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 BiosOptions; /* 0x04 */ U32 IOCSettings; /* 0x08 */ - U32 Reserved1; /* 0x0C */ + U8 SSUTimeout; /* 0x0C */ + U8 Reserved1; /* 0x0D */ + U16 Reserved2; /* 0x0E */ U32 DeviceSettings; /* 0x10 */ U16 NumberOfDevices; /* 0x14 */ U16 UEFIVersion; /* 0x16 */ @@ -1342,18 +1427,36 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 } MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1, Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t; -#define MPI2_BIOSPAGE1_PAGEVERSION (0x05) +#define MPI2_BIOSPAGE1_PAGEVERSION (0x07) /* values for BIOS Page 1 BiosOptions field */ -#define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) -#define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) +#define MPI2_BIOSPAGE1_OPTIONS_BOOT_LIST_ADD_ALT_BOOT_DEVICE (0x00008000) +#define MPI2_BIOSPAGE1_OPTIONS_ADVANCED_CONFIG (0x00004000) + +#define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800) +#define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL (0x00000000) +#define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE (0x00000800) +#define MPI2_BIOSPAGE1_OPTIONS_PNS_LWWID (0x00001000) +#define MPI2_BIOSPAGE1_OPTIONS_PNS_PSENS (0x00001800) +#define MPI2_BIOSPAGE1_OPTIONS_PNS_ESPHY (0x00002000) -#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006) -#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000) -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002) -#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004) +#define MPI2_BIOSPAGE1_OPTIONS_X86_DISABLE_BIOS (0x00000400) -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) +#define MPI2_BIOSPAGE1_OPTIONS_MASK_REGISTRATION_UEFI_BSD (0x00000300) +#define MPI2_BIOSPAGE1_OPTIONS_USE_BIT0_REGISTRATION_UEFI_BSD (0x00000000) +#define MPI2_BIOSPAGE1_OPTIONS_FULL_REGISTRATION_UEFI_BSD (0x00000100) +#define MPI2_BIOSPAGE1_OPTIONS_ADAPTER_REGISTRATION_UEFI_BSD (0x00000200) +#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_REGISTRATION_UEFI_BSD (0x00000300) + +#define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) +#define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) + +#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006) +#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000) +#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002) +#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004) + +#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) /* values for BIOS Page 1 IOCSettings field */ #define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) @@ -1477,6 +1580,8 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_2 /* BIOS Page 3 */ +#define MPI2_BIOSPAGE3_NUM_ADAPTER (4) + typedef struct _MPI2_ADAPTER_INFO { U8 PciBusNumber; /* 0x00 */ @@ -1488,17 +1593,26 @@ typedef struct _MPI2_ADAPTER_INFO #define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) #define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) +typedef struct _MPI2_ADAPTER_ORDER_AUX +{ + U64 WWID; /* 0x00 */ + U32 Reserved1; /* 0x08 */ + U32 Reserved2; /* 0x0C */ +} MPI2_ADAPTER_ORDER_AUX, MPI2_POINTER PTR_MPI2_ADAPTER_ORDER_AUX, + Mpi2AdapterOrderAux_t, MPI2_POINTER pMpi2AdapterOrderAux_t; + typedef struct _MPI2_CONFIG_PAGE_BIOS_3 { MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 GlobalFlags; /* 0x04 */ U32 BiosVersion; /* 0x08 */ - MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */ + MPI2_ADAPTER_INFO AdapterOrder[MPI2_BIOSPAGE3_NUM_ADAPTER]; /* 0x0C */ U32 Reserved1; /* 0x1C */ + MPI2_ADAPTER_ORDER_AUX AdapterOrderAux[MPI2_BIOSPAGE3_NUM_ADAPTER]; /* 0x20 */ /* MPI v2.5 and newer */ } MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3, Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t; -#define MPI2_BIOSPAGE3_PAGEVERSION (0x00) +#define MPI2_BIOSPAGE3_PAGEVERSION (0x01) /* values for BIOS Page 3 GlobalFlags */ #define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002) @@ -1990,6 +2104,8 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 #define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) /* values for SAS IO Unit Page 0 PhyFlags */ +#define MPI2_SASIOUNIT0_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) +#define MPI2_SASIOUNIT0_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) #define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10) #define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) @@ -2082,6 +2198,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 #define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) /* MPI v2.0 only. Obsolete in MPI v2.5 and later. */ /* values for SAS IO Unit Page 1 AdditionalControlFlags */ +#define MPI2_SASIOUNIT1_ACONTROL_DA_PERSIST_CONNECT (0x0100) #define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) #define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) #define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) @@ -2099,6 +2216,8 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 #define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) /* values for SAS IO Unit Page 1 PhyFlags */ +#define MPI2_SASIOUNIT1_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) +#define MPI2_SASIOUNIT1_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) #define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10) #define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) @@ -2117,7 +2236,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 /* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ -/* SAS IO Unit Page 4 */ +/* SAS IO Unit Page 4 (for MPI v2.5 and earlier) */ typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP { @@ -2148,7 +2267,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 U32 Reserved2; /* 0x1C */ U32 Reserved3; /* 0x20 */ U8 BootDeviceWaitTime; /* 0x24 */ - U8 Reserved4; /* 0x25 */ + U8 SATADeviceWaitTime; /* 0x25 */ U16 Reserved5; /* 0x26 */ U8 NumPhys; /* 0x28 */ U8 PEInitialSpinupDelay; /* 0x29 */ @@ -2595,6 +2714,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 #define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) #define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) #define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) +#define MPI2_SAS_DEVICE0_FLAGS_PERSIST_CAPABLE (0x0004) #define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002) #define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) @@ -2766,6 +2886,19 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG #define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) #define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2) +/* Following codes are product specific and in MPI v2.6 and later */ +#define MPI2_SASPHY3_EVENT_CODE_LCARB_WAIT_TIME (0xD3) +#define MPI2_SASPHY3_EVENT_CODE_RCVD_CONN_RESP_WAIT_TIME (0xD4) +#define MPI2_SASPHY3_EVENT_CODE_LCCONN_TIME (0xD5) +#define MPI2_SASPHY3_EVENT_CODE_SSP_TX_START_TRANSMIT (0xD6) +#define MPI2_SASPHY3_EVENT_CODE_SATA_TX_START (0xD7) +#define MPI2_SASPHY3_EVENT_CODE_SMP_TX_START_TRANSMT (0xD8) +#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_BREAK_CONN (0xD9) +#define MPI2_SASPHY3_EVENT_CODE_SSP_RX_START_RECEIVE (0xDA) +#define MPI2_SASPHY3_EVENT_CODE_SATA_RX_START_RECEIVE (0xDB) +#define MPI2_SASPHY3_EVENT_CODE_SMP_RX_START_RECEIVE (0xDC) + + /* values for the CounterType field */ #define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) #define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01) diff --git a/sys/dev/mpr/mpi/mpi2_hbd.h b/sys/dev/mpr/mpi/mpi2_hbd.h index 520407b..4870071 100644 --- a/sys/dev/mpr/mpi/mpi2_hbd.h +++ b/sys/dev/mpr/mpi/mpi2_hbd.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2009-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_hbd.h * Title: MPI Host Based Discovery messages and structures * Creation Date: October 21, 2009 * - * mpi2_hbd.h Version: 02.00.02 + * mpi2_hbd.h Version: 02.00.03 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -57,6 +58,7 @@ * 08-11-10 02.00.01 Removed PortGroups, DmaGroup, and ControlGroup from * HBD Action request, replaced by AdditionalInfo field. * 11-18-11 02.00.02 Incorporating additions for MPI v2.5. + * 11-18-14 02.00.03 Updated copyright information. * -------------------------------------------------------------------------- */ diff --git a/sys/dev/mpr/mpi/mpi2_history.txt b/sys/dev/mpr/mpi/mpi2_history.txt index e843237..64498a2 100644 --- a/sys/dev/mpr/mpi/mpi2_history.txt +++ b/sys/dev/mpr/mpi/mpi2_history.txt @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,27 +37,28 @@ ============================== Copyright (c) 2000-2015 LSI Corporation. - Copyright (c) 2013-2015 Avago Technologies + Copyright (c) 2013-2016 Avago Technologies + All rights reserved. --------------------------------------- - Header Set Release Version: 02.00.33 - Header Set Release Date: 12-05-13 + Header Set Release Version: 02.00.42 + Header Set Release Date: 01-04-16 --------------------------------------- Filename Current version Prior version ---------- --------------- ------------- - mpi2.h 02.00.33 02.00.32 - mpi2_cnfg.h 02.00.27 02.00.26 - mpi2_init.h 02.00.15 02.00.15 - mpi2_ioc.h 02.00.24 02.00.23 - mpi2_raid.h 02.00.10 02.00.10 - mpi2_sas.h 02.00.08 02.00.08 - mpi2_targ.h 02.00.06 02.00.06 - mpi2_tool.h 02.00.11 02.00.11 - mpi2_type.h 02.00.00 02.00.00 - mpi2_ra.h 02.00.00 02.00.00 - mpi2_hbd.h 02.00.02 02.00.02 - mpi2_history.txt 02.00.33 02.00.32 + mpi2.h 02.00.42 02.00.41 + mpi2_cnfg.h 02.00.35 02.00.34 + mpi2_init.h 02.00.20 02.00.19 + mpi2_ioc.h 02.00.27 02.00.27 + mpi2_raid.h 02.00.11 02.00.11 + mpi2_sas.h 02.00.10 02.00.10 + mpi2_targ.h 02.00.09 02.00.09 + mpi2_tool.h 02.00.13 02.00.13 + mpi2_type.h 02.00.01 02.00.01 + mpi2_ra.h 02.00.01 02.00.01 + mpi2_hbd.h 02.00.03 02.00.03 + mpi2_history.txt 02.00.41 02.00.40 * Date Version Description @@ -134,6 +135,22 @@ mpi2.h * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT. * 08-19-13 02.00.32 Bumped MPI2_HEADER_VERSION_UNIT. * 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT. + * 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT. + * 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT. + * 11-18-14 02.00.36 Updated copyright information. + * Bumped MPI2_HEADER_VERSION_UNIT. + * 03-16-15 02.00.37 Updated for MPI v2.6. + * Bumped MPI2_HEADER_VERSION_UNIT. + * Added Scratchpad registers to + * MPI2_SYSTEM_INTERFACE_REGS. + * Added MPI2_DIAG_SBR_RELOAD. + * Added MPI2_IOCSTATUS_INSUFFICIENT_POWER. + * 03-19-15 02.00.38 Bumped MPI2_HEADER_VERSION_UNIT. + * 05-25-15 02.00.39 Bumped MPI2_HEADER_VERSION_UNIT. + * 08-25-15 02.00.40 Bumped MPI2_HEADER_VERSION_UNIT. + * Added V7 HostDiagnostic register defines + * 12-15-15 02.00.41 Bumped MPI_HEADER_VERSION_UNIT + * 01-04-16 02.00.42 Bumped MPI_HEADER_VERSION_UNIT * -------------------------------------------------------------------------- mpi2_cnfg.h @@ -294,6 +311,21 @@ mpi2_cnfg.h * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. * Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. + * 01-08-14 02.00.28 Added more defines for the BiosOptions field of + * MPI2_CONFIG_PAGE_BIOS_1. + * 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and + * more defines for the BiosOptions field.. + * 11-18-14 02.00.30 Updated copyright information. + * Added MPI2_BIOSPAGE1_OPTIONS_ADVANCED_CONFIG. + * Added AdapterOrderAux fields to BIOS Page 3. + * 03-16-15 02.00.31 Updated for MPI v2.6. + * Added BoardPowerRequirement, PCISlotPowerAllocation, and + * Flags field to IO Unit Page 7. + * Added IO Unit Page 11. + * Added new SAS Phy Event codes + * 05-25-15 02.00.33 Added more defines for the BiosOptions field of + * MPI2_CONFIG_PAGE_BIOS_1. + * 12-18-15 02.00.35 Added SATADeviceWaitTime to SAS IO Unit Page 4. * -------------------------------------------------------------------------- mpi2_init.h @@ -305,7 +337,7 @@ mpi2_init.h * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO * Control field Task Attribute flags. - * Moved LUN field defines to mpi2.h because they are + * Moved LUN field defines to mpi2.h becasue they are * common to many structures. * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to * Query Asynchronous Event. @@ -323,6 +355,16 @@ mpi2_init.h * Priority to match SAM-4. * Added EEDPErrorOffset to MPI2_SCSI_IO_REPLY. * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION. + * 04-09-13 02.00.15 Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY, + * replacing the Reserved4 field. + * 11-18-14 02.00.16 Updated copyright information. + * 03-16-15 02.00.17 Updated for MPI v2.6. + * Added MPI26_SCSIIO_IOFLAGS_ESCAPE_PASSTHROUGH. + * Added MPI2_SEP_REQ_SLOTSTATUS_DEV_OFF and + * MPI2_SEP_REPLY_SLOTSTATUS_DEV_OFF. + * 08-26-15 02.00.18 Added SCSITASKMGMT_MSGFLAGS for Target Reset. + * 12-18-15 02.00.19 Added EEDPObservedValue added to SCSI IO Reply message. + * 01-04-16 02.00.20 Modified EEDP reported values in SCSI IO Reply message. * -------------------------------------------------------------------------- mpi2_ioc.h @@ -441,6 +483,16 @@ mpi2_ioc.h * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. * Added Encrypted Hash Extended Image. * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. + * 11-18-14 02.00.25 Updated copyright information. + * 03-16-15 02.00.26 Updated for MPI v2.6. + * Added MPI2_EVENT_ACTIVE_CABLE_EXCEPTION and + * MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT. + * Added MPI2_EVENT_PCIE_LINK_COUNTER and + * MPI26_EVENT_DATA_PCIE_LINK_COUNTER. + * Added MPI26_CTRL_OP_SHUTDOWN. + * Added MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG + * Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS + * 08-25-15 02.00.27 Added IC ARCH Class based signature defines. * -------------------------------------------------------------------------- mpi2_raid.h @@ -479,6 +531,9 @@ mpi2_sas.h * Passthrough Request message. * 08-19-13 02.00.08 Made MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL obsolete * for anything newer than MPI v2.0. + * 11-18-14 02.00.09 Updated copyright information. + * 03-16-15 02.00.10 Updated for MPI v2.6. + * Added MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA. * -------------------------------------------------------------------------- mpi2_targ.h @@ -496,6 +551,11 @@ mpi2_targ.h * request message structure. * Added AbortType MPI2_TARGET_MODE_ABORT_DEVHANDLE and * MPI2_TARGET_MODE_ABORT_ALL_COMMANDS. + * 06-13-14 02.00.07 Added MinMSIxIndex and MaxMSIxIndex fields to + * MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST. + * 11-18-14 02.00.08 Updated copyright information. + * 03-16-15 02.00.09 Updated for MPI v2.6. + * Added MPI26_TARGET_ASSIST_IOFLAGS_ESCAPE_PASSTHROUGH. * -------------------------------------------------------------------------- mpi2_tool.h @@ -519,14 +579,18 @@ mpi2_tool.h * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that * it uses MPI Chain SGE as well as MPI Simple SGE. * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info. + * 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC. + * 11-18-14 02.00.13 Updated copyright information. * -------------------------------------------------------------------------- mpi2_type.h * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 11-18-14 02.00.01 Updated copyright information. * -------------------------------------------------------------------------- mpi2_ra.h * 05-06-09 02.00.00 Initial version. + * 11-18-14 02.00.01 Updated copyright information. * -------------------------------------------------------------------------- mpi2_hbd.h @@ -534,24 +598,53 @@ mpi2_hbd.h * 08-11-10 02.00.01 Removed PortGroups, DmaGroup, and ControlGroup from * HBD Action request, replaced by AdditionalInfo field. * 11-18-11 02.00.02 Incorporating additions for MPI v2.5. + * 11-18-14 02.00.03 Updated copyright information. * -------------------------------------------------------------------------- mpi2_history.txt Parts list history -Filename 02.00.33 02.00.32 02.00.31 02.00.30 ----------- -------- -------- -------- -------- -mpi2.h 02.00.33 02.00.32 02.00.31 02.00.30 -mpi2_cnfg.h 02.00.27 02.00.26 02.00.25 02.00.25 -mpi2_init.h 02.00.15 02.00.15 02.00.15 02.00.15 -mpi2_ioc.h 02.00.24 02.00.23 02.00.22 02.00.22 -mpi2_raid.h 02.00.10 02.00.10 02.00.10 02.00.09 -mpi2_sas.h 02.00.08 02.00.08 02.00.07 02.00.07 -mpi2_targ.h 02.00.06 02.00.06 02.00.06 02.00.06 -mpi2_tool.h 02.00.11 02.00.11 02.00.10 02.00.10 -mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 -mpi2_ra.h 02.00.00 02.00.00 02.00.00 02.00.00 -mpi2_hbd.h 02.00.02 02.00.02 02.00.02 02.00.02 +Filename 02.00.42 +---------- -------- +mpi2.h 02.00.42 +mpi2_cnfg.h 02.00.35 +mpi2_init.h 02.00.20 +mpi2_ioc.h 02.00.27 +mpi2_raid.h 02.00.11 +mpi2_sas.h 02.00.10 +mpi2_targ.h 02.00.09 +mpi2_tool.h 02.00.13 +mpi2_type.h 02.00.01 +mpi2_ra.h 02.00.01 +mpi2_hbd.h 02.00.03 + +Filename 02.00.41 02.00.40 02.00.39 02.00.38 02.00.37 02.00.36 +---------- -------- -------- -------- -------- -------- -------- +mpi2.h 02.00.41 02.00.40 02.00.39 02.00.38 02.00.37 02.00.36 +mpi2_cnfg.h 02.00.35 02.00.34 02.00.33 02.00.32 02.00.31 02.00.30 +mpi2_init.h 02.00.19 02.00.18 02.00.17 02.00.17 02.00.17 02.00.16 +mpi2_ioc.h 02.00.27 02.00.27 02.00.26 02.00.26 02.00.26 02.00.25 +mpi2_raid.h 02.00.11 02.00.11 02.00.11 02.00.11 02.00.11 02.00.11 +mpi2_sas.h 02.00.10 02.00.10 02.00.10 02.00.10 02.00.10 02.00.09 +mpi2_targ.h 02.00.09 02.00.09 02.00.09 02.00.09 02.00.09 02.00.08 +mpi2_tool.h 02.00.13 02.00.13 02.00.13 02.00.13 02.00.13 02.00.13 +mpi2_type.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01 +mpi2_ra.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01 02.00.01 +mpi2_hbd.h 02.00.03 02.00.03 02.00.03 02.00.03 02.00.03 02.00.03 + +Filename 02.00.35 02.00.34 02.00.33 02.00.32 02.00.31 02.00.30 +---------- -------- -------- -------- -------- -------- -------- +mpi2.h 02.00.35 02.00.34 02.00.33 02.00.32 02.00.31 02.00.30 +mpi2_cnfg.h 02.00.29 02.00.28 02.00.27 02.00.26 02.00.25 02.00.25 +mpi2_init.h 02.00.15 02.00.15 02.00.15 02.00.15 02.00.15 02.00.15 +mpi2_ioc.h 02.00.24 02.00.24 02.00.24 02.00.23 02.00.22 02.00.22 +mpi2_raid.h 02.00.10 02.00.10 02.00.10 02.00.10 02.00.10 02.00.09 +mpi2_sas.h 02.00.08 02.00.08 02.00.08 02.00.08 02.00.07 02.00.07 +mpi2_targ.h 02.00.07 02.00.06 02.00.06 02.00.06 02.00.06 02.00.06 +mpi2_tool.h 02.00.12 02.00.12 02.00.11 02.00.11 02.00.10 02.00.10 +mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 +mpi2_ra.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 +mpi2_hbd.h 02.00.02 02.00.02 02.00.02 02.00.02 02.00.02 02.00.02 Filename 02.00.29 02.00.28 02.00.27 02.00.26 02.00.25 02.00.24 ---------- -------- -------- -------- -------- -------- -------- diff --git a/sys/dev/mpr/mpi/mpi2_init.h b/sys/dev/mpr/mpi/mpi2_init.h index 5b73643..12b2689 100644 --- a/sys/dev/mpr/mpi/mpi2_init.h +++ b/sys/dev/mpr/mpi/mpi2_init.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_init.h * Title: MPI SCSI initiator mode messages and structures * Creation Date: June 23, 2006 * - * mpi2_init.h Version: 02.00.15 + * mpi2_init.h Version: 02.00.20 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -61,7 +62,7 @@ * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO * Control field Task Attribute flags. - * Moved LUN field defines to mpi2.h because they are + * Moved LUN field defines to mpi2.h becasue they are * common to many structures. * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to * Query Asynchronous Event. @@ -81,6 +82,14 @@ * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION. * 04-09-13 02.00.15 Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY, * replacing the Reserved4 field. + * 11-18-14 02.00.16 Updated copyright information. + * 03-16-15 02.00.17 Updated for MPI v2.6. + * Added MPI26_SCSIIO_IOFLAGS_ESCAPE_PASSTHROUGH. + * Added MPI2_SEP_REQ_SLOTSTATUS_DEV_OFF and + * MPI2_SEP_REPLY_SLOTSTATUS_DEV_OFF. + * 08-26-15 02.00.18 Added SCSITASKMGMT_MSGFLAGS for Target Reset. + * 12-18-15 02.00.19 Added EEDPObservedValue added to SCSI IO Reply message. + * 01-04-16 02.00.20 Modified EEDP reported values in SCSI IO Reply message. * -------------------------------------------------------------------------- */ @@ -164,8 +173,9 @@ typedef struct _MPI2_SCSI_IO_REQUEST #define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C) #define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00) #define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04) -#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) -#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) +#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) /* for MPI v2.5 and earlier only */ +#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) /* for MPI v2.5 and earlier only */ +#define MPI26_SCSIIO_MSGFLAGS_IOCCTL_SENSE_ADDR (0x08) /* for MPI v2.6 only */ /* SCSI IO SGLFlags bits */ @@ -268,7 +278,7 @@ typedef union _MPI25_SCSI_IO_CDB_UNION } MPI25_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI25_SCSI_IO_CDB_UNION, Mpi25ScsiIoCdb_t, MPI2_POINTER pMpi25ScsiIoCdb_t; -/* MPI v2.5 SCSI IO Request Message */ +/* MPI v2.5/2.6 SCSI IO Request Message */ typedef struct _MPI25_SCSI_IO_REQUEST { U16 DevHandle; /* 0x00 */ @@ -347,8 +357,10 @@ typedef struct _MPI25_SCSI_IO_REQUEST #define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000) #define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000) +#define MPI26_SCSIIO_IOFLAGS_ESCAPE_PASSTHROUGH (0x2000) /* MPI v2.6 and later */ #define MPI25_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) #define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) +#define MPI26_SCSIIO_IOFLAGS_PORT_REQUEST (0x0400) /* MPI v2.6 and later; IOC use only */ #define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) /* MPI v2.5 defines for the EEDPFlags bits */ @@ -394,11 +406,19 @@ typedef struct _MPI2_SCSI_IO_REPLY U16 TaskTag; /* 0x20 */ U16 SCSIStatusQualifier; /* 0x22 */ U32 BidirectionalTransferCount; /* 0x24 */ - U32 EEDPErrorOffset; /* 0x28 */ /* MPI 2.5 only; Reserved in MPI 2.0 */ - U32 Reserved6; /* 0x2C */ + U32 EEDPErrorOffset; /* 0x28 */ /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U16 EEDPObservedAppTag; /* 0x2C */ /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U16 EEDPObservedGuard; /* 0x2E */ /* MPI 2.5+ only; Reserved in MPI 2.0 */ + U32 EEDPObservedRefTag; /* 0x30 */ /* MPI 2.5+ only; Reserved in MPI 2.0 */ } MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY, Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t; +/* SCSI IO Reply MsgFlags bits */ +#define MPI26_SCSIIO_REPLY_MSGFLAGS_REFTAG_OBSERVED_VALID (0x01) +#define MPI26_SCSIIO_REPLY_MSGFLAGS_GUARD_OBSERVED_VALID (0x02) +#define MPI26_SCSIIO_REPLY_MSGFLAGS_APPTAG_OBSERVED_VALID (0x04) + + /* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */ #define MPI2_SCSI_STATUS_GOOD (0x00) @@ -474,12 +494,10 @@ typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST #define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18) #define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00) +#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) #define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08) #define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10) -#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) - - /* SCSI Task Management Reply Message */ typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY @@ -561,6 +579,7 @@ typedef struct _MPI2_SEP_REQUEST #define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) /* SlotStatus defines */ +#define MPI2_SEP_REQ_SLOTSTATUS_DEV_OFF (0x00080000) /* MPI v2.6 and newer */ #define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) #define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) #define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) @@ -598,6 +617,7 @@ typedef struct _MPI2_SEP_REPLY Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t; /* SlotStatus defines */ +#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_OFF (0x00080000) /* MPI v2.6 and newer */ #define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) #define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) #define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) diff --git a/sys/dev/mpr/mpi/mpi2_ioc.h b/sys/dev/mpr/mpi/mpi2_ioc.h index 54f39a5..37f01c6 100644 --- a/sys/dev/mpr/mpi/mpi2_ioc.h +++ b/sys/dev/mpr/mpi/mpi2_ioc.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_ioc.h * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * - * mpi2_ioc.h Version: 02.00.24 + * mpi2_ioc.h Version: 02.00.27 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -168,6 +169,17 @@ * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. * Added Encrypted Hash Extended Image. * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. + * 11-18-14 02.00.25 Updated copyright information. + * 03-16-15 02.00.26 Updated for MPI v2.6. + * Added MPI2_EVENT_ACTIVE_CABLE_EXCEPTION and + * MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT. + * Added MPI2_EVENT_PCIE_LINK_COUNTER and + * MPI26_EVENT_DATA_PCIE_LINK_COUNTER. + * Added MPI26_CTRL_OP_SHUTDOWN. + * Added MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG + * Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS + * 08-25-15 02.00.27 Added IC ARCH Class based signature defines + * * -------------------------------------------------------------------------- */ @@ -200,8 +212,8 @@ typedef struct _MPI2_IOC_INIT_REQUEST U16 MsgVersion; /* 0x0C */ U16 HeaderVersion; /* 0x0E */ U32 Reserved5; /* 0x10 */ - U16 Reserved6; /* 0x14 */ - U8 Reserved7; /* 0x16 */ + U16 ConfigurationFlags; /* 0x14 */ + U8 HostPageSize; /* 0x16 */ U8 HostMSIxVectors; /* 0x17 */ U16 Reserved8; /* 0x18 */ U16 SystemRequestFrameSize; /* 0x1A */ @@ -329,7 +341,12 @@ typedef struct _MPI2_IOC_FACTS_REPLY U16 MaxDevHandle; /* 0x38 */ U16 MaxPersistentEntries; /* 0x3A */ U16 MinDevHandle; /* 0x3C */ - U16 Reserved4; /* 0x3E */ + U8 CurrentHostPageSize; /* 0x3E */ + U8 Reserved4; /* 0x3F */ + U8 SGEModifierMask; /* 0x40 */ + U8 SGEModifierValue; /* 0x41 */ + U8 SGEModifierShift; /* 0x42 */ + U8 Reserved5; /* 0x43 */ } MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY, Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t; @@ -383,8 +400,8 @@ typedef struct _MPI2_IOC_FACTS_REPLY #define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) /* ProtocolFlags */ -#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) #define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) +#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) /**************************************************************************** @@ -559,6 +576,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY #define MPI2_EVENT_TEMP_THRESHOLD (0x0027) #define MPI2_EVENT_HOST_MESSAGE (0x0028) #define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029) +#define MPI2_EVENT_ACTIVE_CABLE_EXCEPTION (0x0034) /* MPI v2.6 and later */ #define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E) #define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F) @@ -630,7 +648,7 @@ typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t; -/* Power Performance Change Event */ +/* Power Performance Change Event data */ typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE { @@ -656,6 +674,23 @@ typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE #define MPI2_EVENT_PM_MODE_STANDBY (0x06) +/* Active Cable Exception Event data */ + +typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT +{ + U32 ActiveCablePowerRequirement; /* 0x00 */ + U8 ReasonCode; /* 0x04 */ + U8 ReceptacleID; /* 0x05 */ + U16 Reserved1; /* 0x06 */ +} MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT, + MPI2_POINTER PTR_MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT, + Mpi26EventDataActiveCableExcept_t, + MPI2_POINTER pMpi26EventDataActiveCableExcept_t; + +/* defines for ReasonCode field */ +#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00) + + /* Hard Reset Received Event data */ typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED @@ -1130,7 +1165,6 @@ typedef struct _MPI2_EVENT_DATA_HBD_PHY #define MPI2_EVENT_HBD_DT_SAS (0x01) - /**************************************************************************** * EventAck message ****************************************************************************/ @@ -1348,6 +1382,7 @@ typedef struct _MPI2_FW_UPLOAD_REQUEST #define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) #define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) #define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) +#define MPI2_FW_UPLOAD_ITYPE_CBB_BACKUP (0x0D) /* MPI v2.0 FWUpload TransactionContext Element */ typedef struct _MPI2_FW_UPLOAD_TCSGE @@ -1436,7 +1471,7 @@ typedef struct _MPI2_FW_IMAGE_HEADER U32 Reserved54; /* 0x54 */ U32 Reserved58; /* 0x58 */ U32 Reserved5C; /* 0x5C */ - U32 Reserved60; /* 0x60 */ + U32 BootFlags; /* 0x60 */ /* reserved in MPI v2.5 and earlier */ U32 FirmwareVersionNameWhat; /* 0x64 */ U8 FirmwareVersionName[32]; /* 0x68 */ U32 VendorNameWhat; /* 0x88 */ @@ -1462,18 +1497,27 @@ typedef struct _MPI2_FW_IMAGE_HEADER #define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) #define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) #define MPI2_FW_HEADER_SIGNATURE (0xEA000000) +#define MPI26_FW_HEADER_SIGNATURE (0xEB000000) /* Signature0 field */ #define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) #define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) +#define MPI26_FW_HEADER_SIGNATURE0_BASE (0x5AEAA500) /* Last byte is defined by architecture */ +#define MPI26_FW_HEADER_SIGNATURE0_ARC_0 (0x5A) +#define MPI26_FW_HEADER_SIGNATURE0_ARC_1 (0x00) +#define MPI26_FW_HEADER_SIGNATURE0_ARC_2 (0x01) +#define MPI26_FW_HEADER_SIGNATURE0 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_0) // legacy (0x5AEAA55A) +#define MPI26_FW_HEADER_SIGNATURE0_3516 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_1) /* Signature1 field */ #define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) #define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) +#define MPI26_FW_HEADER_SIGNATURE1 (0xA55AEAA5) /* Signature2 field */ #define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) #define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) +#define MPI26_FW_HEADER_SIGNATURE2 (0x5AA55AEA) /* defines for using the ProductID field */ @@ -1491,6 +1535,8 @@ typedef struct _MPI2_FW_IMAGE_HEADER #define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013) #define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014) #define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021) +#define MPI26_FW_HEADER_PID_FAMILY_3324_SAS (0x0028) +#define MPI26_FW_HEADER_PID_FAMILY_3516_SAS (0x0031) /* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ @@ -1499,6 +1545,7 @@ typedef struct _MPI2_FW_IMAGE_HEADER #define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) #define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) +#define MPI26_FW_HEADER_BOOTFLAGS_OFFSET (0x60) #define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) #define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) @@ -1612,7 +1659,10 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA #define MPI2_FLASH_REGION_CONFIG_1 (0x07) #define MPI2_FLASH_REGION_CONFIG_2 (0x08) #define MPI2_FLASH_REGION_MEGARAID (0x09) -#define MPI2_FLASH_REGION_INIT (0x0A) +#define MPI2_FLASH_REGION_COMMON_BOOT_BLOCK (0x0A) +#define MPI2_FLASH_REGION_INIT (MPI2_FLASH_REGION_COMMON_BOOT_BLOCK) /* older name */ +#define MPI2_FLASH_REGION_CBB_BACKUP (0x0D) + /* ImageRevision */ #define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) @@ -1854,5 +1904,91 @@ typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t; +/**************************************************************************** +* IO Unit Control messages (MPI v2.6 and later only.) +****************************************************************************/ + +/* IO Unit Control Request Message */ +typedef struct _MPI26_IOUNIT_CONTROL_REQUEST +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 ChainOffset; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 IOCParameter; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U8 PhyNum; /* 0x0E */ + U8 PrimFlags; /* 0x0F */ + U32 Primitive; /* 0x10 */ + U8 LookupMethod; /* 0x14 */ + U8 Reserved5; /* 0x15 */ + U16 SlotNumber; /* 0x16 */ + U64 LookupAddress; /* 0x18 */ + U32 IOCParameterValue; /* 0x20 */ + U32 Reserved7; /* 0x24 */ + U32 Reserved8; /* 0x28 */ +} MPI26_IOUNIT_CONTROL_REQUEST, + MPI2_POINTER PTR_MPI26_IOUNIT_CONTROL_REQUEST, + Mpi26IoUnitControlRequest_t, MPI2_POINTER pMpi26IoUnitControlRequest_t; + +/* values for the Operation field */ +#define MPI26_CTRL_OP_CLEAR_ALL_PERSISTENT (0x02) +#define MPI26_CTRL_OP_SAS_PHY_LINK_RESET (0x06) +#define MPI26_CTRL_OP_SAS_PHY_HARD_RESET (0x07) +#define MPI26_CTRL_OP_PHY_CLEAR_ERROR_LOG (0x08) +#define MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG (0x09) +#define MPI26_CTRL_OP_SAS_SEND_PRIMITIVE (0x0A) +#define MPI26_CTRL_OP_FORCE_FULL_DISCOVERY (0x0B) +#define MPI26_CTRL_OP_REMOVE_DEVICE (0x0D) +#define MPI26_CTRL_OP_LOOKUP_MAPPING (0x0E) +#define MPI26_CTRL_OP_SET_IOC_PARAMETER (0x0F) +#define MPI26_CTRL_OP_ENABLE_FP_DEVICE (0x10) +#define MPI26_CTRL_OP_DISABLE_FP_DEVICE (0x11) +#define MPI26_CTRL_OP_ENABLE_FP_ALL (0x12) +#define MPI26_CTRL_OP_DISABLE_FP_ALL (0x13) +#define MPI26_CTRL_OP_DEV_ENABLE_NCQ (0x14) +#define MPI26_CTRL_OP_DEV_DISABLE_NCQ (0x15) +#define MPI26_CTRL_OP_SHUTDOWN (0x16) +#define MPI26_CTRL_OP_DEV_ENABLE_PERSIST_CONNECTION (0x17) +#define MPI26_CTRL_OP_DEV_DISABLE_PERSIST_CONNECTION (0x18) +#define MPI26_CTRL_OP_DEV_CLOSE_PERSIST_CONNECTION (0x19) +#define MPI26_CTRL_OP_PRODUCT_SPECIFIC_MIN (0x80) + +/* values for the PrimFlags field */ +#define MPI26_CTRL_PRIMFLAGS_SINGLE (0x08) +#define MPI26_CTRL_PRIMFLAGS_TRIPLE (0x02) +#define MPI26_CTRL_PRIMFLAGS_REDUNDANT (0x01) + +/* values for the LookupMethod field */ +#define MPI26_CTRL_LOOKUP_METHOD_WWID_ADDRESS (0x01) +#define MPI26_CTRL_LOOKUP_METHOD_ENCLOSURE_SLOT (0x02) +#define MPI26_CTRL_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) + + +/* IO Unit Control Reply Message */ +typedef struct _MPI26_IOUNIT_CONTROL_REPLY +{ + U8 Operation; /* 0x00 */ + U8 Reserved1; /* 0x01 */ + U8 MsgLength; /* 0x02 */ + U8 Function; /* 0x03 */ + U16 DevHandle; /* 0x04 */ + U8 IOCParameter; /* 0x06 */ + U8 MsgFlags; /* 0x07 */ + U8 VP_ID; /* 0x08 */ + U8 VF_ID; /* 0x09 */ + U16 Reserved3; /* 0x0A */ + U16 Reserved4; /* 0x0C */ + U16 IOCStatus; /* 0x0E */ + U32 IOCLogInfo; /* 0x10 */ +} MPI26_IOUNIT_CONTROL_REPLY, MPI2_POINTER PTR_MPI26_IOUNIT_CONTROL_REPLY, + Mpi26IoUnitControlReply_t, MPI2_POINTER pMpi26IoUnitControlReply_t; + + #endif diff --git a/sys/dev/mpr/mpi/mpi2_ra.h b/sys/dev/mpr/mpi/mpi2_ra.h index 02304aa..013f598 100644 --- a/sys/dev/mpr/mpi/mpi2_ra.h +++ b/sys/dev/mpr/mpi/mpi2_ra.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2012-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_ra.h * Title: MPI RAID Accelerator messages and structures * Creation Date: April 13, 2009 * - * mpi2_ra.h Version: 02.00.00 + * mpi2_ra.h Version: 02.00.01 * * Version History * --------------- @@ -49,6 +50,7 @@ * Date Version Description * -------- -------- ------------------------------------------------------ * 05-06-09 02.00.00 Initial version. + * 11-18-14 02.00.01 Updated copyright information. * -------------------------------------------------------------------------- */ diff --git a/sys/dev/mpr/mpi/mpi2_raid.h b/sys/dev/mpr/mpi/mpi2_raid.h index 52ebf07..81be995 100644 --- a/sys/dev/mpr/mpi/mpi2_raid.h +++ b/sys/dev/mpr/mpi/mpi2_raid.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_raid.h * Title: MPI Integrated RAID messages and structures * Creation Date: April 26, 2007 * - * mpi2_raid.h Version: 02.00.10 + * mpi2_raid.h Version: 02.00.11 * * Version History * --------------- @@ -66,6 +67,7 @@ * 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR. * Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define. * 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI. + * 11-18-14 02.00.11 Updated copyright information. * -------------------------------------------------------------------------- */ diff --git a/sys/dev/mpr/mpi/mpi2_sas.h b/sys/dev/mpr/mpi/mpi2_sas.h index 7cae2c3..8f90b2b 100644 --- a/sys/dev/mpr/mpi/mpi2_sas.h +++ b/sys/dev/mpr/mpi/mpi2_sas.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_sas.h * Title: MPI Serial Attached SCSI structures and definitions * Creation Date: February 9, 2007 * - * mpi2_sas.h Version: 02.00.08 + * mpi2_sas.h Version: 02.00.10 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -67,6 +68,9 @@ * Passthrough Request message. * 08-19-13 02.00.08 Made MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL obsolete * for anything newer than MPI v2.0. + * 11-18-14 02.00.09 Updated copyright information. + * 03-16-15 02.00.10 Updated for MPI v2.6. + * Added MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA. * -------------------------------------------------------------------------- */ @@ -226,6 +230,7 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST /* values for PassthroughFlags field */ #define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) +#define MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA (0x0040) /* MPI v2.6 and newer */ #define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) #define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) #define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) @@ -262,6 +267,8 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REPLY /**************************************************************************** * SAS IO Unit Control messages +* (MPI v2.5 and earlier only. +* Replaced by IO Unit Control messages in MPI v2.6 and later.) ****************************************************************************/ /* SAS IO Unit Control Request Message */ diff --git a/sys/dev/mpr/mpi/mpi2_targ.h b/sys/dev/mpr/mpi/mpi2_targ.h index 85b5ac5..0216cfe 100644 --- a/sys/dev/mpr/mpi/mpi2_targ.h +++ b/sys/dev/mpr/mpi/mpi2_targ.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_targ.h * Title: MPI Target mode messages and structures * Creation Date: September 8, 2006 * - * mpi2_targ.h Version: 02.00.06 + * mpi2_targ.h Version: 02.00.09 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used @@ -67,6 +68,11 @@ * request message structure. * Added AbortType MPI2_TARGET_MODE_ABORT_DEVHANDLE and * MPI2_TARGET_MODE_ABORT_ALL_COMMANDS. + * 06-13-14 02.00.07 Added MinMSIxIndex and MaxMSIxIndex fields to + * MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST. + * 11-18-14 02.00.08 Updated copyright information. + * 03-16-15 02.00.09 Updated for MPI v2.6. + * Added MPI26_TARGET_ASSIST_IOFLAGS_ESCAPE_PASSTHROUGH. * -------------------------------------------------------------------------- */ @@ -98,7 +104,8 @@ typedef struct _MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST U16 Reserved2; /* 0x0A */ U32 Reserved3; /* 0x0C */ U16 CmdBufferLength; /* 0x10 */ - U16 Reserved4; /* 0x12 */ + U8 MinMSIxIndex; /* 0x12 */ /* MPI 2.5 and newer only; Reserved in MPI 2.0 */ + U8 MaxMSIxIndex; /* 0x13 */ /* MPI 2.5 and newer only; Reserved in MPI 2.0 */ U32 BaseAddressLow; /* 0x14 */ U32 BaseAddressHigh; /* 0x18 */ } MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST, @@ -110,8 +117,9 @@ typedef struct _MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST #define MPI2_CMD_BUF_POST_BASE_ADDRESS_SPACE_MASK (0x0C) #define MPI2_CMD_BUF_POST_BASE_SYSTEM_ADDRESS_SPACE (0x00) #define MPI2_CMD_BUF_POST_BASE_IOCDDR_ADDRESS_SPACE (0x04) -#define MPI2_CMD_BUF_POST_BASE_IOCPLB_ADDRESS_SPACE (0x08) -#define MPI2_CMD_BUF_POST_BASE_IOCPLBNTA_ADDRESS_SPACE (0x0C) +#define MPI2_CMD_BUF_POST_BASE_IOCPLB_ADDRESS_SPACE (0x08) /* only for MPI v2.5 and earlier */ +#define MPI26_CMD_BUF_POST_BASE_IOCCTL_ADDRESS_SPACE (0x08) /* for MPI v2.6 only */ +#define MPI2_CMD_BUF_POST_BASE_IOCPLBNTA_ADDRESS_SPACE (0x0C) /* only for MPI v2.5 and earlier */ #define MPI2_CMD_BUF_POST_BASE_FLAGS_AUTO_POST_ALL (0x01) @@ -406,6 +414,7 @@ typedef struct _MPI25_TARGET_ASSIST_REQUEST #define MPI25_TA_DMAFLAGS_OP_D_H_I_I (0x0F) /* defines for the IoFlags field */ +#define MPI26_TARGET_ASSIST_IOFLAGS_ESCAPE_PASSTHROUGH (0x2000) /* MPI v2.6 and later */ #define MPI25_TARGET_ASSIST_IOFLAGS_BIDIRECTIONAL (0x0800) #define MPI25_TARGET_ASSIST_IOFLAGS_RECEIVE_FIRST (0x0200) diff --git a/sys/dev/mpr/mpi/mpi2_tool.h b/sys/dev/mpr/mpi/mpi2_tool.h index 59917c0..fce98ae 100644 --- a/sys/dev/mpr/mpi/mpi2_tool.h +++ b/sys/dev/mpr/mpi/mpi2_tool.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_tool.h * Title: MPI diagnostic tool structures and definitions * Creation Date: March 26, 2007 * - * mpi2_tool.h Version: 02.00.11 + * mpi2_tool.h Version: 02.00.13 * * Version History * --------------- @@ -68,6 +69,8 @@ * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that * it uses MPI Chain SGE as well as MPI Simple SGE. * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info. + * 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC. + * 11-18-14 02.00.13 Updated copyright information. * -------------------------------------------------------------------------- */ @@ -139,6 +142,7 @@ typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST #define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) #define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) #define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) +#define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000) #define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) #define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) #define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) diff --git a/sys/dev/mpr/mpi/mpi2_type.h b/sys/dev/mpr/mpi/mpi2_type.h index b063683..8e64484 100644 --- a/sys/dev/mpr/mpi/mpi2_type.h +++ b/sys/dev/mpr/mpi/mpi2_type.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,15 @@ /* * Copyright (c) 2000-2015 LSI Corporation. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies + * All rights reserved. * * * Name: mpi2_type.h * Title: MPI basic type definitions * Creation Date: August 16, 2006 * - * mpi2_type.h Version: 02.00.00 + * mpi2_type.h Version: 02.00.01 * * Version History * --------------- @@ -49,6 +50,7 @@ * Date Version Description * -------- -------- ------------------------------------------------------ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. + * 11-18-14 02.00.01 Updated copyright information. * -------------------------------------------------------------------------- */ -- cgit v1.1 From 9b9ab04340b8ac0377759d2197acb215b4d1981a Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:16:00 +0000 Subject: Several style changes and add copyrights for 2016. Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6103 --- sys/dev/mpr/mpr.c | 39 +++++++++---------- sys/dev/mpr/mpr_config.c | 2 +- sys/dev/mpr/mpr_ioctl.h | 2 +- sys/dev/mpr/mpr_mapping.c | 2 +- sys/dev/mpr/mpr_mapping.h | 2 +- sys/dev/mpr/mpr_sas.c | 95 +++++++++++++++++++++-------------------------- sys/dev/mpr/mpr_sas.h | 2 +- sys/dev/mpr/mpr_sas_lsi.c | 38 +++++++++---------- sys/dev/mpr/mpr_table.c | 5 +-- sys/dev/mpr/mpr_user.c | 44 +++++++++++----------- sys/dev/mpr/mprvar.h | 20 +++++----- 11 files changed, 115 insertions(+), 136 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 5580157..5a339db 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,14 +92,11 @@ static __inline void mpr_complete_command(struct mpr_softc *sc, struct mpr_command *cm); static void mpr_dispatch_event(struct mpr_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *reply); -static void mpr_config_complete(struct mpr_softc *sc, - struct mpr_command *cm); +static void mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm); static void mpr_periodic(void *); static int mpr_reregister_events(struct mpr_softc *sc); -static void mpr_enqueue_request(struct mpr_softc *sc, - struct mpr_command *cm); -static int mpr_get_iocfacts(struct mpr_softc *sc, - MPI2_IOC_FACTS_REPLY *facts); +static void mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm); +static int mpr_get_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts); static int mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag); SYSCTL_NODE(_hw, OID_AUTO, mpr, CTLFLAG_RD, 0, "MPR Driver Parameters"); @@ -550,8 +547,8 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) error = mpr_transition_operational(sc); if (error != 0) { if (attaching) { - mpr_printf(sc, "%s failed to transition to " - "operational with error %d\n", __func__, error); + mpr_printf(sc, "%s failed to transition to operational " + "with error %d\n", __func__, error); mpr_free(sc); return (error); } else { @@ -685,7 +682,7 @@ mpr_reinit(struct mpr_softc *sc) if (sc->mpr_flags & MPR_FLAGS_DIAGRESET) { mpr_dprint(sc, MPR_INIT, "%s reset already in progress\n", - __func__); + __func__); return 0; } @@ -1712,9 +1709,9 @@ mpr_complete_command(struct mpr_softc *sc, struct mpr_command *cm) if (cm->cm_complete != NULL) { mpr_dprint(sc, MPR_TRACE, - "%s cm %p calling cm_complete %p data %p reply %p\n", - __func__, cm, cm->cm_complete, cm->cm_complete_data, - cm->cm_reply); + "%s cm %p calling cm_complete %p data %p reply %p\n", + __func__, cm, cm->cm_complete, cm->cm_complete_data, + cm->cm_reply); cm->cm_complete(sc, cm); } @@ -1772,9 +1769,8 @@ mpr_sas_log_info(struct mpr_softc *sc , u32 log_info) } mpr_dprint(sc, MPR_INFO, "log_info(0x%08x): originator(%s), " - "code(0x%02x), sub_code(0x%04x)\n", log_info, - originator_str, sas_loginfo.dw.code, - sas_loginfo.dw.subcode); + "code(0x%02x), sub_code(0x%04x)\n", log_info, originator_str, + sas_loginfo.dw.code, sas_loginfo.dw.subcode); } static void @@ -2463,10 +2459,9 @@ mpr_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) * user they did the wrong thing. */ if ((cm->cm_max_segs != 0) && (nsegs > cm->cm_max_segs)) { - mpr_dprint(sc, MPR_ERROR, - "%s: warning: busdma returned %d segments, " - "more than the %d allowed\n", __func__, nsegs, - cm->cm_max_segs); + mpr_dprint(sc, MPR_ERROR, "%s: warning: busdma returned %d " + "segments, more than the %d allowed\n", __func__, nsegs, + cm->cm_max_segs); } /* @@ -2663,8 +2658,8 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm) if (error) { mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__); rc = mpr_reinit(sc); - mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? - "success" : "failed"); + mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ? "success" : + "failed"); } return (error); } diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index c0ea3d5..0ba44ea 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/mpr/mpr_ioctl.h b/sys/dev/mpr/mpr_ioctl.h index aa1a4cb..df41f56 100644 --- a/sys/dev/mpr/mpr_ioctl.h +++ b/sys/dev/mpr/mpr_ioctl.h @@ -33,7 +33,7 @@ */ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 110e6a3..0feb555 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/mpr/mpr_mapping.h b/sys/dev/mpr/mpr_mapping.h index fafaf9b..05571f2e 100644 --- a/sys/dev/mpr/mpr_mapping.h +++ b/sys/dev/mpr/mpr_mapping.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index dc9a62e..358e1fb 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -119,13 +119,11 @@ static void mprsas_remove_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action(struct cam_sim *sim, union ccb *ccb); static void mprsas_poll(struct cam_sim *sim); static void mprsas_scsiio_timeout(void *data); -static void mprsas_abort_complete(struct mpr_softc *sc, - struct mpr_command *cm); +static void mprsas_abort_complete(struct mpr_softc *sc, struct mpr_command *cm); static void mprsas_action_scsiio(struct mprsas_softc *, union ccb *); static void mprsas_scsiio_complete(struct mpr_softc *, struct mpr_command *); static void mprsas_action_resetdev(struct mprsas_softc *, union ccb *); -static void mprsas_resetdev_complete(struct mpr_softc *, - struct mpr_command *); +static void mprsas_resetdev_complete(struct mpr_softc *, struct mpr_command *); static int mprsas_send_abort(struct mpr_softc *sc, struct mpr_command *tm, struct mpr_command *cm); static void mprsas_async(void *callback_arg, uint32_t code, @@ -142,10 +140,9 @@ static void mprsas_portenable_complete(struct mpr_softc *sc, struct mpr_command *cm); #if __FreeBSD_version >= 900026 -static void mprsas_smpio_complete(struct mpr_softc *sc, - struct mpr_command *cm); -static void mprsas_send_smpcmd(struct mprsas_softc *sassc, - union ccb *ccb, uint64_t sasaddr); +static void mprsas_smpio_complete(struct mpr_softc *sc, struct mpr_command *cm); +static void mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, + uint64_t sasaddr); static void mprsas_action_smpio(struct mprsas_softc *sassc, union ccb *ccb); #endif //FreeBSD_version >= 900026 @@ -1065,15 +1062,15 @@ mprsas_action(struct cam_sim *sim, union ccb *ccb) mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_RESET_DEV: - mpr_dprint(sassc->sc, MPR_XINFO, - "mprsas_action XPT_RESET_DEV\n"); + mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action " + "XPT_RESET_DEV\n"); mprsas_action_resetdev(sassc, ccb); return; case XPT_RESET_BUS: case XPT_ABORT: case XPT_TERM_IO: - mpr_dprint(sassc->sc, MPR_XINFO, - "mprsas_action faking success for abort or reset\n"); + mpr_dprint(sassc->sc, MPR_XINFO, "mprsas_action faking success " + "for abort or reset\n"); mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_SCSI_IO: @@ -1134,8 +1131,8 @@ mprsas_complete_all_commands(struct mpr_softc *sc) if (cm->cm_complete != NULL) { mprsas_log_command(cm, MPR_RECOVERY, - "completing cm %p state %x ccb %p for diag " - "reset\n", cm, cm->cm_state, cm->cm_ccb); + "completing cm %p state %x ccb %p for diag reset\n", + cm, cm->cm_state, cm->cm_ccb); cm->cm_complete(sc, cm); completed = 1; } @@ -1216,14 +1213,13 @@ mprsas_tm_timeout(void *data) mtx_assert(&sc->mpr_mtx, MA_OWNED); - mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, - "task mgmt %p timed out\n", tm); + mprsas_log_command(tm, MPR_INFO|MPR_RECOVERY, "task mgmt %p timed " + "out\n", tm); mpr_reinit(sc); } static void -mprsas_logical_unit_reset_complete(struct mpr_softc *sc, - struct mpr_command *tm) +mprsas_logical_unit_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) { MPI2_SCSI_TASK_MANAGE_REPLY *reply; MPI2_SCSI_TASK_MANAGE_REQUEST *req; @@ -1250,8 +1246,8 @@ mprsas_logical_unit_reset_complete(struct mpr_softc *sc, } if (reply == NULL) { - mprsas_log_command(tm, MPR_RECOVERY, - "NULL reset reply for tm %p\n", tm); + mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm " + "%p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ targ->tm = NULL; @@ -1338,8 +1334,8 @@ mprsas_target_reset_complete(struct mpr_softc *sc, struct mpr_command *tm) } if (reply == NULL) { - mprsas_log_command(tm, MPR_RECOVERY, - "NULL reset reply for tm %p\n", tm); + mprsas_log_command(tm, MPR_RECOVERY, "NULL reset reply for tm " + "%p\n", tm); if ((sc->mpr_flags & MPR_FLAGS_DIAGRESET) != 0) { /* this completion was due to a reset, just cleanup */ targ->tm = NULL; @@ -1626,9 +1622,8 @@ mprsas_scsiio_timeout(void *data) targ = cm->cm_targ; targ->timeouts++; - mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p " - "target %u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, - targ->handle); + mprsas_log_command(cm, MPR_ERROR, "command timeout cm %p ccb %p target " + "%u, handle(0x%04x)\n", cm, cm->cm_ccb, targ->tid, targ->handle); if (targ->encl_level_valid) { mpr_dprint(sc, MPR_ERROR, "At enclosure level %d, slot %d, " "connector name (%4s)\n", targ->encl_level, targ->encl_slot, @@ -1666,8 +1661,8 @@ mprsas_scsiio_timeout(void *data) * more credits than disks in an enclosure, and limit * ourselves to one TM per target for recovery. */ - mpr_dprint(sc, MPR_RECOVERY, - "timedout cm %p failed to allocate a tm\n", cm); + mpr_dprint(sc, MPR_RECOVERY, "timedout cm %p failed to " + "allocate a tm\n", cm); } } @@ -2587,8 +2582,7 @@ bailout: } static void -mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, - uint64_t sasaddr) +mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, uint64_t sasaddr) { struct mpr_command *cm; uint8_t *request, *response; @@ -2621,9 +2615,9 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, */ if ((ccb->smpio.smp_request_sglist_cnt > 1) || (ccb->smpio.smp_response_sglist_cnt > 1)) { - mpr_dprint(sc, MPR_ERROR, - "%s: multiple request or response buffer segments " - "not supported for SMP\n", __func__); + mpr_dprint(sc, MPR_ERROR, "%s: multiple request or " + "response buffer segments not supported for SMP\n", + __func__); mprsas_set_ccbstatus(ccb, CAM_REQ_INVALID); xpt_done(ccb); return; @@ -2724,8 +2718,8 @@ mprsas_send_smpcmd(struct mprsas_softc *sassc, union ccb *ccb, cm = mpr_alloc_command(sc); if (cm == NULL) { - mpr_dprint(sc, MPR_ERROR, - "%s: cannot allocate command\n", __func__); + mpr_dprint(sc, MPR_ERROR, "%s: cannot allocate command\n", + __func__); mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; @@ -2958,14 +2952,13 @@ mprsas_action_resetdev(struct mprsas_softc *sassc, union ccb *ccb) MPR_FUNCTRACE(sassc->sc); mtx_assert(&sassc->sc->mpr_mtx, MA_OWNED); - KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, - ("Target %d out of bounds in XPT_RESET_DEV\n", - ccb->ccb_h.target_id)); + KASSERT(ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out of " + "bounds in XPT_RESET_DEV\n", ccb->ccb_h.target_id)); sc = sassc->sc; tm = mpr_alloc_command(sc); if (tm == NULL) { - mpr_dprint(sc, MPR_ERROR, - "command alloc failure in mprsas_action_resetdev\n"); + mpr_dprint(sc, MPR_ERROR, "command alloc failure in " + "mprsas_action_resetdev\n"); mprsas_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); xpt_done(ccb); return; @@ -3023,9 +3016,8 @@ mprsas_resetdev_complete(struct mpr_softc *sc, struct mpr_command *tm) goto bailout; } - mpr_dprint(sc, MPR_XINFO, - "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", __func__, - le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); + mpr_dprint(sc, MPR_XINFO, "%s: IOCStatus = 0x%x ResponseCode = 0x%x\n", + __func__, le16toh(resp->IOCStatus), le32toh(resp->ResponseCode)); if (le32toh(resp->ResponseCode) == MPI2_SCSITASKMGMT_RSP_TM_COMPLETE) { mprsas_set_ccbstatus(ccb, CAM_REQ_CMP); @@ -3214,8 +3206,8 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, targetid = xpt_path_target_id(path); lunid = xpt_path_lun_id(path); - KASSERT(targetid < sassc->maxtargets, - ("Target %d out of bounds in mprsas_check_eedp\n", targetid)); + KASSERT(targetid < sassc->maxtargets, ("Target %d out of bounds in " + "mprsas_check_eedp\n", targetid)); target = &sassc->targets[targetid]; if (target->handle == 0x0) return; @@ -3225,7 +3217,7 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, * * If this flag is set in the inquiry data, the device supports * protection information, and must support the 16 byte read capacity - * command, otherwise continue without sending read cap 16 + * command, otherwise continue without sending read cap 16. */ if ((cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) == 0) return; @@ -3241,10 +3233,10 @@ mprsas_check_eedp(struct mpr_softc *sc, struct cam_path *path, return; } - if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) - != CAM_REQ_CMP) { + if (xpt_create_path(&local_path, xpt_periph, pathid, targetid, lunid) != + CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "Unable to create path for EEDP " - "support\n"); + "support.\n"); xpt_free_ccb(ccb); return; } @@ -3346,9 +3338,8 @@ mprsas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb) * target. */ sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; - KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, - ("Target %d out of bounds in mprsas_read_cap_done\n", - done_ccb->ccb_h.target_id)); + KASSERT(done_ccb->ccb_h.target_id < sassc->maxtargets, ("Target %d out " + "of bounds in mprsas_read_cap_done\n", done_ccb->ccb_h.target_id)); target = &sassc->targets[done_ccb->ccb_h.target_id]; SLIST_FOREACH(lun, &target->luns, lun_link) { if (lun->lun_id != done_ccb->ccb_h.target_lun) diff --git a/sys/dev/mpr/mpr_sas.h b/sys/dev/mpr/mpr_sas.h index ebeed30..614b5fe 100644 --- a/sys/dev/mpr/mpr_sas.h +++ b/sys/dev/mpr/mpr_sas.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index f162d1f..3d6f9f2 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ #include __FBSDID("$FreeBSD$"); -/* Communications core for LSI MPT3 */ +/* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #include @@ -252,8 +252,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data; if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED) - mpr_dprint(sc, MPR_TRACE,"SAS discovery start " - "event\n"); + mpr_dprint(sc, MPR_TRACE,"SAS discovery start event\n"); if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) { mpr_dprint(sc, MPR_TRACE,"SAS discovery stop event\n"); sassc->flags &= ~MPRSAS_IN_DISCOVERY; @@ -839,8 +838,8 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); } else { mpr_dprint(sc, MPR_ERROR, "Failed to allocate " - "tm for Target Reset after SATA ID " - "command timed out (cm %p)\n", cm); + "tm for Target Reset after SATA ID command " + "timed out (cm %p)\n", cm); } /* * No need to check for more since the target is @@ -901,9 +900,8 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, } } } while (((rc && (rc != EWOULDBLOCK)) || - (ioc_status && - (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR)) - || sas_status) && (try_count < 5)); + (ioc_status && (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR)) + || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { mpr_dprint(sc, MPR_MAPPING, "%s: got SATA identify " @@ -1059,8 +1057,8 @@ mprsas_ata_id_timeout(void *data) __func__, cm, sc); if ((callout_pending(&cm->cm_callout)) || (!callout_active(&cm->cm_callout))) { - mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " - "out\n", __func__); + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n", + __func__); return; } callout_deactivate(&cm->cm_callout); @@ -1072,21 +1070,21 @@ mprsas_ata_id_timeout(void *data) */ mpr_intr_locked(sc); if (cm->cm_state == MPR_CM_STATE_FREE) { - mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed " - "out\n", __func__); + mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n", + __func__); return; } mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); /* - * Send wakeup() to the sleeping thread that issued this ATA ID - * command. wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), - * and this will keep reinit() from being called. This way, an Abort - * Task TM can be issued so that the timed out command can be cleared. - * The Abort Task cannot be sent from here because the driver has not - * completed setting up targets. Instead, the command is flagged so - * that special handling will be used to send the abort. + * Send wakeup() to the sleeping thread that issued this ATA ID command. + * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this + * will keep reinit() from being called. This way, an Abort Task TM can + * be issued so that the timed out command can be cleared. The Abort + * Task cannot be sent from here because the driver has not completed + * setting up targets. Instead, the command is flagged so that special + * handling will be used to send the abort. */ cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; wakeup(cm); diff --git a/sys/dev/mpr/mpr_table.c b/sys/dev/mpr/mpr_table.c index 6e7797e..6ec6492 100644 --- a/sys/dev/mpr/mpr_table.c +++ b/sys/dev/mpr/mpr_table.c @@ -342,9 +342,8 @@ mpr_print_evt_sas(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event) "PHY[%d].LinkRate: %s (0x%x)\n", phynum, mpr_describe_table(mpr_linkrate_names, (phy->LinkRate >> 4) & 0xf), phy->LinkRate); - mpr_dprint_field(sc,MPR_EVENT,"PHY[%d].PhyStatus: " - "%s\n", phynum, - mpr_describe_table(mpr_phystatus_names, + mpr_dprint_field(sc,MPR_EVENT,"PHY[%d].PhyStatus: %s\n", + phynum, mpr_describe_table(mpr_phystatus_names, phy->PhyStatus)); } break; diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 37d9467..8ae8713 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -31,7 +31,7 @@ */ /*- * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -130,24 +130,23 @@ static mpr_user_f mpi_pre_config; static mpr_user_f mpi_pre_sas_io_unit_control; static int mpr_user_read_cfg_header(struct mpr_softc *, - struct mpr_cfg_page_req *); + struct mpr_cfg_page_req *); static int mpr_user_read_cfg_page(struct mpr_softc *, - struct mpr_cfg_page_req *, void *); + struct mpr_cfg_page_req *, void *); static int mpr_user_read_extcfg_header(struct mpr_softc *, - struct mpr_ext_cfg_page_req *); + struct mpr_ext_cfg_page_req *); static int mpr_user_read_extcfg_page(struct mpr_softc *, - struct mpr_ext_cfg_page_req *, void *); + struct mpr_ext_cfg_page_req *, void *); static int mpr_user_write_cfg_page(struct mpr_softc *, - struct mpr_cfg_page_req *, void *); + struct mpr_cfg_page_req *, void *); static int mpr_user_setup_request(struct mpr_command *, - struct mpr_usr_command *); + struct mpr_usr_command *); static int mpr_user_command(struct mpr_softc *, struct mpr_usr_command *); static int mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data); static void mpr_user_get_adapter_data(struct mpr_softc *sc, mpr_adapter_data_t *data); -static void mpr_user_read_pci_info(struct mpr_softc *sc, - mpr_pci_info_t *data); +static void mpr_user_read_pci_info(struct mpr_softc *sc, mpr_pci_info_t *data); static uint8_t mpr_get_fw_diag_buffer_number(struct mpr_softc *sc, uint32_t unique_id); static int mpr_post_fw_diag_buffer(struct mpr_softc *sc, @@ -159,8 +158,8 @@ static int mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, uint32_t *return_code); static int mpr_diag_unregister(struct mpr_softc *sc, mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code); -static int mpr_diag_query(struct mpr_softc *sc, - mpr_fw_diag_query_t *diag_query, uint32_t *return_code); +static int mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query, + uint32_t *return_code); static int mpr_diag_read_buffer(struct mpr_softc *sc, mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf, uint32_t *return_code); @@ -168,10 +167,8 @@ static int mpr_diag_release(struct mpr_softc *sc, mpr_fw_diag_release_t *diag_release, uint32_t *return_code); static int mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, uint8_t *diag_action, uint32_t length, uint32_t *return_code); -static int mpr_user_diag_action(struct mpr_softc *sc, - mpr_diag_action_t *data); -static void mpr_user_event_query(struct mpr_softc *sc, - mpr_event_query_t *data); +static int mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data); +static void mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data); static void mpr_user_event_enable(struct mpr_softc *sc, mpr_event_enable_t *data); static int mpr_user_event_report(struct mpr_softc *sc, @@ -212,11 +209,12 @@ mpr_attach_user(struct mpr_softc *sc) int unit; unit = device_get_unit(sc->mpr_dev); - sc->mpr_cdev = make_dev(&mpr_cdevsw, unit, UID_ROOT, GID_OPERATOR, - 0640, "mpr%d", unit); - if (sc->mpr_cdev == NULL) { + sc->mpr_cdev = make_dev(&mpr_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640, + "mpr%d", unit); + + if (sc->mpr_cdev == NULL) return (ENOMEM); - } + sc->mpr_cdev->si_drv1 = sc; return (0); } @@ -284,8 +282,8 @@ mpr_user_read_cfg_header(struct mpr_softc *sc, } static int -mpr_user_read_cfg_page(struct mpr_softc *sc, - struct mpr_cfg_page_req *page_req, void *buf) +mpr_user_read_cfg_page(struct mpr_softc *sc, struct mpr_cfg_page_req *page_req, + void *buf) { MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr; struct mpr_config_params params; @@ -1718,8 +1716,8 @@ mpr_diag_release(struct mpr_softc *sc, mpr_fw_diag_release_t *diag_release, } static int -mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, - uint8_t *diag_action, uint32_t length, uint32_t *return_code) +mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, uint8_t *diag_action, + uint32_t length, uint32_t *return_code) { mpr_fw_diag_register_t diag_register; mpr_fw_diag_unregister_t diag_unregister; diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 306324b..750ed0d 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -1,7 +1,7 @@ /*- * Copyright (c) 2009 Yahoo! Inc. * Copyright (c) 2011-2015 LSI Corp. - * Copyright (c) 2013-2015 Avago Technologies + * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -585,13 +585,13 @@ do { \ #define mpr_dprint(sc, level, msg, args...) \ do { \ - if ((sc)->mpr_debug & level) \ + if ((sc)->mpr_debug & (level)) \ device_printf((sc)->mpr_dev, msg, ##args); \ } while (0) #define mpr_dprint_field(sc, level, msg, args...) \ do { \ - if ((sc)->mpr_debug & level) \ + if ((sc)->mpr_debug & (level)) \ printf("\t" msg, ##args); \ } while (0) @@ -653,8 +653,7 @@ void mpr_intr_locked(void *); int mpr_register_events(struct mpr_softc *, uint8_t *, mpr_evt_callback_t *, void *, struct mpr_event_handle **); int mpr_restart(struct mpr_softc *); -int mpr_update_events(struct mpr_softc *, struct mpr_event_handle *, - uint8_t *); +int mpr_update_events(struct mpr_softc *, struct mpr_event_handle *, uint8_t *); int mpr_deregister_events(struct mpr_softc *, struct mpr_event_handle *); int mpr_push_sge(struct mpr_command *, MPI2_SGE_SIMPLE64 *, size_t, int); int mpr_push_ieee_sge(struct mpr_command *, void *, int); @@ -671,8 +670,8 @@ void mprsas_record_event(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event_reply); int mpr_map_command(struct mpr_softc *sc, struct mpr_command *cm); -int mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, - int timeout, int sleep_flag); +int mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout, + int sleep_flag); int mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm); int mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t @@ -727,11 +726,10 @@ void mpr_mapping_ir_config_change_event(struct mpr_softc *sc, void mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *event); void mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle); -void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, - uint16_t handle); +void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle); int mprsas_startup(struct mpr_softc *sc); -struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, - int, uint16_t); +struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, int, + uint16_t); void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); -- cgit v1.1 From 1f91a62e29c2cc858291a13fd9597225a819e5a8 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:19:13 +0000 Subject: Add support for the Broadcom (Avago/LSI) 9305 16 and 24 port HBA's. Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Relnotes: yes Differential Revision: https://reviews.freebsd.org/D6098 --- sys/dev/mpr/mpr.c | 43 ++++++++++++++++++++++++++++++++----------- sys/dev/mpr/mpr_pci.c | 12 ++++++++++++ sys/dev/mpr/mpr_sas.c | 4 ++++ sys/dev/mpr/mpr_sas_lsi.c | 17 +++++++++++++++++ sys/dev/mpr/mprvar.h | 4 ++++ 5 files changed, 69 insertions(+), 11 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 5a339db..7d6bba1 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -441,6 +441,8 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching) (saved_facts.IOCCapabilities != sc->facts->IOCCapabilities) || (saved_facts.IOCRequestFrameSize != sc->facts->IOCRequestFrameSize) || + (saved_facts.IOCMaxChainSegmentSize != + sc->facts->IOCMaxChainSegmentSize) || (saved_facts.MaxTargets != sc->facts->MaxTargets) || (saved_facts.MaxSasExpanders != sc->facts->MaxSasExpanders) || (saved_facts.MaxEnclosures != sc->facts->MaxEnclosures) || @@ -1188,7 +1190,28 @@ mpr_alloc_requests(struct mpr_softc *sc) bus_dmamap_load(sc->req_dmat, sc->req_map, sc->req_frames, rsize, mpr_memaddr_cb, &sc->req_busaddr, 0); - rsize = sc->facts->IOCRequestFrameSize * sc->max_chains * 4; + /* + * Gen3 and beyond uses the IOCMaxChainSegmentSize from IOC Facts to + * get the size of a Chain Frame. Previous versions use the size as a + * Request Frame for the Chain Frame size. If IOCMaxChainSegmentSize + * is 0, use the default value. The IOCMaxChainSegmentSize is the + * number of 16-byte elelements that can fit in a Chain Frame, which is + * the size of an IEEE Simple SGE. + */ + if (sc->facts->MsgVersion >= MPI2_VERSION_02_05) { + sc->chain_seg_size = + htole16(sc->facts->IOCMaxChainSegmentSize); + if (sc->chain_seg_size == 0) { + sc->chain_frame_size = MPR_DEFAULT_CHAIN_SEG_SIZE * + MPR_MAX_CHAIN_ELEMENT_SIZE; + } else { + sc->chain_frame_size = sc->chain_seg_size * + MPR_MAX_CHAIN_ELEMENT_SIZE; + } + } else { + sc->chain_frame_size = sc->facts->IOCRequestFrameSize * 4; + } + rsize = sc->chain_frame_size * sc->max_chains; if (bus_dma_tag_create( sc->mpr_parent_dmat, /* parent */ 16, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ @@ -1246,9 +1269,9 @@ mpr_alloc_requests(struct mpr_softc *sc) for (i = 0; i < sc->max_chains; i++) { chain = &sc->chains[i]; chain->chain = (MPI2_SGE_IO_UNION *)(sc->chain_frames + - i * sc->facts->IOCRequestFrameSize * 4); + i * sc->chain_frame_size); chain->chain_busaddr = sc->chain_busaddr + - i * sc->facts->IOCRequestFrameSize * 4; + i * sc->chain_frame_size; mpr_free_chain(sc, chain); sc->chain_free_lowwater++; } @@ -2169,7 +2192,7 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) MPI2_REQUEST_HEADER *req; MPI25_IEEE_SGE_CHAIN64 *ieee_sgc; struct mpr_chain *chain; - int space, sgc_size, current_segs, rem_segs, segs_per_frame; + int sgc_size, current_segs, rem_segs, segs_per_frame; uint8_t next_chain_offset = 0; /* @@ -2191,8 +2214,6 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) if (chain == NULL) return (ENOBUFS); - space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4; - /* * Note: a double-linked list is used to make it easier to walk for * debugging. @@ -2218,13 +2239,14 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) */ current_segs = (cm->cm_sglsize / sgc_size) - 1; rem_segs = segsleft - current_segs; - segs_per_frame = space / sgc_size; + segs_per_frame = sc->chain_frame_size / sgc_size; if (rem_segs > segs_per_frame) { next_chain_offset = segs_per_frame - 1; } } ieee_sgc = &((MPI25_SGE_IO_UNION *)cm->cm_sge)->IeeeChain; - ieee_sgc->Length = next_chain_offset ? htole32((uint32_t)space) : + ieee_sgc->Length = next_chain_offset ? + htole32((uint32_t)sc->chain_frame_size) : htole32((uint32_t)rem_segs * (uint32_t)sgc_size); ieee_sgc->NextChainOffset = next_chain_offset; ieee_sgc->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | @@ -2233,10 +2255,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft) ieee_sgc->Address.High = htole32(chain->chain_busaddr >> 32); cm->cm_sge = &((MPI25_SGE_IO_UNION *)chain->chain)->IeeeSimple; req = (MPI2_REQUEST_HEADER *)cm->cm_req; - req->ChainOffset = ((sc->facts->IOCRequestFrameSize * 4) - - sgc_size) >> 4; + req->ChainOffset = (sc->chain_frame_size - sgc_size) >> 4; - cm->cm_sglsize = space; + cm->cm_sglsize = sc->chain_frame_size; return (0); } diff --git a/sys/dev/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index 7430eac..17f3f3e 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -110,6 +110,18 @@ struct mpr_ident { 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" }, { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_1, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3316_1" }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_2, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3316_2" }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_1, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3324_1" }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_2, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3324_2" }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3216" }, + { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224, + 0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3224" }, { 0, 0, 0, 0, 0, NULL } }; diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 358e1fb..a7b74e3 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -704,6 +704,7 @@ mprsas_register_events(struct mpr_softc *sc) setbit(events, MPI2_EVENT_IR_PHYSICAL_DISK); setbit(events, MPI2_EVENT_IR_OPERATION_STATUS); setbit(events, MPI2_EVENT_TEMP_THRESHOLD); + setbit(events, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); mpr_register_events(sc, events, mprsas_evt_handler, NULL, &sc->sassc->mprsas_eh); @@ -2048,6 +2049,9 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb_scsiio *csio, case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: desc_ioc_state = "eedp app tag error"; break; + case MPI2_IOCSTATUS_INSUFFICIENT_POWER: + desc_ioc_state = "insufficient power"; + break; default: desc_ioc_state = "unknown"; break; diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 3d6f9f2..4ede5f7 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -645,6 +645,23 @@ skip_fp_send: } break; } + case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: + { + pMpi26EventDataActiveCableExcept_t ace_event_data; + ace_event_data = + (pMpi26EventDataActiveCableExcept_t)fw_event->event_data; + + if (ace_event_data->ReasonCode == + MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) { + mpr_printf(sc, "Currently an active cable with " + "ReceptacleID %d cannot be powered and device " + "connected to this active cable will not be seen. " + "This active cable requires %d mW of power.\n", + ace_event_data->ReceptacleID, + ace_event_data->ActiveCablePowerRequirement); + } + break; + } case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: default: diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 750ed0d..8b7426d 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -46,6 +46,8 @@ #define MPR_SGE64_SIZE 12 #define MPR_SGE32_SIZE 8 #define MPR_SGC_SIZE 8 +#define MPR_DEFAULT_CHAIN_SEG_SIZE 8 +#define MPR_MAX_CHAIN_ELEMENT_SIZE 16 #define MPR_FUNCTRACE(sc) \ mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) @@ -263,6 +265,8 @@ struct mpr_softc { int chain_free; int max_chains; int chain_free_lowwater; + uint32_t chain_frame_size; + uint16_t chain_seg_size; u_int enable_ssu; int spinup_wait_time; uint64_t chain_alloc_fail; -- cgit v1.1 From 24842df2a6a2c71b9fd8763a7e9feae95fa9cd80 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:21:14 +0000 Subject: No log bit in IOCStatus and endian-safe changes. Use MPI2_IOCSTATUS_MASK when checking IOCStatus to mask off the log bit, and make a few more things endian-safe. Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6097 --- sys/dev/mpr/mpr.c | 5 +++-- sys/dev/mpr/mpr_sas.c | 16 ++++++++++------ sys/dev/mpr/mpr_user.c | 15 +++++++++------ 3 files changed, 22 insertions(+), 14 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 7d6bba1..b2342eb 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1942,9 +1942,10 @@ mpr_intr_locked(void *data) */ rel_rep = (MPI2_DIAG_RELEASE_REPLY *)reply; - if (le16toh(rel_rep->IOCStatus) == + if ((le16toh(rel_rep->IOCStatus) & + MPI2_IOCSTATUS_MASK) == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) - { + { pBuffer = &sc->fw_diag_buffer_list[ rel_rep->BufferType]; diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index a7b74e3..b51f7f3 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -372,15 +372,16 @@ mprsas_remove_volume(struct mpr_softc *sc, struct mpr_command *tm) return; } - if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { + if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != + MPI2_IOCSTATUS_SUCCESS) { mpr_dprint(sc, MPR_FAULT, "IOCStatus = 0x%x while resetting " - "device 0x%x\n", reply->IOCStatus, handle); + "device 0x%x\n", le16toh(reply->IOCStatus), handle); mprsas_free_tm(sc, tm); return; } mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", - reply->TerminationCount); + le32toh(reply->TerminationCount)); mpr_free_reply(sc, tm->cm_reply_data); tm->cm_reply = NULL; /* Ensures the reply won't get re-freed */ @@ -393,7 +394,8 @@ mprsas_remove_volume(struct mpr_softc *sc, struct mpr_command *tm) * this target id if possible, and so we can assign the same target id * to this device if it comes back in the future. */ - if (reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) { + if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) == + MPI2_IOCSTATUS_SUCCESS) { targ = tm->cm_targ; targ->handle = 0x0; targ->encl_handle = 0x0; @@ -573,7 +575,8 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) return; } - if (le16toh(reply->IOCStatus) != MPI2_IOCSTATUS_SUCCESS) { + if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != + MPI2_IOCSTATUS_SUCCESS) { mpr_dprint(sc, MPR_FAULT, "IOCStatus = 0x%x while resetting " "device 0x%x\n", le16toh(reply->IOCStatus), handle); mprsas_free_tm(sc, tm); @@ -658,7 +661,8 @@ mprsas_remove_complete(struct mpr_softc *sc, struct mpr_command *tm) * this target id if possible, and so we can assign the same target id * to this device if it comes back in the future. */ - if (le16toh(reply->IOCStatus) == MPI2_IOCSTATUS_SUCCESS) { + if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) == + MPI2_IOCSTATUS_SUCCESS) { targ = tm->cm_targ; targ->handle = 0x0; targ->encl_handle = 0x0; diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 8ae8713..db8de93 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -1255,12 +1255,14 @@ mpr_post_fw_diag_buffer(struct mpr_softc *sc, * Process POST reply. */ reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply; - if (reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) { + if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != + MPI2_IOCSTATUS_SUCCESS) { status = MPR_DIAG_FAILURE; mpr_dprint(sc, MPR_FAULT, "%s: post of FW Diag Buffer failed " "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and " - "TransferLength = 0x%x\n", __func__, reply->IOCStatus, - reply->IOCLogInfo, reply->TransferLength); + "TransferLength = 0x%x\n", __func__, + le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo), + le32toh(reply->TransferLength)); goto done; } @@ -1339,12 +1341,13 @@ mpr_release_fw_diag_buffer(struct mpr_softc *sc, * Process RELEASE reply. */ reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply; - if ((reply->IOCStatus != MPI2_IOCSTATUS_SUCCESS) || - pBuffer->owned_by_firmware) { + if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != + MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) { status = MPR_DIAG_FAILURE; mpr_dprint(sc, MPR_FAULT, "%s: release of FW Diag Buffer " "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n", - __func__, reply->IOCStatus, reply->IOCLogInfo); + __func__, le16toh(reply->IOCStatus), + le32toh(reply->IOCLogInfo)); goto done; } -- cgit v1.1 From 27c56699350423b315490d40f6b1c5d362ab41cd Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:24:16 +0000 Subject: Change logging level for a debug string to use MPR_LOG instead of MPR_INFO. Approved by: ken, scottl, ambrisko MFC after: 1 week --- sys/dev/mpr/mpr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index b2342eb..5ae9f4c 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1791,7 +1791,7 @@ mpr_sas_log_info(struct mpr_softc *sc , u32 log_info) break; } - mpr_dprint(sc, MPR_INFO, "log_info(0x%08x): originator(%s), " + mpr_dprint(sc, MPR_LOG, "log_info(0x%08x): originator(%s), " "code(0x%02x), sub_code(0x%04x)\n", log_info, originator_str, sas_loginfo.dw.code, sas_loginfo.dw.subcode); } -- cgit v1.1 From 6d54cc00246d649b2810e8c4e47fd9601a404fef Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:26:34 +0000 Subject: Fix possible use of invalid pointer. It was possible to use an invalid pointer to get the target ID value. To fix this, initialize a local Target ID variable to an invalid value and change that variable to a valid value only if the pointer to the Target ID is not NULL. Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6100 --- sys/dev/mpr/mpr_sas.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index b51f7f3..6d16b0f 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -243,6 +243,8 @@ mprsas_alloc_tm(struct mpr_softc *sc) void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) { + int target_id = 0xFFFFFFFF; + MPR_FUNCTRACE(sc); if (tm == NULL) return; @@ -254,10 +256,11 @@ mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm) */ if (tm->cm_targ != NULL) { tm->cm_targ->flags &= ~MPRSAS_TARGET_INRESET; + target_id = tm->cm_targ->tid; } if (tm->cm_ccb) { mpr_dprint(sc, MPR_INFO, "Unfreezing devq for target ID %d\n", - tm->cm_targ->tid); + target_id); xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE); xpt_free_path(tm->cm_ccb->ccb_h.path); xpt_free_ccb(tm->cm_ccb); -- cgit v1.1 From 9e229a4fb891f807c37c26e75e22f00668608556 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:29:25 +0000 Subject: No need to set the MPRSAS_SHUTDOWN flag because it's never used. Approved by: ken, scottl, ambrisko MFC after: 1 week --- sys/dev/mpr/mpr_sas.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 6d16b0f..addbfb8 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -931,7 +931,6 @@ mpr_detach_sas(struct mpr_softc *sc) cam_sim_free(sassc->sim, FALSE); } - sassc->flags |= MPRSAS_SHUTDOWN; mpr_unlock(sc); if (sassc->devq != NULL) -- cgit v1.1 From c4c7b1c9922c950d5121df85298d0a98518effe7 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:31:43 +0000 Subject: Use callout_reset_sbt() instead of callout_reset() if FreeBSD ver is >= 1000029 Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6101 --- sys/dev/mpr/mpr_sas.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sys') diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index addbfb8..c1cc394 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -1929,8 +1929,13 @@ mprsas_action_scsiio(struct mprsas_softc *sassc, union ccb *ccb) cm->cm_desc.SCSIIO.DevHandle = htole16(targ->handle); } +#if __FreeBSD_version >= 1000029 callout_reset_sbt(&cm->cm_callout, SBT_1MS * ccb->ccb_h.timeout, 0, mprsas_scsiio_timeout, cm, 0); +#else //__FreeBSD_version < 1000029 + callout_reset(&cm->cm_callout, (ccb->ccb_h.timeout * hz) / 1000, + mprsas_scsiio_timeout, cm); +#endif //__FreeBSD_version >= 1000029 targ->issued++; targ->outstanding++; -- cgit v1.1 From 5ad95da0d51e2be4ff785c5cea49df99784c2025 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:34:06 +0000 Subject: done_ccb pointer can be used if it is NULL. To prevent this, move check for done_ccb == NULL to before done_ccb is used in mprsas_stop_unit_done(). Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6099 --- sys/dev/mpr/mpr_sas_lsi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 4ede5f7..640338a 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -1272,15 +1272,15 @@ mprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb) struct mprsas_softc *sassc; char path_str[64]; + if (done_ccb == NULL) + return; + sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str)); mpr_dprint(sassc->sc, MPR_INFO, "Completing stop unit for %s\n", path_str); - if (done_ccb == NULL) - return; - /* * Nothing more to do except free the CCB and path. If the command * timed out, an abort reset, then target reset will be issued during -- cgit v1.1 From c299ac9344469043d58fff9806733e0c52ce17c7 Mon Sep 17 00:00:00 2001 From: tuexen Date: Mon, 9 May 2016 16:35:05 +0000 Subject: Cleanup a comment. MFC after: 1 week --- sys/netinet/sctp_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sys') diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 2d29fcb..ae6ec49 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -1076,8 +1076,8 @@ sctp_cookie_timer(struct sctp_inpcb *inp, return (1); } /* - * cleared threshold management now lets backoff the address & select - * an alternate + * Cleared threshold management, now lets backoff the address and + * select an alternate */ stcb->asoc.dropped_special_cnt = 0; sctp_backoff_on_timeout(stcb, cookie->whoTo, 1, 0, 0); @@ -1122,8 +1122,8 @@ sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, return (1); } /* - * cleared threshold management now lets backoff the address & select - * an alternate + * Cleared threshold management, now lets backoff the address and + * select an alternate */ sctp_backoff_on_timeout(stcb, strrst->whoTo, 1, 0, 0); alt = sctp_find_alternate_net(stcb, strrst->whoTo, 0); -- cgit v1.1 From 0a5339fd05de2ba1f3dccb404d326022b4a7f781 Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:36:40 +0000 Subject: Disks can go missing until a reboot is done in some cases. This is due to the DevHandle not being released, which causes the Firmware to not allow that disk to be re-added. Reviewed by: ken, scottl, ambrisko, asomers Approved by: ken, scottl, ambrisko MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D6102 --- sys/dev/mpr/mpr_sas.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'sys') diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index c1cc394..45c0bbd 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -377,10 +377,8 @@ mprsas_remove_volume(struct mpr_softc *sc, struct mpr_command *tm) if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mpr_dprint(sc, MPR_FAULT, "IOCStatus = 0x%x while resetting " + mpr_dprint(sc, MPR_ERROR, "IOCStatus = 0x%x while resetting " "device 0x%x\n", le16toh(reply->IOCStatus), handle); - mprsas_free_tm(sc, tm); - return; } mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", @@ -566,8 +564,6 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) mpr_dprint(sc, MPR_ERROR, "%s: cm_flags = %#x for remove of " "handle %#04x! This should not happen!\n", __func__, tm->cm_flags, handle); - mprsas_free_tm(sc, tm); - return; } if (reply == NULL) { @@ -580,10 +576,8 @@ mprsas_remove_device(struct mpr_softc *sc, struct mpr_command *tm) if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { - mpr_dprint(sc, MPR_FAULT, "IOCStatus = 0x%x while resetting " + mpr_dprint(sc, MPR_ERROR, "IOCStatus = 0x%x while resetting " "device 0x%x\n", le16toh(reply->IOCStatus), handle); - mprsas_free_tm(sc, tm); - return; } mpr_dprint(sc, MPR_XINFO, "Reset aborted %u commands\n", -- cgit v1.1 From b58e11fc4e5f2c5674a06845d9bd6ea52bbbe13b Mon Sep 17 00:00:00 2001 From: slm Date: Mon, 9 May 2016 16:38:51 +0000 Subject: Bump version of mpr driver to 13.00.00.00-fbsd Approved by: ken, scottl, ambrisko MFC after: 1 week --- sys/dev/mpr/mprvar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys') diff --git a/sys/dev/mpr/mprvar.h b/sys/dev/mpr/mprvar.h index 8b7426d..dd4b40f 100644 --- a/sys/dev/mpr/mprvar.h +++ b/sys/dev/mpr/mprvar.h @@ -33,7 +33,7 @@ #ifndef _MPRVAR_H #define _MPRVAR_H -#define MPR_DRIVER_VERSION "09.255.01.00-fbsd" +#define MPR_DRIVER_VERSION "13.00.00.00-fbsd" #define MPR_DB_MAX_WAIT 2500 -- cgit v1.1 From efb4c021b99888e7ead6bac8a2c4adb3aef8ad02 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 9 May 2016 17:19:17 +0000 Subject: [bhnd] fix incorrect typing. Pointed out by: emaste --- sys/dev/bhnd/bhndb/bhndb_pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/bhnd/bhndb/bhndb_pci.c b/sys/dev/bhnd/bhndb/bhndb_pci.c index 33da141..baf28473 100644 --- a/sys/dev/bhnd/bhndb/bhndb_pci.c +++ b/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -73,7 +73,7 @@ static void bhndb_init_sromless_pci_config( struct bhndb_pci_softc *sc); static bus_addr_t bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc); -static size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc); +static bus_size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc); /** * Default bhndb_pci implementation of device_probe(). @@ -167,7 +167,8 @@ bhndb_pci_init_full_config(device_t dev, device_t child, const char *dname; if (bootverbose) { - device_printf(dev, "found SPROM (%zu bytes)\n", nv_sz); + device_printf(dev, "found SPROM (%u bytes)\n", + (unsigned int) nv_sz); } /* Add sprom device */ -- cgit v1.1 From 7033f894b183cfe6ba99547afa6929182c66ff95 Mon Sep 17 00:00:00 2001 From: hiren Date: Mon, 9 May 2016 19:19:03 +0000 Subject: Add an option to use rfc6675 based pipe/inflight bytes calculation in htcp. Submitted by: Kevin Bowling MFC after: 1 week Sponsored by: Limelight Networks --- sys/netinet/cc/cc_htcp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'sys') diff --git a/sys/netinet/cc/cc_htcp.c b/sys/netinet/cc/cc_htcp.c index 5cd84f3..ada0a43 100644 --- a/sys/netinet/cc/cc_htcp.c +++ b/sys/netinet/cc/cc_htcp.c @@ -346,8 +346,10 @@ htcp_mod_init(void) static void htcp_post_recovery(struct cc_var *ccv) { + int pipe; struct htcp *htcp_data; + pipe = 0; htcp_data = ccv->cc_data; if (IN_FASTRECOVERY(CCV(ccv, t_flags))) { @@ -358,10 +360,13 @@ htcp_post_recovery(struct cc_var *ccv) * * XXXLAS: Find a way to do this without needing curack */ - if (SEQ_GT(ccv->curack + CCV(ccv, snd_ssthresh), - CCV(ccv, snd_max))) - CCV(ccv, snd_cwnd) = CCV(ccv, snd_max) - ccv->curack + - CCV(ccv, t_maxseg); + if (V_tcp_do_rfc6675_pipe) + pipe = tcp_compute_pipe(ccv->ccvc.tcp); + else + pipe = CCV(ccv, snd_max) - ccv->curack; + + if (pipe < CCV(ccv, snd_ssthresh)) + CCV(ccv, snd_cwnd) = pipe + CCV(ccv, t_maxseg); else CCV(ccv, snd_cwnd) = max(1, ((htcp_data->beta * htcp_data->prev_cwnd / CCV(ccv, t_maxseg)) -- cgit v1.1 From b76fae1c12ce383a7cde8358e5e5d3af1448a782 Mon Sep 17 00:00:00 2001 From: pfg Date: Mon, 9 May 2016 19:28:22 +0000 Subject: otus: minor catchup with OpenBSD. Bump the OpenBSD revision tag since the corresponding changes don't apply to us and drop an unnecessary header. No functional change. --- sys/dev/otus/if_otus.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sys') diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c index 7b069a6..f08332c 100644 --- a/sys/dev/otus/if_otus.c +++ b/sys/dev/otus/if_otus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_otus.c,v 1.46 2015/03/14 03:38:49 jsg Exp $ */ +/* $OpenBSD: if_otus.c,v 1.49 2015/11/24 13:33:18 mpi Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include -- cgit v1.1 From 393a1cbb3fad603649ae63c26331b6ce67a86957 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 9 May 2016 20:01:34 +0000 Subject: Forward declare 'struct cpl_set_tcb_rpl' before including t4_tom.h. Other structures needed by prototypes in t4_tom.h are explicitly declared in this file, so adding the prototype here seems most consistent with existing code. --- sys/dev/cxgbe/iw_cxgbe/cm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sys') diff --git a/sys/dev/cxgbe/iw_cxgbe/cm.c b/sys/dev/cxgbe/iw_cxgbe/cm.c index c2b72fa..3759140 100644 --- a/sys/dev/cxgbe/iw_cxgbe/cm.c +++ b/sys/dev/cxgbe/iw_cxgbe/cm.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); struct sge_iq; struct rss_header; +struct cpl_set_tcb_rpl; #include #include "offload.h" #include "tom/t4_tom.h" -- cgit v1.1