diff --git a/NEWS b/NEWS
index 2558a95e1c52b0bc33e9261f290f1a0a839e3e1e..512cf9c8f05241ecb9d0dfff5c2210ea6883446d 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,7 @@ documents those changes that are of interest to users and administrators.
  -- Prevent job stuck in configuring state if slurmctld daemon restarted while
     PrologSlurmctld is running. Also re-issue burst_buffer/pre-load operation
     as needed.
+ -- Correct task affinity support for FreeBSD.
 
 * Changes in Slurm 16.05.0
 ==========================
diff --git a/doc/man/man5/slurm.conf.5 b/doc/man/man5/slurm.conf.5
index d2b10983525173ee26cf09bf73075f9c0b788563..9179e308cb408c62a64ffd60947aa09f539550dd 100644
--- a/doc/man/man5/slurm.conf.5
+++ b/doc/man/man5/slurm.conf.5
@@ -1,4 +1,4 @@
-.TH "slurm.conf" "5" "Slurm Configuration File" "April 2016" "Slurm Configuration File"
+.TH "slurm.conf" "5" "Slurm Configuration File" "June 2016" "Slurm Configuration File"
 
 .SH "NAME"
 slurm.conf \- Slurm configuration file
@@ -3355,6 +3355,8 @@ exclusive and since they decrease scheduling flexibility are not generally
 recommended (select no more than one of them).
 \fBCpusets\fR and \fBSched\fR
 are mutually exclusive (select only one of them).
+All TaskPluginParam options are supported on FreeBSD except \fBCpusets\fR.
+The \fBSched\fR option uses cpuset_setaffinity() on FreeBSD, not sched_setaffinity().
 
 .RS
 .TP 10
diff --git a/src/plugins/task/affinity/affinity.c b/src/plugins/task/affinity/affinity.c
index d4f4a558c0d958fd09bcb07cb64918a3f286dc34..e1190a93f34d72c0d09c1d1004e7627081958109 100644
--- a/src/plugins/task/affinity/affinity.c
+++ b/src/plugins/task/affinity/affinity.c
@@ -290,12 +290,34 @@ int get_cpuset(cpu_set_t *mask, stepd_step_rec_t *job)
 	return false;
 }
 
+/* For sysctl() functions */
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
+#define	BUFFLEN	127
+
 /* Return true if Power7 processor */
 static bool _is_power_cpu(void)
 {
 	if (is_power == -1) {
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+
+		char    buffer[BUFFLEN+1];
+		size_t  len = BUFFLEN;
+
+		if ( sysctlbyname("hw.model", buffer, &len, NULL, 0) == 0 )
+		    is_power = ( strstr(buffer, "POWER7") != NULL );
+		else {
+		    error("_get_is_power: sysctl could not retrieve hw.model");
+		    return false;
+		}
+
+#elif defined(__linux__)
+
 		FILE *cpu_info_file;
-		char buffer[128];
+		char buffer[BUFFLEN+1];
 		char* _cpuinfo_path = "/proc/cpuinfo";
 		cpu_info_file = fopen(_cpuinfo_path, "r");
 		if (cpu_info_file == NULL) {
@@ -312,6 +334,14 @@ static bool _is_power_cpu(void)
 			}
 		}
 		fclose(cpu_info_file);
+
+#else
+
+/* Assuming other platforms don't support sysctlbyname() or /proc/cpuinfo */
+#warning	"Power7 check not implemented for this platform."
+	is_power = 0;
+
+#endif
 	}
 
 	if (is_power == 1)
@@ -335,7 +365,11 @@ void reset_cpuset(cpu_set_t *new_mask, cpu_set_t *cur_mask)
 	if (slurm_getaffinity(1, sizeof(full_mask), &full_mask)) {
 		/* Try to get full CPU mask from process init */
 		CPU_ZERO(&full_mask);
+#ifdef __FreeBSD__
+		CPU_OR(&full_mask, cur_mask);
+#else
 		CPU_OR(&full_mask, &full_mask, cur_mask);
+#endif
 	}
 	CPU_ZERO(&newer_mask);
 	for (cur_offset = 0; cur_offset < CPU_SETSIZE; cur_offset++) {
@@ -360,7 +394,10 @@ int slurm_setaffinity(pid_t pid, size_t size, const cpu_set_t *mask)
 	int rval;
 	char mstr[1 + CPU_SETSIZE / 4];
 
-#ifdef SCHED_GETAFFINITY_THREE_ARGS
+#ifdef __FreeBSD__
+        rval = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
+				pid, size, mask);
+#elif defined(SCHED_GETAFFINITY_THREE_ARGS)
 	rval = sched_setaffinity(pid, size, mask);
 #else
 	rval = sched_setaffinity(pid, mask);
@@ -378,7 +415,19 @@ int slurm_getaffinity(pid_t pid, size_t size, cpu_set_t *mask)
 	char mstr[1 + CPU_SETSIZE / 4];
 
 	CPU_ZERO(mask);
-#ifdef SCHED_GETAFFINITY_THREE_ARGS
+
+	/*
+	 * The FreeBSD cpuset API is a superset of the Linux API.
+	 * In addition to PIDs, it supports threads, interrupts,
+	 * jails, and potentially other objects.  The first two arguments
+	 * to cpuset_*etaffinity() below indicate that the third argument
+	 * is a PID.  -1 indicates the PID of the calling process.
+	 * Linux sched_*etaffinity() uses 0 for this.
+	 */
+#ifdef __FreeBSD__
+        rval = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
+				pid, size, mask);
+#elif SCHED_GETAFFINITY_THREE_ARGS
 	rval = sched_getaffinity(pid, size, mask);
 #else
 	rval = sched_getaffinity(pid, mask);
diff --git a/src/plugins/task/affinity/affinity.h b/src/plugins/task/affinity/affinity.h
index 2c05ffd7422b1d2e73ab56a570c445b350a24337..afd2ce627c9fac8845b6380fa3177038fc83b5ad 100644
--- a/src/plugins/task/affinity/affinity.h
+++ b/src/plugins/task/affinity/affinity.h
@@ -33,7 +33,9 @@
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 \*****************************************************************************/
 
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
 
 #ifndef _GNU_SOURCE
 #  define _GNU_SOURCE
@@ -47,6 +49,17 @@
 #  include <numa.h>
 #endif
 
+/*
+ * FreeBSD and Linux affinity functions have a slightly different interface
+ * and are defined in different headers.  See platform-dependencies in
+ * affinity.c.
+ */
+#ifdef __FreeBSD__
+#  include <sys/param.h>
+#  include <sys/cpuset.h>
+   typedef cpuset_t cpu_set_t;
+#endif
+
 #ifdef HAVE_SYS_PRCTL_H
 #  include <sys/prctl.h>
 #endif