Kernel – 4.10-rc3 Released..

Kernel 4.10-rc3 is out, and brief details of changes since -rc2 are here:  http://lkml.iu.edu/hypermail/linux/kernel/1701.1/00183.html

Tested patched VMware (12.5.2) and patched NVIDIA (375.26) and both compile OK..   Same results as with -rc2..

Robert Gadsdon.    January 8, 2017.

Kernel – 4.9.1 Released, Still Getting ‘Too Many CPUs’ Warnings, on i7..

Updated the main (Intel i7) system to kernel 4.9.1, but still getting ACPI/CPU warnings on boot, which started appearing with 4.9.0:

................
[ 0.000000] Linux version 4.9.1 (root@rglinux-i7) (gcc version 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC) ) #1 SMP Fri Jan 6 11:07:16 PST 2017
............... 
[ 0.000000] ACPI: PM-Timer IO Port: 0x408
[ 0.000000] ACPI: Local APIC address 0xfee00000
[ 0.000000] APIC: NR_CPUS/possible_cpus limit of 4 reached. Processor 4/0x1 ignored.
[ 0.000000] APIC: NR_CPUS/possible_cpus limit of 4 reached. Processor 5/0x3 ignored.
[ 0.000000] APIC: NR_CPUS/possible_cpus limit of 4 reached. Processor 6/0x5 ignored.
[ 0.000000] APIC: NR_CPUS/possible_cpus limit of 4 reached. Processor 7/0x7 ignored.
[ 0.000000] ACPI: LAPIC_NMI (acpi_id[0xff] high edge lint[0x1])
[ 0.000000] IOAPIC[0]: apic_id 2, version 32, address 0xfec00000, GSI 0-23
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
[ 0.000000] ACPI: IRQ0 used by override.
[ 0.000000] ACPI: IRQ9 used by override.
[ 0.000000] Using ACPI (MADT) for SMP configuration information
[ 0.000000] ACPI: HPET id: 0x8086a701 base: 0xfed00000
[ 0.000000] smpboot: 8 Processors exceeds NR_CPUS limit of 4
[ 0.000000] smpboot: Allowing 4 CPUs, 0 hotplug CPUs
.................

This only occurs on my i7 system, and older Core-Duo systems are OK.    The system boots successfully, and runs without any problems..

Patched VMware 12.5.2, and NVIDIA 375.26, are both OK..

Robert Gadsdon.   January 6, 2017.

NVIDIA – Now, a Fix for 4.10-rc Kernels..

Thanks to Tomas Pruzina, there is a patch for NVIDIA driver 375.26 with 4.10-rc kernels.   Details, and the link, are here: https://devtalk.nvidia.com/default/topic/981993/linux/-patches-included-4-10-kernel-staging-/

Easiest way to get the patch is to select ‘Raw’ and just cut/paste the text..

I have tested this on kernel 4.10-rc2, and it compiles successfully (with a few warnings):

................................
 /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm/uvm8.c: In function ‘uvm_vm_fault_sigbus’:
 /usr/src/linux-4.10-rc2/include/linux/kern_levels.h:4:18: warning: format ‘%p’ expects argument of type ‘void *’, but argument 6 has type ‘long unsigned int’ [-Wformat=]
 #define KERN_SOH "\001" /* ASCII Start Of Header */
 ^
 /usr/src/linux-4.10-rc2/include/linux/printk.h:413:10: note: in definition of macro ‘printk_ratelimited’
 printk(fmt, ##__VA_ARGS__); \
 ^~~
 /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm/uvm_common.h:85:13: note: in expansion of macro ‘UVM_PRINT_FUNC_PREFIX’
 UVM_PRINT_FUNC_PREFIX(func, prefix, fmt, ##__VA_ARGS__); \
 ^~~~~~~~~~~~~~~~~~~~~
 /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm/uvm_common.h:99:5: note: in expansion of macro ‘UVM_PRINT_FUNC_PREFIX_CHECK’
 UVM_PRINT_FUNC_PREFIX_CHECK(printk_ratelimited, KERN_DEBUG NVIDIA_UVM_PRETTY_PRINTING_PREFIX, " " fmt, ##__VA_ARGS__)
 ^~~~~~~~~~~~~~~~~~~~~~~~~~~
 /usr/src/linux-4.10-rc2/include/linux/kern_levels.h:14:20: note: in expansion of macro ‘KERN_SOH’
 #define KERN_DEBUG KERN_SOH "7" /* debug-level messages */
 ^~~~~~~~
 /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm/uvm_common.h:99:53: note: in expansion of macro ‘KERN_DEBUG’
 UVM_PRINT_FUNC_PREFIX_CHECK(printk_ratelimited, KERN_DEBUG NVIDIA_UVM_PRETTY_PRINTING_PREFIX, " " fmt, ##__VA_ARGS__)
 ^~~~~~~~~~
 /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm/uvm8.c:104:5: note: in expansion of macro ‘UVM_DBG_PRINT_RL’
 UVM_DBG_PRINT_RL("Fault to address 0x%p in disabled vma\n", vmf->address);
 ^~~~~~~~~~~~~~~~
 .................................
 Building modules, stage 2.
 MODPOST 4 modules
 CC /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-drm.mod.o
 LD [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-drm.ko
 CC /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-modeset.mod.o
 LD [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-modeset.ko
 CC /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm.mod.o
 LD [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia-uvm.ko
 CC /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia.mod.o
 LD [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26.patched/kernel/nvidia.ko
 make[2]: Leaving directory '/usr/src/linux-4.10-rc2'
 make[1]: Leaving directory '/usr/src/linux-4.10-rc2'

As is mentioned, the CONFIG_CPU_HOTPLUG code is simply ‘bypassed’, as this is very rarely needed by desktop/workstation users..

The patch is for 4.10-based kernels only, and is not backwards-compatible, in its current state..

Robert Gadsdon   January 2, 2017.

Kernel – 4.10-rc2 Out – OK With aarch64, now..

Kernel 4.10-rc2 has been released, and it has a very small number of changes from -rc1:  http://lkml.iu.edu/hypermail/linux/kernel/1701.0/00069.html

I suspect that the major reason for this release is to fix the embarrassing compile fail with ARM64/aarch64, and it does compile OK now (tested on the Odroid C2)..

Robert Gadsdon.   January 2, 2017.

Android – New Year, New Fork?

Now that Cyanogenmod has summarily shut down, there is a planned new forked version, at http://lineageos.org/

Remains to be seen whether this will flourish, and whether it will survive any potential legal shenanigans, but at least it shows one of the core benefits of Open-Source code..!

Robert Gadsdon.   December 27, 2016.

ARM64 – Kernel 4.10-rc1 Compile Errors – The Official Fix..

There is now an ‘official’ fix for the 4.10-rc1 compile failure with ARM64/aarch64, from Al Viro, and the patch itself is available here:

https://git.kernel.org/cgit/linux/kernel/git/viro/vfs.git/commit/?h=arm64-fix&id=b4b8664d291ac1998e0f0bcdc96b6397f0fe68b3

I have applied this to kernel 4.10-rc1 on the Odroid C2, and the kernel compiles successfully..

Robert Gadsdon.   December 27, 2016.

ARM64 – Odroid C2 – Boots with Kernel 4.10-rc1 – Ethernet OK? – Not yet..

After applying the aarch64 compile fix (see previous article) I was able to compile Kernel 4.10-rc1 on the Odroid C2, and it boots OK (headless..), and the Ethernet link stays up, but still needs the TX patch..   (updated, as the link did still hang – eventually..  RG)..

...........
meson8b-dwmac c9410000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
Link is Up - 1000/Full
............
Fedora 25 (Workstation Edition)
Kernel 4.10.0-rc1 on an aarch64 (ttyAML0)
....................
# uname -a
Linux rgc2 4.10.0-rc1 #2 SMP Mon Dec 26 15:38:01 EST 2016 aarch64 aarch64 aarch64 GNU/Linux

Hopefully there will be a complete mainline version of U-Boot for the C2, soon..

Robert Gadsdon.   December 26, 2016.

ARM64 – Catastrophic Compile Errors with 4.10-rc1 – and a Fix..

Tried compiling Kernel 4.10-rc1 for aarch64, and got – literally – hundreds of errors:

......
./include/linux/sched.h:3299: Error: unknown mnemonic `return' -- `return test_ti_thread_flag(task_thread_info(tsk),flag)'
./include/linux/sched.h:3300: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3302: Error: unknown mnemonic `static' -- `static inline void set_tsk_need_resched(struct task_struct*tsk)'
./include/linux/sched.h:3303: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3304: Error: unknown mnemonic `set_tsk_thread_flag' -- `set_tsk_thread_flag(tsk,1)'
./include/linux/sched.h:3305: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3307: Error: unknown mnemonic `static' -- `static inline void clear_tsk_need_resched(struct task_struct*tsk)'
./include/linux/sched.h:3308: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3309: Error: unknown mnemonic `clear_tsk_thread_flag' -- `clear_tsk_thread_flag(tsk,1)'
./include/linux/sched.h:3310: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3312: Error: unknown mnemonic `static' -- `static inline int test_tsk_need_resched(struct task_struct*tsk)'
./include/linux/sched.h:3313: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3314: Error: unknown mnemonic `return' -- `return unlikely(test_tsk_thread_flag(tsk,1))'
./include/linux/sched.h:3315: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3317: Error: unknown mnemonic `static' -- `static inline int restart_syscall(void)'
./include/linux/sched.h:3318: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3319: Error: unknown mnemonic `set_tsk_thread_flag' -- `set_tsk_thread_flag(current, 0)'
./include/linux/sched.h:3320: Error: unknown mnemonic `return' -- `return -513'
./include/linux/sched.h:3321: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3323: Error: unknown mnemonic `static' -- `static inline int signal_pending(struct task_struct*p)'
./include/linux/sched.h:3324: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3325: Error: unknown mnemonic `return' -- `return unlikely(test_tsk_thread_flag(p,0))'
./include/linux/sched.h:3326: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3328: Error: unknown mnemonic `static' -- `static inline int __fatal_signal_pending(struct task_struct*p)'
./include/linux/sched.h:3329: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3330: Error: unknown mnemonic `return' -- `return unlikely(sigismember(&p->pending.signal,9))'
./include/linux/sched.h:3331: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3333: Error: unknown mnemonic `static' -- `static inline int fatal_signal_pending(struct task_struct*p)'
./include/linux/sched.h:3334: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3335: Error: unknown mnemonic `return' -- `return signal_pending(p)&&__fatal_signal_pending(p)'
./include/linux/sched.h:3336: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3338: Error: unknown mnemonic `static' -- `static inline int signal_pending_state(long state,struct task_struct*p)'
./include/linux/sched.h:3339: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3340: Error: unknown mnemonic `if' -- `if (!(state&(1|128)))'
./include/linux/sched.h:3341: Error: unknown mnemonic `return' -- `return 0'
./include/linux/sched.h:3342: Error: unknown mnemonic `if' -- `if (!signal_pending(p))'
./include/linux/sched.h:3343: Error: unknown mnemonic `return' -- `return 0'
./include/linux/sched.h:3345: Error: unknown mnemonic `return' -- `return (state&1)||__fatal_signal_pending(p)'
./include/linux/sched.h:3346: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3358: Error: unknown mnemonic `static' -- `static inline int _cond_resched(void){return 0'
./include/linux/sched.h:3358: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3366: Error: unknown mnemonic `extern' -- `extern int __cond_resched_lock(spinlock_t*lock)'
./include/linux/sched.h:3373: Error: unknown mnemonic `extern' -- `extern int __cond_resched_softirq(void)'
./include/linux/sched.h:3380: Error: unknown mnemonic `static' -- `static inline void cond_resched_rcu(void)'
./include/linux/sched.h:3381: Error: junk at end of line, first unrecognized character is `{'
./include/linux/sched.h:3387: Error: junk at end of line, first unrecognized character is `}'
./include/linux/sched.h:3389: Error: unknown mnemonic `static' -- `static inline unsigned long get_preempt_disable_ip(struct task_struct*p)'
- and many more..

The problems only occurs with ARM64/aarch64.   I have tested ARMv7 kernel compiles, and these appear to be OK (and x86 is OK too..)

There is a ‘revert’ patch to fix this – although the longer-term solution may be different:  http://lkml.iu.edu/hypermail/linux/kernel/1612.3/00280.html

I have applied this, and it appears to fix the compile errors (Odroid C2)..

Robert Gadsdon.   December 26, 2016.

 

KERNEL – 4.10-rc1 Out – OK with VMware, Breaks NVIDIA..

Kernel 4.10-rc1 is out, and brief details are here: http://lkml.iu.edu/hypermail/linux/kernel/1612.3/00220.html

Installed it on the test system, and (4.9-patched) VMware 12.5.2 is OK, but the latest NVIDIA driver (375.26) fails to compile:

....................
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/common/inc/nv-mm.h: In function ‘NV_GET_USER_PAGES_REMOTE’:
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/common/inc/nv-mm.h:86:20: error: too few arguments to function ‘get_user_pages_remote’
 return get_user_pages_remote(tsk, mm, start, nr_pages, flags, pages, vmas);
 ^~~~~~~~~~~~~~~~~~~~~
....................

There was already a patch to fix this, and details are at: https://devtalk.nvidia.com/default/topic/982667/linux/heads-up-375-26-build-breaks-after-recent-commits-to-kernel/post/5043956/#5043956

I applied this, but got more errors:

$ cat nv-410rc1_patch.patch |patch -p0
patching file a/kernel/common/inc/nv-mm.h
patching file a/kernel/nvidia/nv-p2p.c
patching file a/kernel/nvidia-drm/nvidia-drm-fence.c
patching file a/kernel/nvidia-drm/nvidia-drm-gem.h
patching file a/kernel/nvidia-drm/nvidia-drm-modeset.c
patching file a/kernel/nvidia-drm/nvidia-drm-priv.h
patching file a/kernel/nvidia-uvm/uvm8.c
patching file a/kernel/nvidia-uvm/uvm8_test.c
patching file a/kernel/nvidia-uvm/uvm_lite.c
Hunk #1 succeeded at 1333 with fuzz 2.
....................................
 << Compile.. >>
....................................
 CONFTEST: drm_atomic_available
 CONFTEST: drm_atomic_modeset_nonblocking_commit_available
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-frontend.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-instance.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-acpi.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-chrdev.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-cray.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-dma.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-gvi.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-i2c.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-mempool.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-mmap.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-p2p.o
 CC [M] /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.o
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c: In function ‘nvidia_cpu_callback’:
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c:213:14: error: ‘CPU_DOWN_FAILED’ undeclared (first use in this function)
 case CPU_DOWN_FAILED:
 ^~~~~~~~~~~~~~~
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c:213:14: note: each undeclared identifier is reported only once for each function it appears in
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c:220:14: error: ‘CPU_DOWN_PREPARE’ undeclared (first use in this function)
 case CPU_DOWN_PREPARE:
 ^~~~~~~~~~~~~~~~
In file included from /home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c:15:0:
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c: In function ‘nv_init_pat_support’:
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/common/inc/nv-linux.h:391:34: error: implicit declaration of function ‘register_cpu_notifier’ [-Werror=implicit-function-declaration]
 #define register_hotcpu_notifier register_cpu_notifier
 ^
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c:258:17: note: in expansion of macro ‘register_hotcpu_notifier’
 if (register_hotcpu_notifier(&nv_hotcpu_nfb) != 0)
 ^~~~~~~~~~~~~~~~~~~~~~~~
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c: In function ‘nv_teardown_pat_support’:
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/common/inc/nv-linux.h:388:36: error: implicit declaration of function ‘unregister_cpu_notifier’ [-Werror=implicit-function-declaration]
 #define unregister_hotcpu_notifier unregister_cpu_notifier
 ^
/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.c:283:9: note: in expansion of macro ‘unregister_hotcpu_notifier’
 unregister_hotcpu_notifier(&nv_hotcpu_nfb);
 ^~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
/usr/src/linux-4.10-rc1/scripts/Makefile.build:293: recipe for target '/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.o' failed
make[3]: *** [/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel/nvidia/nv-pat.o] Error 1
/usr/src/linux-4.10-rc1/Makefile:1490: recipe for target '_module_/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel' failed
make[2]: *** [_module_/home/rgadsdon/kernel/NVIDIA-Linux-x86_64-375.26/kernel] Error 2
make[2]: Leaving directory '/usr/src/linux-4.10-rc1'
Makefile:150: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
make[1]: Leaving directory '/usr/src/linux-4.10-rc1'
Makefile:81: recipe for target 'modules' failed
make: *** [modules] Error 2

It may be that more Kernel code changes were incorporated after the patch was created, and before 4.10-rc1 was released?

I have just encountered a potentially more serious problem with compiling this kernel on ARM64 (aarch64) systems, but need more tests to confirm this, and will post results in a later article..

Robert Gadsdon.  December 26, 2016.

 

ARM64 – Odroid C2 – Latest Ethernet Patch..

After some of the recent ‘Ethernet fix’ patches have not worked with more recent linux-next kernels, I have found one that – at least at the moment – does fix the ‘hang’ problem – again..

The patch is applied to meson-gxbb-odroidc2.dts, and can be found here:  http://archive.arm.linux.org.uk/lurker/message/20161221.113134.3ac4d1e6.en.html

I did have to revert this kasir_offset patch (…-R) to stop the linux-next (December 22) kernel compile from failing:  http://archive.arm.linux.org.uk/lurker/message/20161211.005055.ad5e5693.en.html but hopefully this will be fixed in a later version..

With this dts patch, I now have a stable Ethernet connection on the C2 – again..

..........
meson8b-dwmac c9410000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
Link is Up - 1000/Full
.........
Fedora 25 (Workstation Edition)
Kernel 4.9.0-next-20161222-tx on an aarch64 (ttyAML0)
......................
]# uname -a
Linux rgc2 4.9.0-next-20161222-tx #1 SMP Thu Dec 22 00:33:30 EST 2016 aarch64 aarch64 aarch64 GNU/Linux

I should mention that this only gives a headless boot, as USB/Graphics still do not work, on my C2..

Robert Gadsdon.   December 22, 2016.