summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@redhat.com>2014-04-12 19:57:02 -0400
committerJosh Boyer <jwboyer@redhat.com>2014-04-12 19:57:17 -0400
commitf9bb91845a30b5ec296ef6f01c9d2eca4cd0b0bb (patch)
treeae6f188c3254fa288da2b260e96c186010236a9c
parent58049b49658b32aa5195bc7517018539e6eba59c (diff)
downloadkernel-f9bb91845a30b5ec296ef6f01c9d2eca4cd0b0bb.tar.gz
kernel-f9bb91845a30b5ec296ef6f01c9d2eca4cd0b0bb.tar.xz
kernel-f9bb91845a30b5ec296ef6f01c9d2eca4cd0b0bb.zip
Linux v3.14.1-rc1
-rw-r--r--0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.patch1054
-rw-r--r--0001-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch38
-rw-r--r--0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch101
-rw-r--r--3.14.1-rc1.patch1982
-rw-r--r--Bluetooth-allocate-static-minor-for-vhci.patch71
-rw-r--r--Input-elantech-add-support-for-newer-August-2013-dev.patch36
-rw-r--r--KVM-Improve-create-VCPU-parameter.patch93
-rw-r--r--KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch38
-rw-r--r--KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch247
-rw-r--r--KVM-x86-Fix-potential-divide-by-0-in-lapic.patch102
-rw-r--r--KVM-x86-fix-guest-initiated-crash-with-x2apic.patch109
-rw-r--r--Revert-userns-Allow-unprivileged-users-to-create-use.patch44
-rw-r--r--acpi-sony-nonvs-blacklist.patch38
-rw-r--r--alx-Reset-phy-speed-after-resume.patch33
-rw-r--r--arm-am33xx-arm-soc-upstream.patch2468
-rw-r--r--arm-am33xx-bblack.patch610
-rw-r--r--arm-am33xx-cpsw.patch23
-rw-r--r--arm-imx6-utilite.patch153
-rw-r--r--arm-tegra-paz00-panel-dts.patch99
-rw-r--r--config-arm-generic67
-rw-r--r--config-arm6414
-rw-r--r--config-armv7133
-rw-r--r--config-armv7-generic138
-rw-r--r--config-armv7-lpae35
-rw-r--r--config-debug3
-rw-r--r--config-generic160
-rw-r--r--config-nodebug3
-rw-r--r--config-powerpc-generic4
-rw-r--r--config-powerpc6412
-rw-r--r--config-powerpc64p712
-rw-r--r--config-x86-32-generic7
-rw-r--r--config-x86-generic13
-rw-r--r--config-x86_64-generic16
-rw-r--r--cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch43
-rw-r--r--dell-laptop.patch1017
-rw-r--r--dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch34
-rw-r--r--drm-i915-dp-stfu.patch53
-rw-r--r--drm-i915-hush-check-crtc-state.patch20
-rw-r--r--drm-qxl-backport-fixes-for-Fedora.patch213
-rw-r--r--elantech-Properly-differentiate-between-clickpads-an.patch110
-rw-r--r--fs-proc-devtree-remove_proc_entry.patch12
-rw-r--r--iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch48
-rw-r--r--kernel.spec186
-rw-r--r--keys-expand-keyring.patch6834
-rw-r--r--keys-fixes.patch1025
-rw-r--r--keys-krb-support.patch748
-rw-r--r--keys-x509-improv.patch1808
-rw-r--r--lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch63
-rw-r--r--makefile-after_link.patch14
-rw-r--r--modsign-uefi.patch61
-rw-r--r--nfs-check-gssd-running-before-krb5i-auth.patch44
-rw-r--r--sb-hibernate.patch3
-rw-r--r--secure-modules.patch149
-rw-r--r--silence-acpi-blacklist.patch25
-rw-r--r--sources4
-rw-r--r--sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch233
-rw-r--r--sunrpc-replace-gssd_running-with-more-reliable-check.patch139
-rw-r--r--sysrq-secure-boot.patch53
-rw-r--r--x86-allow-1024-cpus.patch13
-rw-r--r--xfs-underflow-bug-in-xfs_attrlist_by_handle.patch149
60 files changed, 4232 insertions, 16825 deletions
diff --git a/0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.patch b/0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.patch
new file mode 100644
index 000000000..b3ec026c3
--- /dev/null
+++ b/0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.patch
@@ -0,0 +1,1054 @@
+Bugzilla: 1048314
+Upstream-status: Queued for 3.16
+
+From 39141443c8ea2900af627d688a255e064e2b6e19 Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Date: Wed, 9 Apr 2014 11:09:21 -0400
+Subject: [PATCH] HID: rmi: introduce RMI driver for Synaptics touchpads
+
+This driver add support for RMI4 over USB or I2C.
+The current state is that it uses its own RMI4 implementation, but once
+RMI4 is merged upstream, the driver will be a transport driver for the
+RMI4 library.
+
+Part of this driver should be considered as temporary. Most of the RMI4
+processing and input handling will be deleted at some point.
+
+I based my work on Andrew's regarding its port of RMI4 over HID (see
+https://github.com/mightybigcar/synaptics-rmi4/tree/rmihid )
+This repo presents how the driver may looks like at the end:
+https://github.com/mightybigcar/synaptics-rmi4/blob/rmihid/drivers/input/rmi4/rmi_hid.c
+
+Without this temporary solution, the workaround we gave to users
+is to disable i2c-hid, which leads to disabling the touchscreen on the
+XPS 11 and 12 (Haswell generation).
+
+Related bugs:
+https://bugzilla.redhat.com/show_bug.cgi?id=1048314
+https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1218973
+
+Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+
+- Removed obviously wrong hid_hw_stop() at the end of probe
+- emulate hid_hw_raw_request and hid_hw_output_report that has been
+ interoduced in 3.15
+
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+---
+ drivers/hid/Kconfig | 8 +
+ drivers/hid/Makefile | 1 +
+ drivers/hid/compat.h | 43 +++
+ drivers/hid/hid-core.c | 2 +
+ drivers/hid/hid-rmi.c | 890 +++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/hid.h | 2 +
+ 6 files changed, 946 insertions(+)
+ create mode 100644 drivers/hid/compat.h
+ create mode 100644 drivers/hid/hid-rmi.c
+
+diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
+index 34e2d39..b2d733b 100644
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -645,6 +645,14 @@ config HID_SUNPLUS
+ ---help---
+ Support for Sunplus wireless desktop.
+
++config HID_RMI
++ tristate "Synaptics RMI4 device support"
++ depends on HID
++ ---help---
++ Support for Synaptics RMI4 touchpads.
++ Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid
++ and want support for its special functionalities.
++
+ config HID_GREENASIA
+ tristate "GreenAsia (Product ID 0x12) game controller support"
+ depends on HID
+diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
+index 30e4431..b326f79 100644
+--- a/drivers/hid/Makefile
++++ b/drivers/hid/Makefile
+@@ -96,6 +96,7 @@ obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
+ hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
+ hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
+ hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-ryos.o hid-roccat-savu.o
++obj-$(CONFIG_HID_RMI) += hid-rmi.o
+ obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
+ obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
+ obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
+diff --git a/drivers/hid/compat.h b/drivers/hid/compat.h
+new file mode 100644
+index 0000000..1318ca6e
+--- /dev/null
++++ b/drivers/hid/compat.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (c) 2014 Benjamin Tissoires <benjamin.tissoires@gmail.com>
++ * Copyright (c) 2014 Red Hat, Inc
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ */
++
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
++
++static inline int hid_hw_raw_request(struct hid_device *hdev,
++ unsigned char reportnum, __u8 *buf,
++ size_t len, unsigned char rtype, int reqtype)
++{
++ if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
++ return -EINVAL;
++
++ switch (reqtype) {
++ case HID_REQ_SET_REPORT:
++ if (reportnum != buf[0])
++ return -EINVAL;
++ return hdev->hid_output_raw_report(hdev, buf, len, rtype);
++ case HID_REQ_GET_REPORT:
++ return hdev->hid_get_raw_report(hdev, reportnum, buf, len, rtype);
++ }
++
++ return -ENOSYS;
++}
++
++static inline int hid_hw_output_report(struct hid_device *hdev, __u8 *buf,
++ size_t len)
++{
++ if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
++ return -EINVAL;
++
++ return hdev->hid_output_raw_report(hdev, buf, len, HID_OUTPUT_REPORT);
++}
++
++#endif
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 253fe23..543dd1f 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1836,6 +1836,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
++ { HID_I2C_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
+diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
+new file mode 100644
+index 0000000..a4f04d4
+--- /dev/null
++++ b/drivers/hid/hid-rmi.c
+@@ -0,0 +1,890 @@
++/*
++ * Copyright (c) 2013 Andrew Duggan <aduggan@synaptics.com>
++ * Copyright (c) 2013 Synaptics Incorporated
++ * Copyright (c) 2014 Benjamin Tissoires <benjamin.tissoires@gmail.com>
++ * Copyright (c) 2014 Red Hat, Inc
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the Free
++ * Software Foundation; either version 2 of the License, or (at your option)
++ * any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/hid.h>
++#include <linux/input.h>
++#include <linux/input/mt.h>
++#include <linux/module.h>
++#include <linux/pm.h>
++#include <linux/slab.h>
++#include <linux/wait.h>
++#include <linux/sched.h>
++#include "hid-ids.h"
++
++#include "compat.h"
++
++#define RMI_MOUSE_REPORT_ID 0x01 /* Mouse emulation Report */
++#define RMI_WRITE_REPORT_ID 0x09 /* Output Report */
++#define RMI_READ_ADDR_REPORT_ID 0x0a /* Output Report */
++#define RMI_READ_DATA_REPORT_ID 0x0b /* Input Report */
++#define RMI_ATTN_REPORT_ID 0x0c /* Input Report */
++#define RMI_SET_RMI_MODE_REPORT_ID 0x0f /* Feature Report */
++
++/* flags */
++#define RMI_READ_REQUEST_PENDING BIT(0)
++#define RMI_READ_DATA_PENDING BIT(1)
++#define RMI_STARTED BIT(2)
++
++enum rmi_mode_type {
++ RMI_MODE_OFF = 0,
++ RMI_MODE_ATTN_REPORTS = 1,
++ RMI_MODE_NO_PACKED_ATTN_REPORTS = 2,
++};
++
++struct rmi_function {
++ unsigned page; /* page of the function */
++ u16 query_base_addr; /* base address for queries */
++ u16 command_base_addr; /* base address for commands */
++ u16 control_base_addr; /* base address for controls */
++ u16 data_base_addr; /* base address for datas */
++ unsigned int interrupt_base; /* cross-function interrupt number
++ * (uniq in the device)*/
++ unsigned int interrupt_count; /* number of interrupts */
++ unsigned int report_size; /* size of a report */
++ unsigned long irq_mask; /* mask of the interrupts
++ * (to be applied against ATTN IRQ) */
++};
++
++/**
++ * struct rmi_data - stores information for hid communication
++ *
++ * @page_mutex: Locks current page to avoid changing pages in unexpected ways.
++ * @page: Keeps track of the current virtual page
++ *
++ * @wait: Used for waiting for read data
++ *
++ * @writeReport: output buffer when writing RMI registers
++ * @readReport: input buffer when reading RMI registers
++ *
++ * @input_report_size: size of an input report (advertised by HID)
++ * @output_report_size: size of an output report (advertised by HID)
++ *
++ * @flags: flags for the current device (started, reading, etc...)
++ *
++ * @f11: placeholder of internal RMI function F11 description
++ * @f30: placeholder of internal RMI function F30 description
++ *
++ * @max_fingers: maximum finger count reported by the device
++ * @max_x: maximum x value reported by the device
++ * @max_y: maximum y value reported by the device
++ *
++ * @gpio_led_count: count of GPIOs + LEDs reported by F30
++ * @button_count: actual physical buttons count
++ * @button_mask: button mask used to decode GPIO ATTN reports
++ * @button_state_mask: pull state of the buttons
++ *
++ * @input: pointer to the kernel input device
++ *
++ * @reset_work: worker which will be called in case of a mouse report
++ * @hdev: pointer to the struct hid_device
++ */
++struct rmi_data {
++ struct mutex page_mutex;
++ int page;
++
++ wait_queue_head_t wait;
++
++ u8 *writeReport;
++ u8 *readReport;
++
++ int input_report_size;
++ int output_report_size;
++
++ unsigned long flags;
++
++ struct rmi_function f11;
++ struct rmi_function f30;
++
++ unsigned int max_fingers;
++ unsigned int max_x;
++ unsigned int max_y;
++ unsigned int x_size_mm;
++ unsigned int y_size_mm;
++
++ unsigned int gpio_led_count;
++ unsigned int button_count;
++ unsigned long button_mask;
++ unsigned long button_state_mask;
++
++ struct input_dev *input;
++
++ struct work_struct reset_work;
++ struct hid_device *hdev;
++};
++
++#define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
++
++static int rmi_write_report(struct hid_device *hdev, u8 *report, int len);
++
++/**
++ * rmi_set_page - Set RMI page
++ * @hdev: The pointer to the hid_device struct
++ * @page: The new page address.
++ *
++ * RMI devices have 16-bit addressing, but some of the physical
++ * implementations (like SMBus) only have 8-bit addressing. So RMI implements
++ * a page address at 0xff of every page so we can reliable page addresses
++ * every 256 registers.
++ *
++ * The page_mutex lock must be held when this function is entered.
++ *
++ * Returns zero on success, non-zero on failure.
++ */
++static int rmi_set_page(struct hid_device *hdev, u8 page)
++{
++ struct rmi_data *data = hid_get_drvdata(hdev);
++ int retval;
++
++ data->writeReport[0] = RMI_WRITE_REPORT_ID;
++ data->writeReport[1] = 1;
++ data->writeReport[2] = 0xFF;
++ data->writeReport[4] = page;
++
++ retval = rmi_write_report(hdev, data->writeReport,
++ data->output_report_size);
++ if (retval != data->output_report_size) {
++ dev_err(&hdev->dev,
++ "%s: set page failed: %d.", __func__, retval);
++ return retval;
++ }
++
++ data->page = page;
++ return 0;
++}
++
++static int rmi_set_mode(struct hid_device *hdev, u8 mode)
++{
++ int ret;
++ u8 txbuf[2] = {RMI_SET_RMI_MODE_REPORT_ID, mode};
++
++ ret = hid_hw_raw_request(hdev, RMI_SET_RMI_MODE_REPORT_ID, txbuf,
++ sizeof(txbuf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
++ if (ret < 0) {
++ dev_err(&hdev->dev, "unable to set rmi mode to %d (%d)\n", mode,
++ ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int rmi_write_report(struct hid_device *hdev, u8 *report, int len)
++{
++ int ret;
++
++ ret = hid_hw_output_report(hdev, (void *)report, len);
++ if (ret < 0) {
++ dev_err(&hdev->dev, "failed to write hid report (%d)\n", ret);
++ return ret;
++ }
++
++ return ret;
++}
++
++static int rmi_read_block(struct hid_device *hdev, u16 addr, void *buf,
++ const int len)
++{
++ struct rmi_data *data = hid_get_drvdata(hdev);
++ int ret;
++ int bytes_read;
++ int bytes_needed;
++ int retries;
++ int read_input_count;
++
++ mutex_lock(&data->page_mutex);
++
++ if (RMI_PAGE(addr) != data->page) {
++ ret = rmi_set_page(hdev, RMI_PAGE(addr));
++ if (ret < 0)
++ goto exit;
++ }
++
++ for (retries = 5; retries > 0; retries--) {
++ data->writeReport[0] = RMI_READ_ADDR_REPORT_ID;
++ data->writeReport[1] = 0; /* old 1 byte read count */
++ data->writeReport[2] = addr & 0xFF;
++ data->writeReport[3] = (addr >> 8) & 0xFF;
++ data->writeReport[4] = len & 0xFF;
++ data->writeReport[5] = (len >> 8) & 0xFF;
++
++ set_bit(RMI_READ_REQUEST_PENDING, &data->flags);
++
++ ret = rmi_write_report(hdev, data->writeReport,
++ data->output_report_size);
++ if (ret != data->output_report_size) {
++ clear_bit(RMI_READ_REQUEST_PENDING, &data->flags);
++ dev_err(&hdev->dev,
++ "failed to write request output report (%d)\n",
++ ret);
++ goto exit;
++ }
++
++ bytes_read = 0;
++ bytes_needed = len;
++ while (bytes_read < len) {
++ if (!wait_event_timeout(data->wait,
++ test_bit(RMI_READ_DATA_PENDING, &data->flags),
++ msecs_to_jiffies(1000))) {
++ hid_warn(hdev, "%s: timeout elapsed\n",
++ __func__);
++ ret = -EAGAIN;
++ break;
++ }
++
++ read_input_count = data->readReport[1];
++ memcpy(buf + bytes_read, &data->readReport[2],
++ read_input_count < bytes_needed ?
++ read_input_count : bytes_needed);
++
++ bytes_read += read_input_count;
++ bytes_needed -= read_input_count;
++ clear_bit(RMI_READ_DATA_PENDING, &data->flags);
++ }
++
++ if (ret >= 0) {
++ ret = 0;
++ break;
++ }
++ }
++
++exit:
++ clear_bit(RMI_READ_REQUEST_PENDING, &data->flags);
++ mutex_unlock(&data->page_mutex);
++ return ret;
++}
++
++static inline int rmi_read(struct hid_device *hdev, u16 addr, void *buf)
++{
++ return rmi_read_block(hdev, addr, buf, 1);
++}
++
++static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
++ u8 finger_state, u8 *touch_data)
++{
++ int x, y, wx, wy;
++ int wide, major, minor;
++ int z;
++
++ input_mt_slot(hdata->input, slot);
++ input_mt_report_slot_state(hdata->input, MT_TOOL_FINGER,
++ finger_state == 0x01);
++ if (finger_state == 0x01) {
++ x = (touch_data[0] << 4) | (touch_data[2] & 0x07);
++ y = (touch_data[1] << 4) | (touch_data[2] >> 4);
++ wx = touch_data[3] & 0x07;
++ wy = touch_data[3] >> 4;
++ wide = (wx > wy);
++ major = max(wx, wy);
++ minor = min(wx, wy);
++ z = touch_data[4];
++
++ /* y is inverted */
++ y = hdata->max_y - y;
++
++ input_event(hdata->input, EV_ABS, ABS_MT_POSITION_X, x);
++ input_event(hdata->input, EV_ABS, ABS_MT_POSITION_Y, y);
++ input_event(hdata->input, EV_ABS, ABS_MT_ORIENTATION, wide);
++ input_event(hdata->input, EV_ABS, ABS_MT_PRESSURE, z);
++ input_event(hdata->input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
++ input_event(hdata->input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
++ }
++}
++
++static void rmi_reset_work(struct work_struct *work)
++{
++ struct rmi_data *hdata = container_of(work, struct rmi_data,
++ reset_work);
++
++ /* switch the device to RMI if we receive a generic mouse report */
++ rmi_set_mode(hdata->hdev, RMI_MODE_ATTN_REPORTS);
++}
++
++static inline int rmi_schedule_reset(struct hid_device *hdev)
++{
++ struct rmi_data *hdata = hid_get_drvdata(hdev);
++ return schedule_work(&hdata->reset_work);
++}
++
++static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data,
++ int size)
++{
++ struct rmi_data *hdata = hid_get_drvdata(hdev);
++ int offset;
++ int i;
++
++ if (size < hdata->f11.report_size)
++ return 0;
++
++ if (!(irq & hdata->f11.irq_mask))
++ return 0;
++
++ offset = (hdata->max_fingers >> 2) + 1;
++ for (i = 0; i < hdata->max_fingers; i++) {
++ int fs_byte_position = i >> 2;
++ int fs_bit_position = (i & 0x3) << 1;
++ int finger_state = (data[fs_byte_position] >> fs_bit_position) &
++ 0x03;
++
++ rmi_f11_process_touch(hdata, i, finger_state,
++ &data[offset + 5 * i]);
++ }
++ input_mt_sync_frame(hdata->input);
++ input_sync(hdata->input);
++ return hdata->f11.report_size;
++}
++
++static int rmi_f30_input_event(struct hid_device *hdev, u8 irq, u8 *data,
++ int size)
++{
++ struct rmi_data *hdata = hid_get_drvdata(hdev);
++ int i;
++ int button = 0;
++ bool value;
++
++ if (!(irq & hdata->f30.irq_mask))
++ return 0;
++
++ for (i = 0; i < hdata->gpio_led_count; i++) {
++ if (test_bit(i, &hdata->button_mask)) {
++ value = (data[i / 8] >> (i & 0x07)) & BIT(0);
++ if (test_bit(i, &hdata->button_state_mask))
++ value = !value;
++ input_event(hdata->input, EV_KEY, BTN_LEFT + button++,
++ value);
++ }
++ }
++ return hdata->f30.report_size;
++}
++
++static int rmi_input_event(struct hid_device *hdev, u8 *data, int size)
++{
++ struct rmi_data *hdata = hid_get_drvdata(hdev);
++ unsigned long irq_mask = 0;
++ unsigned index = 2;
++
++ if (!(test_bit(RMI_STARTED, &hdata->flags)))
++ return 0;
++
++ irq_mask |= hdata->f11.irq_mask;
++ irq_mask |= hdata->f30.irq_mask;
++
++ if (data[1] & ~irq_mask)
++ hid_warn(hdev, "unknown intr source:%02lx %s:%d\n",
++ data[1] & ~irq_mask, __FILE__, __LINE__);
++
++ if (hdata->f11.interrupt_base < hdata->f30.interrupt_base) {
++ index += rmi_f11_input_event(hdev, data[1], &data[index],
++ size - index);
++ index += rmi_f30_input_event(hdev, data[1], &data[index],
++ size - index);
++ } else {
++ index += rmi_f30_input_event(hdev, data[1], &data[index],
++ size - index);
++ index += rmi_f11_input_event(hdev, data[1], &data[index],
++ size - index);
++ }
++
++ return 1;
++}
++
++static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size)
++{
++ struct rmi_data *hdata = hid_get_drvdata(hdev);
++
++ if (!test_bit(RMI_READ_REQUEST_PENDING, &hdata->flags)) {
++ hid_err(hdev, "no read request pending\n");
++ return 0;
++ }
++
++ memcpy(hdata->readReport, data, size < hdata->input_report_size ?
++ size : hdata->input_report_size);
++ set_bit(RMI_READ_DATA_PENDING, &hdata->flags);
++ wake_up(&hdata->wait);
++
++ return 1;
++}
++
++static int rmi_raw_event(struct hid_device *hdev,
++ struct hid_report *report, u8 *data, int size)
++{
++ switch (data[0]) {
++ case RMI_READ_DATA_REPORT_ID:
++ return rmi_read_data_event(hdev, data, size);
++ case RMI_ATTN_REPORT_ID:
++ return rmi_input_event(hdev, data, size);
++ case RMI_MOUSE_REPORT_ID:
++ rmi_schedule_reset(hdev);
++ break;
++ }
++
++ return 0;
++}
++
++static int rmi_post_reset(struct hid_device *hdev)
++{
++ return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
++}
++
++static int rmi_post_resume(struct hid_device *hdev)
++{
++ return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
++}
++
++#define RMI4_MAX_PAGE 0xff
++#define RMI4_PAGE_SIZE 0x0100
++
++#define PDT_START_SCAN_LOCATION 0x00e9
++#define PDT_END_SCAN_LOCATION 0x0005
++#define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
++
++struct pdt_entry {
++ u8 query_base_addr:8;
++ u8 command_base_addr:8;
++ u8 control_base_addr:8;
++ u8 data_base_addr:8;
++ u8 interrupt_source_count:3;
++ u8 bits3and4:2;
++ u8 function_version:2;
++ u8 bit7:1;
++ u8 function_number:8;
++} __attribute__((__packed__));
++
++static inline unsigned long rmi_gen_mask(unsigned irq_base, unsigned irq_count)
++{
++ return GENMASK(irq_count + irq_base - 1, irq_base);
++}
++
++static void rmi_register_function(struct rmi_data *data,
++ struct pdt_entry *pdt_entry, int page, unsigned interrupt_count)
++{
++ struct rmi_function *f = NULL;
++ u16 page_base = page << 8;
++
++ switch (pdt_entry->function_number) {
++ case 0x11:
++ f = &data->f11;
++ break;
++ case 0x30:
++ f = &data->f30;
++ break;
++ }
++
++ if (f) {
++ f->page = page;
++ f->query_base_addr = page_base | pdt_entry->query_base_addr;
++ f->command_base_addr = page_base | pdt_entry->command_base_addr;
++ f->control_base_addr = page_base | pdt_entry->control_base_addr;
++ f->data_base_addr = page_base | pdt_entry->data_base_addr;
++ f->interrupt_base = interrupt_count;
++ f->interrupt_count = pdt_entry->interrupt_source_count;
++ f->irq_mask = rmi_gen_mask(f->interrupt_base,
++ f->interrupt_count);
++ }
++}
++
++static int rmi_scan_pdt(struct hid_device *hdev)
++{
++ struct rmi_data *data = hid_get_drvdata(hdev);
++ struct pdt_entry entry;
++ int page;
++ bool page_has_function;
++ int i;
++ int retval;
++ int interrupt = 0;
++ u16 page_start, pdt_start , pdt_end;
++
++ hid_info(hdev, "Scanning PDT...\n");
++
++ for (page = 0; (page <= RMI4_MAX_PAGE); page++) {
++ page_start = RMI4_PAGE_SIZE * page;
++ pdt_start = page_start + PDT_START_SCAN_LOCATION;
++ pdt_end = page_start + PDT_END_SCAN_LOCATION;
++
++ page_has_function = false;
++ for (i = pdt_start; i >= pdt_end; i -= sizeof(entry)) {
++ retval = rmi_read_block(hdev, i, &entry, sizeof(entry));
++ if (retval) {
++ hid_err(hdev,
++ "Read of PDT entry at %#06x failed.\n",
++ i);
++ goto error_exit;
++ }
++
++ if (RMI4_END_OF_PDT(entry.function_number))
++ break;
++
++ page_has_function = true;
++
++ hid_info(hdev, "Found F%02X on page %#04x\n",
++ entry.function_number, page);
++
++ rmi_register_function(data, &entry, page, interrupt);
++ interrupt += entry.interrupt_source_count;
++ }
++
++ if (!page_has_function)
++ break;
++ }
++
++ hid_info(hdev, "%s: Done with PDT scan.\n", __func__);
++ retval = 0;
++
++error_exit:
++ return retval;
++}
++
++static int rmi_populate_f11(struct hid_device *hdev)
++{
++ struct rmi_data *data = hid_get_drvdata(hdev);
++ u8 buf[20];
++ int ret;
++ bool has_query12;
++ bool has_physical_props;
++ unsigned x_size, y_size;
++
++ if (!data->f11.query_base_addr) {
++ hid_err(hdev, "No 2D sensor found, giving up.\n");
++ return -ENODEV;
++ }
++
++ /* query 0 contains some useful information */
++ ret = rmi_read(hdev, data->f11.query_base_addr, buf);
++ if (ret) {
++ hid_err(hdev, "can not get query 0: %d.\n", ret);
++ return ret;
++ }
++ has_query12 = !!(buf[0] & BIT(5));
++
++ /* query 1 to get the max number of fingers */
++ ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf);
++ if (ret) {
++ hid_err(hdev, "can not get NumberOfFingers: %d.\n", ret);
++ return ret;
++ }
++ data->max_fingers = (buf[0] & 0x07) + 1;
++ if (data->max_fingers > 5)
++ data->max_fingers = 10;
++
++ data->f11.report_size = data->max_fingers * 5 +
++ DIV_ROUND_UP(data->max_fingers, 4);
++
++ if (!(buf[0] & BIT(4))) {
++ hid_err(hdev, "No absolute events, giving up.\n");
++ return -ENODEV;
++ }
++
++ /*
++ * query 12 to know if the physical properties are reported
++ * (query 12 is at offset 10 for HID devices)
++ */
++ if (has_query12) {
++ ret = rmi_read(hdev, data->f11.query_base_addr + 10, buf);
++ if (ret) {
++ hid_err(hdev, "can not get query 12: %d.\n", ret);
++ return ret;
++ }
++ has_physical_props = !!(buf[0] & BIT(5));
++
++ if (has_physical_props) {
++ ret = rmi_read_block(hdev,
++ data->f11.query_base_addr + 11, buf, 4);
++ if (ret) {
++ hid_err(hdev, "can not read query 15-18: %d.\n",
++ ret);
++ return ret;
++ }
++
++ x_size = buf[0] | (buf[1] << 8);
++ y_size = buf[2] | (buf[3] << 8);
++
++ data->x_size_mm = DIV_ROUND_CLOSEST(x_size, 10);
++ data->y_size_mm = DIV_ROUND_CLOSEST(y_size, 10);
++
++ hid_info(hdev, "%s: size in mm: %d x %d\n",
++ __func__, data->x_size_mm, data->y_size_mm);
++ }
++ }
++
++ /* retrieve the ctrl registers */
++ ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 20);
++ if (ret) {
++ hid_err(hdev, "can not read ctrl block of size 20: %d.\n", ret);
++ return ret;
++ }
++
++ data->max_x = buf[6] | (buf[7] << 8);
++ data->max_y = buf[8] | (buf[9] << 8);
++
++ return 0;
++}
++
++static int rmi_populate_f30(struct hid_device *hdev)
++{
++ struct rmi_data *data = hid_get_drvdata(hdev);
++ u8 buf[20];
++ int ret;
++ bool has_gpio, has_led;
++ unsigned bytes_per_ctrl;
++ u8 ctrl2_addr;
++ int ctrl2_3_length;
++ int i;
++
++ /* function F30 is for physical buttons */
++ if (!data->f30.query_base_addr) {
++ hid_err(hdev, "No GPIO/LEDs found, giving up.\n");
++ return -ENODEV;
++ }
++
++ ret = rmi_read_block(hdev, data->f30.query_base_addr, buf, 2);
++ if (ret) {
++ hid_err(hdev, "can not get F30 query registers: %d.\n", ret);
++ return ret;
++ }
++
++ has_gpio = !!(buf[0] & BIT(3));
++ has_led = !!(buf[0] & BIT(2));
++ data->gpio_led_count = buf[1] & 0x1f;
++
++ /* retrieve ctrl 2 & 3 registers */
++ bytes_per_ctrl = (data->gpio_led_count + 7) / 8;
++ /* Ctrl0 is present only if both has_gpio and has_led are set*/
++ ctrl2_addr = (has_gpio && has_led) ? bytes_per_ctrl : 0;
++ /* Ctrl1 is always be present */
++ ctrl2_addr += bytes_per_ctrl;
++ ctrl2_3_length = 2 * bytes_per_ctrl;
++
++ data->f30.report_size = bytes_per_ctrl;
++
++ ret = rmi_read_block(hdev, data->f30.control_base_addr + ctrl2_addr,
++ buf, ctrl2_3_length);
++ if (ret) {
++ hid_err(hdev, "can not read ctrl 2&3 block of size %d: %d.\n",
++ ctrl2_3_length, ret);
++ return ret;
++ }
++
++ for (i = 0; i < data->gpio_led_count; i++) {
++ int byte_position = i >> 3;
++ int bit_position = i & 0x07;
++ u8 dir_byte = buf[byte_position];
++ u8 data_byte = buf[byte_position + bytes_per_ctrl];
++ bool dir = (dir_byte >> bit_position) & BIT(0);
++ bool dat = (data_byte >> bit_position) & BIT(0);
++
++ if (dir == 0) {
++ /* input mode */
++ if (dat) {
++ /* actual buttons have pull up resistor */
++ data->button_count++;
++ set_bit(i, &data->button_mask);
++ set_bit(i, &data->button_state_mask);
++ }
++ }
++
++ }
++
++ return 0;
++}
++
++static int rmi_populate(struct hid_device *hdev)
++{
++ int ret;
++
++ ret = rmi_scan_pdt(hdev);
++ if (ret) {
++ hid_err(hdev, "PDT scan failed with code %d.\n", ret);
++ return ret;
++ }
++
++ ret = rmi_populate_f11(hdev);
++ if (ret) {
++ hid_err(hdev, "Error while initializing F11 (%d).\n", ret);
++ return ret;
++ }
++
++ ret = rmi_populate_f30(hdev);
++ if (ret)
++ hid_warn(hdev, "Error while initializing F30 (%d).\n", ret);
++
++ return 0;
++}
++
++static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
++{
++ struct rmi_data *data = hid_get_drvdata(hdev);
++ struct input_dev *input = hi->input;
++ int ret;
++ int res_x, res_y, i;
++
++ data->input = input;
++
++ hid_dbg(hdev, "Opening low level driver\n");
++ ret = hid_hw_open(hdev);
++ if (ret)
++ return;
++
++ /* Allow incoming hid reports */
++ hid_device_io_start(hdev);
++
++ ret = rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
++ if (ret < 0) {
++ dev_err(&hdev->dev, "failed to set rmi mode\n");
++ goto exit;
++ }
++
++ ret = rmi_set_page(hdev, 0);
++ if (ret < 0) {
++ dev_err(&hdev->dev, "failed to set page select to 0.\n");
++ goto exit;
++ }
++
++ ret = rmi_populate(hdev);
++ if (ret)
++ goto exit;
++
++ __set_bit(EV_ABS, input->evbit);
++ input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->max_x, 0, 0);
++ input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->max_y, 0, 0);
++
++ if (data->x_size_mm && data->x_size_mm) {
++ res_x = (data->max_x - 1) / data->x_size_mm;
++ res_y = (data->max_y - 1) / data->x_size_mm;
++
++ input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
++ input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
++ }
++
++ input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
++ input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0);
++ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
++ input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
++
++ input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
++
++ if (data->button_count) {
++ __set_bit(EV_KEY, input->evbit);
++ for (i = 0; i < data->button_count; i++)
++ __set_bit(BTN_LEFT + i, input->keybit);
++
++ if (data->button_count == 1)
++ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
++ }
++
++ set_bit(RMI_STARTED, &data->flags);
++
++exit:
++ hid_device_io_stop(hdev);
++ hid_hw_close(hdev);
++}
++
++static int rmi_input_mapping(struct hid_device *hdev,
++ struct hid_input *hi, struct hid_field *field,
++ struct hid_usage *usage, unsigned long **bit, int *max)
++{
++ /* we want to make HID ignore the advertised HID collection */
++ return -1;
++}
++
++static int rmi_probe(struct hid_device *hdev, const struct hid_device_id *id)
++{
++ struct rmi_data *data = NULL;
++ int ret;
++ size_t alloc_size;
++
++ data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ INIT_WORK(&data->reset_work, rmi_reset_work);
++ data->hdev = hdev;
++
++ hid_set_drvdata(hdev, data);
++
++ hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
++
++ ret = hid_parse(hdev);
++ if (ret) {
++ hid_err(hdev, "parse failed\n");
++ return ret;
++ }
++
++ data->input_report_size = (hdev->report_enum[HID_INPUT_REPORT]
++ .report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3)
++ + 1 /* report id */;
++ data->output_report_size = (hdev->report_enum[HID_OUTPUT_REPORT]
++ .report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3)
++ + 1 /* report id */;
++
++ alloc_size = data->output_report_size + data->input_report_size;
++
++ data->writeReport = devm_kzalloc(&hdev->dev, alloc_size, GFP_KERNEL);
++ if (!data->writeReport) {
++ ret = -ENOMEM;
++ return ret;
++ }
++
++ data->readReport = data->writeReport + data->output_report_size;
++
++ init_waitqueue_head(&data->wait);
++
++ mutex_init(&data->page_mutex);
++
++ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
++ if (ret) {
++ hid_err(hdev, "hw start failed\n");
++ return ret;
++ }
++
++ if (!test_bit(RMI_STARTED, &data->flags)) {
++ hid_hw_stop(hdev);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static void rmi_remove(struct hid_device *hdev)
++{
++ struct rmi_data *hdata = hid_get_drvdata(hdev);
++
++ clear_bit(RMI_STARTED, &hdata->flags);
++
++ hid_hw_stop(hdev);
++}
++
++static const struct hid_device_id rmi_id[] = {
++ { HID_I2C_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, HID_ANY_ID) },
++ { }
++};
++MODULE_DEVICE_TABLE(hid, rmi_id);
++
++static struct hid_driver rmi_driver = {
++ .name = "hid-rmi",
++ .id_table = rmi_id,
++ .probe = rmi_probe,
++ .remove = rmi_remove,
++ .raw_event = rmi_raw_event,
++ .input_mapping = rmi_input_mapping,
++ .input_configured = rmi_input_configured,
++#ifdef CONFIG_PM
++ .resume = rmi_post_resume,
++ .reset_resume = rmi_post_reset,
++#endif
++};
++
++module_hid_driver(rmi_driver);
++
++MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>");
++MODULE_DESCRIPTION("RMI HID driver");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 31b9d29..1b5f1e9 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -571,6 +571,8 @@ struct hid_descriptor {
+ .bus = BUS_USB, .vendor = (ven), .product = (prod)
+ #define HID_BLUETOOTH_DEVICE(ven, prod) \
+ .bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod)
++#define HID_I2C_DEVICE(ven, prod) \
++ .bus = BUS_I2C, .vendor = (ven), .product = (prod)
+
+ #define HID_REPORT_ID(rep) \
+ .report_type = (rep)
+--
+1.8.3.1
+
diff --git a/0001-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch b/0001-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
new file mode 100644
index 000000000..d25452268
--- /dev/null
+++ b/0001-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
@@ -0,0 +1,38 @@
+Bugzilla: N/A
+Upstream-status: Nak'd, supposedly replacement coming to auto-select
+
+From 0f3f5c5b4ca2eb1f41947c50bedb9b17aa1a1f80 Mon Sep 17 00:00:00 2001
+From: Josh Boyer <jwboyer@fedoraproject.org>
+Date: Mon, 11 Nov 2013 08:39:16 -0500
+Subject: [PATCH] lib/cpumask: Make CPUMASK_OFFSTACK usable without debug
+ dependency
+
+When CPUMASK_OFFSTACK was added in 2008, it was dependent upon
+DEBUG_PER_CPU_MAPS being enabled, or an architecture could select it.
+The debug dependency adds additional overhead that isn't required for
+operation of the feature, and we need CPUMASK_OFFSTACK to increase the
+NR_CPUS value beyond 512 on x86. We drop the current dependency and make
+sure SMP is set.
+
+Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
+---
+ lib/Kconfig | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/lib/Kconfig b/lib/Kconfig
+index b3c8be0..50b47cd 100644
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -342,7 +342,8 @@ config CHECK_SIGNATURE
+ bool
+
+ config CPUMASK_OFFSTACK
+- bool "Force CPU masks off stack" if DEBUG_PER_CPU_MAPS
++ bool "Force CPU masks off stack"
++ depends on SMP
+ help
+ Use dynamic allocation for cpumask_var_t, instead of putting
+ them on the stack. This is a bit more expensive, but avoids
+--
+1.8.3.1
+
diff --git a/0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch b/0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch
deleted file mode 100644
index 4b8c68f1a..000000000
--- a/0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch
+++ /dev/null
@@ -1,101 +0,0 @@
-Bugzilla: 896695
-Upstream-status: Still pending upstream
-
-From 3efd689c41080b0d4a9cc263a51f2868e3d5a37b Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Wed, 9 Oct 2013 15:03:57 +0200
-Subject: [PATCH] iwlwifi: don't WARN on bad firmware state
-
-When we restart firmware is possible and hance firmware is marked as not
-alive, we can still get calls from mac80211. Don't WARN on in this
-situation as this triggers automatic bug reports with no valuable
-information.
-
-This extend change from:
-
-commit 8ca95995e64f5d270889badb3e449dca91106a2b
-Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-Date: Sun Sep 15 11:37:17 2013 +0300
-
- iwlwifi: don't WARN on host commands sent when firmware is dead
-
-which remove WARN_ONCE from one place, but those warnings are also
-triggered from other functions.
-
-Patch adds also unlikely() statement.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/iwlwifi/iwl-trans.h | 22 +++++++++++-----------
- 1 files changed, 11 insertions(+), 11 deletions(-)
-
-diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
-index 80b4750..c6bac7c 100644
---- a/drivers/net/wireless/iwlwifi/iwl-trans.h
-+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
-@@ -601,7 +601,7 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
- {
- int ret;
-
-- if (trans->state != IWL_TRANS_FW_ALIVE) {
-+ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
- return -EIO;
- }
-@@ -640,8 +640,8 @@ static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
- static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
- struct iwl_device_cmd *dev_cmd, int queue)
- {
-- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-- "%s bad state = %d", __func__, trans->state);
-+ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
-+ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- return trans->ops->tx(trans, skb, dev_cmd, queue);
- }
-@@ -649,16 +649,16 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
- static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
- int ssn, struct sk_buff_head *skbs)
- {
-- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-- "%s bad state = %d", __func__, trans->state);
-+ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
-+ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- trans->ops->reclaim(trans, queue, ssn, skbs);
- }
-
- static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue)
- {
-- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-- "%s bad state = %d", __func__, trans->state);
-+ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
-+ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- trans->ops->txq_disable(trans, queue);
- }
-@@ -669,8 +669,8 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
- {
- might_sleep();
-
-- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-- "%s bad state = %d", __func__, trans->state);
-+ if (unlikely((trans->state != IWL_TRANS_FW_ALIVE)))
-+ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- trans->ops->txq_enable(trans, queue, fifo, sta_id, tid,
- frame_limit, ssn);
-@@ -685,8 +685,8 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
-
- static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
- {
-- WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-- "%s bad state = %d", __func__, trans->state);
-+ if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
-+ IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
-
- return trans->ops->wait_tx_queue_empty(trans);
- }
---
-1.7.1
-
diff --git a/3.14.1-rc1.patch b/3.14.1-rc1.patch
new file mode 100644
index 000000000..402957492
--- /dev/null
+++ b/3.14.1-rc1.patch
@@ -0,0 +1,1982 @@
+From tiwai@suse.de Tue Apr 8 14:31:41 2014
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 8 Apr 2014 18:49:00 +0200
+Subject: Revert "ALSA: hda - Increment default stream numbers for AMD HDMI controllers"
+To: stable@vger.kernel.org
+Cc: Anssi Hannula <anssi.hannula@iki.fi>, Christian Güdel <cg@dmesg.ch>
+Message-ID: <1396975740-22160-1-git-send-email-tiwai@suse.de>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+This reverts commit 7546abfb8e1f9933b549f05898377e9444ee4cb2.
+
+The commit [7546abfb: ALSA: hda - Increment default stream numbers for
+AMD HDMI controllers] introduced a regression where the AMD HDMI
+playback streams don't work properly. As the simplest fix, this patch
+reverts that commit.
+
+The upstream code has been changed largely and already contains
+another fix (by changing the stream assignment order), this revert
+should be applied only to 3.14 kernel where the regression was
+introduced.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=77002
+Reported-by: Christian Güdel <cg@dmesg.ch>
+Reported-by: Anssi Hannula <anssi.hannula@iki.fi>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+
+Greg, there is no upstream commit id due to the reason describe in the
+above. It's a simple revert, so please take as is.
+
+thanks,
+
+Takashi
+
+ sound/pci/hda/hda_intel.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -297,9 +297,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO
+ #define ULI_NUM_CAPTURE 5
+ #define ULI_NUM_PLAYBACK 6
+
+-/* ATI HDMI may have up to 8 playbacks and 0 capture */
++/* ATI HDMI has 1 playback and 0 capture */
+ #define ATIHDMI_NUM_CAPTURE 0
+-#define ATIHDMI_NUM_PLAYBACK 8
++#define ATIHDMI_NUM_PLAYBACK 1
+
+ /* TERA has 4 playback and 3 capture */
+ #define TERA_NUM_CAPTURE 3
+From f64410ec665479d7b4b77b7519e814253ed0f686 Mon Sep 17 00:00:00 2001
+From: Paul Moore <pmoore@redhat.com>
+Date: Wed, 19 Mar 2014 16:46:18 -0400
+Subject: selinux: correctly label /proc inodes in use before the policy is loaded
+
+From: Paul Moore <pmoore@redhat.com>
+
+commit f64410ec665479d7b4b77b7519e814253ed0f686 upstream.
+
+This patch is based on an earlier patch by Eric Paris, he describes
+the problem below:
+
+ "If an inode is accessed before policy load it will get placed on a
+ list of inodes to be initialized after policy load. After policy
+ load we call inode_doinit() which calls inode_doinit_with_dentry()
+ on all inodes accessed before policy load. In the case of inodes
+ in procfs that means we'll end up at the bottom where it does:
+
+ /* Default to the fs superblock SID. */
+ isec->sid = sbsec->sid;
+
+ if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
+ if (opt_dentry) {
+ isec->sclass = inode_mode_to_security_class(...)
+ rc = selinux_proc_get_sid(opt_dentry,
+ isec->sclass,
+ &sid);
+ if (rc)
+ goto out_unlock;
+ isec->sid = sid;
+ }
+ }
+
+ Since opt_dentry is null, we'll never call selinux_proc_get_sid()
+ and will leave the inode labeled with the label on the superblock.
+ I believe a fix would be to mimic the behavior of xattrs. Look
+ for an alias of the inode. If it can't be found, just leave the
+ inode uninitialized (and pick it up later) if it can be found, we
+ should be able to call selinux_proc_get_sid() ..."
+
+On a system exhibiting this problem, you will notice a lot of files in
+/proc with the generic "proc_t" type (at least the ones that were
+accessed early in the boot), for example:
+
+ # ls -Z /proc/sys/kernel/shmmax | awk '{ print $4 " " $5 }'
+ system_u:object_r:proc_t:s0 /proc/sys/kernel/shmmax
+
+However, with this patch in place we see the expected result:
+
+ # ls -Z /proc/sys/kernel/shmmax | awk '{ print $4 " " $5 }'
+ system_u:object_r:sysctl_kernel_t:s0 /proc/sys/kernel/shmmax
+
+Cc: Eric Paris <eparis@redhat.com>
+Signed-off-by: Paul Moore <pmoore@redhat.com>
+Acked-by: Eric Paris <eparis@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/selinux/hooks.c | 36 +++++++++++++++++++++++++++---------
+ 1 file changed, 27 insertions(+), 9 deletions(-)
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1418,15 +1418,33 @@ static int inode_doinit_with_dentry(stru
+ isec->sid = sbsec->sid;
+
+ if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
+- if (opt_dentry) {
+- isec->sclass = inode_mode_to_security_class(inode->i_mode);
+- rc = selinux_proc_get_sid(opt_dentry,
+- isec->sclass,
+- &sid);
+- if (rc)
+- goto out_unlock;
+- isec->sid = sid;
+- }
++ /* We must have a dentry to determine the label on
++ * procfs inodes */
++ if (opt_dentry)
++ /* Called from d_instantiate or
++ * d_splice_alias. */
++ dentry = dget(opt_dentry);
++ else
++ /* Called from selinux_complete_init, try to
++ * find a dentry. */
++ dentry = d_find_alias(inode);
++ /*
++ * This can be hit on boot when a file is accessed
++ * before the policy is loaded. When we load policy we
++ * may find inodes that have no dentry on the
++ * sbsec->isec_head list. No reason to complain as
++ * these will get fixed up the next time we go through
++ * inode_doinit() with a dentry, before these inodes
++ * could be used again by userspace.
++ */
++ if (!dentry)
++ goto out_unlock;
++ isec->sclass = inode_mode_to_security_class(inode->i_mode);
++ rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
++ dput(dentry);
++ if (rc)
++ goto out_unlock;
++ isec->sid = sid;
+ }
+ break;
+ }
+From 42a5477251f0e0f33ad5f6a95c48d685ec03191e Mon Sep 17 00:00:00 2001
+From: Borislav Petkov <bp@suse.de>
+Date: Sat, 18 Jan 2014 12:48:16 +0100
+Subject: x86, pageattr: Export page unmapping interface
+
+From: Borislav Petkov <bp@suse.de>
+
+commit 42a5477251f0e0f33ad5f6a95c48d685ec03191e upstream.
+
+We will use it in efi so expose it.
+
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Tested-by: Toshi Kani <toshi.kani@hp.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/pgtable_types.h | 2 +
+ arch/x86/mm/pageattr.c | 44 ++++++++++++++++++++++++-----------
+ 2 files changed, 33 insertions(+), 13 deletions(-)
+
+--- a/arch/x86/include/asm/pgtable_types.h
++++ b/arch/x86/include/asm/pgtable_types.h
+@@ -385,6 +385,8 @@ extern pte_t *lookup_address(unsigned lo
+ extern phys_addr_t slow_virt_to_phys(void *__address);
+ extern int kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn, unsigned long address,
+ unsigned numpages, unsigned long page_flags);
++void kernel_unmap_pages_in_pgd(pgd_t *root, unsigned long address,
++ unsigned numpages);
+ #endif /* !__ASSEMBLY__ */
+
+ #endif /* _ASM_X86_PGTABLE_DEFS_H */
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -692,6 +692,18 @@ static bool try_to_free_pmd_page(pmd_t *
+ return true;
+ }
+
++static bool try_to_free_pud_page(pud_t *pud)
++{
++ int i;
++
++ for (i = 0; i < PTRS_PER_PUD; i++)
++ if (!pud_none(pud[i]))
++ return false;
++
++ free_page((unsigned long)pud);
++ return true;
++}
++
+ static bool unmap_pte_range(pmd_t *pmd, unsigned long start, unsigned long end)
+ {
+ pte_t *pte = pte_offset_kernel(pmd, start);
+@@ -805,6 +817,16 @@ static void unmap_pud_range(pgd_t *pgd,
+ */
+ }
+
++static void unmap_pgd_range(pgd_t *root, unsigned long addr, unsigned long end)
++{
++ pgd_t *pgd_entry = root + pgd_index(addr);
++
++ unmap_pud_range(pgd_entry, addr, end);
++
++ if (try_to_free_pud_page((pud_t *)pgd_page_vaddr(*pgd_entry)))
++ pgd_clear(pgd_entry);
++}
++
+ static int alloc_pte_page(pmd_t *pmd)
+ {
+ pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
+@@ -999,9 +1021,8 @@ static int populate_pud(struct cpa_data
+ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
+ {
+ pgprot_t pgprot = __pgprot(_KERNPG_TABLE);
+- bool allocd_pgd = false;
+- pgd_t *pgd_entry;
+ pud_t *pud = NULL; /* shut up gcc */
++ pgd_t *pgd_entry;
+ int ret;
+
+ pgd_entry = cpa->pgd + pgd_index(addr);
+@@ -1015,7 +1036,6 @@ static int populate_pgd(struct cpa_data
+ return -1;
+
+ set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
+- allocd_pgd = true;
+ }
+
+ pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
+@@ -1023,19 +1043,11 @@ static int populate_pgd(struct cpa_data
+
+ ret = populate_pud(cpa, addr, pgd_entry, pgprot);
+ if (ret < 0) {
+- unmap_pud_range(pgd_entry, addr,
++ unmap_pgd_range(cpa->pgd, addr,
+ addr + (cpa->numpages << PAGE_SHIFT));
+-
+- if (allocd_pgd) {
+- /*
+- * If I allocated this PUD page, I can just as well
+- * free it in this error path.
+- */
+- pgd_clear(pgd_entry);
+- free_page((unsigned long)pud);
+- }
+ return ret;
+ }
++
+ cpa->numpages = ret;
+ return 0;
+ }
+@@ -1861,6 +1873,12 @@ out:
+ return retval;
+ }
+
++void kernel_unmap_pages_in_pgd(pgd_t *root, unsigned long address,
++ unsigned numpages)
++{
++ unmap_pgd_range(root, address, address + (numpages << PAGE_SHIFT));
++}
++
+ /*
+ * The testcases use internal knowledge of the implementation that shouldn't
+ * be exposed to the rest of the kernel. Include these directly here.
+From b7b898ae0c0a82489511a1ce1b35f26215e6beb5 Mon Sep 17 00:00:00 2001
+From: Borislav Petkov <bp@suse.de>
+Date: Sat, 18 Jan 2014 12:48:17 +0100
+Subject: x86/efi: Make efi virtual runtime map passing more robust
+
+From: Borislav Petkov <bp@suse.de>
+
+commit b7b898ae0c0a82489511a1ce1b35f26215e6beb5 upstream.
+
+Currently, running SetVirtualAddressMap() and passing the physical
+address of the virtual map array was working only by a lucky coincidence
+because the memory was present in the EFI page table too. Until Toshi
+went and booted this on a big HP box - the krealloc() manner of resizing
+the memmap we're doing did allocate from such physical addresses which
+were not mapped anymore and boom:
+
+http://lkml.kernel.org/r/1386806463.1791.295.camel@misato.fc.hp.com
+
+One way to take care of that issue is to reimplement the krealloc thing
+but with pages. We start with contiguous pages of order 1, i.e. 2 pages,
+and when we deplete that memory (shouldn't happen all that often but you
+know firmware) we realloc the next power-of-two pages.
+
+Having the pages, it is much more handy and easy to map them into the
+EFI page table with the already existing mapping code which we're using
+for building the virtual mappings.
+
+Thanks to Toshi Kani and Matt for the great debugging help.
+
+Reported-by: Toshi Kani <toshi.kani@hp.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Tested-by: Toshi Kani <toshi.kani@hp.com>
+Signed-off-by: Matt Fleming <matt.fleming@intel.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/efi.h | 3 -
+ arch/x86/platform/efi/efi.c | 99 ++++++++++++++++++++++++++++++++---------
+ arch/x86/platform/efi/efi_32.c | 7 ++
+ arch/x86/platform/efi/efi_64.c | 32 ++++++++++++-
+ 4 files changed, 115 insertions(+), 26 deletions(-)
+
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -130,7 +130,8 @@ extern void efi_memory_uc(u64 addr, unsi
+ extern void __init efi_map_region(efi_memory_desc_t *md);
+ extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
+ extern void efi_sync_low_kernel_mappings(void);
+-extern void efi_setup_page_tables(void);
++extern int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages);
++extern void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages);
+ extern void __init old_map_region(efi_memory_desc_t *md);
+ extern void __init runtime_code_page_mkexec(void);
+ extern void __init efi_runtime_mkexec(void);
+--- a/arch/x86/platform/efi/efi.c
++++ b/arch/x86/platform/efi/efi.c
+@@ -939,14 +939,36 @@ static void __init efi_map_regions_fixed
+
+ }
+
++static void *realloc_pages(void *old_memmap, int old_shift)
++{
++ void *ret;
++
++ ret = (void *)__get_free_pages(GFP_KERNEL, old_shift + 1);
++ if (!ret)
++ goto out;
++
++ /*
++ * A first-time allocation doesn't have anything to copy.
++ */
++ if (!old_memmap)
++ return ret;
++
++ memcpy(ret, old_memmap, PAGE_SIZE << old_shift);
++
++out:
++ free_pages((unsigned long)old_memmap, old_shift);
++ return ret;
++}
++
+ /*
+- * Map efi memory ranges for runtime serivce and update new_memmap with virtual
+- * addresses.
++ * Map the efi memory ranges of the runtime services and update new_mmap with
++ * virtual addresses.
+ */
+-static void * __init efi_map_regions(int *count)
++static void * __init efi_map_regions(int *count, int *pg_shift)
+ {
++ void *p, *new_memmap = NULL;
++ unsigned long left = 0;
+ efi_memory_desc_t *md;
+- void *p, *tmp, *new_memmap = NULL;
+
+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+ md = p;
+@@ -961,20 +983,23 @@ static void * __init efi_map_regions(int
+ efi_map_region(md);
+ get_systab_virt_addr(md);
+
+- tmp = krealloc(new_memmap, (*count + 1) * memmap.desc_size,
+- GFP_KERNEL);
+- if (!tmp)
+- goto out;
+- new_memmap = tmp;
++ if (left < memmap.desc_size) {
++ new_memmap = realloc_pages(new_memmap, *pg_shift);
++ if (!new_memmap)
++ return NULL;
++
++ left += PAGE_SIZE << *pg_shift;
++ (*pg_shift)++;
++ }
++
+ memcpy(new_memmap + (*count * memmap.desc_size), md,
+ memmap.desc_size);
++
++ left -= memmap.desc_size;
+ (*count)++;
+ }
+
+ return new_memmap;
+-out:
+- kfree(new_memmap);
+- return NULL;
+ }
+
+ /*
+@@ -1000,9 +1025,9 @@ out:
+ */
+ void __init efi_enter_virtual_mode(void)
+ {
+- efi_status_t status;
++ int err, count = 0, pg_shift = 0;
+ void *new_memmap = NULL;
+- int err, count = 0;
++ efi_status_t status;
+
+ efi.systab = NULL;
+
+@@ -1019,20 +1044,24 @@ void __init efi_enter_virtual_mode(void)
+ efi_map_regions_fixed();
+ } else {
+ efi_merge_regions();
+- new_memmap = efi_map_regions(&count);
++ new_memmap = efi_map_regions(&count, &pg_shift);
+ if (!new_memmap) {
+ pr_err("Error reallocating memory, EFI runtime non-functional!\n");
+ return;
+ }
+- }
+
+- err = save_runtime_map();
+- if (err)
+- pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
++ err = save_runtime_map();
++ if (err)
++ pr_err("Error saving runtime map, efi runtime on kexec non-functional!!\n");
++ }
+
+ BUG_ON(!efi.systab);
+
+- efi_setup_page_tables();
++ if (!efi_setup) {
++ if (efi_setup_page_tables(__pa(new_memmap), 1 << pg_shift))
++ return;
++ }
++
+ efi_sync_low_kernel_mappings();
+
+ if (!efi_setup) {
+@@ -1072,7 +1101,35 @@ void __init efi_enter_virtual_mode(void)
+
+ efi_runtime_mkexec();
+
+- kfree(new_memmap);
++
++ /*
++ * We mapped the descriptor array into the EFI pagetable above but we're
++ * not unmapping it here. Here's why:
++ *
++ * We're copying select PGDs from the kernel page table to the EFI page
++ * table and when we do so and make changes to those PGDs like unmapping
++ * stuff from them, those changes appear in the kernel page table and we
++ * go boom.
++ *
++ * From setup_real_mode():
++ *
++ * ...
++ * trampoline_pgd[0] = init_level4_pgt[pgd_index(__PAGE_OFFSET)].pgd;
++ *
++ * In this particular case, our allocation is in PGD 0 of the EFI page
++ * table but we've copied that PGD from PGD[272] of the EFI page table:
++ *
++ * pgd_index(__PAGE_OFFSET = 0xffff880000000000) = 272
++ *
++ * where the direct memory mapping in kernel space is.
++ *
++ * new_memmap's VA comes from that direct mapping and thus clearing it,
++ * it would get cleared in the kernel page table too.
++ *
++ * efi_cleanup_page_tables(__pa(new_memmap), 1 << pg_shift);
++ */
++ if (!efi_setup)
++ free_pages((unsigned long)new_memmap, pg_shift);
+
+ /* clean DUMMY object */
+ efi.set_variable(efi_dummy_name, &EFI_DUMMY_GUID,
+--- a/arch/x86/platform/efi/efi_32.c
++++ b/arch/x86/platform/efi/efi_32.c
+@@ -40,7 +40,12 @@
+ static unsigned long efi_rt_eflags;
+
+ void efi_sync_low_kernel_mappings(void) {}
+-void efi_setup_page_tables(void) {}
++void __init efi_dump_pagetable(void) {}
++int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
++{
++ return 0;
++}
++void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages) {}
+
+ void __init efi_map_region(efi_memory_desc_t *md)
+ {
+--- a/arch/x86/platform/efi/efi_64.c
++++ b/arch/x86/platform/efi/efi_64.c
+@@ -137,12 +137,38 @@ void efi_sync_low_kernel_mappings(void)
+ sizeof(pgd_t) * num_pgds);
+ }
+
+-void efi_setup_page_tables(void)
++int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
+ {
++ pgd_t *pgd;
++
++ if (efi_enabled(EFI_OLD_MEMMAP))
++ return 0;
++
+ efi_scratch.efi_pgt = (pgd_t *)(unsigned long)real_mode_header->trampoline_pgd;
++ pgd = __va(efi_scratch.efi_pgt);
++
++ /*
++ * It can happen that the physical address of new_memmap lands in memory
++ * which is not mapped in the EFI page table. Therefore we need to go
++ * and ident-map those pages containing the map before calling
++ * phys_efi_set_virtual_address_map().
++ */
++ if (kernel_map_pages_in_pgd(pgd, pa_memmap, pa_memmap, num_pages, _PAGE_NX)) {
++ pr_err("Error ident-mapping new memmap (0x%lx)!\n", pa_memmap);
++ return 1;
++ }
++
++ efi_scratch.use_pgd = true;
++
++
++ return 0;
++}
++
++void efi_cleanup_page_tables(unsigned long pa_memmap, unsigned num_pages)
++{
++ pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
+
+- if (!efi_enabled(EFI_OLD_MEMMAP))
+- efi_scratch.use_pgd = true;
++ kernel_unmap_pages_in_pgd(pgd, pa_memmap, num_pages);
+ }
+
+ static void __init __map_region(efi_memory_desc_t *md, u64 va)
+From 69cd9eba38867a493a043bb13eb9b33cad5f1a9a Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 8 Apr 2014 15:30:07 -0700
+Subject: futex: avoid race between requeue and wake
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 69cd9eba38867a493a043bb13eb9b33cad5f1a9a upstream.
+
+Jan Stancek reported:
+ "pthread_cond_broadcast/4-1.c testcase from openposix testsuite (LTP)
+ occasionally fails, because some threads fail to wake up.
+
+ Testcase creates 5 threads, which are all waiting on same condition.
+ Main thread then calls pthread_cond_broadcast() without holding mutex,
+ which calls:
+
+ futex(uaddr1, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, uaddr2, ..)
+
+ This immediately wakes up single thread A, which unlocks mutex and
+ tries to wake up another thread:
+
+ futex(uaddr2, FUTEX_WAKE_PRIVATE, 1)
+
+ If thread A manages to call futex_wake() before any waiters are
+ requeued for uaddr2, no other thread is woken up"
+
+The ordering constraints for the hash bucket waiter counting are that
+the waiter counts have to be incremented _before_ getting the spinlock
+(because the spinlock acts as part of the memory barrier), but the
+"requeue" operation didn't honor those rules, and nobody had even
+thought about that case.
+
+This fairly simple patch just increments the waiter count for the target
+hash bucket (hb2) when requeing a futex before taking the locks. It
+then decrements them again after releasing the lock - the code that
+actually moves the futex(es) between hash buckets will do the additional
+required waiter count housekeeping.
+
+Reported-and-tested-by: Jan Stancek <jstancek@redhat.com>
+Acked-by: Davidlohr Bueso <davidlohr@hp.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/futex.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1450,6 +1450,7 @@ retry:
+ hb2 = hash_futex(&key2);
+
+ retry_private:
++ hb_waiters_inc(hb2);
+ double_lock_hb(hb1, hb2);
+
+ if (likely(cmpval != NULL)) {
+@@ -1459,6 +1460,7 @@ retry_private:
+
+ if (unlikely(ret)) {
+ double_unlock_hb(hb1, hb2);
++ hb_waiters_dec(hb2);
+
+ ret = get_user(curval, uaddr1);
+ if (ret)
+@@ -1508,6 +1510,7 @@ retry_private:
+ break;
+ case -EFAULT:
+ double_unlock_hb(hb1, hb2);
++ hb_waiters_dec(hb2);
+ put_futex_key(&key2);
+ put_futex_key(&key1);
+ ret = fault_in_user_writeable(uaddr2);
+@@ -1517,6 +1520,7 @@ retry_private:
+ case -EAGAIN:
+ /* The owner was exiting, try again. */
+ double_unlock_hb(hb1, hb2);
++ hb_waiters_dec(hb2);
+ put_futex_key(&key2);
+ put_futex_key(&key1);
+ cond_resched();
+@@ -1592,6 +1596,7 @@ retry_private:
+
+ out_unlock:
+ double_unlock_hb(hb1, hb2);
++ hb_waiters_dec(hb2);
+
+ /*
+ * drop_futex_key_refs() must be called outside the spinlocks. During
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Paul Durrant <Paul.Durrant@citrix.com>
+Date: Fri, 28 Mar 2014 11:39:05 +0000
+Subject: xen-netback: remove pointless clause from if statement
+
+From: Paul Durrant <Paul.Durrant@citrix.com>
+
+[ Upstream commit 0576eddf24df716d8570ef8ca11452a9f98eaab2 ]
+
+This patch removes a test in start_new_rx_buffer() that checks whether
+a copy operation is less than MAX_BUFFER_OFFSET in length, since
+MAX_BUFFER_OFFSET is defined to be PAGE_SIZE and the only caller of
+start_new_rx_buffer() already limits copy operations to PAGE_SIZE or less.
+
+Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
+Cc: Ian Campbell <ian.campbell@citrix.com>
+Cc: Wei Liu <wei.liu2@citrix.com>
+Cc: Sander Eikelenboom <linux@eikelenboom.it>
+Reported-By: Sander Eikelenboom <linux@eikelenboom.it>
+Tested-By: Sander Eikelenboom <linux@eikelenboom.it>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/xen-netback/netback.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/xen-netback/netback.c
++++ b/drivers/net/xen-netback/netback.c
+@@ -192,8 +192,8 @@ static bool start_new_rx_buffer(int offs
+ * into multiple copies tend to give large frags their
+ * own buffers as before.
+ */
+- if ((offset + size > MAX_BUFFER_OFFSET) &&
+- (size <= MAX_BUFFER_OFFSET) && offset && !head)
++ BUG_ON(size > MAX_BUFFER_OFFSET);
++ if ((offset + size > MAX_BUFFER_OFFSET) && offset && !head)
+ return true;
+
+ return false;
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Paul Durrant <Paul.Durrant@citrix.com>
+Date: Fri, 28 Mar 2014 11:39:06 +0000
+Subject: xen-netback: worse-case estimate in xenvif_rx_action is underestimating
+
+From: Paul Durrant <Paul.Durrant@citrix.com>
+
+[ Upstream commit a02eb4732cf975d7fc71b6d1a71c058c9988b949 ]
+
+The worse-case estimate for skb ring slot usage in xenvif_rx_action()
+fails to take fragment page_offset into account. The page_offset does,
+however, affect the number of times the fragmentation code calls
+start_new_rx_buffer() (i.e. consume another slot) and the worse-case
+should assume that will always return true. This patch adds the page_offset
+into the DIV_ROUND_UP for each frag.
+
+Unfortunately some frontends aggressively limit the number of requests
+they post into the shared ring so to avoid an estimate that is 'too'
+pessimal it is capped at MAX_SKB_FRAGS.
+
+Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
+Cc: Ian Campbell <ian.campbell@citrix.com>
+Cc: Wei Liu <wei.liu2@citrix.com>
+Cc: Sander Eikelenboom <linux@eikelenboom.it>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/xen-netback/netback.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/xen-netback/netback.c
++++ b/drivers/net/xen-netback/netback.c
+@@ -493,9 +493,28 @@ static void xenvif_rx_action(struct xenv
+ PAGE_SIZE);
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ unsigned int size;
++ unsigned int offset;
++
+ size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+- max_slots_needed += DIV_ROUND_UP(size, PAGE_SIZE);
++ offset = skb_shinfo(skb)->frags[i].page_offset;
++
++ /* For a worse-case estimate we need to factor in
++ * the fragment page offset as this will affect the
++ * number of times xenvif_gop_frag_copy() will
++ * call start_new_rx_buffer().
++ */
++ max_slots_needed += DIV_ROUND_UP(offset + size,
++ PAGE_SIZE);
+ }
++
++ /* To avoid the estimate becoming too pessimal for some
++ * frontends that limit posted rx requests, cap the estimate
++ * at MAX_SKB_FRAGS.
++ */
++ if (max_slots_needed > MAX_SKB_FRAGS)
++ max_slots_needed = MAX_SKB_FRAGS;
++
++ /* We may need one more slot for GSO metadata */
+ if (skb_is_gso(skb) &&
+ (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 ||
+ skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6))
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Paul Durrant <Paul.Durrant@citrix.com>
+Date: Fri, 28 Mar 2014 11:39:07 +0000
+Subject: xen-netback: BUG_ON in xenvif_rx_action() not catching overflow
+
+From: Paul Durrant <Paul.Durrant@citrix.com>
+
+[ Upstream commit 1425c7a4e8d3d2eebf308bcbdc3fa3c1247686b4 ]
+
+The BUG_ON to catch ring overflow in xenvif_rx_action() makes the assumption
+that meta_slots_used == ring slots used. This is not necessarily the case
+for GSO packets, because the non-prefix GSO protocol consumes one more ring
+slot than meta-slot for the 'extra_info'. This patch changes the test to
+actually check ring slots.
+
+Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
+Cc: Ian Campbell <ian.campbell@citrix.com>
+Cc: Wei Liu <wei.liu2@citrix.com>
+Cc: Sander Eikelenboom <linux@eikelenboom.it>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/xen-netback/netback.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/xen-netback/netback.c
++++ b/drivers/net/xen-netback/netback.c
+@@ -482,6 +482,8 @@ static void xenvif_rx_action(struct xenv
+
+ while ((skb = skb_dequeue(&vif->rx_queue)) != NULL) {
+ RING_IDX max_slots_needed;
++ RING_IDX old_req_cons;
++ RING_IDX ring_slots_used;
+ int i;
+
+ /* We need a cheap worse case estimate for the number of
+@@ -530,8 +532,12 @@ static void xenvif_rx_action(struct xenv
+ vif->rx_last_skb_slots = 0;
+
+ sco = (struct skb_cb_overlay *)skb->cb;
++
++ old_req_cons = vif->rx.req_cons;
+ sco->meta_slots_used = xenvif_gop_skb(skb, &npo);
+- BUG_ON(sco->meta_slots_used > max_slots_needed);
++ ring_slots_used = vif->rx.req_cons - old_req_cons;
++
++ BUG_ON(ring_slots_used > max_slots_needed);
+
+ __skb_queue_tail(&rxq, skb);
+ }
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Date: Mon, 31 Mar 2014 20:14:10 +0200
+Subject: ipv6: some ipv6 statistic counters failed to disable bh
+
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+
+[ Upstream commit 43a43b6040165f7b40b5b489fe61a4cb7f8c4980 ]
+
+After commit c15b1ccadb323ea ("ipv6: move DAD and addrconf_verify
+processing to workqueue") some counters are now updated in process context
+and thus need to disable bh before doing so, otherwise deadlocks can
+happen on 32-bit archs. Fabio Estevam noticed this while while mounting
+a NFS volume on an ARM board.
+
+As a compensation for missing this I looked after the other *_STATS_BH
+and found three other calls which need updating:
+
+1) icmp6_send: ip6_fragment -> icmpv6_send -> icmp6_send (error handling)
+2) ip6_push_pending_frames: rawv6_sendmsg -> rawv6_push_pending_frames -> ...
+ (only in case of icmp protocol with raw sockets in error handling)
+3) ping6_v6_sendmsg (error handling)
+
+Fixes: c15b1ccadb323ea ("ipv6: move DAD and addrconf_verify processing to workqueue")
+Reported-by: Fabio Estevam <festevam@gmail.com>
+Tested-by: Fabio Estevam <fabio.estevam@freescale.com>
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/icmp.c | 2 +-
+ net/ipv6/ip6_output.c | 4 ++--
+ net/ipv6/mcast.c | 11 ++++++-----
+ net/ipv6/ping.c | 4 ++--
+ 4 files changed, 11 insertions(+), 10 deletions(-)
+
+--- a/net/ipv6/icmp.c
++++ b/net/ipv6/icmp.c
+@@ -520,7 +520,7 @@ static void icmp6_send(struct sk_buff *s
+ np->tclass, NULL, &fl6, (struct rt6_info *)dst,
+ MSG_DONTWAIT, np->dontfrag);
+ if (err) {
+- ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
++ ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
+ ip6_flush_pending_frames(sk);
+ } else {
+ err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -1566,8 +1566,8 @@ int ip6_push_pending_frames(struct sock
+ if (proto == IPPROTO_ICMPV6) {
+ struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+
+- ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type);
+- ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
++ ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type);
++ ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
+ }
+
+ err = ip6_local_out(skb);
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1620,11 +1620,12 @@ static void mld_sendpack(struct sk_buff
+ dst_output);
+ out:
+ if (!err) {
+- ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
+- ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+- IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
+- } else
+- IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
++ ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
++ ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
++ IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
++ } else {
++ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
++ }
+
+ rcu_read_unlock();
+ return;
+--- a/net/ipv6/ping.c
++++ b/net/ipv6/ping.c
+@@ -182,8 +182,8 @@ int ping_v6_sendmsg(struct kiocb *iocb,
+ MSG_DONTWAIT, np->dontfrag);
+
+ if (err) {
+- ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev,
+- ICMP6_MIB_OUTERRORS);
++ ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev,
++ ICMP6_MIB_OUTERRORS);
+ ip6_flush_pending_frames(sk);
+ } else {
+ err = icmpv6_push_pending_frames(sk, &fl6,
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Pablo Neira <pablo@netfilter.org>
+Date: Tue, 1 Apr 2014 19:38:44 +0200
+Subject: netlink: don't compare the nul-termination in nla_strcmp
+
+From: Pablo Neira <pablo@netfilter.org>
+
+[ Upstream commit 8b7b932434f5eee495b91a2804f5b64ebb2bc835 ]
+
+nla_strcmp compares the string length plus one, so it's implicitly
+including the nul-termination in the comparison.
+
+ int nla_strcmp(const struct nlattr *nla, const char *str)
+ {
+ int len = strlen(str) + 1;
+ ...
+ d = memcmp(nla_data(nla), str, len);
+
+However, if NLA_STRING is used, userspace can send us a string without
+the nul-termination. This is a problem since the string
+comparison will not match as the last byte may be not the
+nul-termination.
+
+Fix this by skipping the comparison of the nul-termination if the
+attribute data is nul-terminated. Suggested by Thomas Graf.
+
+Cc: Florian Westphal <fw@strlen.de>
+Cc: Thomas Graf <tgraf@suug.ch>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ lib/nlattr.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/lib/nlattr.c
++++ b/lib/nlattr.c
+@@ -303,9 +303,15 @@ int nla_memcmp(const struct nlattr *nla,
+ */
+ int nla_strcmp(const struct nlattr *nla, const char *str)
+ {
+- int len = strlen(str) + 1;
+- int d = nla_len(nla) - len;
++ int len = strlen(str);
++ char *buf = nla_data(nla);
++ int attrlen = nla_len(nla);
++ int d;
+
++ if (attrlen > 0 && buf[attrlen - 1] == '\0')
++ attrlen--;
++
++ d = attrlen - len;
+ if (d == 0)
+ d = memcmp(nla_data(nla), str, len);
+
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Wei Liu <wei.liu2@citrix.com>
+Date: Tue, 1 Apr 2014 12:46:12 +0100
+Subject: xen-netback: disable rogue vif in kthread context
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Wei Liu <wei.liu2@citrix.com>
+
+[ Upstream commit e9d8b2c2968499c1f96563e6522c56958d5a1d0d ]
+
+When netback discovers frontend is sending malformed packet it will
+disables the interface which serves that frontend.
+
+However disabling a network interface involving taking a mutex which
+cannot be done in softirq context, so we need to defer this process to
+kthread context.
+
+This patch does the following:
+1. introduce a flag to indicate the interface is disabled.
+2. check that flag in TX path, don't do any work if it's true.
+3. check that flag in RX path, turn off that interface if it's true.
+
+The reason to disable it in RX path is because RX uses kthread. After
+this change the behavior of netback is still consistent -- it won't do
+any TX work for a rogue frontend, and the interface will be eventually
+turned off.
+
+Also change a "continue" to "break" after xenvif_fatal_tx_err, as it
+doesn't make sense to continue processing packets if frontend is rogue.
+
+This is a fix for XSA-90.
+
+Reported-by: Török Edwin <edwin@etorok.net>
+Signed-off-by: Wei Liu <wei.liu2@citrix.com>
+Cc: Ian Campbell <ian.campbell@citrix.com>
+Reviewed-by: David Vrabel <david.vrabel@citrix.com>
+Acked-by: Ian Campbell <ian.campbell@citrix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/xen-netback/common.h | 5 +++++
+ drivers/net/xen-netback/interface.c | 11 +++++++++++
+ drivers/net/xen-netback/netback.c | 16 ++++++++++++++--
+ 3 files changed, 30 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/xen-netback/common.h
++++ b/drivers/net/xen-netback/common.h
+@@ -113,6 +113,11 @@ struct xenvif {
+ domid_t domid;
+ unsigned int handle;
+
++ /* Is this interface disabled? True when backend discovers
++ * frontend is rogue.
++ */
++ bool disabled;
++
+ /* Use NAPI for guest TX */
+ struct napi_struct napi;
+ /* When feature-split-event-channels = 0, tx_irq = rx_irq. */
+--- a/drivers/net/xen-netback/interface.c
++++ b/drivers/net/xen-netback/interface.c
+@@ -62,6 +62,15 @@ static int xenvif_poll(struct napi_struc
+ struct xenvif *vif = container_of(napi, struct xenvif, napi);
+ int work_done;
+
++ /* This vif is rogue, we pretend we've there is nothing to do
++ * for this vif to deschedule it from NAPI. But this interface
++ * will be turned off in thread context later.
++ */
++ if (unlikely(vif->disabled)) {
++ napi_complete(napi);
++ return 0;
++ }
++
+ work_done = xenvif_tx_action(vif, budget);
+
+ if (work_done < budget) {
+@@ -321,6 +330,8 @@ struct xenvif *xenvif_alloc(struct devic
+ vif->ip_csum = 1;
+ vif->dev = dev;
+
++ vif->disabled = false;
++
+ vif->credit_bytes = vif->remaining_credit = ~0UL;
+ vif->credit_usec = 0UL;
+ init_timer(&vif->credit_timeout);
+--- a/drivers/net/xen-netback/netback.c
++++ b/drivers/net/xen-netback/netback.c
+@@ -680,7 +680,8 @@ static void xenvif_tx_err(struct xenvif
+ static void xenvif_fatal_tx_err(struct xenvif *vif)
+ {
+ netdev_err(vif->dev, "fatal error; disabling device\n");
+- xenvif_carrier_off(vif);
++ vif->disabled = true;
++ xenvif_kick_thread(vif);
+ }
+
+ static int xenvif_count_requests(struct xenvif *vif,
+@@ -1151,7 +1152,7 @@ static unsigned xenvif_tx_build_gops(str
+ vif->tx.sring->req_prod, vif->tx.req_cons,
+ XEN_NETIF_TX_RING_SIZE);
+ xenvif_fatal_tx_err(vif);
+- continue;
++ break;
+ }
+
+ work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
+@@ -1573,7 +1574,18 @@ int xenvif_kthread(void *data)
+ while (!kthread_should_stop()) {
+ wait_event_interruptible(vif->wq,
+ rx_work_todo(vif) ||
++ vif->disabled ||
+ kthread_should_stop());
++
++ /* This frontend is found to be rogue, disable it in
++ * kthread context. Currently this is only set when
++ * netback finds out frontend sends malformed packet,
++ * but we cannot disable the interface in softirq
++ * context so we defer it here.
++ */
++ if (unlikely(vif->disabled && netif_carrier_ok(vif->dev)))
++ xenvif_carrier_off(vif);
++
+ if (kthread_should_stop())
+ break;
+
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Daniel Pieczko <dpieczko@solarflare.com>
+Date: Tue, 1 Apr 2014 13:10:34 +0100
+Subject: Call efx_set_channels() before efx->type->dimension_resources()
+
+From: Daniel Pieczko <dpieczko@solarflare.com>
+
+[ Upstream commit 52ad762b85ed7947ec9eff6b036eb985352f6874 ]
+
+When using the "separate_tx_channels=1" module parameter, the TX queues are
+initially numbered starting from the first TX-only channel number (after all the
+RX-only channels). efx_set_channels() renumbers the queues so that they are
+indexed from zero.
+
+On EF10, the TX queues need to be relabelled in this way before calling the
+dimension_resources NIC type operation, otherwise the TX queue PIO buffers can be
+linked to the wrong VIs when using "separate_tx_channels=1".
+
+Added comments to explain UC/WC mappings for PIO buffers
+
+Signed-off-by: Shradha Shah <sshah@solarflare.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/sfc/ef10.c | 7 +++++++
+ drivers/net/ethernet/sfc/efx.c | 3 ++-
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/sfc/ef10.c
++++ b/drivers/net/ethernet/sfc/ef10.c
+@@ -565,10 +565,17 @@ static int efx_ef10_dimension_resources(
+ * several of each (in fact that's the only option if host
+ * page size is >4K). So we may allocate some extra VIs just
+ * for writing PIO buffers through.
++ *
++ * The UC mapping contains (min_vis - 1) complete VIs and the
++ * first half of the next VI. Then the WC mapping begins with
++ * the second half of this last VI.
+ */
+ uc_mem_map_size = PAGE_ALIGN((min_vis - 1) * EFX_VI_PAGE_SIZE +
+ ER_DZ_TX_PIOBUF);
+ if (nic_data->n_piobufs) {
++ /* pio_write_vi_base rounds down to give the number of complete
++ * VIs inside the UC mapping.
++ */
+ pio_write_vi_base = uc_mem_map_size / EFX_VI_PAGE_SIZE;
+ wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base +
+ nic_data->n_piobufs) *
+--- a/drivers/net/ethernet/sfc/efx.c
++++ b/drivers/net/ethernet/sfc/efx.c
+@@ -1603,6 +1603,8 @@ static int efx_probe_nic(struct efx_nic
+ if (rc)
+ goto fail1;
+
++ efx_set_channels(efx);
++
+ rc = efx->type->dimension_resources(efx);
+ if (rc)
+ goto fail2;
+@@ -1613,7 +1615,6 @@ static int efx_probe_nic(struct efx_nic
+ efx->rx_indir_table[i] =
+ ethtool_rxfh_indir_default(i, efx->rss_spread);
+
+- efx_set_channels(efx);
+ netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels);
+ netif_set_real_num_rx_queues(efx->net_dev, efx->n_rx_channels);
+
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Mike Rapoport <mike.rapoport@ravellosystems.com>
+Date: Tue, 1 Apr 2014 09:23:01 +0300
+Subject: net: vxlan: fix crash when interface is created with no group
+
+From: Mike Rapoport <mike.rapoport@ravellosystems.com>
+
+[ Upstream commit 5933a7bbb5de66482ea8aa874a7ebaf8e67603c4 ]
+
+If the vxlan interface is created without explicit group definition,
+there are corner cases which may cause kernel panic.
+
+For instance, in the following scenario:
+
+node A:
+$ ip link add dev vxlan42 address 2c:c2:60:00:10:20 type vxlan id 42
+$ ip addr add dev vxlan42 10.0.0.1/24
+$ ip link set up dev vxlan42
+$ arp -i vxlan42 -s 10.0.0.2 2c:c2:60:00:01:02
+$ bridge fdb add dev vxlan42 to 2c:c2:60:00:01:02 dst <IPv4 address>
+$ ping 10.0.0.2
+
+node B:
+$ ip link add dev vxlan42 address 2c:c2:60:00:01:02 type vxlan id 42
+$ ip addr add dev vxlan42 10.0.0.2/24
+$ ip link set up dev vxlan42
+$ arp -i vxlan42 -s 10.0.0.1 2c:c2:60:00:10:20
+
+node B crashes:
+
+ vxlan42: 2c:c2:60:00:10:20 migrated from 4011:eca4:c0a8:6466:c0a8:6415:8e09:2118 to (invalid address)
+ vxlan42: 2c:c2:60:00:10:20 migrated from 4011:eca4:c0a8:6466:c0a8:6415:8e09:2118 to (invalid address)
+ BUG: unable to handle kernel NULL pointer dereference at 0000000000000046
+ IP: [<ffffffff8143c459>] ip6_route_output+0x58/0x82
+ PGD 7bd89067 PUD 7bd4e067 PMD 0
+ Oops: 0000 [#1] SMP
+ Modules linked in:
+ CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.14.0-rc8-hvx-xen-00019-g97a5221-dirty #154
+ Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+ task: ffff88007c774f50 ti: ffff88007c79c000 task.ti: ffff88007c79c000
+ RIP: 0010:[<ffffffff8143c459>] [<ffffffff8143c459>] ip6_route_output+0x58/0x82
+ RSP: 0018:ffff88007fd03668 EFLAGS: 00010282
+ RAX: 0000000000000000 RBX: ffffffff8186a000 RCX: 0000000000000040
+ RDX: 0000000000000000 RSI: ffff88007b0e4a80 RDI: ffff88007fd03754
+ RBP: ffff88007fd03688 R08: ffff88007b0e4a80 R09: 0000000000000000
+ R10: 0200000a0100000a R11: 0001002200000000 R12: ffff88007fd03740
+ R13: ffff88007b0e4a80 R14: ffff88007b0e4a80 R15: ffff88007bba0c50
+ FS: 0000000000000000(0000) GS:ffff88007fd00000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+ CR2: 0000000000000046 CR3: 000000007bb60000 CR4: 00000000000006e0
+ Stack:
+ 0000000000000000 ffff88007fd037a0 ffffffff8186a000 ffff88007fd03740
+ ffff88007fd036c8 ffffffff814320bb 0000000000006e49 ffff88007b8b7360
+ ffff88007bdbf200 ffff88007bcbc000 ffff88007b8b7000 ffff88007b8b7360
+ Call Trace:
+ <IRQ>
+ [<ffffffff814320bb>] ip6_dst_lookup_tail+0x2d/0xa4
+ [<ffffffff814322a5>] ip6_dst_lookup+0x10/0x12
+ [<ffffffff81323b4e>] vxlan_xmit_one+0x32a/0x68c
+ [<ffffffff814a325a>] ? _raw_spin_unlock_irqrestore+0x12/0x14
+ [<ffffffff8104c551>] ? lock_timer_base.isra.23+0x26/0x4b
+ [<ffffffff8132451a>] vxlan_xmit+0x66a/0x6a8
+ [<ffffffff8141a365>] ? ipt_do_table+0x35f/0x37e
+ [<ffffffff81204ba2>] ? selinux_ip_postroute+0x41/0x26e
+ [<ffffffff8139d0c1>] dev_hard_start_xmit+0x2ce/0x3ce
+ [<ffffffff8139d491>] __dev_queue_xmit+0x2d0/0x392
+ [<ffffffff813b380f>] ? eth_header+0x28/0xb5
+ [<ffffffff8139d569>] dev_queue_xmit+0xb/0xd
+ [<ffffffff813a5aa6>] neigh_resolve_output+0x134/0x152
+ [<ffffffff813db741>] ip_finish_output2+0x236/0x299
+ [<ffffffff813dc074>] ip_finish_output+0x98/0x9d
+ [<ffffffff813dc749>] ip_output+0x62/0x67
+ [<ffffffff813da9f2>] dst_output+0xf/0x11
+ [<ffffffff813dc11c>] ip_local_out+0x1b/0x1f
+ [<ffffffff813dcf1b>] ip_send_skb+0x11/0x37
+ [<ffffffff813dcf70>] ip_push_pending_frames+0x2f/0x33
+ [<ffffffff813ff732>] icmp_push_reply+0x106/0x115
+ [<ffffffff813ff9e4>] icmp_reply+0x142/0x164
+ [<ffffffff813ffb3b>] icmp_echo.part.16+0x46/0x48
+ [<ffffffff813c1d30>] ? nf_iterate+0x43/0x80
+ [<ffffffff813d8037>] ? xfrm4_policy_check.constprop.11+0x52/0x52
+ [<ffffffff813ffb62>] icmp_echo+0x25/0x27
+ [<ffffffff814005f7>] icmp_rcv+0x1d2/0x20a
+ [<ffffffff813d8037>] ? xfrm4_policy_check.constprop.11+0x52/0x52
+ [<ffffffff813d810d>] ip_local_deliver_finish+0xd6/0x14f
+ [<ffffffff813d8037>] ? xfrm4_policy_check.constprop.11+0x52/0x52
+ [<ffffffff813d7fde>] NF_HOOK.constprop.10+0x4c/0x53
+ [<ffffffff813d82bf>] ip_local_deliver+0x4a/0x4f
+ [<ffffffff813d7f7b>] ip_rcv_finish+0x253/0x26a
+ [<ffffffff813d7d28>] ? inet_add_protocol+0x3e/0x3e
+ [<ffffffff813d7fde>] NF_HOOK.constprop.10+0x4c/0x53
+ [<ffffffff813d856a>] ip_rcv+0x2a6/0x2ec
+ [<ffffffff8139a9a0>] __netif_receive_skb_core+0x43e/0x478
+ [<ffffffff812a346f>] ? virtqueue_poll+0x16/0x27
+ [<ffffffff8139aa2f>] __netif_receive_skb+0x55/0x5a
+ [<ffffffff8139aaaa>] process_backlog+0x76/0x12f
+ [<ffffffff8139add8>] net_rx_action+0xa2/0x1ab
+ [<ffffffff81047847>] __do_softirq+0xca/0x1d1
+ [<ffffffff81047ace>] irq_exit+0x3e/0x85
+ [<ffffffff8100b98b>] do_IRQ+0xa9/0xc4
+ [<ffffffff814a37ad>] common_interrupt+0x6d/0x6d
+ <EOI>
+ [<ffffffff810378db>] ? native_safe_halt+0x6/0x8
+ [<ffffffff810110c7>] default_idle+0x9/0xd
+ [<ffffffff81011694>] arch_cpu_idle+0x13/0x1c
+ [<ffffffff8107480d>] cpu_startup_entry+0xbc/0x137
+ [<ffffffff8102e741>] start_secondary+0x1a0/0x1a5
+ Code: 24 14 e8 f1 e5 01 00 31 d2 a8 32 0f 95 c2 49 8b 44 24 2c 49 0b 44 24 24 74 05 83 ca 04 eb 1c 4d 85 ed 74 17 49 8b 85 a8 02 00 00 <66> 8b 40 46 66 c1 e8 07 83 e0 07 c1 e0 03 09 c2 4c 89 e6 48 89
+ RIP [<ffffffff8143c459>] ip6_route_output+0x58/0x82
+ RSP <ffff88007fd03668>
+ CR2: 0000000000000046
+ ---[ end trace 4612329caab37efd ]---
+
+When vxlan interface is created without explicit group definition, the
+default_dst protocol family is initialiazed to AF_UNSPEC and the driver
+assumes IPv4 configuration. On the other side, the default_dst protocol
+family is used to differentiate between IPv4 and IPv6 cases and, since,
+AF_UNSPEC != AF_INET, the processing takes the IPv6 path.
+
+Making the IPv4 assumption explicit by settting default_dst protocol
+family to AF_INET4 and preventing mixing of IPv4 and IPv6 addresses in
+snooped fdb entries fixes the corner case crashes.
+
+Signed-off-by: Mike Rapoport <mike.rapoport@ravellosystems.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vxlan.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -871,6 +871,9 @@ static int vxlan_fdb_add(struct ndmsg *n
+ if (err)
+ return err;
+
++ if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family)
++ return -EAFNOSUPPORT;
++
+ spin_lock_bh(&vxlan->hash_lock);
+ err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags,
+ port, vni, ifindex, ndm->ndm_flags);
+@@ -2612,9 +2615,10 @@ static int vxlan_newlink(struct net *net
+ vni = nla_get_u32(data[IFLA_VXLAN_ID]);
+ dst->remote_vni = vni;
+
++ /* Unless IPv6 is explicitly requested, assume IPv4 */
++ dst->remote_ip.sa.sa_family = AF_INET;
+ if (data[IFLA_VXLAN_GROUP]) {
+ dst->remote_ip.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+- dst->remote_ip.sa.sa_family = AF_INET;
+ } else if (data[IFLA_VXLAN_GROUP6]) {
+ if (!IS_ENABLED(CONFIG_IPV6))
+ return -EPFNOSUPPORT;
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+Date: Wed, 2 Apr 2014 12:48:42 +0900
+Subject: isdnloop: Validate NUL-terminated strings from user.
+
+From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+
+[ Upstream commit 77bc6bed7121936bb2e019a8c336075f4c8eef62 ]
+
+Return -EINVAL unless all of user-given strings are correctly
+NUL-terminated.
+
+Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/isdn/isdnloop/isdnloop.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/isdn/isdnloop/isdnloop.c
++++ b/drivers/isdn/isdnloop/isdnloop.c
+@@ -1070,6 +1070,12 @@ isdnloop_start(isdnloop_card *card, isdn
+ return -EBUSY;
+ if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
+ return -EFAULT;
++
++ for (i = 0; i < 3; i++) {
++ if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i])))
++ return -EINVAL;
++ }
++
+ spin_lock_irqsave(&card->isdnloop_lock, flags);
+ switch (sdef.ptype) {
+ case ISDN_PTYPE_EURO:
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 8 Apr 2014 12:23:09 +0300
+Subject: isdnloop: several buffer overflows
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+[ Upstream commit 7563487cbf865284dcd35e9ef5a95380da046737 ]
+
+There are three buffer overflows addressed in this patch.
+
+1) In isdnloop_fake_err() we add an 'E' to a 60 character string and
+then copy it into a 60 character buffer. I have made the destination
+buffer 64 characters and I'm changed the sprintf() to a snprintf().
+
+2) In isdnloop_parse_cmd(), p points to a 6 characters into a 60
+character buffer so we have 54 characters. The ->eazlist[] is 11
+characters long. I have modified the code to return if the source
+buffer is too long.
+
+3) In isdnloop_command() the cbuf[] array was 60 characters long but the
+max length of the string then can be up to 79 characters. I made the
+cbuf array 80 characters long and changed the sprintf() to snprintf().
+I also removed the temporary "dial" buffer and changed it to use "p"
+directly.
+
+Unfortunately, we pass the "cbuf" string from isdnloop_command() to
+isdnloop_writecmd() which truncates anything over 60 characters to make
+it fit in card->omsg[]. (It can accept values up to 255 characters so
+long as there is a '\n' character every 60 characters). For now I have
+just fixed the memory corruption bug and left the other problems in this
+driver alone.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/isdn/isdnloop/isdnloop.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/isdn/isdnloop/isdnloop.c
++++ b/drivers/isdn/isdnloop/isdnloop.c
+@@ -518,9 +518,9 @@ static isdnloop_stat isdnloop_cmd_table[
+ static void
+ isdnloop_fake_err(isdnloop_card *card)
+ {
+- char buf[60];
++ char buf[64];
+
+- sprintf(buf, "E%s", card->omsg);
++ snprintf(buf, sizeof(buf), "E%s", card->omsg);
+ isdnloop_fake(card, buf, -1);
+ isdnloop_fake(card, "NAK", -1);
+ }
+@@ -903,6 +903,8 @@ isdnloop_parse_cmd(isdnloop_card *card)
+ case 7:
+ /* 0x;EAZ */
+ p += 3;
++ if (strlen(p) >= sizeof(card->eazlist[0]))
++ break;
+ strcpy(card->eazlist[ch - 1], p);
+ break;
+ case 8:
+@@ -1133,7 +1135,7 @@ isdnloop_command(isdn_ctrl *c, isdnloop_
+ {
+ ulong a;
+ int i;
+- char cbuf[60];
++ char cbuf[80];
+ isdn_ctrl cmd;
+ isdnloop_cdef cdef;
+
+@@ -1198,7 +1200,6 @@ isdnloop_command(isdn_ctrl *c, isdnloop_
+ break;
+ if ((c->arg & 255) < ISDNLOOP_BCH) {
+ char *p;
+- char dial[50];
+ char dcode[4];
+
+ a = c->arg;
+@@ -1210,10 +1211,10 @@ isdnloop_command(isdn_ctrl *c, isdnloop_
+ } else
+ /* Normal Dial */
+ strcpy(dcode, "CAL");
+- strcpy(dial, p);
+- sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
+- dcode, dial, c->parm.setup.si1,
+- c->parm.setup.si2, c->parm.setup.eazmsn);
++ snprintf(cbuf, sizeof(cbuf),
++ "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
++ dcode, p, c->parm.setup.si1,
++ c->parm.setup.si2, c->parm.setup.eazmsn);
+ i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
+ }
+ break;
+From foo@baz Thu Apr 10 20:31:46 PDT 2014
+From: Sasha Levin <sasha.levin@oracle.com>
+Date: Sat, 29 Mar 2014 20:39:35 -0400
+Subject: rds: prevent dereference of a NULL device in rds_iw_laddr_check
+
+From: Sasha Levin <sasha.levin@oracle.com>
+
+[ Upstream commit bf39b4247b8799935ea91d90db250ab608a58e50 ]
+
+Binding might result in a NULL device which is later dereferenced
+without checking.
+
+Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/rds/iw.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/rds/iw.c
++++ b/net/rds/iw.c
+@@ -239,7 +239,8 @@ static int rds_iw_laddr_check(__be32 add
+ ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
+ /* due to this, we will claim to support IB devices unless we
+ check node_type. */
+- if (ret || cm_id->device->node_type != RDMA_NODE_RNIC)
++ if (ret || !cm_id->device ||
++ cm_id->device->node_type != RDMA_NODE_RNIC)
+ ret = -EADDRNOTAVAIL;
+
+ rdsdebug("addr %pI4 ret %d node type %d\n",
+From foo@baz Thu Apr 10 20:31:47 PDT 2014
+From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
+Date: Sun, 6 Apr 2014 20:37:44 +0200
+Subject: net/at91_ether: avoid NULL pointer dereference
+
+From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
+
+[ Upstream commit c293fb785bdda64d88f197e6758a3c16ae83e569 ]
+
+The at91_ether driver calls macb_mii_init passing a 'struct macb'
+structure whose tx_clk member is initialized to 0. However,
+macb_handle_link_change() expects tx_clk to be the result of
+a call to clk_get, and so IS_ERR(tx_clk) to be true if the clock
+is invalid. This causes an oops when booting Linux 3.14 on the
+csb637 board. The following changes avoids this.
+
+Signed-off-by: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
+Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/cadence/at91_ether.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/ethernet/cadence/at91_ether.c
++++ b/drivers/net/ethernet/cadence/at91_ether.c
+@@ -342,6 +342,9 @@ static int __init at91ether_probe(struct
+ }
+ clk_enable(lp->pclk);
+
++ lp->hclk = ERR_PTR(-ENOENT);
++ lp->tx_clk = ERR_PTR(-ENOENT);
++
+ /* Install the interrupt handler */
+ dev->irq = platform_get_irq(pdev, 0);
+ res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev);
+From 8930b05090acd321b1fc7c642528c697cb105c42 Mon Sep 17 00:00:00 2001
+From: Eyal Shapira <eyal@wizery.com>
+Date: Sun, 16 Mar 2014 05:23:21 +0200
+Subject: iwlwifi: mvm: rs: fix search cycle rules
+
+From: Eyal Shapira <eyal@wizery.com>
+
+commit 8930b05090acd321b1fc7c642528c697cb105c42 upstream.
+
+We should explore all possible columns when searching to be
+as resilient as possible to changing conditions. This fixes
+for example a scenario where even after a sudden creation of
+rssi difference between the 2 antennas we would keep doing MIMO
+at a low rate instead of switching to SISO at a higher rate using
+the better antenna which was the optimal configuration.
+
+Signed-off-by: Eyal Shapira <eyalx.shapira@intel.com>
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/iwlwifi/mvm/rs.c | 36 +++++++++++++++++-----------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
++++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
+@@ -211,9 +211,9 @@ static const struct rs_tx_column rs_tx_c
+ .next_columns = {
+ RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_SISO_ANT_A,
++ RS_COLUMN_SISO_ANT_B,
+ RS_COLUMN_MIMO2,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
++ RS_COLUMN_MIMO2_SGI,
+ },
+ },
+ [RS_COLUMN_LEGACY_ANT_B] = {
+@@ -221,10 +221,10 @@ static const struct rs_tx_column rs_tx_c
+ .ant = ANT_B,
+ .next_columns = {
+ RS_COLUMN_LEGACY_ANT_A,
++ RS_COLUMN_SISO_ANT_A,
+ RS_COLUMN_SISO_ANT_B,
+ RS_COLUMN_MIMO2,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
++ RS_COLUMN_MIMO2_SGI,
+ },
+ },
+ [RS_COLUMN_SISO_ANT_A] = {
+@@ -234,8 +234,8 @@ static const struct rs_tx_column rs_tx_c
+ RS_COLUMN_SISO_ANT_B,
+ RS_COLUMN_MIMO2,
+ RS_COLUMN_SISO_ANT_A_SGI,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
++ RS_COLUMN_SISO_ANT_B_SGI,
++ RS_COLUMN_MIMO2_SGI,
+ },
+ .checks = {
+ rs_siso_allow,
+@@ -248,8 +248,8 @@ static const struct rs_tx_column rs_tx_c
+ RS_COLUMN_SISO_ANT_A,
+ RS_COLUMN_MIMO2,
+ RS_COLUMN_SISO_ANT_B_SGI,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
++ RS_COLUMN_SISO_ANT_A_SGI,
++ RS_COLUMN_MIMO2_SGI,
+ },
+ .checks = {
+ rs_siso_allow,
+@@ -263,8 +263,8 @@ static const struct rs_tx_column rs_tx_c
+ RS_COLUMN_SISO_ANT_B_SGI,
+ RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_SISO_ANT_A,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
++ RS_COLUMN_SISO_ANT_B,
++ RS_COLUMN_MIMO2,
+ },
+ .checks = {
+ rs_siso_allow,
+@@ -279,8 +279,8 @@ static const struct rs_tx_column rs_tx_c
+ RS_COLUMN_SISO_ANT_A_SGI,
+ RS_COLUMN_MIMO2_SGI,
+ RS_COLUMN_SISO_ANT_B,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
++ RS_COLUMN_SISO_ANT_A,
++ RS_COLUMN_MIMO2,
+ },
+ .checks = {
+ rs_siso_allow,
+@@ -292,10 +292,10 @@ static const struct rs_tx_column rs_tx_c
+ .ant = ANT_AB,
+ .next_columns = {
+ RS_COLUMN_SISO_ANT_A,
++ RS_COLUMN_SISO_ANT_B,
++ RS_COLUMN_SISO_ANT_A_SGI,
++ RS_COLUMN_SISO_ANT_B_SGI,
+ RS_COLUMN_MIMO2_SGI,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
+ },
+ .checks = {
+ rs_mimo_allow,
+@@ -307,10 +307,10 @@ static const struct rs_tx_column rs_tx_c
+ .sgi = true,
+ .next_columns = {
+ RS_COLUMN_SISO_ANT_A_SGI,
++ RS_COLUMN_SISO_ANT_B_SGI,
++ RS_COLUMN_SISO_ANT_A,
++ RS_COLUMN_SISO_ANT_B,
+ RS_COLUMN_MIMO2,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
+- RS_COLUMN_INVALID,
+ },
+ .checks = {
+ rs_mimo_allow,
+From 6eda477b3c54b8236868c8784e5e042ff14244f0 Mon Sep 17 00:00:00 2001
+From: Mischa Jonker <mjonker@synopsys.com>
+Date: Thu, 16 May 2013 19:36:08 +0200
+Subject: ARC: [nsimosci] Change .dts to use generic 8250 UART
+
+From: Mischa Jonker <mjonker@synopsys.com>
+
+commit 6eda477b3c54b8236868c8784e5e042ff14244f0 upstream.
+
+The Synopsys APB DW UART has a couple of special features that are not
+in the System C model. In 3.8, the 8250_dw driver didn't really use these
+features, but from 3.9 onwards, the 8250_dw driver has become incompatible
+with our model.
+
+Signed-off-by: Mischa Jonker <mjonker@synopsys.com>
+Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
+Cc: Francois Bedard <Francois.Bedard@synopsys.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arc/boot/dts/nsimosci.dts | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/arch/arc/boot/dts/nsimosci.dts
++++ b/arch/arc/boot/dts/nsimosci.dts
+@@ -11,7 +11,7 @@
+
+ / {
+ compatible = "snps,nsimosci";
+- clock-frequency = <80000000>; /* 80 MHZ */
++ clock-frequency = <20000000>; /* 20 MHZ */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+@@ -44,15 +44,14 @@
+ };
+
+ uart0: serial@c0000000 {
+- compatible = "snps,dw-apb-uart";
++ compatible = "ns8250";
+ reg = <0xc0000000 0x2000>;
+ interrupts = <11>;
+- #clock-frequency = <80000000>;
+ clock-frequency = <3686400>;
+ baud = <115200>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+- status = "okay";
++ no-loopback-test = <1>;
+ };
+
+ pgu0: pgu@c9000000 {
+From 61fb4bfc010b0d2940f7fd87acbce6a0f03217cb Mon Sep 17 00:00:00 2001
+From: Vineet Gupta <vgupta@synopsys.com>
+Date: Sat, 5 Apr 2014 15:30:22 +0530
+Subject: ARC: [nsimosci] Unbork console
+
+From: Vineet Gupta <vgupta@synopsys.com>
+
+commit 61fb4bfc010b0d2940f7fd87acbce6a0f03217cb upstream.
+
+Despite the switch to right UART driver (prev patch), serial console
+still doesn't work due to missing CONFIG_SERIAL_OF_PLATFORM
+
+Also fix the default cmdline in DT to not refer to out-of-tree
+ARC framebuffer driver for console.
+
+Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
+Cc: Francois Bedard <Francois.Bedard@synopsys.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arc/boot/dts/nsimosci.dts | 5 ++++-
+ arch/arc/configs/nsimosci_defconfig | 1 +
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+--- a/arch/arc/boot/dts/nsimosci.dts
++++ b/arch/arc/boot/dts/nsimosci.dts
+@@ -17,7 +17,10 @@
+ interrupt-parent = <&intc>;
+
+ chosen {
+- bootargs = "console=tty0 consoleblank=0";
++ /* this is for console on PGU */
++ /* bootargs = "console=tty0 consoleblank=0"; */
++ /* this is for console on serial */
++ bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
+ };
+
+ aliases {
+--- a/arch/arc/configs/nsimosci_defconfig
++++ b/arch/arc/configs/nsimosci_defconfig
+@@ -54,6 +54,7 @@ CONFIG_SERIO_ARC_PS2=y
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_8250_DW=y
++CONFIG_SERIAL_OF_PLATFORM=y
+ CONFIG_SERIAL_ARC=y
+ CONFIG_SERIAL_ARC_CONSOLE=y
+ # CONFIG_HW_RANDOM is not set
+From 03b8c7b623c80af264c4c8d6111e5c6289933666 Mon Sep 17 00:00:00 2001
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+Date: Sun, 2 Mar 2014 13:09:47 +0100
+Subject: futex: Allow architectures to skip futex_atomic_cmpxchg_inatomic() test
+
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+
+commit 03b8c7b623c80af264c4c8d6111e5c6289933666 upstream.
+
+If an architecture has futex_atomic_cmpxchg_inatomic() implemented and there
+is no runtime check necessary, allow to skip the test within futex_init().
+
+This allows to get rid of some code which would always give the same result,
+and also allows the compiler to optimize a couple of if statements away.
+
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Cc: Finn Thain <fthain@telegraphics.com.au>
+Cc: Geert Uytterhoeven <geert@linux-m68k.org>
+Link: http://lkml.kernel.org/r/20140302120947.GA3641@osiris
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/s390/Kconfig | 1 +
+ include/linux/futex.h | 4 ++++
+ init/Kconfig | 7 +++++++
+ kernel/futex.c | 37 ++++++++++++++++++++++++-------------
+ 4 files changed, 36 insertions(+), 13 deletions(-)
+
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -117,6 +117,7 @@ config S390
+ select HAVE_FUNCTION_GRAPH_TRACER
+ select HAVE_FUNCTION_TRACER
+ select HAVE_FUNCTION_TRACE_MCOUNT_TEST
++ select HAVE_FUTEX_CMPXCHG if FUTEX
+ select HAVE_KERNEL_BZIP2
+ select HAVE_KERNEL_GZIP
+ select HAVE_KERNEL_LZ4
+--- a/include/linux/futex.h
++++ b/include/linux/futex.h
+@@ -55,7 +55,11 @@ union futex_key {
+ #ifdef CONFIG_FUTEX
+ extern void exit_robust_list(struct task_struct *curr);
+ extern void exit_pi_state_list(struct task_struct *curr);
++#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
++#define futex_cmpxchg_enabled 1
++#else
+ extern int futex_cmpxchg_enabled;
++#endif
+ #else
+ static inline void exit_robust_list(struct task_struct *curr)
+ {
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1387,6 +1387,13 @@ config FUTEX
+ support for "fast userspace mutexes". The resulting kernel may not
+ run glibc-based applications correctly.
+
++config HAVE_FUTEX_CMPXCHG
++ bool
++ help
++ Architectures should select this if futex_atomic_cmpxchg_inatomic()
++ is implemented and always working. This removes a couple of runtime
++ checks.
++
+ config EPOLL
+ bool "Enable eventpoll support" if EXPERT
+ default y
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -157,7 +157,9 @@
+ * enqueue.
+ */
+
++#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
+ int __read_mostly futex_cmpxchg_enabled;
++#endif
+
+ /*
+ * Futex flags used to encode options to functions and preserve them across
+@@ -2880,9 +2882,28 @@ SYSCALL_DEFINE6(futex, u32 __user *, uad
+ return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
+ }
+
+-static int __init futex_init(void)
++static void __init futex_detect_cmpxchg(void)
+ {
++#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
+ u32 curval;
++
++ /*
++ * This will fail and we want it. Some arch implementations do
++ * runtime detection of the futex_atomic_cmpxchg_inatomic()
++ * functionality. We want to know that before we call in any
++ * of the complex code paths. Also we want to prevent
++ * registration of robust lists in that case. NULL is
++ * guaranteed to fault and we get -EFAULT on functional
++ * implementation, the non-functional ones will return
++ * -ENOSYS.
++ */
++ if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
++ futex_cmpxchg_enabled = 1;
++#endif
++}
++
++static int __init futex_init(void)
++{
+ unsigned int futex_shift;
+ unsigned long i;
+
+@@ -2898,18 +2919,8 @@ static int __init futex_init(void)
+ &futex_shift, NULL,
+ futex_hashsize, futex_hashsize);
+ futex_hashsize = 1UL << futex_shift;
+- /*
+- * This will fail and we want it. Some arch implementations do
+- * runtime detection of the futex_atomic_cmpxchg_inatomic()
+- * functionality. We want to know that before we call in any
+- * of the complex code paths. Also we want to prevent
+- * registration of robust lists in that case. NULL is
+- * guaranteed to fault and we get -EFAULT on functional
+- * implementation, the non-functional ones will return
+- * -ENOSYS.
+- */
+- if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
+- futex_cmpxchg_enabled = 1;
++
++ futex_detect_cmpxchg();
+
+ for (i = 0; i < futex_hashsize; i++) {
+ atomic_set(&futex_queues[i].waiters, 0);
+From e571c58f313d35c56e0018470e3375ddd1fd320e Mon Sep 17 00:00:00 2001
+From: Finn Thain <fthain@telegraphics.com.au>
+Date: Thu, 6 Mar 2014 10:29:27 +1100
+Subject: m68k: Skip futex_atomic_cmpxchg_inatomic() test
+
+From: Finn Thain <fthain@telegraphics.com.au>
+
+commit e571c58f313d35c56e0018470e3375ddd1fd320e upstream.
+
+Skip the futex_atomic_cmpxchg_inatomic() test in futex_init(). It causes a
+fatal exception on 68030 (and presumably 68020 also).
+
+Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
+Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1403061006440.5525@nippy.intranet
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/m68k/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/m68k/Kconfig
++++ b/arch/m68k/Kconfig
+@@ -17,6 +17,7 @@ config M68K
+ select FPU if MMU
+ select ARCH_WANT_IPC_PARSE_VERSION
+ select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
++ select HAVE_FUTEX_CMPXCHG if MMU && FUTEX
+ select HAVE_MOD_ARCH_SPECIFIC
+ select MODULES_USE_ELF_REL
+ select MODULES_USE_ELF_RELA
+From 8ceee72808d1ae3fb191284afc2257a2be964725 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Date: Thu, 27 Mar 2014 18:14:40 +0100
+Subject: crypto: ghash-clmulni-intel - use C implementation for setkey()
+
+From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+
+commit 8ceee72808d1ae3fb191284afc2257a2be964725 upstream.
+
+The GHASH setkey() function uses SSE registers but fails to call
+kernel_fpu_begin()/kernel_fpu_end(). Instead of adding these calls, and
+then having to deal with the restriction that they cannot be called from
+interrupt context, move the setkey() implementation to the C domain.
+
+Note that setkey() does not use any particular SSE features and is not
+expected to become a performance bottleneck.
+
+Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Acked-by: H. Peter Anvin <hpa@linux.intel.com>
+Fixes: 0e1227d356e9b (crypto: ghash - Add PCLMULQDQ accelerated implementation)
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/crypto/ghash-clmulni-intel_asm.S | 29 -----------------------------
+ arch/x86/crypto/ghash-clmulni-intel_glue.c | 14 +++++++++++---
+ 2 files changed, 11 insertions(+), 32 deletions(-)
+
+--- a/arch/x86/crypto/ghash-clmulni-intel_asm.S
++++ b/arch/x86/crypto/ghash-clmulni-intel_asm.S
+@@ -24,10 +24,6 @@
+ .align 16
+ .Lbswap_mask:
+ .octa 0x000102030405060708090a0b0c0d0e0f
+-.Lpoly:
+- .octa 0xc2000000000000000000000000000001
+-.Ltwo_one:
+- .octa 0x00000001000000000000000000000001
+
+ #define DATA %xmm0
+ #define SHASH %xmm1
+@@ -134,28 +130,3 @@ ENTRY(clmul_ghash_update)
+ .Lupdate_just_ret:
+ ret
+ ENDPROC(clmul_ghash_update)
+-
+-/*
+- * void clmul_ghash_setkey(be128 *shash, const u8 *key);
+- *
+- * Calculate hash_key << 1 mod poly
+- */
+-ENTRY(clmul_ghash_setkey)
+- movaps .Lbswap_mask, BSWAP
+- movups (%rsi), %xmm0
+- PSHUFB_XMM BSWAP %xmm0
+- movaps %xmm0, %xmm1
+- psllq $1, %xmm0
+- psrlq $63, %xmm1
+- movaps %xmm1, %xmm2
+- pslldq $8, %xmm1
+- psrldq $8, %xmm2
+- por %xmm1, %xmm0
+- # reduction
+- pshufd $0b00100100, %xmm2, %xmm1
+- pcmpeqd .Ltwo_one, %xmm1
+- pand .Lpoly, %xmm1
+- pxor %xmm1, %xmm0
+- movups %xmm0, (%rdi)
+- ret
+-ENDPROC(clmul_ghash_setkey)
+--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
++++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
+@@ -30,8 +30,6 @@ void clmul_ghash_mul(char *dst, const be
+ void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
+ const be128 *shash);
+
+-void clmul_ghash_setkey(be128 *shash, const u8 *key);
+-
+ struct ghash_async_ctx {
+ struct cryptd_ahash *cryptd_tfm;
+ };
+@@ -58,13 +56,23 @@ static int ghash_setkey(struct crypto_sh
+ const u8 *key, unsigned int keylen)
+ {
+ struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
++ be128 *x = (be128 *)key;
++ u64 a, b;
+
+ if (keylen != GHASH_BLOCK_SIZE) {
+ crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+- clmul_ghash_setkey(&ctx->shash, key);
++ /* perform multiplication by 'x' in GF(2^128) */
++ a = be64_to_cpu(x->a);
++ b = be64_to_cpu(x->b);
++
++ ctx->shash.a = (__be64)((b << 1) | (a >> 63));
++ ctx->shash.b = (__be64)((a << 1) | (b >> 63));
++
++ if (a >> 63)
++ ctx->shash.b ^= cpu_to_be64(0xc2);
+
+ return 0;
+ }
diff --git a/Bluetooth-allocate-static-minor-for-vhci.patch b/Bluetooth-allocate-static-minor-for-vhci.patch
new file mode 100644
index 000000000..8acfb308f
--- /dev/null
+++ b/Bluetooth-allocate-static-minor-for-vhci.patch
@@ -0,0 +1,71 @@
+Bugzilla: 1051748
+Upstream-status: Queued for 3.15
+
+From b075dd40c95d11c2c8690f6c4d6232fc0d9e7f56 Mon Sep 17 00:00:00 2001
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+Date: Tue, 18 Feb 2014 05:19:26 +0000
+Subject: Bluetooth: allocate static minor for vhci
+
+Commit bfacbb9 (Bluetooth: Use devname:vhci module alias for virtual HCI
+driver) added the module alias to hci_vhci module so it's possible to
+create the /dev/vhci node. However creating an alias without
+specifying the minor doesn't allow us to create the node ahead,
+triggerring module auto-load when it's first accessed.
+
+Starting with depmod from kmod 16 we started to warn if there's a
+devname alias without specifying the major and minor.
+
+Let's do the same done for uhid, kvm, fuse and others, specifying a
+fixed minor. In systems with systemd as the init the following will
+happen: on early boot systemd will call "kmod static-nodes" to read
+/lib/modules/$(uname -r)/modules.devname and then create the nodes. When
+first accessed these "dead" nodes will trigger the module loading.
+
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+---
+diff --git a/Documentation/devices.txt b/Documentation/devices.txt
+index 10378cc..04356f5 100644
+--- a/Documentation/devices.txt
++++ b/Documentation/devices.txt
+@@ -353,6 +353,7 @@ Your cooperation is appreciated.
+ 133 = /dev/exttrp External device trap
+ 134 = /dev/apm_bios Advanced Power Management BIOS
+ 135 = /dev/rtc Real Time Clock
++ 137 = /dev/vhci Bluetooth virtual HCI driver
+ 139 = /dev/openprom SPARC OpenBoot PROM
+ 140 = /dev/relay8 Berkshire Products Octal relay card
+ 141 = /dev/relay16 Berkshire Products ISO-16 relay card
+diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
+index 1ef6990..add1c6a 100644
+--- a/drivers/bluetooth/hci_vhci.c
++++ b/drivers/bluetooth/hci_vhci.c
+@@ -359,7 +359,7 @@ static const struct file_operations vhci_fops = {
+ static struct miscdevice vhci_miscdev= {
+ .name = "vhci",
+ .fops = &vhci_fops,
+- .minor = MISC_DYNAMIC_MINOR,
++ .minor = VHCI_MINOR,
+ };
+
+ static int __init vhci_init(void)
+@@ -385,3 +385,4 @@ MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
+ MODULE_VERSION(VERSION);
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("devname:vhci");
++MODULE_ALIAS_MISCDEV(VHCI_MINOR);
+diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
+index 3737f72..7bb6148 100644
+--- a/include/linux/miscdevice.h
++++ b/include/linux/miscdevice.h
+@@ -23,6 +23,7 @@
+ #define TEMP_MINOR 131 /* Temperature Sensor */
+ #define RTC_MINOR 135
+ #define EFI_RTC_MINOR 136 /* EFI Time services */
++#define VHCI_MINOR 137
+ #define SUN_OPENPROM_MINOR 139
+ #define DMAPI_MINOR 140 /* DMAPI */
+ #define NVRAM_MINOR 144
+--
+cgit v0.9.2
diff --git a/Input-elantech-add-support-for-newer-August-2013-dev.patch b/Input-elantech-add-support-for-newer-August-2013-dev.patch
deleted file mode 100644
index e67f2800a..000000000
--- a/Input-elantech-add-support-for-newer-August-2013-dev.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-Bugzilla: 1030802
-Upstream-status: 3.13
-
-From 9cb80b965eaf7af1369f6e16f48a05fbaaccc021 Mon Sep 17 00:00:00 2001
-From: Matt Walker <matt.g.d.walker@gmail.com>
-Date: Thu, 5 Dec 2013 12:39:02 -0800
-Subject: [PATCH] Input: elantech - add support for newer (August 2013) devices
-
-Added detection for newer Elantech touchpads, so that kernel doesn't
-fall-back to default PS/2 driver. Supports touchpads released after
-~August 2013. Fixes bug:
-https://lists.launchpad.net/kernel-packages/msg18481.html
-
-Tested on an Acer Aspire S7-392-6302.
-
-Signed-off by: Matt Walker <matt.g.d.walker@gmail.com>
-Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
----
- drivers/input/mouse/elantech.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
-index 8551dca..597e9b8 100644
---- a/drivers/input/mouse/elantech.c
-+++ b/drivers/input/mouse/elantech.c
-@@ -1313,6 +1313,7 @@ static int elantech_set_properties(struct elantech_data *etd)
- break;
- case 6:
- case 7:
-+ case 8:
- etd->hw_version = 4;
- break;
- default:
---
-1.8.3.1
-
diff --git a/KVM-Improve-create-VCPU-parameter.patch b/KVM-Improve-create-VCPU-parameter.patch
deleted file mode 100644
index 5c5746259..000000000
--- a/KVM-Improve-create-VCPU-parameter.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-Bugzilla: 1042071
-Upstream-status: 3.13 and sent to stable
-Delivered-To: jwboyer@gmail.com
-Received: by 10.76.104.107 with SMTP id gd11csp361298oab;
- Thu, 12 Dec 2013 12:41:21 -0800 (PST)
-X-Received: by 10.50.109.132 with SMTP id hs4mr33803866igb.34.1386880880893;
- Thu, 12 Dec 2013 12:41:20 -0800 (PST)
-Return-Path: <stable-owner@vger.kernel.org>
-Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67])
- by mx.google.com with ESMTP id q8si17378346pav.173.2013.12.12.12.40.57
- for <multiple recipients>;
- Thu, 12 Dec 2013 12:41:20 -0800 (PST)
-Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67;
-Authentication-Results: mx.google.com;
- spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org;
- dkim=neutral (bad format) header.i=@gmail.com
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
- id S1752041Ab3LLUhR (ORCPT <rfc822;kumadasu@gmail.com> + 64 others);
- Thu, 12 Dec 2013 15:37:17 -0500
-Received: from mail-ea0-f179.google.com ([209.85.215.179]:43785 "EHLO
- mail-ea0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
- with ESMTP id S1751761Ab3LLUhN (ORCPT
- <rfc822;stable@vger.kernel.org>); Thu, 12 Dec 2013 15:37:13 -0500
-Received: by mail-ea0-f179.google.com with SMTP id r15so485140ead.24
- for <multiple recipients>; Thu, 12 Dec 2013 12:37:11 -0800 (PST)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20120113;
- h=sender:from:to:cc:subject:date:message-id;
- bh=3nLdta59rbActmGe9iq6aMqjNBfzfF7lqy0gb7EeI0I=;
- b=fWKHZKszZQjXAVDzYAlwX8s4+UNEomYiCAX0zvDzW7A5Yiy28MUt0QbNu6288Pu+Qs
- NJ38SpDcPLWzGknYOLggLa21nXsv4tX9vp4FFEY4i3H5iCVpXbvxIc+n9ZVOzWY2wkxK
- HR1Xf24kJ9FPuV/LoIyu5RlHZUm95BoAe7TxRZWlkcxQ0vEOSAyZQwH4EIj6SS7fXI1d
- PoqZKm7100ib0/wm6I49cF2b0EXRTSOYrgZneyniPVGpfTkpN2atNcEgdLSvAWQKEI+p
- 79Dt0/BJd2CIuqgUbZBlA8pH6a119FtfrVqxVWJAmVvsv9lpkMIjJrFTj9yqpUFKeeYB
- XTeA==
-X-Received: by 10.14.6.136 with SMTP id 8mr9978716een.11.1386880631657;
- Thu, 12 Dec 2013 12:37:11 -0800 (PST)
-Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54])
- by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.00
- for <multiple recipients>
- (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
- Thu, 12 Dec 2013 12:37:01 -0800 (PST)
-From: Paolo Bonzini <pbonzini@redhat.com>
-To: linux-kernel@vger.kernel.org
-Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com,
- Andy Honig <ahonig@google.com>, stable@vger.kernel.org
-Subject: [PATCH] KVM: Improve create VCPU parameter
-Date: Thu, 12 Dec 2013 21:36:51 +0100
-Message-Id: <1386880614-23300-1-git-send-email-pbonzini@redhat.com>
-X-Mailer: git-send-email 1.8.3.1
-Sender: stable-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <stable.vger.kernel.org>
-X-Mailing-List: stable@vger.kernel.org
-
-From: Andy Honig <ahonig@google.com>
-
-In multiple functions the vcpu_id is used as an offset into a bitfield. Ag
-malicious user could specify a vcpu_id greater than 255 in order to set or
-clear bits in kernel memory. This could be used to elevate priveges in the
-kernel. This patch verifies that the vcpu_id provided is less than 255.
-The api documentation already specifies that the vcpu_id must be less than
-max_vcpus, but this is currently not checked.
-
-Reported-by: Andrew Honig <ahonig@google.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: Andrew Honig <ahonig@google.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- virt/kvm/kvm_main.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
-index a0aa84b5941a..4f588bc94186 100644
---- a/virt/kvm/kvm_main.c
-+++ b/virt/kvm/kvm_main.c
-@@ -1898,6 +1898,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id)
- int r;
- struct kvm_vcpu *vcpu, *v;
-
-+ if (id >= KVM_MAX_VCPUS)
-+ return -EINVAL;
-+
- vcpu = kvm_arch_vcpu_create(kvm, id);
- if (IS_ERR(vcpu))
- return PTR_ERR(vcpu);
---
-1.8.3.1
-
---
-To unsubscribe from this list: send the line "unsubscribe stable" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch b/KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch
new file mode 100644
index 000000000..170911e1d
--- /dev/null
+++ b/KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch
@@ -0,0 +1,38 @@
+Bugzilla: 1085016
+Upstream-status: Queued for 3.15
+
+From 5678de3f15010b9022ee45673f33bcfc71d47b60 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Fri, 28 Mar 2014 20:41:50 +0100
+Subject: KVM: ioapic: fix assignment of ioapic->rtc_status.pending_eoi
+ (CVE-2014-0155)
+
+QE reported that they got the BUG_ON in ioapic_service to trigger.
+I cannot reproduce it, but there are two reasons why this could happen.
+
+The less likely but also easiest one, is when kvm_irq_delivery_to_apic
+does not deliver to any APIC and returns -1.
+
+Because irqe.shorthand == 0, the kvm_for_each_vcpu loop in that
+function is never reached. However, you can target the similar loop in
+kvm_irq_delivery_to_apic_fast; just program a zero logical destination
+address into the IOAPIC, or an out-of-range physical destination address.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+
+diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
+index d4b6015..d98d107 100644
+--- a/virt/kvm/ioapic.c
++++ b/virt/kvm/ioapic.c
+@@ -356,7 +356,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
+ BUG_ON(ioapic->rtc_status.pending_eoi != 0);
+ ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
+ ioapic->rtc_status.dest_map);
+- ioapic->rtc_status.pending_eoi = ret;
++ ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
+ } else
+ ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL);
+
+--
+cgit v0.10.1
+
diff --git a/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
deleted file mode 100644
index a37d4cf29..000000000
--- a/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
+++ /dev/null
@@ -1,247 +0,0 @@
-Bugzilla: 1042090
-Upstream-status: 3.13 and sent for stable
-Delivered-To: jwboyer@gmail.com
-Received: by 10.76.104.107 with SMTP id gd11csp361293oab;
- Thu, 12 Dec 2013 12:41:12 -0800 (PST)
-X-Received: by 10.68.244.2 with SMTP id xc2mr15600217pbc.58.1386880872483;
- Thu, 12 Dec 2013 12:41:12 -0800 (PST)
-Return-Path: <stable-owner@vger.kernel.org>
-Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67])
- by mx.google.com with ESMTP id 5si8126292pbj.245.2013.12.12.12.40.49
- for <multiple recipients>;
- Thu, 12 Dec 2013 12:41:12 -0800 (PST)
-Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67;
-Authentication-Results: mx.google.com;
- spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org;
- dkim=neutral (bad format) header.i=@gmail.com
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
- id S1751901Ab3LLUiK (ORCPT <rfc822;kumadasu@gmail.com> + 64 others);
- Thu, 12 Dec 2013 15:38:10 -0500
-Received: from mail-ea0-f169.google.com ([209.85.215.169]:43997 "EHLO
- mail-ea0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
- with ESMTP id S1751940Ab3LLUhR (ORCPT
- <rfc822;stable@vger.kernel.org>); Thu, 12 Dec 2013 15:37:17 -0500
-Received: by mail-ea0-f169.google.com with SMTP id l9so411843eaj.0
- for <multiple recipients>; Thu, 12 Dec 2013 12:37:15 -0800 (PST)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20120113;
- h=sender:from:to:cc:subject:date:message-id;
- bh=2MLmYgVGbv9FpnyP90yrPKk21SJoXFj93yQcaRn4G8Y=;
- b=ouBadI22VTf1UuezbySC80FWJYdpF/8Ks6I8f5rq1/7SDQPTpScjOYjZX0UtIf1ihj
- aeQ7IHqpmIYGKWadUbH2l88ZP1+rP7T+f2dZQeCb3HLNsPum0Ix8dzm/koeDnuS3dx75
- 50E9ZcFXO13Hx24tM8p0SAuYZ1DvbCNnPRK0yxHOmCtCWe+mQLBIgig1rg8TzSAazWm7
- 8LhpztDlIzNyZcfzKQvtdqTOBdnhadx5x39fxOe54Yw4JbppDa7R+BY5Jz6GOd3U0Op1
- Nf97rU0pe/jeyOtjF0LVs/d9iyPPeRoSE+VAr91iT8qj9S2PFEN1QxxWL8sdvsDPZK6B
- ZCmw==
-X-Received: by 10.14.182.199 with SMTP id o47mr10030582eem.7.1386880635352;
- Thu, 12 Dec 2013 12:37:15 -0800 (PST)
-Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54])
- by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.13
- for <multiple recipients>
- (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
- Thu, 12 Dec 2013 12:37:14 -0800 (PST)
-From: Paolo Bonzini <pbonzini@redhat.com>
-To: linux-kernel@vger.kernel.org
-Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com,
- Andy Honig <ahonig@google.com>, stable@vger.kernel.org
-Subject: [PATCH] KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368)
-Date: Thu, 12 Dec 2013 21:36:53 +0100
-Message-Id: <1386880614-23300-3-git-send-email-pbonzini@redhat.com>
-X-Mailer: git-send-email 1.8.3.1
-Sender: stable-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <stable.vger.kernel.org>
-X-Mailing-List: stable@vger.kernel.org
-
-From: Andy Honig <ahonig@google.com>
-
-In kvm_lapic_sync_from_vapic and kvm_lapic_sync_to_vapic there is the
-potential to corrupt kernel memory if userspace provides an address that
-is at the end of a page. This patches concerts those functions to use
-kvm_write_guest_cached and kvm_read_guest_cached. It also checks the
-vapic_address specified by userspace during ioctl processing and returns
-an error to userspace if the address is not a valid GPA.
-
-This is generally not guest triggerable, because the required write is
-done by firmware that runs before the guest. Also, it only affects AMD
-processors and oldish Intel that do not have the FlexPriority feature
-(unless you disable FlexPriority, of course; then newer processors are
-also affected).
-
-Fixes: b93463aa59d6 ('KVM: Accelerated apic support')
-
-Reported-by: Andrew Honig <ahonig@google.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: Andrew Honig <ahonig@google.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- arch/x86/kvm/lapic.c | 27 +++++++++++++++------------
- arch/x86/kvm/lapic.h | 4 ++--
- arch/x86/kvm/x86.c | 40 +---------------------------------------
- 3 files changed, 18 insertions(+), 53 deletions(-)
-
-diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
-index 89b52ec7d09c..b8bec45c1610 100644
---- a/arch/x86/kvm/lapic.c
-+++ b/arch/x86/kvm/lapic.c
-@@ -1692,7 +1692,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu,
- void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
- {
- u32 data;
-- void *vapic;
-
- if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention))
- apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic);
-@@ -1700,9 +1699,8 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
- if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
- return;
-
-- vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
-- data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
-- kunmap_atomic(vapic);
-+ kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
-+ sizeof(u32));
-
- apic_set_tpr(vcpu->arch.apic, data & 0xff);
- }
-@@ -1738,7 +1736,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
- u32 data, tpr;
- int max_irr, max_isr;
- struct kvm_lapic *apic = vcpu->arch.apic;
-- void *vapic;
-
- apic_sync_pv_eoi_to_guest(vcpu, apic);
-
-@@ -1754,18 +1751,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
- max_isr = 0;
- data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
-
-- vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
-- *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
-- kunmap_atomic(vapic);
-+ kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
-+ sizeof(u32));
- }
-
--void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
-+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
- {
-- vcpu->arch.apic->vapic_addr = vapic_addr;
-- if (vapic_addr)
-+ if (vapic_addr) {
-+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
-+ &vcpu->arch.apic->vapic_cache,
-+ vapic_addr, sizeof(u32)))
-+ return -EINVAL;
- __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
-- else
-+ } else {
- __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention);
-+ }
-+
-+ vcpu->arch.apic->vapic_addr = vapic_addr;
-+ return 0;
- }
-
- int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
-diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
-index c730ac9fe801..c8b0d0d2da5c 100644
---- a/arch/x86/kvm/lapic.h
-+++ b/arch/x86/kvm/lapic.h
-@@ -34,7 +34,7 @@ struct kvm_lapic {
- */
- void *regs;
- gpa_t vapic_addr;
-- struct page *vapic_page;
-+ struct gfn_to_hva_cache vapic_cache;
- unsigned long pending_events;
- unsigned int sipi_vector;
- };
-@@ -76,7 +76,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data);
- void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset);
- void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector);
-
--void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
-+int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
- void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
- void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
-
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index 21ef1ba184ae..5d004da1e35d 100644
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -3214,8 +3214,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
- r = -EFAULT;
- if (copy_from_user(&va, argp, sizeof va))
- goto out;
-- r = 0;
-- kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
-+ r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
- break;
- }
- case KVM_X86_SETUP_MCE: {
-@@ -5739,36 +5738,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
- !kvm_event_needs_reinjection(vcpu);
- }
-
--static int vapic_enter(struct kvm_vcpu *vcpu)
--{
-- struct kvm_lapic *apic = vcpu->arch.apic;
-- struct page *page;
--
-- if (!apic || !apic->vapic_addr)
-- return 0;
--
-- page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-- if (is_error_page(page))
-- return -EFAULT;
--
-- vcpu->arch.apic->vapic_page = page;
-- return 0;
--}
--
--static void vapic_exit(struct kvm_vcpu *vcpu)
--{
-- struct kvm_lapic *apic = vcpu->arch.apic;
-- int idx;
--
-- if (!apic || !apic->vapic_addr)
-- return;
--
-- idx = srcu_read_lock(&vcpu->kvm->srcu);
-- kvm_release_page_dirty(apic->vapic_page);
-- mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-- srcu_read_unlock(&vcpu->kvm->srcu, idx);
--}
--
- static void update_cr8_intercept(struct kvm_vcpu *vcpu)
- {
- int max_irr, tpr;
-@@ -6069,11 +6038,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
- struct kvm *kvm = vcpu->kvm;
-
- vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-- r = vapic_enter(vcpu);
-- if (r) {
-- srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
-- return r;
-- }
-
- r = 1;
- while (r > 0) {
-@@ -6132,8 +6096,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
-
- srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
-
-- vapic_exit(vcpu);
--
- return r;
- }
-
---
-1.8.3.1
-
---
-To unsubscribe from this list: send the line "unsubscribe stable" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/KVM-x86-Fix-potential-divide-by-0-in-lapic.patch b/KVM-x86-Fix-potential-divide-by-0-in-lapic.patch
deleted file mode 100644
index 8e144dff4..000000000
--- a/KVM-x86-Fix-potential-divide-by-0-in-lapic.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-Bugzilla: 1042081
-Upstream-status: 3.13 and sent for stable
-Delivered-To: jwboyer@gmail.com
-Received: by 10.76.104.107 with SMTP id gd11csp361402oab;
- Thu, 12 Dec 2013 12:43:43 -0800 (PST)
-X-Received: by 10.68.241.134 with SMTP id wi6mr15423072pbc.44.1386881023599;
- Thu, 12 Dec 2013 12:43:43 -0800 (PST)
-Return-Path: <linux-kernel-owner@vger.kernel.org>
-Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67])
- by mx.google.com with ESMTP id w3si17375457pbh.89.2013.12.12.12.43.07
- for <multiple recipients>;
- Thu, 12 Dec 2013 12:43:43 -0800 (PST)
-Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67;
-Authentication-Results: mx.google.com;
- spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=linux-kernel-owner@vger.kernel.org;
- dkim=neutral (bad format) header.i=@gmail.com
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
- id S1752145Ab3LLUiu (ORCPT <rfc822;multinymous@gmail.com>
- + 99 others); Thu, 12 Dec 2013 15:38:50 -0500
-Received: from mail-ee0-f45.google.com ([74.125.83.45]:47138 "EHLO
- mail-ee0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
- with ESMTP id S1751902Ab3LLUhP (ORCPT
- <rfc822;linux-kernel@vger.kernel.org>);
- Thu, 12 Dec 2013 15:37:15 -0500
-Received: by mail-ee0-f45.google.com with SMTP id d49so478739eek.32
- for <multiple recipients>; Thu, 12 Dec 2013 12:37:13 -0800 (PST)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20120113;
- h=sender:from:to:cc:subject:date:message-id;
- bh=Fa9qXXe9oER+jgB6WXA5v2LyR8O2Vaag7ZsOsv67MLg=;
- b=WbBUzKN8o3OzB75st3w60z/rVczWaaxrvWc2URlwJwZ0lgqObvbXvAb3ophFJxsr/O
- P3rEj33CGt5vFAmZWsrST8I4pVb7IPZYqmPuBklMhDmvegy2um2xEDCyIuI0oybwgple
- n1dYPBTNqBhiiLgIUeKgEf88yU5dsAgKOZSTnkMYhDSy9pnGxRda4WtErJ+SHjvcMaX3
- t2Vt97egJ2n+e+2BvnpS8xZ8biqp6/l3EzvdsL4W849fUUshAKva4Npu0T/D4E3JIp2O
- 3uY+geb/txJL2rOCacT3RljUb3+zAy2zhqGSjKR3AHePFNIX9RxfMi/vlPmTjO0vfmCP
- H86Q==
-X-Received: by 10.14.2.73 with SMTP id 49mr10139590eee.15.1386880633625;
- Thu, 12 Dec 2013 12:37:13 -0800 (PST)
-Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54])
- by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.11
- for <multiple recipients>
- (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
- Thu, 12 Dec 2013 12:37:12 -0800 (PST)
-From: Paolo Bonzini <pbonzini@redhat.com>
-To: linux-kernel@vger.kernel.org
-Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com,
- Andy Honig <ahonig@google.com>, stable@vger.kernel.org
-Subject: [PATCH] KVM: x86: Fix potential divide by 0 in lapic (CVE-2013-6367)
-Date: Thu, 12 Dec 2013 21:36:52 +0100
-Message-Id: <1386880614-23300-2-git-send-email-pbonzini@redhat.com>
-X-Mailer: git-send-email 1.8.3.1
-Sender: linux-kernel-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <linux-kernel.vger.kernel.org>
-X-Mailing-List: linux-kernel@vger.kernel.org
-
-From: Andy Honig <ahonig@google.com>
-
-Under guest controllable circumstances apic_get_tmcct will execute a
-divide by zero and cause a crash. If the guest cpuid support
-tsc deadline timers and performs the following sequence of requests
-the host will crash.
-- Set the mode to periodic
-- Set the TMICT to 0
-- Set the mode bits to 11 (neither periodic, nor one shot, nor tsc deadline)
-- Set the TMICT to non-zero.
-Then the lapic_timer.period will be 0, but the TMICT will not be. If the
-guest then reads from the TMCCT then the host will perform a divide by 0.
-
-This patch ensures that if the lapic_timer.period is 0, then the division
-does not occur.
-
-Reported-by: Andrew Honig <ahonig@google.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: Andrew Honig <ahonig@google.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- arch/x86/kvm/lapic.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
-index 5439117d5c4c..89b52ec7d09c 100644
---- a/arch/x86/kvm/lapic.c
-+++ b/arch/x86/kvm/lapic.c
-@@ -841,7 +841,8 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
- ASSERT(apic != NULL);
-
- /* if initial count is 0, current count should also be 0 */
-- if (kvm_apic_get_reg(apic, APIC_TMICT) == 0)
-+ if (kvm_apic_get_reg(apic, APIC_TMICT) == 0 ||
-+ apic->lapic_timer.period == 0)
- return 0;
-
- remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
---
-1.8.3.1
-
---
-To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
-Please read the FAQ at http://www.tux.org/lkml/
diff --git a/KVM-x86-fix-guest-initiated-crash-with-x2apic.patch b/KVM-x86-fix-guest-initiated-crash-with-x2apic.patch
deleted file mode 100644
index c84fc61b9..000000000
--- a/KVM-x86-fix-guest-initiated-crash-with-x2apic.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-Bugzilla: 1042099
-Upstream-status: 3.13 and sent for stable
-Delivered-To: jwboyer@gmail.com
-Received: by 10.76.104.107 with SMTP id gd11csp361370oab;
- Thu, 12 Dec 2013 12:42:56 -0800 (PST)
-X-Received: by 10.43.172.4 with SMTP id nw4mr8453091icc.25.1386880976232;
- Thu, 12 Dec 2013 12:42:56 -0800 (PST)
-Return-Path: <stable-owner@vger.kernel.org>
-Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67])
- by mx.google.com with ESMTP id 2si15667240pax.109.2013.12.12.12.42.31
- for <multiple recipients>;
- Thu, 12 Dec 2013 12:42:56 -0800 (PST)
-Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67;
-Authentication-Results: mx.google.com;
- spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org;
- dkim=neutral (bad format) header.i=@gmail.com
-Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
- id S1751853Ab3LLUiJ (ORCPT <rfc822;kumadasu@gmail.com> + 64 others);
- Thu, 12 Dec 2013 15:38:09 -0500
-Received: from mail-ee0-f54.google.com ([74.125.83.54]:48290 "EHLO
- mail-ee0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
- with ESMTP id S1751884Ab3LLUhS (ORCPT
- <rfc822;stable@vger.kernel.org>); Thu, 12 Dec 2013 15:37:18 -0500
-Received: by mail-ee0-f54.google.com with SMTP id e51so406857eek.13
- for <multiple recipients>; Thu, 12 Dec 2013 12:37:17 -0800 (PST)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20120113;
- h=sender:from:to:cc:subject:date:message-id;
- bh=VG00enyRpNYeJLwAwqWOGuy3mCBmvpmEBgLPB1IiKNo=;
- b=p0BlraPBMTIxTXGUuJyYTYRxuMKATenNpVX01fyzNpSYZsMruyMU/sJ8gdc2991eao
- ZU+66Xlnbd+AyQiuq4P9sMv6Gvax6MvJg04SMZWnLWoZGonmIIwSPch1UKLSJzRN7K+N
- +Ot3jLtNBYBoREljPkbscbMVOJ2y+S7N61oOZ7IHZNyXVFWDlW8aunduSgc3cytBEhkx
- UMUUbHVLo+XrXtuggFrmn8oUfJ1hiHQSpOyx8bi0ztxlEjL4DEFpJsKbjRe4sGRgeUy6
- dRk+7dEcILKBTRVvXaJSriXG5bhZTbcZ5gZab27Ilm1H8Va5Z6R+9C1AwX2x5CQA7Mb1
- Edug==
-X-Received: by 10.14.107.3 with SMTP id n3mr9951281eeg.67.1386880636981;
- Thu, 12 Dec 2013 12:37:16 -0800 (PST)
-Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54])
- by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.15
- for <multiple recipients>
- (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
- Thu, 12 Dec 2013 12:37:16 -0800 (PST)
-From: Paolo Bonzini <pbonzini@redhat.com>
-To: linux-kernel@vger.kernel.org
-Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com,
- stable@vger.kernel.org
-Subject: [PATCH] KVM: x86: fix guest-initiated crash with x2apic (CVE-2013-6376)
-Date: Thu, 12 Dec 2013 21:36:54 +0100
-Message-Id: <1386880614-23300-4-git-send-email-pbonzini@redhat.com>
-X-Mailer: git-send-email 1.8.3.1
-Sender: stable-owner@vger.kernel.org
-Precedence: bulk
-List-ID: <stable.vger.kernel.org>
-X-Mailing-List: stable@vger.kernel.org
-
-From: Gleb Natapov <gleb@redhat.com>
-
-A guest can cause a BUG_ON() leading to a host kernel crash.
-When the guest writes to the ICR to request an IPI, while in x2apic
-mode the following things happen, the destination is read from
-ICR2, which is a register that the guest can control.
-
-kvm_irq_delivery_to_apic_fast uses the high 16 bits of ICR2 as the
-cluster id. A BUG_ON is triggered, which is a protection against
-accessing map->logical_map with an out-of-bounds access and manages
-to avoid that anything really unsafe occurs.
-
-The logic in the code is correct from real HW point of view. The problem
-is that KVM supports only one cluster with ID 0 in clustered mode, but
-the code that has the bug does not take this into account.
-
-Reported-by: Lars Bull <larsbull@google.com>
-Cc: stable@vger.kernel.org
-Signed-off-by: Gleb Natapov <gleb@redhat.com>
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- arch/x86/kvm/lapic.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
-index b8bec45c1610..801dc3fd66e1 100644
---- a/arch/x86/kvm/lapic.c
-+++ b/arch/x86/kvm/lapic.c
-@@ -143,6 +143,8 @@ static inline int kvm_apic_id(struct kvm_lapic *apic)
- return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
- }
-
-+#define KMV_X2APIC_CID_BITS 0
-+
- static void recalculate_apic_map(struct kvm *kvm)
- {
- struct kvm_apic_map *new, *old = NULL;
-@@ -180,7 +182,8 @@ static void recalculate_apic_map(struct kvm *kvm)
- if (apic_x2apic_mode(apic)) {
- new->ldr_bits = 32;
- new->cid_shift = 16;
-- new->cid_mask = new->lid_mask = 0xffff;
-+ new->cid_mask = (1 << KMV_X2APIC_CID_BITS) - 1;
-+ new->lid_mask = 0xffff;
- } else if (kvm_apic_sw_enabled(apic) &&
- !new->cid_mask /* flat mode */ &&
- kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {
---
-1.8.3.1
-
---
-To unsubscribe from this list: send the line "unsubscribe stable" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Revert-userns-Allow-unprivileged-users-to-create-use.patch b/Revert-userns-Allow-unprivileged-users-to-create-use.patch
new file mode 100644
index 000000000..cea6bff01
--- /dev/null
+++ b/Revert-userns-Allow-unprivileged-users-to-create-use.patch
@@ -0,0 +1,44 @@
+Bugzilla: 917708
+Upstream-status: Fedora mustard
+
+From e3da68be55914bfeedb8866f191cc0958579611d Mon Sep 17 00:00:00 2001
+From: Josh Boyer <jwboyer@fedoraproject.org>
+Date: Wed, 13 Nov 2013 10:21:18 -0500
+Subject: [PATCH] Revert "userns: Allow unprivileged users to create user
+ namespaces."
+
+This reverts commit 5eaf563e53294d6696e651466697eb9d491f3946.
+
+Conflicts:
+ kernel/fork.c
+---
+ kernel/fork.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index f6d11fc..e04c9a7 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -1573,6 +1573,19 @@ long do_fork(unsigned long clone_flags,
+ long nr;
+
+ /*
++ * Do some preliminary argument and permissions checking before we
++ * actually start allocating stuff
++ */
++ if (clone_flags & CLONE_NEWUSER) {
++ /* hopefully this check will go away when userns support is
++ * complete
++ */
++ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||
++ !capable(CAP_SETGID))
++ return -EPERM;
++ }
++
++ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+ * requested, no event is reported; otherwise, report if the event
+--
+1.8.3.1
+
diff --git a/acpi-sony-nonvs-blacklist.patch b/acpi-sony-nonvs-blacklist.patch
deleted file mode 100644
index db500e8bf..000000000
--- a/acpi-sony-nonvs-blacklist.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
-index 3ed80b2..17fc718 100644
---- a/drivers/acpi/sleep.c
-+++ b/drivers/acpi/sleep.c
-@@ -390,6 +390,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
- },
- {
- .callback = init_nvs_nosave,
-+ .ident = "Sony Vaio VGN-FW21E",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
-+ },
-+ },
-+ {
-+ .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-SR11M",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
-index 0e46fae..6d9a3ab 100644
---- a/drivers/acpi/sleep.c
-+++ b/drivers/acpi/sleep.c
-@@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
- },
- {
- .callback = init_nvs_nosave,
-+ .ident = "Sony Vaio VPCEB17FX",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
-+ },
-+ },
-+ {
-+ .callback = init_nvs_nosave,
- .ident = "Sony Vaio VGN-SR11M",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
diff --git a/alx-Reset-phy-speed-after-resume.patch b/alx-Reset-phy-speed-after-resume.patch
deleted file mode 100644
index 3af169f78..000000000
--- a/alx-Reset-phy-speed-after-resume.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-Bugzilla: 1011362
-Upstream-status: queued for 3.13
-
-From b54629e226d196e802abdd30c5e34f2a47cddcf2 Mon Sep 17 00:00:00 2001
-From: hahnjo <hahnjo@hahnjo.de>
-Date: Tue, 12 Nov 2013 17:19:24 +0000
-Subject: alx: Reset phy speed after resume
-
-This fixes bug 62491 (https://bugzilla.kernel.org/show_bug.cgi?id=62491).
-After resuming some users got the following error flooding the kernel log:
-alx 0000:02:00.0: invalid PHY speed/duplex: 0xffff
-
-Signed-off-by: Jonas Hahnfeld <linux@hahnjo.de>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-(limited to 'drivers/net/ethernet/atheros/alx')
-
-diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
-index 5aa5e81..c3c4c26 100644
---- a/drivers/net/ethernet/atheros/alx/main.c
-+++ b/drivers/net/ethernet/atheros/alx/main.c
-@@ -1388,6 +1388,9 @@ static int alx_resume(struct device *dev)
- {
- struct pci_dev *pdev = to_pci_dev(dev);
- struct alx_priv *alx = pci_get_drvdata(pdev);
-+ struct alx_hw *hw = &alx->hw;
-+
-+ alx_reset_phy(hw);
-
- if (!netif_running(alx->dev))
- return 0;
---
-cgit v0.9.2
diff --git a/arm-am33xx-arm-soc-upstream.patch b/arm-am33xx-arm-soc-upstream.patch
deleted file mode 100644
index 3129c1a7a..000000000
--- a/arm-am33xx-arm-soc-upstream.patch
+++ /dev/null
@@ -1,2468 +0,0 @@
-Bugzilla: 1012025
-Upstream-status: Landed in 3.13-rc1
-
-From 9096ef3ab805b2e9fda732f3128a761810c1dea4 Mon Sep 17 00:00:00 2001
-From: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-Date: Sat, 3 Aug 2013 20:00:54 +0200
-Subject: [PATCH 01/15] ARM: dts: AM33XX: Add PMU support
-
-ARM Performance Monitor Units are available on the am33xx,
-add the support in the dtsi.
-
-Tested with perf and oprofile on a regular beaglebone.
-
-Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am33xx.dtsi | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index f9c5da9..4d1c632 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -57,6 +57,11 @@
- };
- };
-
-+ pmu {
-+ compatible = "arm,cortex-a8-pmu";
-+ interrupts = <3>;
-+ };
-+
- /*
- * The soc node represents the soc top level view. It is uses for IPs
- * that are not memory mapped in the MPU view or for the MPU itself.
---
-1.8.4.rc3
-
-From 41bae5a6301ff1cd48fd0c4ff32146059b8e1b73 Mon Sep 17 00:00:00 2001
-From: Lars Poeschel <poeschel@lemonage.de>
-Date: Wed, 7 Aug 2013 13:06:32 +0200
-Subject: [PATCH 02/15] ARM: dts: AM33xx: Correct gpio #interrupt-cells
- property
-
-Following commit ff5c9059 and therefore other omap platforms using
-the gpio-omap driver correct the #interrupt-cells property on am33xx
-too. The omap gpio binding documentaion also states that
-the #interrupt-cells property should be 2.
-
-Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
-Reviewed-by: Javier Martinez Canillas <javier@dowhile0.org>
-Acked-by: Mark Rutland <mark.rutland@arm.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am33xx.dtsi | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index 4d1c632..a7731ea 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -111,7 +111,7 @@
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
-- #interrupt-cells = <1>;
-+ #interrupt-cells = <2>;
- reg = <0x44e07000 0x1000>;
- interrupts = <96>;
- };
-@@ -122,7 +122,7 @@
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
-- #interrupt-cells = <1>;
-+ #interrupt-cells = <2>;
- reg = <0x4804c000 0x1000>;
- interrupts = <98>;
- };
-@@ -133,7 +133,7 @@
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
-- #interrupt-cells = <1>;
-+ #interrupt-cells = <2>;
- reg = <0x481ac000 0x1000>;
- interrupts = <32>;
- };
-@@ -144,7 +144,7 @@
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
-- #interrupt-cells = <1>;
-+ #interrupt-cells = <2>;
- reg = <0x481ae000 0x1000>;
- interrupts = <62>;
- };
---
-1.8.4.rc3
-
-From 200835d6072367d401cc6eb76b05fef2a2919291 Mon Sep 17 00:00:00 2001
-From: Matt Porter <mdp@ti.com>
-Date: Tue, 10 Sep 2013 14:24:37 -0500
-Subject: [PATCH 03/15] ARM: dts: AM33XX: Add EDMA support
-
-Adds AM33XX EDMA support to the am33xx.dtsi as documented in
-Documentation/devicetree/bindings/dma/ti-edma.txt
-
-[Joel Fernandes <joelf@ti.com>]
-Drop DT entries that are non-hardware-description as discussed in [1]
-
-[1] https://patchwork.kernel.org/patch/2226761/
-
-Signed-off-by: Matt Porter <mporter@ti.com>
-Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am33xx.dtsi | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index a7731ea..7a53e07 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -105,6 +105,18 @@
- reg = <0x48200000 0x1000>;
- };
-
-+ edma: edma@49000000 {
-+ compatible = "ti,edma3";
-+ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
-+ reg = <0x49000000 0x10000>,
-+ <0x44e10f90 0x10>;
-+ interrupts = <12 13 14>;
-+ #dma-cells = <1>;
-+ dma-channels = <64>;
-+ ti,edma-regions = <4>;
-+ ti,edma-slots = <256>;
-+ };
-+
- gpio0: gpio@44e07000 {
- compatible = "ti,omap4-gpio";
- ti,hwmods = "gpio1";
---
-1.8.4.rc3
-
-From 62ca70c0e2dfc1a4e9225b801cd769fd92f6de7c Mon Sep 17 00:00:00 2001
-From: Matt Porter <mporter@ti.com>
-Date: Tue, 10 Sep 2013 14:24:38 -0500
-Subject: [PATCH 04/15] ARM: dts: AM33XX: Add SPI DMA support
-
-Adds DMA resources to the AM33XX SPI nodes.
-
-Signed-off-by: Matt Porter <mporter@ti.com>
-Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am33xx.dtsi | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index 7a53e07..9cd60bf 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -340,6 +340,11 @@
- interrupts = <65>;
- ti,spi-num-cs = <2>;
- ti,hwmods = "spi0";
-+ dmas = <&edma 16
-+ &edma 17
-+ &edma 18
-+ &edma 19>;
-+ dma-names = "tx0", "rx0", "tx1", "rx1";
- status = "disabled";
- };
-
-@@ -351,6 +356,11 @@
- interrupts = <125>;
- ti,spi-num-cs = <2>;
- ti,hwmods = "spi1";
-+ dmas = <&edma 42
-+ &edma 43
-+ &edma 44
-+ &edma 45>;
-+ dma-names = "tx0", "rx0", "tx1", "rx1";
- status = "disabled";
- };
-
---
-1.8.4.rc3
-
-From de80038efb2254fd72e77f848eb867fc193b5a74 Mon Sep 17 00:00:00 2001
-From: Matt Porter <mporter@ti.com>
-Date: Tue, 10 Sep 2013 14:24:39 -0500
-Subject: [PATCH 05/15] ARM: dts: AM33XX: Add MMC support and documentation
-
-Adds AM33XX MMC support for am335x-bone, am335x-evm and am335x-evmsk boards.
-
-Also added is the DMA binding definitions based on the generic DMA request
-binding.
-
-Additional changes made to DTS:
-* Interrupt, reg and compatible properties added
-* ti,needs-special-hs-handling added
-
-Signed-off-by: Matt Porter <mporter@ti.com>
-Acked-by: Tony Lindgren <tony@atomide.com>
-Signed-off-by: Joel Fernandes <joelf@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 26 ++++++++++++++-
- arch/arm/boot/dts/am335x-bone.dts | 11 +++++++
- arch/arm/boot/dts/am335x-evm.dts | 7 ++++
- arch/arm/boot/dts/am335x-evmsk.dts | 7 ++++
- arch/arm/boot/dts/am33xx.dtsi | 38 ++++++++++++++++++++++
- 5 files changed, 88 insertions(+), 1 deletion(-)
-
-diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
-index ed271fc..8c8908a 100644
---- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
-+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
-@@ -20,8 +20,29 @@ ti,dual-volt: boolean, supports dual voltage cards
- ti,non-removable: non-removable slot (like eMMC)
- ti,needs-special-reset: Requires a special softreset sequence
- ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
-+dmas: List of DMA specifiers with the controller specific format
-+as described in the generic DMA client binding. A tx and rx
-+specifier is required.
-+dma-names: List of DMA request names. These strings correspond
-+1:1 with the DMA specifiers listed in dmas. The string naming is
-+to be "rx" and "tx" for RX and TX DMA requests, respectively.
-+
-+Examples:
-+
-+[hwmod populated DMA resources]
-+
-+ mmc1: mmc@0x4809c000 {
-+ compatible = "ti,omap4-hsmmc";
-+ reg = <0x4809c000 0x400>;
-+ ti,hwmods = "mmc1";
-+ ti,dual-volt;
-+ bus-width = <4>;
-+ vmmc-supply = <&vmmc>; /* phandle to regulator node */
-+ ti,non-removable;
-+ };
-+
-+[generic DMA request binding]
-
--Example:
- mmc1: mmc@0x4809c000 {
- compatible = "ti,omap4-hsmmc";
- reg = <0x4809c000 0x400>;
-@@ -30,4 +51,7 @@ Example:
- bus-width = <4>;
- vmmc-supply = <&vmmc>; /* phandle to regulator node */
- ti,non-removable;
-+ dmas = <&edma 24
-+ &edma 25>;
-+ dma-names = "tx", "rx";
- };
-diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
-index 7993c48..d5f43fe 100644
---- a/arch/arm/boot/dts/am335x-bone.dts
-+++ b/arch/arm/boot/dts/am335x-bone.dts
-@@ -9,3 +9,14 @@
-
- #include "am33xx.dtsi"
- #include "am335x-bone-common.dtsi"
-+
-+&ldo3_reg {
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <3300000>;
-+ regulator-always-on;
-+};
-+
-+&mmc1 {
-+ status = "okay";
-+ vmmc-supply = <&ldo3_reg>;
-+};
-diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
-index e8ec875..bc4a69d 100644
---- a/arch/arm/boot/dts/am335x-evm.dts
-+++ b/arch/arm/boot/dts/am335x-evm.dts
-@@ -477,6 +477,8 @@
- };
-
- vmmc_reg: regulator@12 {
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- };
-@@ -517,3 +519,8 @@
- ti,adc-channels = <4 5 6 7>;
- };
- };
-+
-+&mmc1 {
-+ status = "okay";
-+ vmmc-supply = <&vmmc_reg>;
-+};
-diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
-index 4f339fa..55fd194 100644
---- a/arch/arm/boot/dts/am335x-evmsk.dts
-+++ b/arch/arm/boot/dts/am335x-evmsk.dts
-@@ -393,6 +393,8 @@
- };
-
- vmmc_reg: regulator@12 {
-+ regulator-min-microvolt = <1800000>;
-+ regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
- };
-@@ -419,3 +421,8 @@
- phy_id = <&davinci_mdio>, <1>;
- phy-mode = "rgmii-txid";
- };
-+
-+&mmc1 {
-+ status = "okay";
-+ vmmc-supply = <&vmmc_reg>;
-+};
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index 9cd60bf..553adc6 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -245,6 +245,44 @@
- status = "disabled";
- };
-
-+ mmc1: mmc@48060000 {
-+ compatible = "ti,omap4-hsmmc";
-+ ti,hwmods = "mmc1";
-+ ti,dual-volt;
-+ ti,needs-special-reset;
-+ ti,needs-special-hs-handling;
-+ dmas = <&edma 24
-+ &edma 25>;
-+ dma-names = "tx", "rx";
-+ interrupts = <64>;
-+ interrupt-parent = <&intc>;
-+ reg = <0x48060000 0x1000>;
-+ status = "disabled";
-+ };
-+
-+ mmc2: mmc@481d8000 {
-+ compatible = "ti,omap4-hsmmc";
-+ ti,hwmods = "mmc2";
-+ ti,needs-special-reset;
-+ dmas = <&edma 2
-+ &edma 3>;
-+ dma-names = "tx", "rx";
-+ interrupts = <28>;
-+ interrupt-parent = <&intc>;
-+ reg = <0x481d8000 0x1000>;
-+ status = "disabled";
-+ };
-+
-+ mmc3: mmc@47810000 {
-+ compatible = "ti,omap4-hsmmc";
-+ ti,hwmods = "mmc3";
-+ ti,needs-special-reset;
-+ interrupts = <29>;
-+ interrupt-parent = <&intc>;
-+ reg = <0x47810000 0x1000>;
-+ status = "disabled";
-+ };
-+
- wdt2: wdt@44e35000 {
- compatible = "ti,omap3-wdt";
- ti,hwmods = "wd_timer2";
---
-1.8.4.rc3
-
-From 889d5b18a88681d7d1e5a1d1b5d2ffda07c506df Mon Sep 17 00:00:00 2001
-From: Alexander Holler <holler@ahsoftware.de>
-Date: Thu, 12 Sep 2013 20:35:32 +0200
-Subject: [PATCH 06/15] ARM: dts: am335x-bone: add CD for mmc1
-
-This enables the use of MMC cards even when no card was inserted at boot.
-
-Signed-off-by: Alexander Holler <holler@ahsoftware.de>
-Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
-Tested-by: Kevin Hilman <khilman@linaro.org>
-Reviewed-by: Nishanth Menon <nm@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 14 ++++++++++++++
- arch/arm/boot/dts/am335x-bone.dts | 1 -
- 2 files changed, 14 insertions(+), 1 deletion(-)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index 2f66ded..0d95d54 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -107,6 +107,12 @@
- 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
- >;
- };
-+
-+ mmc1_pins: pinmux_mmc1_pins {
-+ pinctrl-single,pins = <
-+ 0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
-+ >;
-+ };
- };
-
- ocp {
-@@ -260,3 +266,11 @@
- pinctrl-0 = <&davinci_mdio_default>;
- pinctrl-1 = <&davinci_mdio_sleep>;
- };
-+
-+&mmc1 {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mmc1_pins>;
-+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
-+ cd-inverted;
-+};
-diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
-index d5f43fe..0d63348 100644
---- a/arch/arm/boot/dts/am335x-bone.dts
-+++ b/arch/arm/boot/dts/am335x-bone.dts
-@@ -17,6 +17,5 @@
- };
-
- &mmc1 {
-- status = "okay";
- vmmc-supply = <&ldo3_reg>;
- };
---
-1.8.4.rc3
-
-From 7e60fa2391c2e89f07452c2037209235dee67aee Mon Sep 17 00:00:00 2001
-From: Koen Kooi <koen@dominion.thruhere.net>
-Date: Thu, 12 Sep 2013 20:35:33 +0200
-Subject: [PATCH 07/15] ARM: dts: am335x-boneblack: add eMMC DT entry
-
-The pinmux is specified in am335x-bone-common.dtsi to be
-reused by the eMMC cape.
-
-Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
-Tested-by: Kevin Hilman <khilman@linaro.org>
-Reviewed-by: Nishanth Menon <nm@ti.com>
-[bcousson@baylibre.com: Fix traling spaces and useless comments]
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 22 ++++++++++++++++++++++
- arch/arm/boot/dts/am335x-boneblack.dts | 13 +++++++++++++
- 2 files changed, 35 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index 0d95d54..c560cb7 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -113,6 +113,21 @@
- 0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
- >;
- };
-+
-+ emmc_pins: pinmux_emmc_pins {
-+ pinctrl-single,pins = <
-+ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_csn2.mmc1_cmd */
-+ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-+ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-+ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-+ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
-+ 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
-+ 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
-+ 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
-+ 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
-+ >;
-+ };
- };
-
- ocp {
-@@ -242,6 +257,13 @@
- regulator-always-on;
- };
- };
-+
-+ vmmcsd_fixed: fixedregulator@0 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vmmcsd_fixed";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ };
- };
-
- &cpsw_emac0 {
-diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
-index 197cadf..16b3bea 100644
---- a/arch/arm/boot/dts/am335x-boneblack.dts
-+++ b/arch/arm/boot/dts/am335x-boneblack.dts
-@@ -15,3 +15,16 @@
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-+
-+&mmc1 {
-+ vmmc-supply = <&vmmcsd_fixed>;
-+};
-+
-+&mmc2 {
-+ vmmc-supply = <&vmmcsd_fixed>;
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&emmc_pins>;
-+ bus-width = <8>;
-+ status = "okay";
-+ ti,vcc-aux-disable-is-sleep;
-+};
---
-1.8.4.rc3
-
-From 2b3a35fea12469734e2216a06c7fea6d5cb0d4d8 Mon Sep 17 00:00:00 2001
-From: Koen Kooi <koen@dominion.thruhere.net>
-Date: Thu, 12 Sep 2013 20:35:34 +0200
-Subject: [PATCH 08/15] ARM: dts: am335x-bone-common: switch mmc1 to 4-bit mode
-
-The micro-SD slot hooks up all four data pins so lets' use them.
-
-Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
-Tested-by: Kevin Hilman <khilman@linaro.org>
-Reviewed-by: Nishanth Menon <nm@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index c560cb7..fbb11dd 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -291,6 +291,7 @@
-
- &mmc1 {
- status = "okay";
-+ bus-width = <0x4>;
- pinctrl-names = "default";
- pinctrl-0 = <&mmc1_pins>;
- cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
---
-1.8.4.rc3
-
-From 387d315741b4126f228ee788094f9a00ecf8fde0 Mon Sep 17 00:00:00 2001
-From: Koen Kooi <koen@dominion.thruhere.net>
-Date: Thu, 12 Sep 2013 20:35:35 +0200
-Subject: [PATCH 09/15] ARM: dts: am335x-bone-common: add cpu0 and mmc1
- triggers
-
-This matches the vendor 3.8.x configuration that is shipping
-with the boards.
-
-The LED layout is now:
- USR0: heartbeat
- USR1: mmc0 (micro-SD slot)
- USR2: cpu0
- USR3: mmc1 (eMMC)
-
-The cpu0 triggers was put in between the mmc triggers to make
-is easier to see where the disk activity is.
-
-Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
-Tested-by: Kevin Hilman <khilman@linaro.org>
-Reviewed-by: Nishanth Menon <nm@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index fbb11dd..56361ce 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -204,12 +204,14 @@
- led@4 {
- label = "beaglebone:green:usr2";
- gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
-+ linux,default-trigger = "cpu0";
- default-state = "off";
- };
-
- led@5 {
- label = "beaglebone:green:usr3";
- gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
-+ linux,default-trigger = "mmc1";
- default-state = "off";
- };
- };
---
-1.8.4.rc3
-
-From 28d36734db6d9682208ced9032de9ebda568da96 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Fri, 20 Sep 2013 17:00:00 +0200
-Subject: [PATCH 10/15] ARM: dts: AM33XX: use pinmux node defined in included
- file
-
-am33xx boards DTS include the am33xx.dtsi Device Tree
-source file that already define a pinmux device node for
-the AM33XX SoC Pin Multiplex.
-
-Redefining this for each board makes the Device Tree files
-harder to modify and maintain so let's just use what is
-already defined in the included .dtsi file.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 218 ++++++++++++-------------
- arch/arm/boot/dts/am335x-evm.dts | 254 ++++++++++++++---------------
- arch/arm/boot/dts/am335x-evmsk.dts | 258 +++++++++++++++---------------
- 3 files changed, 365 insertions(+), 365 deletions(-)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index 56361ce..29799ac 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -21,115 +21,6 @@
- reg = <0x80000000 0x10000000>; /* 256 MB */
- };
-
-- am33xx_pinmux: pinmux@44e10800 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&clkout2_pin>;
--
-- user_leds_s0: user_leds_s0 {
-- pinctrl-single,pins = <
-- 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
-- 0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */
-- 0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */
-- 0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */
-- >;
-- };
--
-- i2c0_pins: pinmux_i2c0_pins {
-- pinctrl-single,pins = <
-- 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
-- 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
-- >;
-- };
--
-- uart0_pins: pinmux_uart0_pins {
-- pinctrl-single,pins = <
-- 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-- 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-- >;
-- };
--
-- clkout2_pin: pinmux_clkout2_pin {
-- pinctrl-single,pins = <
-- 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-- >;
-- };
--
-- cpsw_default: cpsw_default {
-- pinctrl-single,pins = <
-- /* Slave 1 */
-- 0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
-- 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
-- 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
-- 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
-- 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
-- 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
-- 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
-- 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
-- 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
-- 0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
-- 0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
-- 0x13c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
-- 0x140 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
-- >;
-- };
--
-- cpsw_sleep: cpsw_sleep {
-- pinctrl-single,pins = <
-- /* Slave 1 reset value */
-- 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- >;
-- };
--
-- davinci_mdio_default: davinci_mdio_default {
-- pinctrl-single,pins = <
-- /* MDIO */
-- 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
-- 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
-- >;
-- };
--
-- davinci_mdio_sleep: davinci_mdio_sleep {
-- pinctrl-single,pins = <
-- /* MDIO reset value */
-- 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- >;
-- };
--
-- mmc1_pins: pinmux_mmc1_pins {
-- pinctrl-single,pins = <
-- 0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
-- >;
-- };
--
-- emmc_pins: pinmux_emmc_pins {
-- pinctrl-single,pins = <
-- 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-- 0x84 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_csn2.mmc1_cmd */
-- 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-- 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-- 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-- 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
-- 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
-- 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
-- 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
-- 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
-- >;
-- };
-- };
--
- ocp {
- uart0: serial@44e09000 {
- pinctrl-names = "default";
-@@ -217,6 +108,115 @@
- };
- };
-
-+&am33xx_pinmux {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&clkout2_pin>;
-+
-+ user_leds_s0: user_leds_s0 {
-+ pinctrl-single,pins = <
-+ 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
-+ 0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */
-+ 0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */
-+ 0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */
-+ >;
-+ };
-+
-+ i2c0_pins: pinmux_i2c0_pins {
-+ pinctrl-single,pins = <
-+ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
-+ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
-+ >;
-+ };
-+
-+ uart0_pins: pinmux_uart0_pins {
-+ pinctrl-single,pins = <
-+ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-+ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-+ >;
-+ };
-+
-+ clkout2_pin: pinmux_clkout2_pin {
-+ pinctrl-single,pins = <
-+ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-+ >;
-+ };
-+
-+ cpsw_default: cpsw_default {
-+ pinctrl-single,pins = <
-+ /* Slave 1 */
-+ 0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
-+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
-+ 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
-+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
-+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
-+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
-+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
-+ 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
-+ 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
-+ 0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
-+ 0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
-+ 0x13c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
-+ 0x140 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
-+ >;
-+ };
-+
-+ cpsw_sleep: cpsw_sleep {
-+ pinctrl-single,pins = <
-+ /* Slave 1 reset value */
-+ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ >;
-+ };
-+
-+ davinci_mdio_default: davinci_mdio_default {
-+ pinctrl-single,pins = <
-+ /* MDIO */
-+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
-+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
-+ >;
-+ };
-+
-+ davinci_mdio_sleep: davinci_mdio_sleep {
-+ pinctrl-single,pins = <
-+ /* MDIO reset value */
-+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ >;
-+ };
-+
-+ mmc1_pins: pinmux_mmc1_pins {
-+ pinctrl-single,pins = <
-+ 0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
-+ >;
-+ };
-+
-+ emmc_pins: pinmux_emmc_pins {
-+ pinctrl-single,pins = <
-+ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_csn2.mmc1_cmd */
-+ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
-+ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
-+ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
-+ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
-+ 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
-+ 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
-+ 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
-+ 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
-+ >;
-+ };
-+};
-+
- /include/ "tps65217.dtsi"
-
- &tps {
-diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
-index bc4a69d..1525cd6 100644
---- a/arch/arm/boot/dts/am335x-evm.dts
-+++ b/arch/arm/boot/dts/am335x-evm.dts
-@@ -24,133 +24,6 @@
- reg = <0x80000000 0x10000000>; /* 256 MB */
- };
-
-- am33xx_pinmux: pinmux@44e10800 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;
--
-- matrix_keypad_s0: matrix_keypad_s0 {
-- pinctrl-single,pins = <
-- 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
-- 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a6.gpio1_22 */
-- 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a9.gpio1_25 */
-- 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a10.gpio1_26 */
-- 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio1_27 */
-- >;
-- };
--
-- volume_keys_s0: volume_keys_s0 {
-- pinctrl-single,pins = <
-- 0x150 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_sclk.gpio0_2 */
-- 0x154 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_d0.gpio0_3 */
-- >;
-- };
--
-- i2c0_pins: pinmux_i2c0_pins {
-- pinctrl-single,pins = <
-- 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
-- 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
-- >;
-- };
--
-- i2c1_pins: pinmux_i2c1_pins {
-- pinctrl-single,pins = <
-- 0x158 (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */
-- 0x15c (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */
-- >;
-- };
--
-- uart0_pins: pinmux_uart0_pins {
-- pinctrl-single,pins = <
-- 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-- 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-- >;
-- };
--
-- clkout2_pin: pinmux_clkout2_pin {
-- pinctrl-single,pins = <
-- 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-- >;
-- };
--
-- nandflash_pins_s0: nandflash_pins_s0 {
-- pinctrl-single,pins = <
-- 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
-- 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
-- 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
-- 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
-- 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
-- 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
-- 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
-- 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
-- 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
-- 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */
-- 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
-- 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
-- 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
-- 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
-- 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
-- >;
-- };
--
-- ecap0_pins: backlight_pins {
-- pinctrl-single,pins = <
-- 0x164 0x0 /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
-- >;
-- };
--
-- cpsw_default: cpsw_default {
-- pinctrl-single,pins = <
-- /* Slave 1 */
-- 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
-- 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
-- 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
-- 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
-- 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
-- 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
-- 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
-- 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
-- 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
-- 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
-- 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
-- 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
-- >;
-- };
--
-- cpsw_sleep: cpsw_sleep {
-- pinctrl-single,pins = <
-- /* Slave 1 reset value */
-- 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- >;
-- };
--
-- davinci_mdio_default: davinci_mdio_default {
-- pinctrl-single,pins = <
-- /* MDIO */
-- 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
-- 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
-- >;
-- };
--
-- davinci_mdio_sleep: davinci_mdio_sleep {
-- pinctrl-single,pins = <
-- /* MDIO reset value */
-- 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- >;
-- };
-- };
--
- ocp {
- uart0: serial@44e09000 {
- pinctrl-names = "default";
-@@ -405,6 +278,133 @@
- };
- };
-
-+&am33xx_pinmux {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;
-+
-+ matrix_keypad_s0: matrix_keypad_s0 {
-+ pinctrl-single,pins = <
-+ 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
-+ 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a6.gpio1_22 */
-+ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a9.gpio1_25 */
-+ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a10.gpio1_26 */
-+ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio1_27 */
-+ >;
-+ };
-+
-+ volume_keys_s0: volume_keys_s0 {
-+ pinctrl-single,pins = <
-+ 0x150 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_sclk.gpio0_2 */
-+ 0x154 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_d0.gpio0_3 */
-+ >;
-+ };
-+
-+ i2c0_pins: pinmux_i2c0_pins {
-+ pinctrl-single,pins = <
-+ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
-+ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
-+ >;
-+ };
-+
-+ i2c1_pins: pinmux_i2c1_pins {
-+ pinctrl-single,pins = <
-+ 0x158 (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */
-+ 0x15c (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */
-+ >;
-+ };
-+
-+ uart0_pins: pinmux_uart0_pins {
-+ pinctrl-single,pins = <
-+ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-+ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-+ >;
-+ };
-+
-+ clkout2_pin: pinmux_clkout2_pin {
-+ pinctrl-single,pins = <
-+ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-+ >;
-+ };
-+
-+ nandflash_pins_s0: nandflash_pins_s0 {
-+ pinctrl-single,pins = <
-+ 0x0 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
-+ 0x4 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
-+ 0x8 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
-+ 0xc (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
-+ 0x10 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
-+ 0x14 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
-+ 0x18 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
-+ 0x1c (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
-+ 0x70 (PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
-+ 0x74 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */
-+ 0x7c (PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
-+ 0x90 (PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
-+ 0x94 (PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
-+ 0x98 (PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
-+ 0x9c (PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
-+ >;
-+ };
-+
-+ ecap0_pins: backlight_pins {
-+ pinctrl-single,pins = <
-+ 0x164 0x0 /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
-+ >;
-+ };
-+
-+ cpsw_default: cpsw_default {
-+ pinctrl-single,pins = <
-+ /* Slave 1 */
-+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
-+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
-+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
-+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
-+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
-+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
-+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
-+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
-+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
-+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
-+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
-+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
-+ >;
-+ };
-+
-+ cpsw_sleep: cpsw_sleep {
-+ pinctrl-single,pins = <
-+ /* Slave 1 reset value */
-+ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ >;
-+ };
-+
-+ davinci_mdio_default: davinci_mdio_default {
-+ pinctrl-single,pins = <
-+ /* MDIO */
-+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
-+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
-+ >;
-+ };
-+
-+ davinci_mdio_sleep: davinci_mdio_sleep {
-+ pinctrl-single,pins = <
-+ /* MDIO reset value */
-+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ >;
-+ };
-+};
-+
- #include "tps65910.dtsi"
-
- &tps {
-diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
-index 55fd194..f0066fe 100644
---- a/arch/arm/boot/dts/am335x-evmsk.dts
-+++ b/arch/arm/boot/dts/am335x-evmsk.dts
-@@ -31,135 +31,6 @@
- reg = <0x80000000 0x10000000>; /* 256 MB */
- };
-
-- am33xx_pinmux: pinmux@44e10800 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
--
-- user_leds_s0: user_leds_s0 {
-- pinctrl-single,pins = <
-- 0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */
-- 0x14 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad5.gpio1_5 */
-- 0x18 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad6.gpio1_6 */
-- 0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad7.gpio1_7 */
-- >;
-- };
--
-- gpio_keys_s0: gpio_keys_s0 {
-- pinctrl-single,pins = <
-- 0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */
-- 0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */
-- 0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.gpio0_30 */
-- 0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */
-- >;
-- };
--
-- i2c0_pins: pinmux_i2c0_pins {
-- pinctrl-single,pins = <
-- 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
-- 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
-- >;
-- };
--
-- uart0_pins: pinmux_uart0_pins {
-- pinctrl-single,pins = <
-- 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-- 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-- >;
-- };
--
-- clkout2_pin: pinmux_clkout2_pin {
-- pinctrl-single,pins = <
-- 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-- >;
-- };
--
-- ecap2_pins: backlight_pins {
-- pinctrl-single,pins = <
-- 0x19c 0x4 /* mcasp0_ahclkr.ecap2_in_pwm2_out MODE4 */
-- >;
-- };
--
-- cpsw_default: cpsw_default {
-- pinctrl-single,pins = <
-- /* Slave 1 */
-- 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
-- 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
-- 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
-- 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
-- 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
-- 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
-- 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
-- 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
-- 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
-- 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
-- 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
-- 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
--
-- /* Slave 2 */
-- 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
-- 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
-- 0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
-- 0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
-- 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
-- 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
-- 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
-- 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
-- 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
-- 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
-- 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
-- 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
-- >;
-- };
--
-- cpsw_sleep: cpsw_sleep {
-- pinctrl-single,pins = <
-- /* Slave 1 reset value */
-- 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
--
-- /* Slave 2 reset value*/
-- 0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- >;
-- };
--
-- davinci_mdio_default: davinci_mdio_default {
-- pinctrl-single,pins = <
-- /* MDIO */
-- 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
-- 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
-- >;
-- };
--
-- davinci_mdio_sleep: davinci_mdio_sleep {
-- pinctrl-single,pins = <
-- /* MDIO reset value */
-- 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-- >;
-- };
-- };
--
- ocp {
- uart0: serial@44e09000 {
- pinctrl-names = "default";
-@@ -321,6 +192,135 @@
- };
- };
-
-+&am33xx_pinmux {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
-+
-+ user_leds_s0: user_leds_s0 {
-+ pinctrl-single,pins = <
-+ 0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */
-+ 0x14 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad5.gpio1_5 */
-+ 0x18 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad6.gpio1_6 */
-+ 0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad7.gpio1_7 */
-+ >;
-+ };
-+
-+ gpio_keys_s0: gpio_keys_s0 {
-+ pinctrl-single,pins = <
-+ 0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */
-+ 0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */
-+ 0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.gpio0_30 */
-+ 0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */
-+ >;
-+ };
-+
-+ i2c0_pins: pinmux_i2c0_pins {
-+ pinctrl-single,pins = <
-+ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
-+ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
-+ >;
-+ };
-+
-+ uart0_pins: pinmux_uart0_pins {
-+ pinctrl-single,pins = <
-+ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-+ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-+ >;
-+ };
-+
-+ clkout2_pin: pinmux_clkout2_pin {
-+ pinctrl-single,pins = <
-+ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-+ >;
-+ };
-+
-+ ecap2_pins: backlight_pins {
-+ pinctrl-single,pins = <
-+ 0x19c 0x4 /* mcasp0_ahclkr.ecap2_in_pwm2_out MODE4 */
-+ >;
-+ };
-+
-+ cpsw_default: cpsw_default {
-+ pinctrl-single,pins = <
-+ /* Slave 1 */
-+ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
-+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
-+ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
-+ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
-+ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
-+ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
-+ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
-+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
-+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
-+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
-+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
-+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
-+
-+ /* Slave 2 */
-+ 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
-+ 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
-+ 0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
-+ 0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
-+ 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
-+ 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
-+ 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
-+ 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
-+ 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
-+ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
-+ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
-+ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
-+ >;
-+ };
-+
-+ cpsw_sleep: cpsw_sleep {
-+ pinctrl-single,pins = <
-+ /* Slave 1 reset value */
-+ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+
-+ /* Slave 2 reset value*/
-+ 0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ >;
-+ };
-+
-+ davinci_mdio_default: davinci_mdio_default {
-+ pinctrl-single,pins = <
-+ /* MDIO */
-+ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
-+ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
-+ >;
-+ };
-+
-+ davinci_mdio_sleep: davinci_mdio_sleep {
-+ pinctrl-single,pins = <
-+ /* MDIO reset value */
-+ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-+ >;
-+ };
-+};
-+
- #include "tps65910.dtsi"
-
- &tps {
---
-1.8.4.rc3
-
-From ff7a46710ffc245a5c8e32cf1843aa3fea7aa1ff Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Date: Fri, 20 Sep 2013 17:42:19 +0200
-Subject: [PATCH 11/15] ARM: dts: AM33XX: don't redefine OCP bus and device
- nodes
-
-The On Chip Peripherals (OCP) device node is a simplified
-representation of the AM33XX SoC interconnect. An OCP dev
-node is already defined in the am33xx.dtsi Device Tree
-source file included by am33xx based boards so there is
-no need to redefine this on each board DT file.
-
-Also, the OCP and IP modules directly connected to it are SoC
-internal details that is better to keep outside of board files.
-
-Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 100 ++++----
- arch/arm/boot/dts/am335x-evm.dts | 380 +++++++++++++++---------------
- arch/arm/boot/dts/am335x-evmsk.dts | 148 ++++++------
- 3 files changed, 311 insertions(+), 317 deletions(-)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index 29799ac..ff5c3ca 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -21,57 +21,6 @@
- reg = <0x80000000 0x10000000>; /* 256 MB */
- };
-
-- ocp {
-- uart0: serial@44e09000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&uart0_pins>;
--
-- status = "okay";
-- };
--
-- musb: usb@47400000 {
-- status = "okay";
--
-- control@44e10000 {
-- status = "okay";
-- };
--
-- usb-phy@47401300 {
-- status = "okay";
-- };
--
-- usb-phy@47401b00 {
-- status = "okay";
-- };
--
-- usb@47401000 {
-- status = "okay";
-- };
--
-- usb@47401800 {
-- status = "okay";
-- dr_mode = "host";
-- };
--
-- dma-controller@07402000 {
-- status = "okay";
-- };
-- };
--
-- i2c0: i2c@44e0b000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&i2c0_pins>;
--
-- status = "okay";
-- clock-frequency = <400000>;
--
-- tps: tps@24 {
-- reg = <0x24>;
-- };
--
-- };
-- };
--
- leds {
- pinctrl-names = "default";
- pinctrl-0 = <&user_leds_s0>;
-@@ -217,6 +166,55 @@
- };
- };
-
-+&uart0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+
-+ status = "okay";
-+};
-+
-+&usb {
-+ status = "okay";
-+
-+ control@44e10000 {
-+ status = "okay";
-+ };
-+
-+ usb-phy@47401300 {
-+ status = "okay";
-+ };
-+
-+ usb-phy@47401b00 {
-+ status = "okay";
-+ };
-+
-+ usb@47401000 {
-+ status = "okay";
-+ };
-+
-+ usb@47401800 {
-+ status = "okay";
-+ dr_mode = "host";
-+ };
-+
-+ dma-controller@07402000 {
-+ status = "okay";
-+ };
-+};
-+
-+&i2c0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c0_pins>;
-+
-+ status = "okay";
-+ clock-frequency = <400000>;
-+
-+ tps: tps@24 {
-+ reg = <0x24>;
-+ };
-+
-+};
-+
- /include/ "tps65217.dtsi"
-
- &tps {
-diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
-index 1525cd6..23b0a3e 100644
---- a/arch/arm/boot/dts/am335x-evm.dts
-+++ b/arch/arm/boot/dts/am335x-evm.dts
-@@ -24,197 +24,6 @@
- reg = <0x80000000 0x10000000>; /* 256 MB */
- };
-
-- ocp {
-- uart0: serial@44e09000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&uart0_pins>;
--
-- status = "okay";
-- };
--
-- i2c0: i2c@44e0b000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&i2c0_pins>;
--
-- status = "okay";
-- clock-frequency = <400000>;
--
-- tps: tps@2d {
-- reg = <0x2d>;
-- };
-- };
--
-- musb: usb@47400000 {
-- status = "okay";
--
-- control@44e10000 {
-- status = "okay";
-- };
--
-- usb-phy@47401300 {
-- status = "okay";
-- };
--
-- usb-phy@47401b00 {
-- status = "okay";
-- };
--
-- usb@47401000 {
-- status = "okay";
-- };
--
-- usb@47401800 {
-- status = "okay";
-- dr_mode = "host";
-- };
--
-- dma-controller@07402000 {
-- status = "okay";
-- };
-- };
--
-- i2c1: i2c@4802a000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&i2c1_pins>;
--
-- status = "okay";
-- clock-frequency = <100000>;
--
-- lis331dlh: lis331dlh@18 {
-- compatible = "st,lis331dlh", "st,lis3lv02d";
-- reg = <0x18>;
-- Vdd-supply = <&lis3_reg>;
-- Vdd_IO-supply = <&lis3_reg>;
--
-- st,click-single-x;
-- st,click-single-y;
-- st,click-single-z;
-- st,click-thresh-x = <10>;
-- st,click-thresh-y = <10>;
-- st,click-thresh-z = <10>;
-- st,irq1-click;
-- st,irq2-click;
-- st,wakeup-x-lo;
-- st,wakeup-x-hi;
-- st,wakeup-y-lo;
-- st,wakeup-y-hi;
-- st,wakeup-z-lo;
-- st,wakeup-z-hi;
-- st,min-limit-x = <120>;
-- st,min-limit-y = <120>;
-- st,min-limit-z = <140>;
-- st,max-limit-x = <550>;
-- st,max-limit-y = <550>;
-- st,max-limit-z = <750>;
-- };
--
-- tsl2550: tsl2550@39 {
-- compatible = "taos,tsl2550";
-- reg = <0x39>;
-- };
--
-- tmp275: tmp275@48 {
-- compatible = "ti,tmp275";
-- reg = <0x48>;
-- };
-- };
--
-- elm: elm@48080000 {
-- status = "okay";
-- };
--
-- epwmss0: epwmss@48300000 {
-- status = "okay";
--
-- ecap0: ecap@48300100 {
-- status = "okay";
-- pinctrl-names = "default";
-- pinctrl-0 = <&ecap0_pins>;
-- };
-- };
--
-- gpmc: gpmc@50000000 {
-- status = "okay";
-- pinctrl-names = "default";
-- pinctrl-0 = <&nandflash_pins_s0>;
-- ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */
-- nand@0,0 {
-- reg = <0 0 0>; /* CS0, offset 0 */
-- nand-bus-width = <8>;
-- ti,nand-ecc-opt = "bch8";
-- gpmc,device-nand = "true";
-- gpmc,device-width = <1>;
-- gpmc,sync-clk-ps = <0>;
-- gpmc,cs-on-ns = <0>;
-- gpmc,cs-rd-off-ns = <44>;
-- gpmc,cs-wr-off-ns = <44>;
-- gpmc,adv-on-ns = <6>;
-- gpmc,adv-rd-off-ns = <34>;
-- gpmc,adv-wr-off-ns = <44>;
-- gpmc,we-on-ns = <0>;
-- gpmc,we-off-ns = <40>;
-- gpmc,oe-on-ns = <0>;
-- gpmc,oe-off-ns = <54>;
-- gpmc,access-ns = <64>;
-- gpmc,rd-cycle-ns = <82>;
-- gpmc,wr-cycle-ns = <82>;
-- gpmc,wait-on-read = "true";
-- gpmc,wait-on-write = "true";
-- gpmc,bus-turnaround-ns = <0>;
-- gpmc,cycle2cycle-delay-ns = <0>;
-- gpmc,clk-activation-ns = <0>;
-- gpmc,wait-monitoring-ns = <0>;
-- gpmc,wr-access-ns = <40>;
-- gpmc,wr-data-mux-bus-ns = <0>;
--
-- #address-cells = <1>;
-- #size-cells = <1>;
-- elm_id = <&elm>;
--
-- /* MTD partition table */
-- partition@0 {
-- label = "SPL1";
-- reg = <0x00000000 0x000020000>;
-- };
--
-- partition@1 {
-- label = "SPL2";
-- reg = <0x00020000 0x00020000>;
-- };
--
-- partition@2 {
-- label = "SPL3";
-- reg = <0x00040000 0x00020000>;
-- };
--
-- partition@3 {
-- label = "SPL4";
-- reg = <0x00060000 0x00020000>;
-- };
--
-- partition@4 {
-- label = "U-boot";
-- reg = <0x00080000 0x001e0000>;
-- };
--
-- partition@5 {
-- label = "environment";
-- reg = <0x00260000 0x00020000>;
-- };
--
-- partition@6 {
-- label = "Kernel";
-- reg = <0x00280000 0x00500000>;
-- };
--
-- partition@7 {
-- label = "File-System";
-- reg = <0x00780000 0x0F880000>;
-- };
-- };
-- };
-- };
--
- vbat: fixedregulator@0 {
- compatible = "regulator-fixed";
- regulator-name = "vbat";
-@@ -405,6 +214,195 @@
- };
- };
-
-+&uart0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+
-+ status = "okay";
-+};
-+
-+&i2c0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c0_pins>;
-+
-+ status = "okay";
-+ clock-frequency = <400000>;
-+
-+ tps: tps@2d {
-+ reg = <0x2d>;
-+ };
-+};
-+
-+&usb {
-+ status = "okay";
-+
-+ control@44e10000 {
-+ status = "okay";
-+ };
-+
-+ usb-phy@47401300 {
-+ status = "okay";
-+ };
-+
-+ usb-phy@47401b00 {
-+ status = "okay";
-+ };
-+
-+ usb@47401000 {
-+ status = "okay";
-+ };
-+
-+ usb@47401800 {
-+ status = "okay";
-+ dr_mode = "host";
-+ };
-+
-+ dma-controller@07402000 {
-+ status = "okay";
-+ };
-+};
-+
-+&i2c1 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c1_pins>;
-+
-+ status = "okay";
-+ clock-frequency = <100000>;
-+
-+ lis331dlh: lis331dlh@18 {
-+ compatible = "st,lis331dlh", "st,lis3lv02d";
-+ reg = <0x18>;
-+ Vdd-supply = <&lis3_reg>;
-+ Vdd_IO-supply = <&lis3_reg>;
-+
-+ st,click-single-x;
-+ st,click-single-y;
-+ st,click-single-z;
-+ st,click-thresh-x = <10>;
-+ st,click-thresh-y = <10>;
-+ st,click-thresh-z = <10>;
-+ st,irq1-click;
-+ st,irq2-click;
-+ st,wakeup-x-lo;
-+ st,wakeup-x-hi;
-+ st,wakeup-y-lo;
-+ st,wakeup-y-hi;
-+ st,wakeup-z-lo;
-+ st,wakeup-z-hi;
-+ st,min-limit-x = <120>;
-+ st,min-limit-y = <120>;
-+ st,min-limit-z = <140>;
-+ st,max-limit-x = <550>;
-+ st,max-limit-y = <550>;
-+ st,max-limit-z = <750>;
-+ };
-+
-+ tsl2550: tsl2550@39 {
-+ compatible = "taos,tsl2550";
-+ reg = <0x39>;
-+ };
-+
-+ tmp275: tmp275@48 {
-+ compatible = "ti,tmp275";
-+ reg = <0x48>;
-+ };
-+};
-+
-+&elm {
-+ status = "okay";
-+};
-+
-+&epwmss0 {
-+ status = "okay";
-+
-+ ecap0: ecap@48300100 {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&ecap0_pins>;
-+ };
-+};
-+
-+&gpmc {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&nandflash_pins_s0>;
-+ ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */
-+ nand@0,0 {
-+ reg = <0 0 0>; /* CS0, offset 0 */
-+ nand-bus-width = <8>;
-+ ti,nand-ecc-opt = "bch8";
-+ gpmc,device-nand = "true";
-+ gpmc,device-width = <1>;
-+ gpmc,sync-clk-ps = <0>;
-+ gpmc,cs-on-ns = <0>;
-+ gpmc,cs-rd-off-ns = <44>;
-+ gpmc,cs-wr-off-ns = <44>;
-+ gpmc,adv-on-ns = <6>;
-+ gpmc,adv-rd-off-ns = <34>;
-+ gpmc,adv-wr-off-ns = <44>;
-+ gpmc,we-on-ns = <0>;
-+ gpmc,we-off-ns = <40>;
-+ gpmc,oe-on-ns = <0>;
-+ gpmc,oe-off-ns = <54>;
-+ gpmc,access-ns = <64>;
-+ gpmc,rd-cycle-ns = <82>;
-+ gpmc,wr-cycle-ns = <82>;
-+ gpmc,wait-on-read = "true";
-+ gpmc,wait-on-write = "true";
-+ gpmc,bus-turnaround-ns = <0>;
-+ gpmc,cycle2cycle-delay-ns = <0>;
-+ gpmc,clk-activation-ns = <0>;
-+ gpmc,wait-monitoring-ns = <0>;
-+ gpmc,wr-access-ns = <40>;
-+ gpmc,wr-data-mux-bus-ns = <0>;
-+
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ elm_id = <&elm>;
-+
-+ /* MTD partition table */
-+ partition@0 {
-+ label = "SPL1";
-+ reg = <0x00000000 0x000020000>;
-+ };
-+
-+ partition@1 {
-+ label = "SPL2";
-+ reg = <0x00020000 0x00020000>;
-+ };
-+
-+ partition@2 {
-+ label = "SPL3";
-+ reg = <0x00040000 0x00020000>;
-+ };
-+
-+ partition@3 {
-+ label = "SPL4";
-+ reg = <0x00060000 0x00020000>;
-+ };
-+
-+ partition@4 {
-+ label = "U-boot";
-+ reg = <0x00080000 0x001e0000>;
-+ };
-+
-+ partition@5 {
-+ label = "environment";
-+ reg = <0x00260000 0x00020000>;
-+ };
-+
-+ partition@6 {
-+ label = "Kernel";
-+ reg = <0x00280000 0x00500000>;
-+ };
-+
-+ partition@7 {
-+ label = "File-System";
-+ reg = <0x00780000 0x0F880000>;
-+ };
-+ };
-+};
-+
- #include "tps65910.dtsi"
-
- &tps {
-diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
-index f0066fe..bc93895 100644
---- a/arch/arm/boot/dts/am335x-evmsk.dts
-+++ b/arch/arm/boot/dts/am335x-evmsk.dts
-@@ -31,81 +31,6 @@
- reg = <0x80000000 0x10000000>; /* 256 MB */
- };
-
-- ocp {
-- uart0: serial@44e09000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&uart0_pins>;
--
-- status = "okay";
-- };
--
-- i2c0: i2c@44e0b000 {
-- pinctrl-names = "default";
-- pinctrl-0 = <&i2c0_pins>;
--
-- status = "okay";
-- clock-frequency = <400000>;
--
-- tps: tps@2d {
-- reg = <0x2d>;
-- };
--
-- lis331dlh: lis331dlh@18 {
-- compatible = "st,lis331dlh", "st,lis3lv02d";
-- reg = <0x18>;
-- Vdd-supply = <&lis3_reg>;
-- Vdd_IO-supply = <&lis3_reg>;
--
-- st,click-single-x;
-- st,click-single-y;
-- st,click-single-z;
-- st,click-thresh-x = <10>;
-- st,click-thresh-y = <10>;
-- st,click-thresh-z = <10>;
-- st,irq1-click;
-- st,irq2-click;
-- st,wakeup-x-lo;
-- st,wakeup-x-hi;
-- st,wakeup-y-lo;
-- st,wakeup-y-hi;
-- st,wakeup-z-lo;
-- st,wakeup-z-hi;
-- st,min-limit-x = <120>;
-- st,min-limit-y = <120>;
-- st,min-limit-z = <140>;
-- st,max-limit-x = <550>;
-- st,max-limit-y = <550>;
-- st,max-limit-z = <750>;
-- };
-- };
--
-- musb: usb@47400000 {
-- status = "okay";
--
-- control@44e10000 {
-- status = "okay";
-- };
--
-- usb-phy@47401300 {
-- status = "okay";
-- };
--
-- usb@47401000 {
-- status = "okay";
-- };
-- };
--
-- epwmss2: epwmss@48304000 {
-- status = "okay";
--
-- ecap2: ecap@48304100 {
-- status = "okay";
-- pinctrl-names = "default";
-- pinctrl-0 = <&ecap2_pins>;
-- };
-- };
-- };
--
- vbat: fixedregulator@0 {
- compatible = "regulator-fixed";
- regulator-name = "vbat";
-@@ -321,6 +246,79 @@
- };
- };
-
-+&uart0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+
-+ status = "okay";
-+};
-+
-+&i2c0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c0_pins>;
-+
-+ status = "okay";
-+ clock-frequency = <400000>;
-+
-+ tps: tps@2d {
-+ reg = <0x2d>;
-+ };
-+
-+ lis331dlh: lis331dlh@18 {
-+ compatible = "st,lis331dlh", "st,lis3lv02d";
-+ reg = <0x18>;
-+ Vdd-supply = <&lis3_reg>;
-+ Vdd_IO-supply = <&lis3_reg>;
-+
-+ st,click-single-x;
-+ st,click-single-y;
-+ st,click-single-z;
-+ st,click-thresh-x = <10>;
-+ st,click-thresh-y = <10>;
-+ st,click-thresh-z = <10>;
-+ st,irq1-click;
-+ st,irq2-click;
-+ st,wakeup-x-lo;
-+ st,wakeup-x-hi;
-+ st,wakeup-y-lo;
-+ st,wakeup-y-hi;
-+ st,wakeup-z-lo;
-+ st,wakeup-z-hi;
-+ st,min-limit-x = <120>;
-+ st,min-limit-y = <120>;
-+ st,min-limit-z = <140>;
-+ st,max-limit-x = <550>;
-+ st,max-limit-y = <550>;
-+ st,max-limit-z = <750>;
-+ };
-+};
-+
-+&usb {
-+ status = "okay";
-+
-+ control@44e10000 {
-+ status = "okay";
-+ };
-+
-+ usb-phy@47401300 {
-+ status = "okay";
-+ };
-+
-+ usb@47401000 {
-+ status = "okay";
-+ };
-+};
-+
-+&epwmss2 {
-+ status = "okay";
-+
-+ ecap2: ecap@48304100 {
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&ecap2_pins>;
-+ };
-+};
-+
- #include "tps65910.dtsi"
-
- &tps {
---
-1.8.4.rc3
-
-From a9a966a91ca0304de63c03ef5131c08b1d19f60d Mon Sep 17 00:00:00 2001
-From: Dan Murphy <dmurphy@ti.com>
-Date: Wed, 2 Oct 2013 12:58:33 -0500
-Subject: [PATCH 12/15] ARM: dts: AM33XX: add ethernet alias's for am33xx
-
-Set the alias for ethernet0 and ethernet1 so that uBoot
-can set the MAC address appropriately.
-
-Currently u-boot cannot find the alias and there for does
-not set the MAC address.
-
-Signed-off-by: Dan Murphy <dmurphy@ti.com>
-Tested-by: Mugunthan V N <mugunthanvnm@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am33xx.dtsi | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index 553adc6..8aabaa0 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -30,6 +30,8 @@
- usb1 = &usb1;
- phy0 = &usb0_phy;
- phy1 = &usb1_phy;
-+ ethernet0 = &cpsw_emac0;
-+ ethernet1 = &cpsw_emac1;
- };
-
- cpus {
---
-1.8.4.rc3
-
-From 5339e0ba31b312715a5542a53c6a46c3e9a5f53b Mon Sep 17 00:00:00 2001
-From: Nishanth Menon <nm@ti.com>
-Date: Mon, 30 Sep 2013 09:40:16 -0500
-Subject: [PATCH 13/15] ARM: dts: am335x-boneblack: move fixed regulator to
- board level
-
-3.3V fixed regulator does not belong to TPS node - as a result
-the fixed regulator is never probed and MMC is continually deferred
-due to lack of regulator.
-
-Move the fixed regulator to be at root of platform.
-
-Cc: Joel Fernandes <joelf@ti.com>
-Cc: Sekhar Nori <nsekhar@ti.com>
-Cc: Koen Kooi <koen@dominion.thruhere.net>
-Signed-off-by: Nishanth Menon <nm@ti.com>
-Tested-by: Felipe Balbi <balbi@ti.com>
-Tested-by: Balaji T K <balajitk@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index ff5c3ca..b3e6fcf 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -55,6 +55,13 @@
- default-state = "off";
- };
- };
-+
-+ vmmcsd_fixed: fixedregulator@0 {
-+ compatible = "regulator-fixed";
-+ regulator-name = "vmmcsd_fixed";
-+ regulator-min-microvolt = <3300000>;
-+ regulator-max-microvolt = <3300000>;
-+ };
- };
-
- &am33xx_pinmux {
-@@ -257,13 +264,6 @@
- regulator-always-on;
- };
- };
--
-- vmmcsd_fixed: fixedregulator@0 {
-- compatible = "regulator-fixed";
-- regulator-name = "vmmcsd_fixed";
-- regulator-min-microvolt = <3300000>;
-- regulator-max-microvolt = <3300000>;
-- };
- };
-
- &cpsw_emac0 {
---
-1.8.4.rc3
-
-From 085e4e139ae508aab69c568d6bf2a6860a0bd607 Mon Sep 17 00:00:00 2001
-From: Balaji T K <balajitk@ti.com>
-Date: Fri, 27 Sep 2013 17:05:09 +0530
-Subject: [PATCH 14/15] ARM: dts: am335x-bone-common: correct mux mode for cmd
- line
-
-Set pinmux_emmc_pins mux mode for cmd line to MODE2 in order
-to detect eMMC on BBB and BBW + eMMC cape.
-
-Signed-off-by: Balaji T K <balajitk@ti.com>
-Tested-by: Felipe Balbi <balbi@ti.com>
-Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index b3e6fcf..e3f27ec 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -160,7 +160,7 @@
- emmc_pins: pinmux_emmc_pins {
- pinctrl-single,pins = <
- 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
-- 0x84 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_csn2.mmc1_cmd */
-+ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
- 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
- 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
- 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
---
-1.8.4.rc3
-
-commit d6cfc1e266d34d5b1f8a26bb272d2d2c466d89b8
-Author: Benoit Parrot <bparrot@ti.com>
-Date: Thu Aug 8 18:28:14 2013 -0500
-
- ARM: dts: AM33XX: Add LCDC info into am335x-evm
-
- Add LCDC device node in DT for am33xx
- Add LCDC and Panel info in DT for am335x-evm
-
- Changes:
- - remove redundant/unnecessary SoC specific setting in the board dts
- - resolved conflicts on for_3.13/dts
-
- Signed-off-by: Benoit Parrot <bparrot@ti.com>
- Signed-off-by: Joel Fernandes <joelf@ti.com>
- Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
-
-diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
-index ff834ad..eabacf9 100644
---- a/arch/arm/boot/dts/am335x-evm.dts
-+++ b/arch/arm/boot/dts/am335x-evm.dts
-@@ -85,6 +85,40 @@
- brightness-levels = <0 51 53 56 62 75 101 152 255>;
- default-brightness-level = <8>;
- };
-+
-+ panel {
-+ compatible = "ti,tilcdc,panel";
-+ status = "okay";
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&lcd_pins_s0>;
-+ panel-info {
-+ ac-bias = <255>;
-+ ac-bias-intrpt = <0>;
-+ dma-burst-sz = <16>;
-+ bpp = <32>;
-+ fdd = <0x80>;
-+ sync-edge = <0>;
-+ sync-ctrl = <1>;
-+ raster-order = <0>;
-+ fifo-th = <0>;
-+ };
-+
-+ display-timings {
-+ 800x480p62 {
-+ clock-frequency = <30000000>;
-+ hactive = <800>;
-+ vactive = <480>;
-+ hfront-porch = <39>;
-+ hback-porch = <39>;
-+ hsync-len = <47>;
-+ vback-porch = <29>;
-+ vfront-porch = <13>;
-+ vsync-len = <2>;
-+ hsync-active = <1>;
-+ vsync-active = <1>;
-+ };
-+ };
-+ };
- };
-
- &am33xx_pinmux {
-@@ -212,6 +246,39 @@
- 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
- >;
- };
-+
-+ lcd_pins_s0: lcd_pins_s0 {
-+ pinctrl-single,pins = <
-+ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
-+ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
-+ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
-+ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
-+ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
-+ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
-+ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
-+ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
-+ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */
-+ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */
-+ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */
-+ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */
-+ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */
-+ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */
-+ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */
-+ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */
-+ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */
-+ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */
-+ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */
-+ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */
-+ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */
-+ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */
-+ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */
-+ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */
-+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
-+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
-+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
-+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
-+ >;
-+ };
- };
-
- &uart0 {
-@@ -308,6 +375,10 @@
- };
- };
-
-+&lcdc {
-+ status = "okay";
-+};
-+
- &elm {
- status = "okay";
- };
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index c87bf4b..7db3c81 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -684,6 +684,15 @@
- status = "disabled";
- };
-
-+ lcdc: lcdc@4830e000 {
-+ compatible = "ti,am33xx-tilcdc";
-+ reg = <0x4830e000 0x1000>;
-+ interrupt-parent = <&intc>;
-+ interrupts = <36>;
-+ ti,hwmods = "lcdc";
-+ status = "disabled";
-+ };
-+
- tscadc: tscadc@44e0d000 {
- compatible = "ti,am3359-tscadc";
- reg = <0x44e0d000 0x1000>;
-commit 559a08e89350e269a4bba93629f39da5dd8e4fef
-Author: Darren Etheridge <detheridge@ti.com>
-Date: Fri Sep 20 15:01:42 2013 -0500
-
- ARM: dts: AM33XX beagle black: add pinmux and hdmi node to enable display
-
- Enable the hdmi output and the LCD Controller on BeagleBone
- Black. Also configure the correct pinmux for output of
- video data from the SoC to the HDMI encoder.
-
- Signed-off-by: Darren Etheridge <detheridge@ti.com>
- Signed-off-by: Joel Fernandes <joelf@ti.com>
- Signed-off-by: Benoit Cousson <bcousson@baylibre.com>
-
-diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
-index 16b3bea..6b71ad9 100644
---- a/arch/arm/boot/dts/am335x-boneblack.dts
-+++ b/arch/arm/boot/dts/am335x-boneblack.dts
-@@ -28,3 +28,51 @@
- status = "okay";
- ti,vcc-aux-disable-is-sleep;
- };
-+
-+&am33xx_pinmux {
-+ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
-+ pinctrl-single,pins = <
-+ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
-+ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
-+ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
-+ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
-+ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
-+ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
-+ >;
-+ };
-+ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
-+ pinctrl-single,pins = <
-+ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
-+ >;
-+ };
-+};
-+
-+&lcdc {
-+ status = "okay";
-+};
-+
-+/ {
-+ hdmi {
-+ compatible = "ti,tilcdc,slave";
-+ i2c = <&i2c0>;
-+ pinctrl-names = "default", "off";
-+ pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
-+ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
-+ status = "okay";
-+ };
-+};
-commit d4cbe80db468dcfaa058f9f00a332784e5dff316
-Author: Suman Anna <s-anna@ti.com>
-Date: Thu Oct 10 16:15:35 2013 -0500
-
- ARM: dts: AM33XX: Add hwspinlock node
-
- Add the hwspinlock device tree node for AM33xx family
- of SoCs.
-
- Signed-off-by: Suman Anna <s-anna@ti.com>
- Signed-off-by: Tony Lindgren <tony@atomide.com>
-
-diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
-index 0ca13ad..9ae258e 100644
---- a/arch/arm/boot/dts/am33xx.dtsi
-+++ b/arch/arm/boot/dts/am33xx.dtsi
-@@ -288,6 +288,12 @@
- status = "disabled";
- };
-
-+ hwspinlock: spinlock@480ca000 {
-+ compatible = "ti,omap4-hwspinlock";
-+ reg = <0x480ca000 0x1000>;
-+ ti,hwmods = "spinlock";
-+ };
-+
- wdt2: wdt@44e35000 {
- compatible = "ti,omap3-wdt";
- ti,hwmods = "wd_timer2";
diff --git a/arm-am33xx-bblack.patch b/arm-am33xx-bblack.patch
deleted file mode 100644
index 4f62c9dd5..000000000
--- a/arm-am33xx-bblack.patch
+++ /dev/null
@@ -1,610 +0,0 @@
-Bugzilla: 1012025
-Upstream-status: In beagle github repository https://github.com/beagleboard/kernel
-
-From 82fe302f565e00cfde3e96c6132df93b39525e7b Mon Sep 17 00:00:00 2001
-From: Philipp Zabel <p.zabel@pengutronix.de>
-Date: Tue, 28 May 2013 17:06:15 +0200
-Subject: [PATCH] reset: Add driver for gpio-controlled reset pins
-
-This driver implements a reset controller device that toggle a gpio
-connected to a reset pin of a peripheral IC. The delay between assertion
-and de-assertion of the reset signal can be configured via device tree.
-
-Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
-Reviewed-by: Stephen Warren <swarren@nvidia.com>
----
- .../devicetree/bindings/reset/gpio-reset.txt | 35 +++++
- drivers/reset/Kconfig | 11 ++
- drivers/reset/Makefile | 1 +
- drivers/reset/gpio-reset.c | 169 +++++++++++++++++++++
- 4 files changed, 216 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/reset/gpio-reset.txt
- create mode 100644 drivers/reset/gpio-reset.c
-
-diff --git a/Documentation/devicetree/bindings/reset/gpio-reset.txt b/Documentation/devicetree/bindings/reset/gpio-reset.txt
-new file mode 100644
-index 0000000..bca5348
---- /dev/null
-+++ b/Documentation/devicetree/bindings/reset/gpio-reset.txt
-@@ -0,0 +1,35 @@
-+GPIO reset controller
-+=====================
-+
-+A GPIO reset controller controls a single GPIO that is connected to the reset
-+pin of a peripheral IC. Please also refer to reset.txt in this directory for
-+common reset controller binding usage.
-+
-+Required properties:
-+- compatible: Should be "gpio-reset"
-+- reset-gpios: A gpio used as reset line. The gpio specifier for this property
-+ depends on the gpio controller that provides the gpio.
-+- #reset-cells: 0, see below
-+
-+Optional properties:
-+- reset-delay-us: delay in microseconds. The gpio reset line will be asserted for
-+ this duration to reset.
-+- initially-in-reset: boolean. If not set, the initial state should be a
-+ deasserted reset line. If this property exists, the
-+ reset line should be kept in reset.
-+
-+example:
-+
-+sii902x_reset: gpio-reset {
-+ compatible = "gpio-reset";
-+ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
-+ reset-delay-us = <10000>;
-+ initially-in-reset;
-+ #reset-cells = <0>;
-+};
-+
-+/* Device with nRESET pin connected to GPIO5_0 */
-+sii902x@39 {
-+ /* ... */
-+ resets = <&sii902x_reset>; /* active-low GPIO5_0, 10 ms delay */
-+};
-diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
-index c9d04f7..1a862df 100644
---- a/drivers/reset/Kconfig
-+++ b/drivers/reset/Kconfig
-@@ -11,3 +11,14 @@ menuconfig RESET_CONTROLLER
- via GPIOs or SoC-internal reset controller modules.
-
- If unsure, say no.
-+
-+if RESET_CONTROLLER
-+
-+config RESET_GPIO
-+ tristate "GPIO reset controller support"
-+ depends on GPIOLIB && OF
-+ help
-+ This driver provides support for reset lines that are controlled
-+ directly by GPIOs.
-+
-+endif
-diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
-index 1e2d83f..b854f20 100644
---- a/drivers/reset/Makefile
-+++ b/drivers/reset/Makefile
-@@ -1 +1,2 @@
- obj-$(CONFIG_RESET_CONTROLLER) += core.o
-+obj-$(CONFIG_RESET_GPIO) += gpio-reset.o
-diff --git a/drivers/reset/gpio-reset.c b/drivers/reset/gpio-reset.c
-new file mode 100644
-index 0000000..acc1076
---- /dev/null
-+++ b/drivers/reset/gpio-reset.c
-@@ -0,0 +1,169 @@
-+/*
-+ * GPIO Reset Controller driver
-+ *
-+ * Copyright 2013 Philipp Zabel, Pengutronix
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/gpio.h>
-+#include <linux/module.h>
-+#include <linux/of_gpio.h>
-+#include <linux/platform_device.h>
-+#include <linux/reset-controller.h>
-+
-+struct gpio_reset_data {
-+ struct reset_controller_dev rcdev;
-+ unsigned int gpio;
-+ bool active_low;
-+ u32 delay_us;
-+};
-+
-+static void __gpio_reset_set(struct reset_controller_dev *rcdev, int asserted)
-+{
-+ struct gpio_reset_data *drvdata = container_of(rcdev,
-+ struct gpio_reset_data, rcdev);
-+ int value = asserted;
-+
-+ if (drvdata->active_low)
-+ value = !value;
-+
-+ gpio_set_value(drvdata->gpio, value);
-+}
-+
-+static int gpio_reset(struct reset_controller_dev *rcdev, unsigned long id)
-+{
-+ struct gpio_reset_data *drvdata = container_of(rcdev,
-+ struct gpio_reset_data, rcdev);
-+
-+ if (drvdata->delay_us < 0)
-+ return -ENOSYS;
-+
-+ __gpio_reset_set(rcdev, 1);
-+ udelay(drvdata->delay_us);
-+ __gpio_reset_set(rcdev, 0);
-+
-+ return 0;
-+}
-+
-+static int gpio_reset_assert(struct reset_controller_dev *rcdev,
-+ unsigned long id)
-+{
-+ __gpio_reset_set(rcdev, 1);
-+
-+ return 0;
-+}
-+
-+static int gpio_reset_deassert(struct reset_controller_dev *rcdev,
-+ unsigned long id)
-+{
-+ __gpio_reset_set(rcdev, 0);
-+
-+ return 0;
-+}
-+
-+static struct reset_control_ops gpio_reset_ops = {
-+ .reset = gpio_reset,
-+ .assert = gpio_reset_assert,
-+ .deassert = gpio_reset_deassert,
-+};
-+
-+static int of_gpio_reset_xlate(struct reset_controller_dev *rcdev,
-+ const struct of_phandle_args *reset_spec)
-+{
-+ if (WARN_ON(reset_spec->args_count != 0))
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static int gpio_reset_probe(struct platform_device *pdev)
-+{
-+ struct device_node *np = pdev->dev.of_node;
-+ struct gpio_reset_data *drvdata;
-+ enum of_gpio_flags flags;
-+ unsigned long gpio_flags;
-+ bool initially_in_reset;
-+ int ret;
-+
-+ drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
-+ if (drvdata == NULL)
-+ return -ENOMEM;
-+
-+ if (of_gpio_named_count(np, "reset-gpios") != 1)
-+ return -EINVAL;
-+
-+ drvdata->gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
-+ if (drvdata->gpio == -EPROBE_DEFER) {
-+ return drvdata->gpio;
-+ } else if (!gpio_is_valid(drvdata->gpio)) {
-+ dev_err(&pdev->dev, "invalid reset gpio: %d\n", drvdata->gpio);
-+ return drvdata->gpio;
-+ }
-+
-+ drvdata->active_low = flags & OF_GPIO_ACTIVE_LOW;
-+
-+ ret = of_property_read_u32(np, "reset-delay-us", &drvdata->delay_us);
-+ if (ret < 0)
-+ return ret;
-+
-+ initially_in_reset = of_property_read_bool(np, "initially-in-reset");
-+ if (drvdata->active_low ^ initially_in_reset)
-+ gpio_flags = GPIOF_OUT_INIT_HIGH;
-+ else
-+ gpio_flags = GPIOF_OUT_INIT_LOW;
-+
-+ ret = devm_gpio_request_one(&pdev->dev, drvdata->gpio, gpio_flags, NULL);
-+ if (ret < 0) {
-+ dev_err(&pdev->dev, "failed to request gpio %d: %d\n",
-+ drvdata->gpio, ret);
-+ return ret;
-+ }
-+
-+ drvdata->rcdev.of_node = np;
-+ drvdata->rcdev.owner = THIS_MODULE;
-+ drvdata->rcdev.nr_resets = 1;
-+ drvdata->rcdev.ops = &gpio_reset_ops;
-+ drvdata->rcdev.of_xlate = of_gpio_reset_xlate;
-+ reset_controller_register(&drvdata->rcdev);
-+
-+ platform_set_drvdata(pdev, drvdata);
-+
-+ return 0;
-+}
-+
-+static int gpio_reset_remove(struct platform_device *pdev)
-+{
-+ struct gpio_reset_data *drvdata = platform_get_drvdata(pdev);
-+
-+ reset_controller_unregister(&drvdata->rcdev);
-+
-+ return 0;
-+}
-+
-+static struct of_device_id gpio_reset_dt_ids[] = {
-+ { .compatible = "gpio-reset" },
-+ { }
-+};
-+
-+static struct platform_driver gpio_reset_driver = {
-+ .probe = gpio_reset_probe,
-+ .remove = gpio_reset_remove,
-+ .driver = {
-+ .name = "gpio-reset",
-+ .owner = THIS_MODULE,
-+ .of_match_table = of_match_ptr(gpio_reset_dt_ids),
-+ },
-+};
-+
-+module_platform_driver(gpio_reset_driver);
-+
-+MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
-+MODULE_DESCRIPTION("gpio reset controller");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("platform:gpio-reset");
-+MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids);
---
-1.8.2.1
-
-From 03664ac63b20b55af9522449bbad048476d259d5 Mon Sep 17 00:00:00 2001
-From: Joel Fernandes <joelf@ti.com>
-Date: Wed, 3 Jul 2013 17:29:44 -0500
-Subject: [PATCH 2/2] sound: soc: soc-dmaengine-pcm: Add support for new
- DMAEngine request API
-
-Formerly these resources were coming HWMOD on OMAP-like SoCs. With the
-impending removal of HWMOD data, drivers are being converted to use the
-"of-dma" method of requesting DMA channels which from DT and can be obtained
-using the dma_request_slave_channel API. Add support to the soc-dmaengine-pcm
-helpers so that we can fetch and open channels using this method.
-
-Signed-off-by: Joel Fernandes <joelf@ti.com>
----
- sound/core/pcm_dmaengine.c | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
-
-diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
-index aa924d9..461fe4f 100644
---- a/sound/core/pcm_dmaengine.c
-+++ b/sound/core/pcm_dmaengine.c
-@@ -276,6 +276,16 @@ struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
- }
- EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel);
-
-+struct dma_chan *snd_dmaengine_pcm_request_slave_channel(
-+ struct snd_pcm_substream *substream, char *name)
-+{
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct device *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-+
-+ return dma_request_slave_channel(dev, name);
-+}
-+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_slave_channel);
-+
- /**
- * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
- * @substream: PCM substream
-@@ -334,6 +344,18 @@ int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
- }
- EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
-
-+int snd_dmaengine_pcm_open_request_slave_chan(struct snd_pcm_substream *substream, char *name)
-+{
-+ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+ return snd_dmaengine_pcm_open(substream,
-+ snd_dmaengine_pcm_request_slave_channel(substream, "tx"));
-+ } else {
-+ return snd_dmaengine_pcm_open(substream,
-+ snd_dmaengine_pcm_request_slave_channel(substream, "rx"));
-+ }
-+}
-+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_slave_chan);
-+
- /**
- * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
- * @substream: PCM substream
---
-1.8.4.rc3
-
-From ae38683badc8c80b29ccc8aa4e059f900b603551 Mon Sep 17 00:00:00 2001
-From: Pantelis Antoniou <panto@antoniou-consulting.com>
-Date: Fri, 26 Oct 2012 15:48:00 +0300
-Subject: [PATCH 1/2] omap-hsmmc: Correct usage of of_find_node_by_name
-
-of_find_node_by_name expect to have the parent node reference taken.
----
- drivers/mmc/host/omap_hsmmc.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
-index 6ac63df..f5b660c 100644
---- a/drivers/mmc/host/omap_hsmmc.c
-+++ b/drivers/mmc/host/omap_hsmmc.c
-@@ -1893,6 +1893,16 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
- * as we want. */
- mmc->max_segs = 1024;
-
-+ /* Eventually we should get our max_segs limitation for EDMA by
-+ * querying the dmaengine API */
-+ if (pdev->dev.of_node) {
-+ struct device_node *parent = of_node_get(pdev->dev.of_node->parent);
-+ struct device_node *node;
-+ node = of_find_node_by_name(parent, "edma");
-+ if (node)
-+ mmc->max_segs = 16;
-+ }
-+
- mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
- mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
- mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
---
-1.8.2.1
-
-From 5d93a65cfc4ff6aaf78ab49f71daa2a644ea2ace Mon Sep 17 00:00:00 2001
-From: Pantelis Antoniou <panto@antoniou-consulting.com>
-Date: Fri, 30 Nov 2012 12:18:16 +0200
-Subject: [PATCH 2/2] omap_hsmmc: Add reset gpio
-
-Add a gpio property for controlling reset of the mmc device.
-eMMC on the beaglebone black requires it.
-
-Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
----
- drivers/mmc/host/omap_hsmmc.c | 40 +++++++++++++++++++++++++++++++++-
- include/linux/platform_data/mmc-omap.h | 3 +++
- 2 files changed, 42 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
-index f5b660c..1bdb90f 100644
---- a/drivers/mmc/host/omap_hsmmc.c
-+++ b/drivers/mmc/host/omap_hsmmc.c
-@@ -41,6 +41,8 @@
- #include <linux/pinctrl/consumer.h>
- #include <linux/pm_runtime.h>
- #include <linux/platform_data/mmc-omap.h>
-+#include <linux/pinctrl/consumer.h>
-+#include <linux/err.h>
-
- /* OMAP HSMMC Host Controller Registers */
- #define OMAP_HSMMC_SYSSTATUS 0x0014
-@@ -392,6 +394,7 @@ static inline int omap_hsmmc_have_reg(void)
- static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
- {
- int ret;
-+ unsigned long flags;
-
- if (gpio_is_valid(pdata->slots[0].switch_pin)) {
- if (pdata->slots[0].cover)
-@@ -421,6 +424,24 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
- } else
- pdata->slots[0].gpio_wp = -EINVAL;
-
-+ if (gpio_is_valid(pdata->slots[0].gpio_reset)) {
-+ flags = pdata->slots[0].gpio_reset_active_low ?
-+ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
-+ ret = gpio_request_one(pdata->slots[0].gpio_reset, flags,
-+ "mmc_reset");
-+ if (ret)
-+ goto err_free_wp;
-+
-+ /* hold reset */
-+ udelay(pdata->slots[0].gpio_reset_hold_us);
-+
-+ gpio_set_value(pdata->slots[0].gpio_reset,
-+ !pdata->slots[0].gpio_reset_active_low);
-+
-+ } else
-+ pdata->slots[0].gpio_reset = -EINVAL;
-+
-+
- return 0;
-
- err_free_wp:
-@@ -434,6 +455,8 @@ err_free_sp:
-
- static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
- {
-+ if (gpio_is_valid(pdata->slots[0].gpio_reset))
-+ gpio_free(pdata->slots[0].gpio_reset);
- if (gpio_is_valid(pdata->slots[0].gpio_wp))
- gpio_free(pdata->slots[0].gpio_wp);
- if (gpio_is_valid(pdata->slots[0].switch_pin))
-@@ -788,7 +811,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
- * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
- * a val of 0x3, rest 0x0.
- */
-- if (cmd == host->mrq->stop)
-+ if (host->mrq && cmd == host->mrq->stop)
- cmdtype = 0x3;
-
- cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
-@@ -830,6 +853,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
- int dma_ch;
- unsigned long flags;
-
-+ BUG_ON(mrq == NULL);
-+
- spin_lock_irqsave(&host->irq_lock, flags);
- host->req_in_progress = 0;
- dma_ch = host->dma_ch;
-@@ -1720,6 +1745,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
- struct device_node *np = dev->of_node;
- u32 bus_width, max_freq;
- int cd_gpio, wp_gpio;
-+ enum of_gpio_flags reset_flags;
-
- cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
- wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
-@@ -1737,6 +1763,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
- pdata->nr_slots = 1;
- pdata->slots[0].switch_pin = cd_gpio;
- pdata->slots[0].gpio_wp = wp_gpio;
-+ reset_flags = 0;
-+ pdata->slots[0].gpio_reset = of_get_named_gpio_flags(np,
-+ "reset-gpios", 0, &reset_flags);
-+ pdata->slots[0].gpio_reset_active_low =
-+ (reset_flags & OF_GPIO_ACTIVE_LOW) != 0;
-+ pdata->slots[0].gpio_reset_hold_us = 100; /* default */
-+ of_property_read_u32(np, "reset-gpio-hold-us",
-+ &pdata->slots[0].gpio_reset_hold_us);
-
- if (of_find_property(np, "ti,non-removable", NULL)) {
- pdata->slots[0].nonremovable = true;
-@@ -1802,6 +1836,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
- return -ENXIO;
- }
-
-+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-+ if (IS_ERR(pinctrl))
-+ dev_warn(&pdev->dev, "unable to select pin group\n");
-+
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (res == NULL || irq < 0)
-diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
-index 2bf1b30..d548994 100644
---- a/include/linux/platform_data/mmc-omap.h
-+++ b/include/linux/platform_data/mmc-omap.h
-@@ -115,6 +115,9 @@ struct omap_mmc_platform_data {
-
- int switch_pin; /* gpio (card detect) */
- int gpio_wp; /* gpio (write protect) */
-+ int gpio_reset; /* gpio (reset) */
-+ int gpio_reset_active_low; /* 1 if reset is active low */
-+ u32 gpio_reset_hold_us; /* time to hold in us */
-
- int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
- int (*set_power)(struct device *dev, int slot,
---
-1.8.2.1
-
-From b45e4df71f07f2178db133db540e3f15e0b4ec05 Mon Sep 17 00:00:00 2001
-From: Pantelis Antoniou <panto@antoniou-consulting.com>
-Date: Sat, 15 Sep 2012 12:00:41 +0300
-Subject: [PATCH] pinctrl: pinctrl-single must be initialized early.
-
-When using pinctrl-single to handle i2c initialization, it has
-to be done early. Whether this is the best way to do so, is an
-exercise left to the reader.
----
- drivers/pinctrl/pinctrl-single.c | 12 +++++++++++-
- 1 file changed, 11 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
-index a82ace4..aeef35d 100644
---- a/drivers/pinctrl/pinctrl-single.c
-+++ b/drivers/pinctrl/pinctrl-single.c
-@@ -1673,7 +1673,17 @@ static struct platform_driver pcs_driver = {
- #endif
- };
-
--module_platform_driver(pcs_driver);
-+static int __init pcs_init(void)
-+{
-+ return platform_driver_register(&pcs_driver);
-+}
-+postcore_initcall(pcs_init);
-+
-+static void __exit pcs_exit(void)
-+{
-+ platform_driver_unregister(&pcs_driver);
-+}
-+module_exit(pcs_exit);
-
- MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
- MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver");
---
-1.8.2.1
-
-From e5e7abd2de7d8d4c74b5a1ccc6d47988250bd17d Mon Sep 17 00:00:00 2001
-From: Pantelis Antoniou <panto@antoniou-consulting.com>
-Date: Fri, 28 Jun 2013 18:39:55 +0300
-Subject: [PATCH 1/4] dts: beaglebone: Add I2C definitions for EEPROMs & capes
-
-Add the I2C definitions for the EEPROM devices on the baseboard
-and on the possibly connected capes.
-
-Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
----
- arch/arm/boot/dts/am335x-bone-common.dtsi | 39 +++++++++++++++++++++++++++++++
- 1 file changed, 39 insertions(+)
-
-diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
-index e3f27ec..2d12775 100644
---- a/arch/arm/boot/dts/am335x-bone-common.dtsi
-+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
-@@ -84,6 +84,13 @@
- >;
- };
-
-+ i2c2_pins: pinmux_i2c2_pins {
-+ pinctrl-single,pins = <
-+ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
-+ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
-+ >;
-+ };
-+
- uart0_pins: pinmux_uart0_pins {
- pinctrl-single,pins = <
- 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
-@@ -220,6 +227,38 @@
- reg = <0x24>;
- };
-
-+ baseboard_eeprom: baseboard_eeprom@50 {
-+ compatible = "at,24c256";
-+ reg = <0x50>;
-+ };
-+};
-+
-+&i2c2 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2c2_pins>;
-+
-+ status = "okay";
-+ clock-frequency = <100000>;
-+
-+ cape_eeprom0: cape_eeprom0@54 {
-+ compatible = "at,24c256";
-+ reg = <0x54>;
-+ };
-+
-+ cape_eeprom1: cape_eeprom1@55 {
-+ compatible = "at,24c256";
-+ reg = <0x55>;
-+ };
-+
-+ cape_eeprom2: cape_eeprom2@56 {
-+ compatible = "at,24c256";
-+ reg = <0x56>;
-+ };
-+
-+ cape_eeprom3: cape_eeprom3@57 {
-+ compatible = "at,24c256";
-+ reg = <0x57>;
-+ };
- };
-
- /include/ "tps65217.dtsi"
---
-1.8.4.rc3
diff --git a/arm-am33xx-cpsw.patch b/arm-am33xx-cpsw.patch
deleted file mode 100644
index 1a38cdd2b..000000000
--- a/arm-am33xx-cpsw.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-Bugzilla: 1012025
-Upstream-status: An initial work around for the cpsw driver issue trying to access HW registers
-with clock disabled. Upstream is working on a proper fix with the hope to land it in 3.13.
-
---- linux-3.12.4-1.fc20.x86_64/drivers/net/ethernet/ti/cpsw.c.orig 2013-12-11 20:52:41.576478796 +0000
-+++ linux-3.12.4-1.fc20.x86_64/drivers/net/ethernet/ti/cpsw.c 2013-12-11 20:55:14.418692261 +0000
-@@ -2001,6 +2001,8 @@
- goto clean_cpsw_iores_ret;
- }
- priv->regs = ss_regs;
-+
-+ pm_runtime_get_sync(&pdev->dev);
- priv->version = __raw_readl(&priv->regs->id_ver);
- priv->host_port = HOST_PORT_NUM;
-
-@@ -2161,6 +2163,7 @@
- goto clean_irq_ret;
- }
- }
-+ pm_runtime_put_sync(&pdev->dev);
-
- return 0;
-
diff --git a/arm-imx6-utilite.patch b/arm-imx6-utilite.patch
index 58a839a6e..35f34c166 100644
--- a/arm-imx6-utilite.patch
+++ b/arm-imx6-utilite.patch
@@ -1,36 +1,55 @@
-Add initial support for cm-fx6 module.
+commit 682d055e6ac5c3855f51649de6d68e9bb29c26a6
+Author: Valentin Raevsky <valentin@compulab.co.il>
+Date: Tue Oct 29 14:11:43 2013 +0200
-cm-fx6 is a module based on mx6q SoC with the following features:
-- Up to 4GB of DDR3
-- 1 LCD/DVI output port
-- 1 HDMI output port
-- 2 LVDS LCD ports
-- Gigabit Ethernet
-- Analog Audio
-- CAN
-- SATA
-- NAND
-- PCIE
-
-This patch allows to boot up the module, configures the serial console,
-the Ethernet adapter and the hearbeat led.
-
-Signed-off-by: Valentin Raevsky <valentin@xxxxxxxxxxxxxx>
-Acked-by: Igor Grinberg <grinberg@xxxxxxxxxxxxxx>
----
- arch/arm/boot/dts/imx6q-cm-fx6.dts | 51 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 51 insertions(+)
- create mode 100644 arch/arm/boot/dts/imx6q-cm-fx6.dts
+ ARM: dts: Add initial support for cm-fx6.
+
+ Add initial support for cm-fx6 module.
+
+ cm-fx6 is a module based on mx6q SoC with the following features:
+ - Up to 4GB of DDR3
+ - 1 LCD/DVI output port
+ - 1 HDMI output port
+ - 2 LVDS LCD ports
+ - Gigabit Ethernet
+ - Analog Audio
+ - CAN
+ - SATA
+ - NAND
+ - PCIE
+
+ This patch allows to boot up the module, configures the serial console,
+ the Ethernet adapter and the heartbeat led.
+
+ cm-fx6 is embedded inside the Utilite computer.
+
+ Signed-off-by: Valentin Raevsky <valentin@compulab.co.il>
+ Signed-off-by: Igor Grinberg <grinberg@compulab.co.il>
+ Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 8081479..5672e91 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -162,6 +162,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
+ imx6dl-sabresd.dtb \
+ imx6dl-wandboard.dtb \
+ imx6q-arm2.dtb \
++ imx6q-cm-fx6.dtb \
+ imx6q-cubox-i.dtb \
+ imx6q-phytec-pbab01.dtb \
+ imx6q-sabreauto.dtb \
diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
new file mode 100644
-index 0000000..1080215
+index 0000000..99b46f8
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
-@@ -0,0 +1,51 @@
+@@ -0,0 +1,107 @@
+/*
+ * Copyright 2013 CompuLab Ltd.
+ *
++ * Author: Valentin Raevsky <valentin@compulab.co.il>
++ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
@@ -53,7 +72,7 @@ index 0000000..1080215
+ leds {
+ compatible = "gpio-leds";
+
-+ debug-led {
++ heartbeat-led {
+ label = "Heartbeat";
+ gpios = <&gpio2 31 0>;
+ linux,default-trigger = "heartbeat";
@@ -61,35 +80,79 @@ index 0000000..1080215
+ };
+};
+
-+&gpmi {
++&fec {
+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_gpmi_nand_1>;
++ pinctrl-0 = <&pinctrl_enet>;
++ phy-mode = "rgmii";
+ status = "okay";
+};
+
-+&fec {
++&gpmi {
+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_enet_1>;
-+ phy-mode = "rgmii";
++ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ status = "okay";
+};
+
++&iomuxc {
++ imx6q-cm-fx6 {
++ pinctrl_enet: enetgrp {
++ fsl,pins = <
++ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
++ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
++ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
++ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
++ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
++ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
++ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
++ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
++ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
++ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
++ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
++ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
++ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
++ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
++ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
++ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
++ >;
++ };
++
++ pinctrl_gpmi_nand: gpminandgrp {
++ fsl,pins = <
++ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
++ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
++ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
++ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
++ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
++ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
++ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
++ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
++ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
++ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
++ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
++ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
++ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
++ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
++ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
++ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
++ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
++ >;
++ };
++
++ pinctrl_uart4: uart4grp {
++ fsl,pins = <
++ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
++ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
++ >;
++ };
++ };
++};
++
+&uart4 {
+ pinctrl-names = "default";
-+ pinctrl-0 = <&pinctrl_uart4_1>;
++ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
-diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -137,6 +137,7 @@
- imx6dl-sabresd.dtb \
- imx6dl-wandboard.dtb \
- imx6q-arm2.dtb \
-+ imx6q-cm-fx6.dtb \
- imx6q-phytec-pbab01.dtb \
- imx6q-sabreauto.dtb \
- imx6q-sabrelite.dtb \
---
-1.7.9.5
-
++
++&sata {
++ status = "okay";
++};
diff --git a/arm-tegra-paz00-panel-dts.patch b/arm-tegra-paz00-panel-dts.patch
new file mode 100644
index 000000000..e64f2ce1e
--- /dev/null
+++ b/arm-tegra-paz00-panel-dts.patch
@@ -0,0 +1,99 @@
+From fb4a8356eb67514b10618d1e9e4059ced14c05f2 Mon Sep 17 00:00:00 2001
+From: Marc Dietrich <marvin24@gmx.de>
+Date: Sat, 21 Dec 2013 21:38:13 +0100
+Subject: [PATCH] ARM: tegra: paz00: Add LVDS support to device tree
+
+Add backlight and panel nodes for the PAZ00 TFT LCD panel.
+
+Signed-off-by: Marc Dietrich <marvin24@gmx.de>
+---
+ arch/arm/boot/dts/tegra20-paz00.dts | 46 ++++++++++++++++++++++++++++++++++-
+ 1 files changed, 45 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
+index c7cd8e6..9a39a80 100644
+--- a/arch/arm/boot/dts/tegra20-paz00.dts
++++ b/arch/arm/boot/dts/tegra20-paz00.dts
+@@ -17,6 +17,14 @@
+ };
+
+ host1x@50000000 {
++ dc@54200000 {
++ rgb {
++ status = "okay";
++
++ nvidia,panel = <&panel>;
++ };
++ };
++
+ hdmi@54280000 {
+ status = "okay";
+
+@@ -257,7 +265,11 @@
+ status = "okay";
+ };
+
+- i2c@7000c000 {
++ pwm: pwm@7000a000 {
++ status = "okay";
++ };
++
++ lvds_ddc: i2c@7000c000 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+@@ -475,6 +487,18 @@
+ non-removable;
+ };
+
++ backlight: backlight {
++ compatible = "pwm-backlight";
++
++ enable-gpios = <&gpio TEGRA_GPIO(U, 4) GPIO_ACTIVE_HIGH>;
++ pwms = <&pwm 0 5000000>;
++
++ brightness-levels = <0 16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 255>;
++ default-brightness-level = <10>;
++
++ backlight-boot-off;
++ };
++
+ clocks {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+@@ -509,6 +533,16 @@
+ };
+ };
+
++ panel: panel {
++ compatible = "samsung,ltn101nt05", "simple-panel";
++
++ ddc-i2c-bus = <&lvds_ddc>;
++ power-supply = <&vdd_pnl_reg>;
++ enable-gpios = <&gpio TEGRA_GPIO(M, 6) GPIO_ACTIVE_HIGH>;
++
++ backlight = <&backlight>;
++ };
++
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+@@ -522,6 +556,16 @@
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
++
++ vdd_pnl_reg: regulator@1 {
++ compatible = "regulator-fixed";
++ reg = <1>;
++ regulator-name = "+3VS,vdd_pnl";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio TEGRA_GPIO(A, 4) GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
+ };
+
+ sound {
+--
+1.7.1
diff --git a/config-arm-generic b/config-arm-generic
index a0cf6e6f8..cd56b2493 100644
--- a/config-arm-generic
+++ b/config-arm-generic
@@ -6,8 +6,12 @@ CONFIG_FB_SSD1307=m
CONFIG_HW_PERF_EVENTS=y
CONFIG_MMC=y
CONFIG_NFS_FS=y
+
# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+# CONFIG_BIG_LITTLE is not set
+
CONFIG_PWM=y
CONFIG_PWM_SYSFS=y
@@ -16,21 +20,32 @@ CONFIG_RESET_GPIO=y
CONFIG_RCU_FANOUT_LEAF=16
# CONFIG_RTC_DRV_SNVS is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
CONFIG_BACKLIGHT_PWM=m
CONFIG_INPUT_PWM_BEEPER=m
CONFIG_ARM_SP805_WATCHDOG=m
CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
# CONFIG_ARM_DT_BL_CPUFREQ is not set
CONFIG_NR_CPUS=8
-CONFIG_ARM_DMA_USE_IOMMU=y
+
+CONFIG_SWIOTLB=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_FB_SIMPLE=y
+
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
# ARM AMBA generic HW
CONFIG_ARM_AMBA=y
+CONFIG_ARM_CCI=y
+CONFIG_ARM_DMA_USE_IOMMU=y
CONFIG_ARM_GIC=y
+CONFIG_ARM_GLOBAL_TIMER=y
+CONFIG_ARM_SMMU=y
CONFIG_MMC_ARMMMCI=y
-CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_SERIO_AMBAKMI=y
CONFIG_OC_ETM=y
CONFIG_FB_ARMCLCD=y
@@ -56,14 +71,18 @@ CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_I2C=m
+CONFIG_OF_IOMMU=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=m
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OF_PCI_IRQ=m
CONFIG_OF_PCI=m
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_PATA_OF_PLATFORM=m
# CONFIG_OF_SELFTEST is not set
CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_THERMAL_OF=y
# External Connectors
CONFIG_EXTCON=m
@@ -88,18 +107,21 @@ CONFIG_MTD_PHYSMAP_OF=m
# GPIO
CONFIG_GPIO_DEVRES=y
CONFIG_GPIO_GENERIC=m
+CONFIG_GPIO_GENERIC_PLATFORM=m
+CONFIG_GPIO_WATCHDOG=m
CONFIG_GPIOLIB=y
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
CONFIG_MDIO_GPIO=m
+CONFIG_BACKLIGHT_GPIO=m
CONFIG_POWER_RESET_GPIO=y
CONFIG_POWER_RESET_RESTART=y
#i2c
+CONFIG_I2C_ARB_GPIO_CHALLENGE=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_GPIO=m
CONFIG_I2C_MUX=m
-# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
CONFIG_I2C_MUX_GPIO=m
CONFIG_I2C_MUX_PINCTRL=m
CONFIG_I2C_MUX_PCA9541=m
@@ -108,24 +130,54 @@ CONFIG_I2C_MUX_PCA9541=m
CONFIG_SENSORS_IIO_HWMON=m
CONFIG_IIO_SYSFS_TRIGGER=m
+# PHY framework
+CONFIG_GENERIC_PHY=y
+
# MFD
CONFIG_MFD_CORE=m
CONFIG_SMC91X=m
CONFIG_SMC911X=m
+CONFIG_CPU_THERMAL=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+
+# Contiguous Memory Allocator
+CONFIG_CMA=y
+CONFIG_DMA_CMA=y
+# CONFIG_CMA_DEBUG is not set
+CONFIG_CMA_SIZE_MBYTES=16
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_ALIGNMENT=8
+CONFIG_CMA_AREAS=7
+
# CONFIG_CRYPTO_TEST is not set
# CONFIG_TRANSPARENT_HUGEPAGE is not set
# CONFIG_XEN is not set
# CONFIG_DRM_RCAR_DU is not set
+# CONFIG_I2C_RCAR is not set
# CONFIG_DRM_SHMOBILE is not set
+# CONFIG_I2C_SH_MOBILE is not set
# CONFIG_MMC_DW_SOCFPGA is not set
-# CONFIG_ARM_SMMU is not set
# CONFIG_I2C_NOMADIK is not set
# CONFIG_IRQ_DOMAIN_DEBUG is not set
# CONFIG_LEDS_RENESAS_TPU is not set
# CONFIG_LOCK_STAT is not set
+# CONFIG_DRM_ARMADA is not set
+# CONFIG_DRM_TEGRA is not set
+# CONFIG_SHMOBILE_IOMMU is not set
+
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_QCOM is not set
+
+# CONFIG_ARM_PTDUMP is not set
+
+# CONFIG_PATA_PLATFORM is not set
+
### turn off things which make no sense on embedded SoC
# core
@@ -140,6 +192,7 @@ CONFIG_SMC911X=m
# CONFIG_NET_VENDOR_EXAR is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
# scsi
@@ -149,5 +202,11 @@ CONFIG_SMC911X=m
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_SCSI_CXGB4_ISCSI is not set
+# CONFIG_SCSI_BFA_FC is not set
+
+# serial
+# CONFIG_SERIAL_SH_SCI is not set
CONFIG_CRASH=m
+
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
diff --git a/config-arm64 b/config-arm64
index 850295082..38a0debd2 100644
--- a/config-arm64
+++ b/config-arm64
@@ -1,6 +1,8 @@
CONFIG_64BIT=y
CONFIG_ARM64=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+
# arm64 only SoCs
CONFIG_ARCH_XGENE=y
@@ -8,9 +10,8 @@ CONFIG_ARCH_XGENE=y
# CONFIG_AMBA_PL08X is not set
CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
CONFIG_ARCH_REQUIRE_GPIOLIB=y
-CONFIG_ARM64_64K_PAGES=y
-# CONFIG_ARM_DT_BL_CPUFREQ is not set
-CONFIG_ARM_SMMU=y
+# CONFIG_ARM64_64K_PAGES is not set
+CONFIG_COMPAT=y
CONFIG_BCMA_POSSIBLE=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
@@ -39,7 +40,8 @@ CONFIG_HAVE_NET_DSA=y
CONFIG_HVC_DRIVER=y
CONFIG_HZ=100
-# CONFIG_KVM is not set
+CONFIG_KVM=y
+CONFIG_KVM_ARM_MAX_VCPUS=8
CONFIG_LOG_BUF_SHIFT=14
CONFIG_NFS_ACL_SUPPORT=y
@@ -57,15 +59,12 @@ CONFIG_SERIAL_8250_DMA=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPARSEMEM_VMEMMAP=y
-CONFIG_SWIOTLB=y
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_THERMAL is not set
CONFIG_VIRTUALIZATION=y
CONFIG_VM_EVENT_COUNTERS=y
# not arm64
-# CONFIG_HW_RANDOM_ATMEL is not set
-# CONFIG_HW_RANDOM_EXYNOS is not set
# CONFIG_GPIO_ADNP is not set
# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_MDIO_BUS_MUX_GPIO is not set
@@ -80,3 +79,4 @@ CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_PARPORT_PC is not set
# CONFIG_VGA_CONSOLE is not set
CONFIG_POWER_RESET_XGENE=y
+CONFIG_COMMON_CLK_XGENE=y
diff --git a/config-armv7 b/config-armv7
index 5df800c14..d609bc65d 100644
--- a/config-armv7
+++ b/config-armv7
@@ -1,14 +1,15 @@
# ARM unified arch kernel
-# CONFIG_ARCH_EXYNOS_MULTI is not set
+# CONFIG_ARCH_BERLIN is not set
# CONFIG_ARCH_KEYSTONE is not set
CONFIG_ARCH_MVEBU=y
CONFIG_ARCH_MXC=y
-CONFIG_ARCH_OMAP2PLUS=y
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
CONFIG_ARCH_PICOXCELL=y
CONFIG_ARCH_ROCKCHIP=y
CONFIG_ARCH_SOCFPGA=y
-CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_TEGRA=y
CONFIG_ARCH_U8500=y
# CONFIG_ARCH_VIRT is not set
@@ -30,7 +31,6 @@ CONFIG_CACHE_TAUROS2=y
CONFIG_MV_XOR=y
CONFIG_CRYPTO_DEV_MV_CESA=m
CONFIG_MV643XX_ETH=m
-CONFIG_I2C_MV64XXX=m
CONFIG_PINCTRL_MVEBU=y
CONFIG_PINCTRL_ARMADA_370=y
CONFIG_PINCTRL_ARMADA_XP=y
@@ -42,47 +42,41 @@ CONFIG_RTC_DRV_MV=m
CONFIG_MVNETA=m
CONFIG_GPIO_MVEBU=y
CONFIG_MVEBU_CLK_CORE=y
+CONFIG_MVEBU_CLK_COREDIV=y
CONFIG_MVEBU_CLK_GATING=y
CONFIG_MMC_MVSDIO=m
CONFIG_SPI_ORION=m
CONFIG_USB_MV_UDC=m
CONFIG_MVEBU_MBUS=y
+CONFIG_PHY_MVEBU_SATA=y
CONFIG_ARMADA_THERMAL=m
+CONFIG_DRM_ARMADA=m
# omap
CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
-# CONFIG_ARCH_OMAP2 is not set
-CONFIG_ARCH_OMAP3=y
-CONFIG_ARCH_OMAP4=y
CONFIG_SOC_OMAP5=y
# CONFIG_SOC_DRA7XX is not set
-# CONFIG_SOC_OMAP2420 is not set
-# CONFIG_SOC_OMAP2430 is not set
CONFIG_SOC_OMAP3430=y
CONFIG_SOC_TI81XX=y
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_CRANEBOARD=y
CONFIG_MACH_DEVKIT8000=y
+# CONFIG_MACH_NOKIA_RX51 is not set
+CONFIG_MACH_OMAP_3630SDP=y
+CONFIG_MACH_OMAP_GENERIC=y
CONFIG_MACH_OMAP_LDP=y
-CONFIG_MACH_OMAP3530_LV_SOM=y
-CONFIG_MACH_OMAP3_TORPEDO=y
-CONFIG_MACH_OVERO=y
+CONFIG_MACH_OMAP3_BEAGLE=y
# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP_3430SDP=y
+CONFIG_MACH_OMAP3530_LV_SOM=y
# CONFIG_MACH_OMAP3517EVM is not set
-CONFIG_MACH_CRANEBOARD=y
CONFIG_MACH_OMAP3_PANDORA=y
+CONFIG_MACH_OMAP3_TORPEDO=y
+CONFIG_MACH_OVERO=y
CONFIG_MACH_TOUCHBOOK=y
-CONFIG_MACH_OMAP_3430SDP=y
-# CONFIG_MACH_NOKIA_N8X0 is not set
-# CONFIG_MACH_NOKIA_RM680 is not set
-# CONFIG_MACH_NOKIA_RX51 is not set
-CONFIG_MACH_OMAP_ZOOM2=y
-CONFIG_MACH_OMAP_ZOOM3=y
CONFIG_MACH_CM_T35=y
CONFIG_MACH_CM_T3517=y
CONFIG_MACH_IGEP0030=y
CONFIG_MACH_SBC3530=y
-CONFIG_MACH_OMAP_3630SDP=y
# CONFIG_MACH_TI8168EVM is not set
# CONFIG_MACH_TI8148EVM is not set
@@ -106,8 +100,6 @@ CONFIG_OMAP_IOVMM=m
CONFIG_HWSPINLOCK_OMAP=m
CONFIG_OMAP3_EMU=y
# CONFIG_OMAP3_SDRC_AC_TIMING is not set
-CONFIG_OMAP_WATCHDOG=m
-CONFIG_TWL4030_WATCHDOG=m
CONFIG_SERIAL_OMAP=y
CONFIG_SERIAL_OMAP_CONSOLE=y
@@ -131,14 +123,13 @@ CONFIG_TWL6040_CORE=y
CONFIG_CLK_TWL6040=m
CONFIG_OMAP_INTERCONNECT=m
CONFIG_MFD_OMAP_USB_HOST=y
-CONFIG_MTD_ONENAND_OMAP2=m
CONFIG_HDQ_MASTER_OMAP=m
CONFIG_REGULATOR_TWL4030=y
CONFIG_BACKLIGHT_PANDORA=m
CONFIG_OMAP_OCP2SCP=m
CONFIG_USB_EHCI_HCD_OMAP=m
CONFIG_USB_OHCI_HCD_PLATFORM=m
-CONFIG_USB_OHCI_HCD_OMAP3=y
+CONFIG_USB_OHCI_HCD_OMAP3=m
CONFIG_USB_MUSB_AM35X=m
CONFIG_USB_MUSB_OMAP2PLUS=m
CONFIG_OMAP_CONTROL_USB=m
@@ -153,11 +144,11 @@ CONFIG_TWL6030_GPADC=m
# OMAP5 (possibly other devices too)
CONFIG_MFD_PALMAS=y
-CONFIG_PINCTRL_PALMAS=y
CONFIG_EXTCON_PALMAS=m
-CONFIG_RTC_DRV_PALMAS=m
-CONFIG_REGULATOR_PALMAS=m
CONFIG_GPIO_PALMAS=y
+CONFIG_PINCTRL_PALMAS=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_RTC_DRV_PALMAS=m
CONFIG_WL_TI=y
CONFIG_WLCORE_SDIO=m
@@ -167,7 +158,9 @@ CONFIG_WILINK_PLATFORM_DATA=y
CONFIG_MFD_WL1273_CORE=m
CONFIG_NFC_WILINK=m
+CONFIG_MTD_ONENAND_OMAP2=m
CONFIG_MTD_NAND_OMAP2=m
+CONFIG_MTD_NAND_OMAP_BCH=y
CONFIG_SPI_OMAP24XX=m
CONFIG_MFD_TI_SSP=m
CONFIG_SPI_TI_SSP=m
@@ -182,7 +175,7 @@ CONFIG_TOUCHSCREEN_TI_TSCADC=m
# OMAP thermal temp. Can likely be built as module but doesn't autoload so build in to ensure performance on PandaES
CONFIG_OMAP_BANDGAP=y
-CONFIG_TI_SOC_THERMAL=m
+CONFIG_TI_SOC_THERMAL=y
CONFIG_TI_THERMAL=y
CONFIG_OMAP4_THERMAL=y
CONFIG_OMAP5_THERMAL=y
@@ -202,6 +195,7 @@ CONFIG_PWM_TWL_LED=m
CONFIG_CRYPTO_DEV_OMAP_SHAM=m
CONFIG_CRYPTO_DEV_OMAP_AES=m
CONFIG_HW_RANDOM_OMAP=m
+CONFIG_HW_RANDOM_OMAP3_ROM=m
CONFIG_DRM_OMAP=m
CONFIG_DRM_OMAP_NUM_CRTCS=2
@@ -237,6 +231,7 @@ CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02=m
CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01=m
CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1=m
CONFIG_DISPLAY_PANEL_NEC_NL8048HL11=m
+CONFIG_DISPLAY_PANEL_TPO_TD028TTEC1=m
# Enable V4L2 drivers for OMAP2+
CONFIG_MEDIA_CONTROLLER=y
@@ -301,40 +296,40 @@ CONFIG_SOC_AM33XX=y
CONFIG_SOC_AM43XX=y
CONFIG_AM335X_CONTROL_USB=m
CONFIG_AM335X_PHY_USB=m
-CONFIG_USB_MUSB_AM335X_CHILD=y
+CONFIG_USB_MUSB_AM335X_CHILD=m
+CONFIG_TI_CPPI41=m
+CONFIG_USB_TI_CPPI41_DMA=y
CONFIG_MFD_TI_AM335X_TSCADC=m
CONFIG_TI_ST=m
CONFIG_TI_DAC7512=m
+CONFIG_TI_DAVINCI_CPDMA=m
CONFIG_TI_DAVINCI_EMAC=m
CONFIG_TI_DAVINCI_MDIO=m
-CONFIG_TI_DAVINCI_CPDMA=m
CONFIG_TI_CPSW=m
+CONFIG_TI_CPSW_PHY_SEL=y
CONFIG_TI_CPTS=y
+# Needed for BBone White
+CONFIG_REGULATOR_TPS65217=y
CONFIG_TI_EMIF=m
CONFIG_DRM_TILCDC=m
CONFIG_SPI_DAVINCI=m
+CONFIG_SND_DAVINCI_SOC=m
+CONFIG_SND_DAVINCI_SOC_I2S=m
+CONFIG_SND_DAVINCI_SOC_MCASP=m
+CONFIG_SND_DAVINCI_SOC_VCIF=m
+CONFIG_SND_DAVINCI_SOC_GENERIC_EVM=m
+CONFIG_SND_AM33XX_SOC_EVM=m
CONFIG_REGULATOR_TI_ABB=m
-CONFIG_TI_PRIV_EDMA=y
-CONFIG_TI_EDMA=y
-# Terribly unstable so disable for now
-# CONFIG_USB_TI_CPPI41_DMA is not set
-# CONFIG_TI_CPPI41 is not set
-CONFIG_MFD_TI_AM335X_TSCADC=m
-CONFIG_CHARGER_BQ24190=m
CONFIG_TI_ADC081C=m
CONFIG_TI_AM335X_ADC=m
CONFIG_PWM_TIPWMSS=y
-
-# Allwinner a1x
-CONFIG_PINCTRL_SUNXI=y
-CONFIG_SUNXI_WATCHDOG=m
-CONFIG_MDIO_SUN4I=m
-CONFIG_NET_VENDOR_ALLWINNER=y
-CONFIG_SUN4I_EMAC=m
+# CONFIG_GPIO_DAVINCI is not set
+# CONFIG_DAVINCI_WATCHDOG is not set
# i.MX
CONFIG_MXC_IRQ_PRIOR=y
# CONFIG_MXC_DEBUG_BOARD is not set
+CONFIG_SOC_IMX50=y
CONFIG_SOC_IMX53=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
@@ -344,6 +339,8 @@ CONFIG_MACH_IMX51_DT=y
CONFIG_ARM_IMX6Q_CPUFREQ=m
CONFIG_IMX_THERMAL=m
CONFIG_PATA_IMX=m
+CONFIG_PCI_IMX6=y
+# CONFIG_USB_EHCI_MXC is not set
CONFIG_USB_CHIPIDEA=m
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
@@ -352,13 +349,18 @@ CONFIG_USB_FSL_USB2=m
CONFIG_NET_VENDOR_FREESCALE=y
CONFIG_FEC=m
CONFIG_KEYBOARD_IMX=m
+CONFIG_KEYBOARD_STMPE=m
+CONFIG_TOUCHSCREEN_STMPE=m
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_PINCTRL_IMX6SL=y
CONFIG_I2C_IMX=m
+CONFIG_STMPE_I2C=y
CONFIG_SPI_IMX=m
+CONFIG_STMPE_SPI=y
CONFIG_MFD_MC13783=m
CONFIG_MFD_MC13XXX_SPI=m
+CONFIG_MFD_STMPE=y
CONFIG_W1_MASTER_MXC=m
CONFIG_IMX_WEIM=y
CONFIG_IMX2_WDT=m
@@ -366,8 +368,10 @@ CONFIG_HW_RANDOM_MXC_RNGA=m
CONFIG_CRYPTO_DEV_SAHARA=m
CONFIG_RTC_DRV_SNVS=m
# CONFIG_FB_MX3 is not set
+# CONFIG_FB_IMX is not set
CONFIG_SND_IMX_SOC=m
+CONFIG_SND_SOC_FSL_SPDIF=m
CONFIG_SND_SOC_FSL_SSI=m
CONFIG_SND_SOC_FSL_UTILS=m
CONFIG_SND_SOC_IMX_SSI=m
@@ -379,7 +383,6 @@ CONFIG_SND_SOC_IMX_WM8962=m
CONFIG_SND_SOC_IMX_MC13783=m
CONFIG_SND_SOC_IMX_SPDIF=m
-CONFIG_USB_EHCI_MXC=m
CONFIG_USB_IMX21_HCD=m
CONFIG_USB_MXS_PHY=m
CONFIG_MMC_DW_SOCFPGA=m
@@ -396,7 +399,6 @@ CONFIG_AHCI_IMX=m
# CONFIG_MXS_DMA is not set
CONFIG_PWM_IMX=m
-CONFIG_BACKLIGHT_PWM=m
CONFIG_DRM_IMX=m
CONFIG_DRM_IMX_FB_HELPER=m
CONFIG_DRM_IMX_HDMI=m
@@ -428,6 +430,7 @@ CONFIG_INPUT_DA9052_ONKEY=m
CONFIG_INPUT_DA9055_ONKEY=m
CONFIG_GPIO_DA9052=m
CONFIG_GPIO_DA9055=m
+CONFIG_GPIO_STMPE=y
CONFIG_BATTERY_DA9052=m
CONFIG_SENSORS_DA9052_ADC=m
CONFIG_SENSORS_DA9055=m
@@ -480,15 +483,9 @@ CONFIG_AB8500_BM=y
CONFIG_AB8500_GPADC=y
CONFIG_SENSORS_AB8500=m
CONFIG_STE_MODEM_RPROC=m
-CONFIG_CW1200=m
-CONFIG_CW1200_WLAN_SDIO=m
-CONFIG_CW1200_WLAN_SPI=m
-CONFIG_UX500_WATCHDOG=m
-CONFIG_IIO_ST_ACCEL_3AXIS=m
-CONFIG_IIO_ST_GYRO_3AXIS=m
+
CONFIG_IIO_ST_GYRO_I2C_3AXIS=m
CONFIG_IIO_ST_GYRO_SPI_3AXIS=m
-CONFIG_IIO_ST_MAGN_3AXIS=m
CONFIG_IIO_ST_MAGN_I2C_3AXIS=m
CONFIG_IIO_ST_MAGN_SPI_3AXIS=m
CONFIG_IIO_ST_PRESS=m
@@ -501,10 +498,12 @@ CONFIG_IIO_ST_SENSORS_CORE=m
# tegra
CONFIG_ARCH_TEGRA_2x_SOC=y
CONFIG_ARCH_TEGRA_3x_SOC=y
-# CONFIG_ARCH_TEGRA_114_SOC is not set
+CONFIG_ARCH_TEGRA_114_SOC=y
+CONFIG_ARCH_TEGRA_124_SOC=y
CONFIG_ARM_TEGRA_CPUFREQ=y
CONFIG_TEGRA20_MC=y
CONFIG_TEGRA30_MC=y
+CONFIG_TRUSTED_FOUNDATIONS=y
CONFIG_SERIAL_TEGRA=y
@@ -514,12 +513,13 @@ CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_MMC_SDHCI_TEGRA=m
CONFIG_I2C_TEGRA=m
+CONFIG_I2C_MUX_PCA954x=m
CONFIG_TEGRA_SYSTEM_DMA=y
CONFIG_TEGRA_EMC_SCALING_ENABLE=y
CONFIG_TEGRA_AHB=y
CONFIG_TEGRA20_APB_DMA=y
-# CONFIG_SPI_TEGRA114 is not set
+CONFIG_SPI_TEGRA114=m
CONFIG_SPI_TEGRA20_SFLASH=m
CONFIG_SPI_TEGRA20_SLINK=m
@@ -533,12 +533,15 @@ CONFIG_RTC_DRV_TEGRA=m
CONFIG_SND_SOC_TEGRA=m
CONFIG_SND_SOC_TEGRA_ALC5632=m
+CONFIG_SND_SOC_TEGRA_MAX98090=m
CONFIG_SND_SOC_TEGRA_RT5640=m
CONFIG_SND_SOC_TEGRA_TRIMSLICE=m
CONFIG_SND_SOC_TEGRA_WM8753=m
CONFIG_SND_SOC_TEGRA_WM8903=m
CONFIG_SND_SOC_TEGRA_WM9712=m
CONFIG_SND_SOC_TEGRA20_AC97=m
+CONFIG_SND_SOC_TEGRA20_DAS=m
+CONFIG_SND_SOC_TEGRA20_SPDIF=m
CONFIG_SND_SOC_TEGRA30_AHUB=m
CONFIG_SND_SOC_TEGRA30_I2S=m
@@ -559,14 +562,16 @@ CONFIG_PWM_TEGRA=m
CONFIG_TEGRA_HOST1X=m
CONFIG_TEGRA_HOST1X_FIREWALL=y
-
-CONFIG_DRM_TEGRA=y
-# CONFIG_DRM_TEGRA_STAGING is not set
+CONFIG_DRM_TEGRA=m
+CONFIG_DRM_TEGRA_FBDEV=y
# CONFIG_DRM_TEGRA_DEBUG is not set
+CONFIG_DRM_TEGRA_STAGING=y
+CONFIG_DRM_PANEL=y
+CONFIG_DRM_PANEL_SIMPLE=m
+
CONFIG_CRYPTO_DEV_TEGRA_AES=m
-CONFIG_LEDS_RENESAS_TPU=y
CONFIG_GPIO_PCA953X=m
# OLPC XO
@@ -586,6 +591,7 @@ CONFIG_XILINX_EMACLITE=m
CONFIG_GPIO_XILINX=y
CONFIG_I2C_XILINX=m
CONFIG_SPI_XILINX=m
+CONFIG_MMC_SDHCI_OF_ARASAN=m
# Multi function devices
CONFIG_MFD_88PM800=m
@@ -625,13 +631,13 @@ CONFIG_REGULATOR_MAX8973=m
# CONFIG_BATTERY_RX51 is not set
# CONFIG_IR_RX51 is not set
-# CONFIG_GENERIC_CPUFREQ_CPU0 is not set
# CONFIG_MFD_SMSC is not set
# CONFIG_MFD_SEC_CORE is not set
# CONFIG_MFD_LP8788 is not set
# CONFIG_MFD_MAX77686 is not set
# CONFIG_MFD_MAX77693 is not set
# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX14577 is not set
# CONFIG_MFD_AAT2870_CORE is not set
# CONFIG_MFD_RC5T583 is not set
# CONFIG_MFD_SMSC is not set
@@ -649,10 +655,9 @@ CONFIG_REGULATOR_MAX8973=m
# CONFIG_VIRTUALIZATION is not set
# CONFIG_POWER_RESET_QNAP is not set
# CONFIG_OMAP2_DSS_DEBUG is not set
-# CONFIG_DRM_TEGRA_DEBUG is not set
# CONFIG_CRYPTO_DEV_UX500_DEBUG is not set
# CONFIG_AB8500_DEBUG is not set
# CONFIG_SOC_VF610 is not set
-# CONFIG_ARM_CCI is not set
# CONFIG_MMC_TMIO is not set
+# CONFIG_SND_SOC_ADI is not set
diff --git a/config-armv7-generic b/config-armv7-generic
index 7800af27f..26e90fe82 100644
--- a/config-armv7-generic
+++ b/config-armv7-generic
@@ -8,6 +8,7 @@ CONFIG_ARM=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_CMDLINE=""
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
CONFIG_HAVE_ARM_ARCH_TIMER=y
CONFIG_HAVE_ARM_TWD=y
CONFIG_AEABI=y
@@ -49,8 +50,10 @@ CONFIG_ALWAYS_USE_PERSISTENT_CLOCK=y
# Platforms enabled/disabled globally on ARMv7
CONFIG_ARCH_HIGHBANK=y
+CONFIG_ARCH_SUNXI=y
CONFIG_ARCH_VEXPRESS_CA9X4=y
CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y
+# CONFIG_ARCH_VEXPRESS_SPC is not set
# CONFIG_ARCH_BCM is not set
# CONFIG_PLAT_SPEAR is not set
# CONFIG_ARCH_STI is not set
@@ -58,14 +61,9 @@ CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA=y
# CONFIG_ARCH_U8500 is not set
# CONFIG_ARCH_WM8850 is not set
# CONFIG_ARCH_SHMOBILE_MULTI is not set
-
-# highbank
-# 2013/04/19 - stability issues
-CONFIG_EDAC_HIGHBANK_MC=m
-CONFIG_EDAC_HIGHBANK_L2=m
-CONFIG_SATA_HIGHBANK=m
-CONFIG_ARM_HIGHBANK_CPUFREQ=m
-CONFIG_ARM_HIGHBANK_CPUIDLE=y
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_HI3xxx is not set
+# CONFIG_ARCH_MSM_DT is not set
# errata
# v5/v6
@@ -110,7 +108,7 @@ CONFIG_RCU_FANOUT=32
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_GOV_LADDER is not set
CONFIG_CPU_IDLE_GOV_MENU=y
-CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
+# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set
@@ -119,8 +117,6 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768
CONFIG_XZ_DEC_ARM=y
-CONFIG_ARM_CPU_SUSPEND=y
-
CONFIG_LOCAL_TIMERS=y
CONFIG_UACCESS_WITH_MEMCPY=y
CONFIG_CC_STACKPROTECTOR=y
@@ -153,10 +149,39 @@ CONFIG_RTC_DRV_PL031=y
CONFIG_PL330_DMA=m
CONFIG_AMBA_PL08X=y
-CONFIG_ARM_SP805_WATCHDOG=m
CONFIG_GPIO_PL061=y
CONFIG_PL320_MBOX=y
+# highbank
+CONFIG_EDAC_HIGHBANK_MC=m
+CONFIG_EDAC_HIGHBANK_L2=m
+CONFIG_SATA_HIGHBANK=m
+CONFIG_ARM_HIGHBANK_CPUFREQ=m
+# CONFIG_ARM_HIGHBANK_CPUIDLE is not set
+
+# Allwinner a1x
+CONFIG_PINCTRL_SUNXI=y
+CONFIG_SUNXI_WATCHDOG=m
+CONFIG_MDIO_SUN4I=m
+CONFIG_NET_VENDOR_ALLWINNER=y
+CONFIG_SUN4I_EMAC=m
+CONFIG_STMMAC_PLATFORM=y
+CONFIG_DWMAC_SUNXI=y
+CONFIG_EEPROM_SUNXI_SID=m
+CONFIG_RTC_DRV_SUNXI=m
+
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=m
+CONFIG_REGMAP_SPI=m
+CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_MMIO=m
+CONFIG_REGMAP_IRQ=y
+
+# Power management
+CONFIG_PM_OPP=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_GENERIC_CPUFREQ_CPU0=m
+
# usb
CONFIG_USB_OTG=y
# CONFIG_USB_OTG_WHITELIST is not set
@@ -201,6 +226,8 @@ CONFIG_USB_CONFIGFS_OBEX=y
# CONFIG_USB_CONFIGFS_RNDIS is not set
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
# CONFIG_MUSB_PIO_ONLY is not set
# CONFIG_USB_MUSB_DEBUG is not set
@@ -243,25 +270,30 @@ CONFIG_PINCTRL_SINGLE=y
CONFIG_GENERIC_PINCONF=y
# CONFIG_PINCTRL_SAMSUNG is not set
# CONFIG_PINCTRL_EXYNOS4 is not set
+# CONFIG_PINCTRL_CAPRI is not set
+# CONFIG_PINCTRL_MSM8X74 is not set
# GPIO
-CONFIG_GPIO_GENERIC_PLATFORM=m
# CONFIG_GPIO_EM is not set
+CONFIG_GPIO_74X164=m
CONFIG_GPIO_ADNP=m
CONFIG_GPIO_MCP23S08=m
-CONFIG_SERIAL_8250_EM=m
-CONFIG_INPUT_GPIO_TILT_POLLED=m
-CONFIG_MDIO_BUS_MUX_GPIO=m
-CONFIG_MDIO_BUS_MUX_MMIOREG=m
-CONFIG_LEDS_GPIO=m
CONFIG_GPIO_MAX7301=m
CONFIG_GPIO_MC33880=m
-CONFIG_GPIO_74X164=m
CONFIG_GPIO_TPS65910=y
CONFIG_GPIO_TPS65912=m
+CONFIG_LEDS_GPIO=m
+CONFIG_MDIO_BUS_MUX=m
+CONFIG_MDIO_BUS_MUX_GPIO=m
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+CONFIG_INPUT_GPIO=m
+CONFIG_INPUT_GPIO_BEEPER=m
+CONFIG_INPUT_GPIO_TILT_POLLED=m
+CONFIG_INPUT_MATRIXKMAP=m
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_MATRIX=m
# CONFIG_GPIO_RCAR is not set
CONFIG_W1_MASTER_GPIO=m
-CONFIG_CHARGER_GPIO=m
# SPI
CONFIG_SPI=y
@@ -287,10 +319,16 @@ CONFIG_NFC_NCI_SPI=y
# i2c
CONFIG_I2C_DESIGNWARE_CORE=m
CONFIG_I2C_DESIGNWARE_PLATFORM=m
+CONFIG_I2C_MV64XXX=m
# HW crypto and rng
CONFIG_CRYPTO_SHA1_ARM=m
CONFIG_CRYPTO_AES_ARM=m
+# CONFIG_CRYPTO_AES_ARM_BS is not set
+
+# DMA
+CONFIG_TI_PRIV_EDMA=y
+CONFIG_TI_EDMA=y
# EDAC
CONFIG_EDAC=y
@@ -313,6 +351,22 @@ CONFIG_MTD_DATAFLASH=m
CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y
CONFIG_MTD_DATAFLASH_OTP=y
CONFIG_MTD_M25P80=m
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_CAFE=m
+# CONFIG_MTD_NAND_DENALI is not set
+CONFIG_MTD_NAND_DOCG4=m
+CONFIG_MTD_NAND_ECC_SMC=y
+CONFIG_MTD_NAND_FSMC=m
+CONFIG_MTD_NAND_GPIO=m
+CONFIG_MTD_NAND_MXC=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_ORION=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_NAND_PXA3xx=m
+CONFIG_MTD_NAND_RICOH=m
+CONFIG_MTD_NAND_TMIO=m
+CONFIG_MTD_SPINAND_MT29F=m
+CONFIG_MTD_SPINAND_ONDIEECC=y
CONFIG_MTD_SST25L=m
CONFIG_EEPROM_AT25=m
CONFIG_EEPROM_93XX46=m
@@ -329,6 +383,7 @@ CONFIG_SPI_DW_PCI=m
# CONFIG_MMC_DW_SOCFPGA is not set
# CONFIG_MMC_DW_EXYNOS is not set
# CONFIG_MMC_DW_IDMAC is not set
+# CONFIG_MMC_DW_K3 is not set
CONFIG_USB_DWC2=m
# CONFIG_USB_DWC2_DEBUG is not set
# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
@@ -337,7 +392,10 @@ CONFIG_USB_DWC3_OMAP=m
CONFIG_USB_DWC3_EXYNOS=m
CONFIG_USB_DWC3_PCI=m
# CONFIG_USB_DWC3_DEBUG is not set
+# CONFIG_USB_DWC3_KEYSTONE is not set
CONFIG_DW_WATCHDOG=m
+CONFIG_PCIE_DW=y
+CONFIG_PCI_EXYNOS=y
# Sound
CONFIG_SND_SOC=m
@@ -375,11 +433,12 @@ CONFIG_RTC_DRV_TPS80031=m
# Regulators
CONFIG_REGULATOR=y
CONFIG_RFKILL_REGULATOR=m
-# CONFIG_REGULATOR_DUMMY is not set
-CONFIG_REGULATOR_FIXED_VOLTAGE=m
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_VIRTUAL_CONSUMER=m
CONFIG_REGULATOR_USERSPACE_CONSUMER=m
CONFIG_REGULATOR_GPIO=m
+# CONFIG_REGULATOR_ACT8865 is not set
CONFIG_REGULATOR_AD5398=m
CONFIG_REGULATOR_DA9210=m
CONFIG_REGULATOR_FAN53555=m
@@ -407,6 +466,10 @@ CONFIG_REGULATOR_TPS65912=m
CONFIG_REGULATOR_TPS80031=m
CONFIG_CHARGER_MANAGER=y
+CONFIG_CHARGER_BQ2415X=m
+CONFIG_CHARGER_BQ24190=m
+CONFIG_CHARGER_BQ24735=m
+CONFIG_CHARGER_GPIO=m
CONFIG_CHARGER_TPS65090=m
CONFIG_PDA_POWER=m
CONFIG_GENERIC_ADC_BATTERY=m
@@ -452,22 +515,11 @@ CONFIG_LEDS_DAC124S085=m
CONFIG_LEDS_PWM=m
CONFIG_BMP085_SPI=m
-# Contiguous Memory Allocator
-CONFIG_OF_RESERVED_MEM=y
-CONFIG_CMA=y
-CONFIG_DMA_CMA=y
-# CONFIG_CMA_DEBUG is not set
-CONFIG_CMA_SIZE_MBYTES=16
-CONFIG_CMA_SIZE_SEL_MBYTES=y
-# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
-# CONFIG_CMA_SIZE_SEL_MIN is not set
-# CONFIG_CMA_SIZE_SEL_MAX is not set
-CONFIG_CMA_ALIGNMENT=8
-CONFIG_CMA_AREAS=7
CONFIG_SRAM=y
# Ethernet
CONFIG_KS8851=m
+CONFIG_KS8851_MLL=m
CONFIG_ENC28J60=m
CONFIG_LIBERTAS_SPI=m
CONFIG_P54_SPI=m
@@ -502,13 +554,18 @@ CONFIG_UBIFS_FS_ZLIB=y
# Sensors
CONFIG_SENSORS_HTU21=m
+# Chromebook
+CONFIG_MFD_CROS_EC=m
+CONFIG_MFD_CROS_EC_I2C=m
+CONFIG_MFD_CROS_EC_SPI=m
+CONFIG_KEYBOARD_CROS_EC=m
+
# Should be in generic
CONFIG_BPF_JIT=y
+
# CONFIG_NET_VENDOR_CIRRUS is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
-
# CONFIG_PATA_PLATFORM is not set
-
# CONFIG_DRM_EXYNOS is not set
# CONFIG_DRM_TILCDC is not set
# CONFIG_DRM_IMX is not set
@@ -529,6 +586,7 @@ CONFIG_BPF_JIT=y
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
# CONFIG_M25PXX_USE_FAST_READ is not set
+# CONFIG_SERIAL_8250_EM is not set
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX310X is not set
# CONFIG_SERIAL_IFX6X60 is not set
@@ -536,6 +594,8 @@ CONFIG_BPF_JIT=y
# CONFIG_SPI_TOPCLIFF_PCH is not set
# CONFIG_SPI_PXA2XX is not set
# CONFIG_SPI_FSL_DSPI is not set
+# CONFIG_FB_XILINX is not set
+# CONFIG_USB_S3C_HSOTG is not set
# these modules all fail with missing __bad_udelay
# http://www.spinics.net/lists/arm/msg15615.html provides some background
@@ -557,7 +617,5 @@ CONFIG_BPF_JIT=y
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_LL is not set
# CONFIG_DEBUG_PINCTRL is not set
-# CONFIG_ARM_DT_BL_CPUFREQ is not set
-
-# FIX ME
-# CONFIG_FB_XILINX is not set
+# CONFIG_DMADEVICES_VDEBUG is not set
+# CONFIG_DMADEVICES_DEBUG is not set
diff --git a/config-armv7-lpae b/config-armv7-lpae
index f2cfb02f2..25fe122d5 100644
--- a/config-armv7-lpae
+++ b/config-armv7-lpae
@@ -1,8 +1,6 @@
# ARM A15 lpae unified arch kernel
-CONFIG_ARCH_EXYNOS_MULTI=y
CONFIG_ARCH_KEYSTONE=y
CONFIG_ARCH_VIRT=y
-CONFIG_ARCH_EXYNOS5=y
# CONFIG_ARCH_MVEBU is not set
# CONFIG_ARCH_MXC is not set
@@ -10,24 +8,19 @@ CONFIG_ARCH_EXYNOS5=y
# CONFIG_ARCH_OMAP4 is not set
# CONFIG_SOC_OMAP5 is not set
# CONFIG_SOC_AM33XX is not set
+# CONFIG_SND_AM33XX_SOC_EVM is not set
# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
# CONFIG_ARCH_ROCKCHIP is not set
# CONFIG_ARCH_SOCFPGA is not set
-# CONFIG_ARCH_SUNXI is not set
# CONFIG_ARCH_TEGRA is not set
# CONFIG_ARCH_ZYNQ is not set
-
-# CONFIG_ARCH_EXYNOS4 is not set
-
-# CONFIG_EXYNOS_ATAGS is not set
-
CONFIG_ARM_LPAE=y
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_ARM_VIRT_EXT=y
CONFIG_VIRTUALIZATION=y
-CONFIG_ARM_SMMU=y
CONFIG_ARM_DMA_IOMMU_ALIGNMENT=8
# Cortex-A15
@@ -40,7 +33,7 @@ CONFIG_KVM_ARM_MAX_VCPUS=8
CONFIG_KVM_ARM_VGIC=y
CONFIG_KVM_ARM_TIMER=y
-CONFIG_XEN=y
+# CONFIG_XEN is not set
CONFIG_XEN_FBDEV_FRONTEND=y
CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m
CONFIG_XEN_BLKDEV_FRONTEND=m
@@ -57,8 +50,8 @@ CONFIG_XEN_SYS_HYPERVISOR=y
CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=m
CONFIG_XEN_WDT=m
+# CONFIG_XEN_BALLOON is not set
-CONFIG_MACH_EXYNOS5_DT=y
CONFIG_SERIAL_SAMSUNG=y
CONFIG_SERIAL_SAMSUNG_CONSOLE=y
# CONFIG_SAMSUNG_PM_DEBUG is not set
@@ -69,13 +62,12 @@ CONFIG_SOC_EXYNOS5440=y
# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
# CONFIG_ARM_EXYNOS5440_CPUFREQ is not set
# CONFIG_ARM_EXYNOS_CPUFREQ is not set
-# CONFIG_GENERIC_CPUFREQ_CPU0 is not set
CONFIG_EXYNOS_THERMAL=m
CONFIG_PCI_EXYNOS=y
-CONFIG_ARM_CCI=y
CONFIG_TCG_TIS_I2C_INFINEON=m
+# CONFIG_EXYNOS_ATAGS is not set
CONFIG_PINCTRL_EXYNOS=y
CONFIG_PINCTRL_EXYNOS5440=y
CONFIG_EXYNOS_IOMMU=y
@@ -114,11 +106,15 @@ CONFIG_SAMSUNG_USB3PHY=m
CONFIG_MMC_DW_EXYNOS=m
CONFIG_RTC_DRV_S3C=m
-# Chromebook
-CONFIG_MFD_CROS_EC=m
-CONFIG_MFD_CROS_EC_I2C=m
-CONFIG_MFD_CROS_EC_SPI=m
-CONFIG_KEYBOARD_CROS_EC=m
+# TI Keystone
+CONFIG_KEYSTONE_USB_PHY=m
+CONFIG_USB_DWC3_KEYSTONE=m
+CONFIG_GPIO_DAVINCI=y
+CONFIG_I2C_DAVINCI=m
+# CONFIG_DAVINCI_WATCHDOG is not set
+# CONFIG_SPI_DAVINCI is not set
+# CONFIG_SND_DAVINCI_SOC is not set
+# CONFIG_TI_SOC_THERMAL is not set
# Arndale/Origen
CONFIG_MFD_MAX8997=y
@@ -137,6 +133,3 @@ CONFIG_S3C_LOWLEVEL_UART_PORT=1
# CONFIG_S3C2410_WATCHDOG is not set
# CONFIG_MMC_SDHCI_S3C is not set
# CONFIG_TEGRA_HOST1X is not set
-# CONFIG_SPI_DAVINCI is not set
-# CONFIG_I2C_DAVINCI is not set
-# CONFIG_TI_SOC_THERMAL is not set
diff --git a/config-debug b/config-debug
index fb7df3e38..e22532600 100644
--- a/config-debug
+++ b/config-debug
@@ -26,8 +26,6 @@ CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
CONFIG_FAIL_IO_TIMEOUT=y
CONFIG_FAIL_MMC_REQUEST=y
-CONFIG_SLUB_DEBUG_ON=y
-
CONFIG_LOCK_STAT=y
CONFIG_DEBUG_STACK_USAGE=y
@@ -104,6 +102,7 @@ CONFIG_KDB_KEYBOARD=y
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_PERCPU_TEST=m
CONFIG_TEST_LIST_SORT=y
CONFIG_TEST_STRING_HELPERS=m
diff --git a/config-generic b/config-generic
index c2f589b17..207145926 100644
--- a/config-generic
+++ b/config-generic
@@ -61,7 +61,7 @@ CONFIG_PID_NS=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_NET_NS=y
-# CONFIG_USER_NS is not set
+CONFIG_USER_NS=y
# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set
CONFIG_POSIX_MQUEUE=y
@@ -72,6 +72,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_SLUB=y
CONFIG_SLUB_CPU_PARTIAL=y
# CONFIG_SLUB_STATS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_AD525X_DPOT is not set
# CONFIG_ATMEL_PWM is not set
@@ -127,7 +128,8 @@ CONFIG_MMC=m
CONFIG_SDIO_UART=m
# CONFIG_MMC_TEST is not set
# CONFIG_MMC_DEBUG is not set
-# CONFIG_MMC_UNSAFE_RESUME is not set
+# https://lists.fedoraproject.org/pipermail/kernel/2014-February/004889.html
+CONFIG_MMC_UNSAFE_RESUME=y
# CONFIG_MMC_CLKGATE is not set
CONFIG_MMC_BLOCK=m
CONFIG_MMC_BLOCK_MINORS=8
@@ -147,6 +149,7 @@ CONFIG_MMC_REALTEK_PCI=m
CONFIG_MMC_VUB300=m
# CONFIG_MMC_SDHCI_PXAV2 is not set
# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
CONFIG_CB710_CORE=m
@@ -181,6 +184,7 @@ CONFIG_INFINIBAND_NES=m
CONFIG_INFINIBAND_QIB=m
CONFIG_INFINIBAND_QIB_DCA=y
# CONFIG_INFINIBAND_OCRDMA is not set
+# CONFIG_INFINIBAND_USNIC is not set
#
# Executable file formats
@@ -195,7 +199,6 @@ CONFIG_BINFMT_MISC=m
# Device Drivers
#
-# CONFIG_COMMON_CLK_DEBUG is not set
# CONFIG_COMMON_CLK_SI5351 is not set
#
@@ -309,8 +312,11 @@ CONFIG_HOTPLUG_PCI_ACPI_IBM=m
# Block devices
#
CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_NULL_BLK=m
CONFIG_BLK_DEV_FD=m
# CONFIG_PARIDE is not set
+CONFIG_ZRAM=m
+# CONFIG_ZRAM_DEBUG is not set
CONFIG_BLK_CPQ_DA=m
CONFIG_BLK_CPQ_CISS_DA=m
@@ -325,6 +331,7 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_NVME=m
+CONFIG_BLK_DEV_SKD=m # 64-bit only but easier to put here
CONFIG_BLK_DEV_OSD=m
CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
@@ -435,8 +442,7 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000
# CONFIG_AIC79XX_DEBUG_ENABLE is not set
CONFIG_AIC79XX_DEBUG_MASK=0
# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
-CONFIG_SCSI_AIC94XX=m
-# CONFIG_AIC94XX_DEBUG is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_ADVANSYS is not set
CONFIG_SCSI_BFA_FC=m
CONFIG_MEGARAID_NEWGEN=y
@@ -662,7 +668,7 @@ CONFIG_FIREWIRE_SBP2=m
CONFIG_FIREWIRE_NET=m
CONFIG_FIREWIRE_OHCI_DEBUG=y
CONFIG_FIREWIRE_NOSY=m
-CONFIG_FIREWIRE_SERIAL=m
+# CONFIG_FIREWIRE_SERIAL is not set
# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
#
@@ -786,6 +792,7 @@ CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=m
CONFIG_IPV6_SIT=m
CONFIG_IPV6_SIT_6RD=y
CONFIG_IPV6_TUNNEL=m
@@ -853,6 +860,7 @@ CONFIG_NETFILTER_XT_TARGET_TPROXY=m
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
CONFIG_NETFILTER_XT_MATCH_CPU=m
@@ -869,8 +877,10 @@ CONFIG_NETFILTER_XT_MATCH_ESP=m
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
CONFIG_NETFILTER_XT_MATCH_HELPER=m
CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_L2TP=m
CONFIG_NETFILTER_XT_MATCH_LENGTH=m
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
CONFIG_NETFILTER_XT_MATCH_MAC=m
@@ -982,6 +992,33 @@ CONFIG_NF_NAT_IPV6=m
CONFIG_IP6_NF_TARGET_MASQUERADE=m
# CONFIG_IP6_NF_TARGET_NPT is not set
+# nf_tables support
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
+CONFIG_NFT_EXTHDR=m
+CONFIG_NFT_META=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_RBTREE=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_REJECT=m
+CONFIG_NFT_COMPAT=m
+
+CONFIG_NF_TABLES_IPV4=m
+CONFIG_NFT_REJECT_IPV4=m
+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_CHAIN_NAT_IPV4=m
+CONFIG_NF_TABLES_ARP=m
+
+CONFIG_NF_TABLES_IPV6=m
+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_CHAIN_NAT_IPV6=m
+
+CONFIG_NF_TABLES_BRIDGE=m
#
# Bridge: Netfilter Configuration
#
@@ -1029,7 +1066,9 @@ CONFIG_IP_SET_HASH_IP=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
CONFIG_IP_SET_HASH_NETPORT=m
CONFIG_IP_SET_HASH_NETIFACE=m
CONFIG_IP_SET_LIST_SET=m
@@ -1107,11 +1146,14 @@ CONFIG_NET_SCH_QFQ=m
CONFIG_NET_SCH_CODEL=m
CONFIG_NET_SCH_FQ_CODEL=m
CONFIG_NET_SCH_FQ=m
+CONFIG_NET_SCH_HHF=m
+CONFIG_NET_SCH_PIE=m
CONFIG_NET_SCH_PLUG=m
CONFIG_NET_CLS=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_CLS_BASIC=m
CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_BPF=m
CONFIG_NET_CLS_FLOW=m
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_IND=y
@@ -1155,7 +1197,6 @@ CONFIG_OPENVSWITCH=m
CONFIG_OPENVSWITCH_GRE=y
CONFIG_OPENVSWITCH_VXLAN=y
CONFIG_VSOCKETS=m
-CONFIG_NETPRIO_CGROUP=m
#
@@ -1343,6 +1384,10 @@ CONFIG_IXGBE_DCB=y
CONFIG_IXGBE_HWMON=y
CONFIG_IXGBE_PTP=y
CONFIG_I40E=m
+# CONFIG_I40E_VXLAN is not set
+# CONFIG_I40E_DCB is not set
+# CONFIG_I40EVF is not set
+
# CONFIG_NET_VENDOR_I825XX is not set
CONFIG_NET_VENDOR_MARVELL=y
@@ -1589,11 +1634,16 @@ CONFIG_ATH9K_HTC=m
CONFIG_ATH9K_BTCOEX_SUPPORT=y
# CONFIG_ATH9K_HTC_DEBUGFS is not set
# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set
+# CONFIG_ATH9K_STATION_STATISTICS is not set
+# CONFIG_ATH9K_WOW is not set
+#
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
# CONFIG_ATH10K_DEBUG is not set
# CONFIG_ATH10K_TRACING is not set
CONFIG_ATH10K_DEBUGFS=y
+CONFIG_WCN36XX=m
+# CONFIG_WCN36XX_DEBUGFS is not set
CONFIG_WIL6210=m
CONFIG_WIL6210_ISR_COR=y
# CONFIG_WIL6210_TRACING is not set
@@ -1704,6 +1754,7 @@ CONFIG_RT73USB=m
CONFIG_RTL8180=m
CONFIG_RTL8187=m
# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_SR9800 is not set
CONFIG_USB_NET_RNDIS_WLAN=m
CONFIG_USB_NET_KALMIA=m
CONFIG_USB_NET_QMI_WWAN=m
@@ -1775,15 +1826,19 @@ CONFIG_BAYCOM_EPP=m
CONFIG_YAM=m
CONFIG_NFC=m
+CONFIG_NFC_DIGITAL=m
CONFIG_NFC_NCI=m
CONFIG_NFC_HCI=m
CONFIG_NFC_SHDLC=y
CONFIG_NFC_LLCP=y
CONFIG_NFC_SIM=m
+CONFIG_NFC_MRVL=m
+CONFIG_NFC_MRVL_USB=m
#
# Near Field Communication (NFC) devices
#
+CONFIG_NFC_PORT100=m
CONFIG_NFC_PN544=m
CONFIG_NFC_PN544_I2C=m
CONFIG_NFC_PN533=m
@@ -2050,6 +2105,7 @@ CONFIG_SERIO_ARC_PS2=m
# CONFIG_SERIO_OLPC_APSP is not set
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
#
# Input Device Drivers
@@ -2057,6 +2113,7 @@ CONFIG_SERIO_ARC_PS2=m
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_SH_KEYSC is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_MATRIX is not set
# CONFIG_KEYBOARD_NEWTON is not set
@@ -2141,6 +2198,7 @@ CONFIG_TOUCHSCREEN_MTOUCH=m
CONFIG_TOUCHSCREEN_MCS5000=m
CONFIG_TOUCHSCREEN_MK712=m
CONFIG_TOUCHSCREEN_PENMOUNT=m
+# CONFIG_TOUCHSCREEN_SUR40 is not set
# CONFIG_TOUCHSCREEN_TPS6507X is not set
CONFIG_TOUCHSCREEN_TSC_SERIO=m
CONFIG_TOUCHSCREEN_TSC2007=m
@@ -2161,6 +2219,7 @@ CONFIG_TOUCHSCREEN_ATMEL_MXT=m
# CONFIG_TOUCHSCREEN_MAX11801 is not set
CONFIG_TOUCHSCREEN_AUO_PIXCIR=m
CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
+CONFIG_TOUCHSCREEN_ZFORCE=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PCSPKR=m
@@ -2207,6 +2266,8 @@ CONFIG_TIFM_7XX1=m
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS=m
# CONFIG_TCG_TIS_I2C_INFINEON is not set
+# CONFIG_TCG_TIS_I2C_ATMEL is not set
+# CONFIG_TCG_TIS_I2C_NUVOTON is not set
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
# CONFIG_TCG_INFINEON is not set
@@ -2271,7 +2332,12 @@ CONFIG_I2C=m
CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+#
#
# I2C Algorithms
@@ -2311,6 +2377,7 @@ CONFIG_I2C_NFORCE2=m
# CONFIG_I2C_OCORES is not set
CONFIG_I2C_PARPORT=m
CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
CONFIG_I2C_PASEMI=m
CONFIG_I2C_PCA_PLATFORM=m
# CONFIG_I2C_PIIX4 is not set
@@ -2495,8 +2562,13 @@ CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=y
# CONFIG_MCP4725 is not set
# CONFIG_ITG3200 is not set
# CONFIG_APDS9300 is not set
+# CONFIG_CM32181 is not set
+# CONFIG_CM36651 is not set
+# CONFIG_GP2AP020A00F is not set
# CONFIG_TSL2583 is not set
# CONFIG_TSL2x7x is not set
+# CONFIG_TCS3472 is not set
+# CONFIG_TSL4531 is not set
# CONFIG_NAU7802 is not set
# CONFIG_TI_ADC081C is not set
# CONFIG_EXYNOS_ADC is not set
@@ -2505,10 +2577,12 @@ CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=y
CONFIG_IIO_ST_GYRO_3AXIS=m
CONFIG_IIO_ST_MAGN_3AXIS=m
CONFIG_IIO_ST_ACCEL_3AXIS=m
+CONFIG_HID_SENSOR_INCLINOMETER_3D=m
# CONFIG_ADJD_S311 is not set
# CONFIG_SENSORS_TSL2563 is not set
# CONFIG_VCNL4000 is not set
# CONFIG_AK8975 is not set
+# CONFIG_MAG3110 is not set
# CONFIG_TMP006 is not set
# CONFIG_IIO_ST_PRESS is not set
# CONFIG_KXSD9 is not set
@@ -2520,6 +2594,7 @@ CONFIG_IIO_ST_ACCEL_3AXIS=m
# CONFIG_AD7887 is not set
# CONFIG_AD7923 is not set
# CONFIG_MCP320X is not set
+# CONFIG_MCP3422 is not set
# CONFIG_AD8366 is not set
# CONFIG_AD5360 is not set
# CONFIG_AD5421 is not set
@@ -2540,6 +2615,8 @@ CONFIG_IIO_ST_ACCEL_3AXIS=m
# CONFIG_ADXRS450 is not set
# CONFIG_ADIS16400 is not set
# CONFIG_ADIS16480 is not set
+# CONFIG_DHT11 is not set
+# CONFIG_MPL3115 is not set
# staging IIO drivers
# CONFIG_AD7291 is not set
@@ -2671,6 +2748,7 @@ CONFIG_WM831X_WATCHDOG=m
# CONFIG_DW_WATCHDOG is not set
CONFIG_W83697UG_WDT=m
# CONFIG_MEN_A21_WDT is not set
+# CONFIG_GPIO_WATCHDOG is not set
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_TIMERIOMEM=m
@@ -2734,6 +2812,7 @@ CONFIG_RTC_DRV_DS3232=m
CONFIG_RTC_DRV_ISL12022=m
# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
# CONFIG_RTC_DRV_MOXART is not set
+# CONFIG_RTC_DRV_ISL12057 is not set
CONFIG_R3964=m
# CONFIG_APPLICOM is not set
@@ -2775,7 +2854,9 @@ CONFIG_DRM_MGAG200=m # do not enable on f17 or older
# CONFIG_DRM_SAVAGE is not set
CONFIG_DRM_I915=m
CONFIG_DRM_I915_KMS=y
+CONFIG_DRM_I915_FBDEV=y
# CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT is not set
+# CONFIG_DRM_I915_UMS is not set
CONFIG_DRM_VIA=m
CONFIG_DRM_NOUVEAU=m
CONFIG_NOUVEAU_DEBUG=5
@@ -2790,6 +2871,7 @@ CONFIG_DRM_UDL=m
CONFIG_DRM_VMWGFX=m
CONFIG_DRM_VMWGFX_FBCON=y
CONFIG_DRM_QXL=m
+CONFIG_DRM_BOCHS=m
#
# PCMCIA character devices
@@ -2823,6 +2905,10 @@ CONFIG_VIDEO_V4L2=y
# CONFIG_VIDEO_V4L2_INT_DEVICE is not set
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_VIDEO_VIVI is not set
+# CONFIG_USB_SI4713 is not set
+# CONFIG_PLATFORM_SI4713 is not set
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_USB_RAREMONO is not set
#
# Video For Linux
@@ -2856,6 +2942,7 @@ CONFIG_VIDEO_CX88_BLACKBIRD=m
CONFIG_VIDEO_CX88_ENABLE_VP3054=y
CONFIG_VIDEO_CX88_VP3054=m
CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_V4L2=m
CONFIG_VIDEO_EM28XX_ALSA=m
CONFIG_VIDEO_EM28XX_DVB=m
CONFIG_VIDEO_EM28XX_RC=y
@@ -3147,6 +3234,7 @@ CONFIG_FB_EFI=y
# CONFIG_FB_BROADSHEET is not set
# CONFIG_FB_UDL is not set
# CONFIG_FB_GOLDFISH is not set
+# CONFIG_FB_OPENCORES is not set
# CONFIG_FIRMWARE_EDID is not set
@@ -3329,6 +3417,7 @@ CONFIG_SND_FIREWIRE=y
CONFIG_SND_FIREWIRE_SPEAKERS=m
CONFIG_SND_ISIGHT=m
CONFIG_SND_SCS1X=m
+CONFIG_SND_DICE=m
#
# Open Sound System
@@ -3370,6 +3459,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
CONFIG_USB_ISP1362_HCD=m
CONFIG_USB_FUSBH200_HCD=m
# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_GR_UDC is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PCI=y
# CONFIG_USB_OHCI_HCD_SSB is not set
@@ -3460,10 +3550,12 @@ CONFIG_HID_ORTEK=m
CONFIG_HID_PANTHERLORD=m
CONFIG_HID_PETALYNX=m
CONFIG_HID_PICOLCD=m
+CONFIG_HID_RMI=m
CONFIG_HID_ROCCAT=m
CONFIG_HID_ROCCAT_KONE=m
CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
+CONFIG_SONY_FF=y
CONFIG_HID_SUNPLUS=m
CONFIG_HID_STEELSERIES=m
CONFIG_HID_GREENASIA=m
@@ -3600,6 +3692,7 @@ CONFIG_USB_NET_RNDIS_HOST=m
CONFIG_USB_NET_CDC_SUBSET=m
CONFIG_USB_NET_CDC_EEM=m
CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
CONFIG_USB_NET_CDC_MBIM=m
CONFIG_USB_NET_ZAURUS=m
CONFIG_USB_NET_CX82310_ETH=m
@@ -3683,6 +3776,7 @@ CONFIG_USB_SERIAL_MOS7715_PARPORT=y
# CONFIG_USB_SERIAL_ZTE is not set
CONFIG_USB_SERIAL_MOS7840=m
CONFIG_USB_SERIAL_MOTOROLA=m
+# CONFIG_USB_SERIAL_MXUPORT is not set
CONFIG_USB_SERIAL_NAVMAN=m
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_OTI6858=m
@@ -3726,7 +3820,11 @@ CONFIG_USB_APPLEDISPLAY=m
# Physical Layer USB driver
CONFIG_USB_PHY=y
+# CONFIG_USB_OTG_FSM is not set
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set
+# CONFIG_PHY_EXYNOS_DP_VIDEO is not set
# CONFIG_OMAP_USB2 is not set
# CONFIG_OMAP_USB3 is not set
# CONFIG_OMAP_CONTROL_USB is not set
@@ -3734,6 +3832,7 @@ CONFIG_USB_PHY=y
# CONFIG_SAMSUNG_USBPHY is not set
# CONFIG_SAMSUNG_USB2PHY is not set
# CONFIG_SAMSUNG_USB3PHY is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
CONFIG_USB_RCAR_PHY=m
CONFIG_USB_ATM=m
CONFIG_USB_CXACRU=m
@@ -3830,6 +3929,7 @@ CONFIG_MFD_VIPERBOARD=m
# CONFIG_HTC_I2CPLD is not set
# CONFIG_MFD_MAX8925 is not set
# CONFIG_MFD_ASIC3 is not set
+# CONFIG_MFD_AS3722 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_TPS6507X is not set
# CONFIG_ABX500_CORE is not set
@@ -3853,6 +3953,7 @@ CONFIG_MFD_VIPERBOARD=m
# CONFIG_MFD_TPS65912 is not set
# CONFIG_MFD_SYSCON is not set
# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_LP3943 is not set
#
# File systems
@@ -3905,6 +4006,7 @@ CONFIG_CEPH_FS=m
CONFIG_CEPH_FSCACHE=y
CONFIG_BLK_DEV_RBD=m
CONFIG_CEPH_LIB=m
+CONFIG_CEPH_FS_POSIX_ACL=y
# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
CONFIG_FSCACHE=m
@@ -4001,6 +4103,7 @@ CONFIG_NFS_V4=y
CONFIG_NFS_SWAP=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+# CONFIG_NFS_V4_1_MIGRATION is not set
CONFIG_NFS_V4_2=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
@@ -4168,6 +4271,7 @@ CONFIG_OPROFILE_EVENT_MULTIPLEX=y
CONFIG_DEBUG_KERNEL=y
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_POINTER=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -4211,6 +4315,7 @@ CONFIG_LOCKUP_DETECTOR=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_TIMEOUT=0
CONFIG_ATOMIC64_SELFTEST=y
CONFIG_MEMORY_FAILURE=y
CONFIG_HWPOISON_INJECT=m
@@ -4354,6 +4459,7 @@ CONFIG_CRC_CCITT=m
CONFIG_CRC_ITU_T=m
CONFIG_CRC_T10DIF=m
CONFIG_CRC8=m
+# CONFIG_RANDOM32_SELFTEST is not set
# CONFIG_CRC7 is not set
CONFIG_CORDIC=m
# CONFIG_DDR is not set
@@ -4381,6 +4487,7 @@ CONFIG_BACKLIGHT_PROGEAR=m
# CONFIG_BACKLIGHT_ADP8860 is not set
# CONFIG_BACKLIGHT_ADP8870 is not set
# CONFIG_BACKLIGHT_LM3630 is not set
+# CONFIG_BACKLIGHT_LM3630A is not set
# CONFIG_BACKLIGHT_LM3639 is not set
CONFIG_FB_NVIDIA_BACKLIGHT=y
CONFIG_FB_RIVA_BACKLIGHT=y
@@ -4419,6 +4526,8 @@ CONFIG_MEMCG_SWAP_ENABLED=y
CONFIG_MEMCG_KMEM=y
# CONFIG_CGROUP_HUGETLB is not set
CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_NET_PRIO=m
+# CONFIG_CGROUP_NET_CLASSID is not set
CONFIG_BLK_CGROUP=y
# CONFIG_SYSFS_DEPRECATED is not set
@@ -4441,6 +4550,7 @@ CONFIG_THERMAL_GOV_FAIR_SHARE=y
# CONFIG_THERMAL_GOV_USER_SPACE is not set
CONFIG_THERMAL_GOV_STEP_WISE=y
# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_THERMAL_OF is not set
# CONFIG_CPU_THERMAL is not set
CONFIG_INOTIFY=y
@@ -4458,6 +4568,7 @@ CONFIG_IBMASR=m
CONFIG_PM=y
CONFIG_PM_STD_PARTITION=""
CONFIG_PM_DEBUG=y
+# CONFIG_DPM_WATCHDOG is not set # revisit this in debug
CONFIG_PM_TRACE=y
CONFIG_PM_TRACE_RTC=y
# CONFIG_PM_TEST_SUSPEND is not set
@@ -4544,6 +4655,7 @@ CONFIG_LEDS_DELL_NETBOOKS=m
# CONFIG_LEDS_PWM is not set
# CONFIG_LEDS_LP8501 is not set
# CONFIG_LEDS_PCA963X is not set
+# CONFIG_LEDS_PCA9685 is not set
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_ONESHOT=m
@@ -4654,6 +4766,7 @@ CONFIG_APM_POWER=m
# CONFIG_CHARGER_PCF50633 is not set
# CONFIG_CHARGER_BQ2415X is not set
# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24735 is not set
CONFIG_POWER_RESET=y
# CONFIG_PDA_POWER is not set
@@ -4699,6 +4812,7 @@ CONFIG_NOZOMI=m
CONFIG_INPUT_APANEL=m
CONFIG_INPUT_GP2A=m
# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
# CONFIG_INTEL_MENLOW is not set
CONFIG_ENCLOSURE_SERVICES=m
@@ -4727,7 +4841,7 @@ CONFIG_OPTIMIZE_INLINING=y
# FIXME: This should be x86/ia64 only
# CONFIG_HP_ILO is not set
-# CONFIG_GPIOLIB is not set
+CONFIG_GPIOLIB=y
# CONFIG_PINCTRL is not set
# CONFIG_DEBUG_PINCTRL is not set
# CONFIG_PINMUX is not set
@@ -4778,6 +4892,9 @@ CONFIG_STAGING_MEDIA=y
# CONFIG_TI_ST is not set
# CONFIG_FB_XGI is not set
# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_I2C_BCM2048 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_OMAP4 is not set
# CONFIG_USB_MSI3101 is not set
# CONFIG_DT3155 is not set
# CONFIG_W35UND is not set
@@ -4805,10 +4922,10 @@ CONFIG_RTL8192E=m
# CONFIG_VIDEO_CX25821 is not set
# CONFIG_R8187SE is not set
# CONFIG_R8188EU is not set
+# CONFIG_R8821AE is not set
# CONFIG_RTL8192U is not set
# CONFIG_FB_SM7XX is not set
# CONFIG_SPECTRA is not set
-# CONFIG_ZRAM is not set
# CONFIG_EASYCAP is not set
# CONFIG_SOLO6X10 is not set
# CONFIG_ACPI_QUICKSTART is not set
@@ -4833,7 +4950,6 @@ CONFIG_ALTERA_STAPL=m
# CONFIG_RTS5139 is not set
# CONFIG_NVEC_LEDS is not set
# CONFIG_VT6655 is not set
-# CONFIG_ZSMALLOC is not set
# CONFIG_RAMSTER is not set
# CONFIG_USB_WPAN_HCD is not set
# CONFIG_WIMAX_GDM72XX is not set
@@ -4850,6 +4966,7 @@ CONFIG_ALTERA_STAPL=m
# CONFIG_XILLYBUS is not set
# CONFIG_DGAP is not set
# CONFIG_DGNC is not set
+# CONFIG_RTS5208 is not set
# END OF STAGING
#
@@ -4904,6 +5021,8 @@ CONFIG_IEEE802154_FAKELB=m
CONFIG_MAC802154=m
CONFIG_NET_MPLS_GSO=m
+# CONFIG_HSR is not set
+
# CONFIG_EXTCON is not set
# CONFIG_EXTCON_ADC_JACK is not set
# CONFIG_MEMORY is not set
@@ -4923,6 +5042,8 @@ CONFIG_PTP_1588_CLOCK_PCH=m
CONFIG_CLEANCACHE=y
CONFIG_FRONTSWAP=y
CONFIG_ZSWAP=y
+CONFIG_ZSMALLOC=y
+# CONFIG_PGTABLE_MAPPING is not set
# CONFIG_MDIO_GPIO is not set
# CONFIG_KEYBOARD_GPIO is not set
@@ -4960,16 +5081,19 @@ CONFIG_GPIO_VIPERBOARD=m
# CONFIG_GPIO_BT8XX is not set
# CONFIG_GPIO_SX150X is not set
# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_PL061 is not set
+# CONFIG_GPIO_BCM_KONA is not set
+# CONFIG_GPIO_SCH311X is not set
# FIXME: Why?
CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
CONFIG_TEST_KSTRTOX=y
CONFIG_XZ_DEC=y
-# CONFIG_XZ_DEC_X86 is not set
-# CONFIG_XZ_DEC_POWERPC is not set
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
# CONFIG_XZ_DEC_IA64 is not set
-# CONFIG_XZ_DEC_ARM is not set
+CONFIG_XZ_DEC_ARM=y
# CONFIG_XZ_DEC_ARMTHUMB is not set
# CONFIG_XZ_DEC_SPARC is not set
# CONFIG_XZ_DEC_TEST is not set
@@ -4992,6 +5116,8 @@ CONFIG_PSTORE_RAM=m
# CONFIG_PSTORE_CONSOLE is not set
# CONFIG_PSTORE_FTRACE is not set
+# CONFIG_TEST_MODULE is not set
+# CONFIG_TEST_USER_COPY is not set
# CONFIG_AVERAGE is not set
# CONFIG_VMXNET3 is not set
@@ -5023,8 +5149,16 @@ CONFIG_FMC_TRIVIAL=m
CONFIG_FMC_WRITE_EEPROM=m
CONFIG_FMC_CHARDEV=m
+# CONFIG_GENWQE is not set
+
+# CONFIG_POWERCAP is not set
+
# CONFIG_HSI is not set
+# CONFIG_CPU_IDLE is not set
+
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+
# CONFIG_PM_DEVFREQ is not set
# CONFIG_MODULE_SIG is not set
# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
diff --git a/config-nodebug b/config-nodebug
index 75fc2200b..ee4842bfc 100644
--- a/config-nodebug
+++ b/config-nodebug
@@ -26,8 +26,6 @@ CONFIG_CPUMASK_OFFSTACK=y
# CONFIG_FAIL_IO_TIMEOUT is not set
# CONFIG_FAIL_MMC_REQUEST is not set
-# CONFIG_SLUB_DEBUG_ON is not set
-
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_STACK_USAGE is not set
@@ -104,6 +102,7 @@ CONFIG_KDB_KEYBOARD=y
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set
+# CONFIG_PERCPU_TEST is not set
# CONFIG_TEST_LIST_SORT is not set
# CONFIG_TEST_STRING_HELPERS is not set
diff --git a/config-powerpc-generic b/config-powerpc-generic
index 7ba1a5da5..9c0ad6011 100644
--- a/config-powerpc-generic
+++ b/config-powerpc-generic
@@ -321,6 +321,7 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m
# CONFIG_PPC_MPC512x is not set
# CONFIG_RTC_DRV_MPC5121 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
# CONFIG_MPC512X_DMA is not set
@@ -360,7 +361,7 @@ CONFIG_RCU_FANOUT_LEAF=16
# CONFIG_SPAPR_TCE_IOMMU is not set
# CONFIG_TRANSPARENT_HUGEPAGE is not set
-# CONFIG_PPC_DENORMALISATION is not set
+CONFIG_PPC_DENORMALISATION=y
# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
# CONFIG_GPIO_ADNP is not set
# CONFIG_MFD_SYSCON is not set
@@ -371,6 +372,7 @@ CONFIG_RCU_FANOUT_LEAF=16
# CONFIG_OF_VIDEOMODE is not set
# CONFIG_POWERNV_MSI is not set
+# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_POWER_RESET_GPIO=y
CONFIG_FB_SSD1307=m
diff --git a/config-powerpc64 b/config-powerpc64
index b430449e0..4b8ba84aa 100644
--- a/config-powerpc64
+++ b/config-powerpc64
@@ -14,6 +14,8 @@ CONFIG_PPC_PMAC=y
CONFIG_PPC_POWERNV=y
CONFIG_POWERNV_MSI=y
CONFIG_PPC_POWERNV_RTAS=y
+CONFIG_HW_RANDOM_POWERNV=m
+CONFIG_SCOM_DEBUGFS=y
# CONFIG_PPC_PASEMI is not set
# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set
# CONFIG_PPC_PS3 is not set
@@ -87,6 +89,8 @@ CONFIG_NR_CPUS=1024
CONFIG_RTAS_PROC=y
CONFIG_IOMMU_VMERGE=y
CONFIG_NUMA=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_PPC_64K_PAGES=y
CONFIG_PPC_SUBPAGE_PROT=y
CONFIG_SCHED_SMT=y
@@ -97,6 +101,8 @@ CONFIG_HZ_100=y
CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_PPC64_SUPPORTS_MEMORY_FAILURE=y
+
CONFIG_CGROUP_HUGETLB=y
# CONFIG_MV643XX_ETH is not set
@@ -139,7 +145,8 @@ CONFIG_RCU_FANOUT=64
CONFIG_CMA=y
# CONFIG_CMA_DEBUG is not set
CONFIG_KVM_BOOK3S_64=m
-CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_KVM_BOOK3S_64_HV=m
+CONFIG_KVM_BOOK3S_64_PR=m
# CONFIG_KVM_EXIT_TIMING is not set
CONFIG_KVM_XICS=y
@@ -156,7 +163,8 @@ CONFIG_PSERIES_ENERGY=m
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_GOV_LADDER is not set
-CONFIG_PSERIES_IDLE=y
+CONFIG_PSERIES_CPUIDLE=y
+CONFIG_POWERNV_CPUIDLE=y
CONFIG_PPC_ICSWX=y
CONFIG_IO_EVENT_IRQ=y
diff --git a/config-powerpc64p7 b/config-powerpc64p7
index 0e0d957ec..4fe09eee2 100644
--- a/config-powerpc64p7
+++ b/config-powerpc64p7
@@ -10,6 +10,8 @@ CONFIG_PPC_PSERIES=y
CONFIG_PPC_POWERNV=y
CONFIG_POWERNV_MSI=y
CONFIG_PPC_POWERNV_RTAS=y
+CONFIG_HW_RANDOM_POWERNV=m
+CONFIG_SCOM_DEBUGFS=y
# CONFIG_PPC_PASEMI is not set
# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set
# CONFIG_PPC_PS3 is not set
@@ -78,6 +80,8 @@ CONFIG_NR_CPUS=1024
CONFIG_RTAS_PROC=y
CONFIG_IOMMU_VMERGE=y
CONFIG_NUMA=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_PPC_64K_PAGES=y
CONFIG_PPC_SUBPAGE_PROT=y
CONFIG_SCHED_SMT=y
@@ -88,6 +92,8 @@ CONFIG_HZ_100=y
CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_PPC64_SUPPORTS_MEMORY_FAILURE=y
+
CONFIG_CGROUP_HUGETLB=y
# CONFIG_MV643XX_ETH is not set
@@ -130,7 +136,8 @@ CONFIG_RCU_FANOUT=64
CONFIG_CMA=y
# CONFIG_CMA_DEBUG is not set
CONFIG_KVM_BOOK3S_64=m
-CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_KVM_BOOK3S_64_HV=m
+CONFIG_KVM_BOOK3S_64_PR=m
# CONFIG_KVM_EXIT_TIMING is not set
CONFIG_KVM_XICS=y
@@ -147,7 +154,8 @@ CONFIG_PSERIES_ENERGY=m
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_GOV_LADDER is not set
-CONFIG_PSERIES_IDLE=y
+CONFIG_PSERIES_CPUIDLE=y
+CONFIG_POWERNV_CPUIDLE=y
CONFIG_PPC_ICSWX=y
CONFIG_IO_EVENT_IRQ=y
diff --git a/config-x86-32-generic b/config-x86-32-generic
index 868a7e3d4..21fe6fe75 100644
--- a/config-x86-32-generic
+++ b/config-x86-32-generic
@@ -73,8 +73,6 @@ CONFIG_APM_CPU_IDLE=y
# CONFIG_APM_DISPLAY_BLANK is not set
# CONFIG_APM_ALLOW_INTS is not set
-CONFIG_ACPI_BLACKLIST_YEAR=1999
-
# CONFIG_X86_POWERNOW_K6 is not set
CONFIG_X86_POWERNOW_K7=y
@@ -226,8 +224,13 @@ CONFIG_BACKLIGHT_PWM=m
# CONFIG_GPIO_ADNP is not set
# CONFIG_BACKLIGHT_OT200 is not set
# CONFIG_RTC_DRV_SNVS is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
# CONFIG_OF_DISPLAY_TIMING is not set
# CONFIG_OF_VIDEOMODE is not set
# CONFIG_MLX5_INFINIBAND is not set
# CONFIG_PINCTRL_SINGLE is not set
+# CONFIG_PINCTRL_CAPRI is not set
+# CONFIG_PINCTRL_MSM8X74 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_QCOM is not set
diff --git a/config-x86-generic b/config-x86-generic
index a21ec7aae..f6b3fa8c5 100644
--- a/config-x86-generic
+++ b/config-x86-generic
@@ -40,6 +40,8 @@ CONFIG_EFI_VARS_PSTORE=y
CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y
CONFIG_EFI_PCDP=y
CONFIG_FB_EFI=y
+CONFIG_EARLY_PRINTK_EFI=y
+CONFIG_EFI_RUNTIME_MAP=y
# needs FB_SIMPLE to work correctly
# CONFIG_X86_SYSFB is not set
@@ -95,6 +97,7 @@ CONFIG_ACPI_APEI_MEMORY_FAILURE=y
CONFIG_ACPI_IPMI=m
CONFIG_ACPI_CUSTOM_METHOD=m
CONFIG_ACPI_BGRT=y
+# CONFIG_ACPI_EXTLOG is not set
CONFIG_X86_INTEL_PSTATE=y
CONFIG_X86_ACPI_CPUFREQ=m
@@ -112,6 +115,9 @@ CONFIG_NVRAM=y
CONFIG_CRYPTO_DEV_PADLOCK=m
CONFIG_CRYPTO_DEV_PADLOCK_AES=m
CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_CCP=y
+CONFIG_CRYPTO_DEV_CCP_DD=m
+CONFIG_CRYPTO_DEV_CCP_CRYPTO=m
CONFIG_GENERIC_ISA_DMA=y
@@ -196,7 +202,9 @@ CONFIG_AMILO_RFKILL=m
CONFIG_ASUS_LAPTOP=m
CONFIG_COMPAL_LAPTOP=m
CONFIG_DELL_LAPTOP=m
+CONFIG_CHROME_PLATFORMS=y
CONFIG_CHROMEOS_LAPTOP=m
+CONFIG_CHROMEOS_PSTORE=m
CONFIG_EEEPC_LAPTOP=m
CONFIG_FUJITSU_TABLET=m
CONFIG_FUJITSU_LAPTOP=m
@@ -213,6 +221,7 @@ CONFIG_ACER_WMI=m
CONFIG_ACERHDF=m
CONFIG_ASUS_WMI=m
CONFIG_ASUS_NB_WMI=m
+CONFIG_HP_WIRELESS=m
CONFIG_HP_WMI=m
# CONFIG_INTEL_SCU_IPC is not set
CONFIG_DELL_WMI=m
@@ -382,6 +391,7 @@ CONFIG_F71808E_WDT=m
CONFIG_HPWDT_NMI_DECODING=y
# CONFIG_MFD_TPS6586X is not set
# CONFIG_INTEL_MID_DMAC is not set
+# CONFIG_GPIO_INTEL_MID is not set
CONFIG_PCH_DMA=m
CONFIG_INTEL_IPS=m
# CONFIG_IBM_RTL is not set
@@ -406,6 +416,7 @@ CONFIG_HP_ACCEL=m
CONFIG_SCHED_SMT=y
CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
CONFIG_RELOCATABLE=y
CONFIG_HYPERV=m
@@ -415,6 +426,7 @@ CONFIG_HYPERV_NET=m
CONFIG_HYPERV_STORAGE=m
CONFIG_HYPERV_BALLOON=m
CONFIG_FB_HYPERV=m
+CONFIG_HYPERV_KEYBOARD=m
# Depends on HOTPLUG_PCI_PCIE
CONFIG_BLK_DEV_PCIESSD_MTIP32XX=m
@@ -441,6 +453,7 @@ CONFIG_PINCTRL_BAYTRAIL=y
# CONFIG_INTEL_POWERCLAMP is not set
CONFIG_X86_PKG_TEMP_THERMAL=m
+CONFIG_ACPI_INT3403_THERMAL=m
CONFIG_VMWARE_VMCI=m
CONFIG_VMWARE_VMCI_VSOCKETS=m
diff --git a/config-x86_64-generic b/config-x86_64-generic
index 4f36d4d89..02883b84b 100644
--- a/config-x86_64-generic
+++ b/config-x86_64-generic
@@ -6,7 +6,8 @@ CONFIG_64BIT=y
CONFIG_GENERIC_CPU=y
# CONFIG_X86_VSMP is not set
-# CONFIG_X86_UV is not set
+CONFIG_X86_UV=y
+CONFIG_UV_MMTIMER=m
CONFIG_NUMA=y
CONFIG_K8_NUMA=y
CONFIG_AMD_NUMA=y
@@ -21,6 +22,9 @@ CONFIG_NR_CPUS=1024
CONFIG_PHYSICAL_START=0x1000000
CONFIG_PHYSICAL_ALIGN=0x1000000
+# https://lists.fedoraproject.org/pipermail/kernel/2013-December/004753.html
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+
CONFIG_IA32_EMULATION=y
# CONFIG_IA32_AOUT is not set
@@ -30,18 +34,22 @@ CONFIG_AMD_IOMMU_V2=m
# CONFIG_IOMMU_DEBUG is not set
CONFIG_SWIOTLB=y
# CONFIG_CALGARY_IOMMU is not set
+# CONFIG_GART_IOMMU is not set
CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_MEM_SOFT_DIRTY=y
CONFIG_KEXEC_JUMP=y
-CONFIG_ACPI_BLACKLIST_YEAR=0
CONFIG_ACPI_HOTPLUG_MEMORY=y
# CONFIG_INTEL_SCU_IPC is not set
+CONFIG_INTEL_MIC_HOST=m
+CONFIG_INTEL_MIC_CARD=m
+
# SHPC has half-arsed PCI probing, which makes it load on too many systems
CONFIG_HOTPLUG_PCI_SHPC=m
@@ -86,7 +94,8 @@ CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP=y
# CONFIG_MOVABLE_NODE is not set
-# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_MEMORY_HOTPLUG=y
+# CONFIG_ARCH_MEMORY_PROBE is not set
# CONFIG_MEMORY_HOTREMOVE is not set
# CONFIG_BLK_DEV_CMD640 is not set
@@ -109,6 +118,7 @@ CONFIG_XEN_DEV_EVTCHN=m
CONFIG_XEN_SYS_HYPERVISOR=y
# CONFIG_XEN_MCE_LOG is not set
# CONFIG_XEN_STUB is not set
+# CONFIG_XEN_PVH is not set
CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
diff --git a/cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch b/cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch
deleted file mode 100644
index 2693b341e..000000000
--- a/cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-Bugzilla: 1000439
-Upstream-status: unknown
-
-From cb8e390d258b7f8073afafcbb163976e27346e9d Mon Sep 17 00:00:00 2001
-From: Josh Boyer <jwboyer@fedoraproject.org>
-Date: Fri, 11 Oct 2013 08:37:53 -0400
-Subject: [PATCH] cpupower: Fix segfault due to incorrect getopt_long arugments
-
-If a user calls 'cpupower set --perf-bias 15', the process will end with a
-SIGSEGV in libc because cpupower-set passes a NULL optarg to the atoi call.
-This is because the getopt_long structure currently has all of the options
-as having an optional_argument when they really have a required argument.
-We change the structure to use required_argument to match the short options
-and it resolves the issue.
-
-This fixes https://bugzilla.redhat.com/show_bug.cgi?id=1000439
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
----
- tools/power/cpupower/utils/cpupower-set.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c
-index dc4de37..bcf1d2f 100644
---- a/tools/power/cpupower/utils/cpupower-set.c
-+++ b/tools/power/cpupower/utils/cpupower-set.c
-@@ -18,9 +18,9 @@
- #include "helpers/bitmask.h"
-
- static struct option set_opts[] = {
-- { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'},
-- { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'},
-- { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'},
-+ { .name = "perf-bias", .has_arg = required_argument, .flag = NULL, .val = 'b'},
-+ { .name = "sched-mc", .has_arg = required_argument, .flag = NULL, .val = 'm'},
-+ { .name = "sched-smt", .has_arg = required_argument, .flag = NULL, .val = 's'},
- { },
- };
-
---
-1.8.3.1
-
diff --git a/dell-laptop.patch b/dell-laptop.patch
deleted file mode 100644
index 906d93519..000000000
--- a/dell-laptop.patch
+++ /dev/null
@@ -1,1017 +0,0 @@
-Bugzilla: 958826
-Upstream-status: 3.13
-
-From 4cc8a57425c623753b10b77b15392e5b83baa5a3 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:16 +0100
-Subject: [PATCH 01/12] Revert "dell-laptop: Remove rfkill code"
-
-Without rfkill functionality in dell-laptop I have the following problems:
--If the hardware radio switch is set to disable the radio, then userspace
- will still think it can use wireless and bluetooth.
--The wwan / 3g modem cannot be soft blocked without the dell-laptop rfkill
- functionality
-
-I know the rfkill functionality was removed from the dell-laptop driver because
-it caused more problems then it fixed, and the blacklist for it was growing out
-of control.
-
-But in the thread discussing this Dell mentioned that they only QA the rfkill
-acpi interface on Latitudes and indeed there have been no blacklist entries
-for Latitudes. Therefor I would like to bring the rfkill functionality back
-only for Latitudes. This patch is a straight-forward revert. The next patch
-in this set will drop the blacklist and replace it with a Latitude check.
-
-This reverts commit a6c2390cd6d2083d27a2359658e08f2d3df375ac.
-
-Conflicts:
- drivers/platform/x86/dell-laptop.c
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 289 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 289 insertions(+)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index bb77e18..55f75a2 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -21,6 +21,7 @@
- #include <linux/err.h>
- #include <linux/dmi.h>
- #include <linux/io.h>
-+#include <linux/rfkill.h>
- #include <linux/power_supply.h>
- #include <linux/acpi.h>
- #include <linux/mm.h>
-@@ -89,6 +90,9 @@ static struct platform_driver platform_driver = {
-
- static struct platform_device *platform_device;
- static struct backlight_device *dell_backlight_device;
-+static struct rfkill *wifi_rfkill;
-+static struct rfkill *bluetooth_rfkill;
-+static struct rfkill *wwan_rfkill;
-
- static const struct dmi_system_id dell_device_table[] __initconst = {
- {
-@@ -115,6 +119,53 @@ static const struct dmi_system_id dell_device_table[] __initconst = {
- };
- MODULE_DEVICE_TABLE(dmi, dell_device_table);
-
-+static struct dmi_system_id dell_blacklist[] = {
-+ /* Supported by compal-laptop */
-+ {
-+ .ident = "Dell Mini 9",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
-+ },
-+ },
-+ {
-+ .ident = "Dell Mini 10",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
-+ },
-+ },
-+ {
-+ .ident = "Dell Mini 10v",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
-+ },
-+ },
-+ {
-+ .ident = "Dell Mini 1012",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
-+ },
-+ },
-+ {
-+ .ident = "Dell Inspiron 11z",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
-+ },
-+ },
-+ {
-+ .ident = "Dell Mini 12",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
-+ },
-+ },
-+ {}
-+};
-+
- static struct dmi_system_id dell_quirks[] = {
- {
- .callback = dmi_matched,
-@@ -355,6 +406,94 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
- return buffer;
- }
-
-+/* Derived from information in DellWirelessCtl.cpp:
-+ Class 17, select 11 is radio control. It returns an array of 32-bit values.
-+
-+ Input byte 0 = 0: Wireless information
-+
-+ result[0]: return code
-+ result[1]:
-+ Bit 0: Hardware switch supported
-+ Bit 1: Wifi locator supported
-+ Bit 2: Wifi is supported
-+ Bit 3: Bluetooth is supported
-+ Bit 4: WWAN is supported
-+ Bit 5: Wireless keyboard supported
-+ Bits 6-7: Reserved
-+ Bit 8: Wifi is installed
-+ Bit 9: Bluetooth is installed
-+ Bit 10: WWAN is installed
-+ Bits 11-15: Reserved
-+ Bit 16: Hardware switch is on
-+ Bit 17: Wifi is blocked
-+ Bit 18: Bluetooth is blocked
-+ Bit 19: WWAN is blocked
-+ Bits 20-31: Reserved
-+ result[2]: NVRAM size in bytes
-+ result[3]: NVRAM format version number
-+
-+ Input byte 0 = 2: Wireless switch configuration
-+ result[0]: return code
-+ result[1]:
-+ Bit 0: Wifi controlled by switch
-+ Bit 1: Bluetooth controlled by switch
-+ Bit 2: WWAN controlled by switch
-+ Bits 3-6: Reserved
-+ Bit 7: Wireless switch config locked
-+ Bit 8: Wifi locator enabled
-+ Bits 9-14: Reserved
-+ Bit 15: Wifi locator setting locked
-+ Bits 16-31: Reserved
-+*/
-+
-+static int dell_rfkill_set(void *data, bool blocked)
-+{
-+ int disable = blocked ? 1 : 0;
-+ unsigned long radio = (unsigned long)data;
-+ int hwswitch_bit = (unsigned long)data - 1;
-+ int ret = 0;
-+
-+ get_buffer();
-+ dell_send_request(buffer, 17, 11);
-+
-+ /* If the hardware switch controls this radio, and the hardware
-+ switch is disabled, don't allow changing the software state */
-+ if ((hwswitch_state & BIT(hwswitch_bit)) &&
-+ !(buffer->output[1] & BIT(16))) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ buffer->input[0] = (1 | (radio<<8) | (disable << 16));
-+ dell_send_request(buffer, 17, 11);
-+
-+out:
-+ release_buffer();
-+ return ret;
-+}
-+
-+static void dell_rfkill_query(struct rfkill *rfkill, void *data)
-+{
-+ int status;
-+ int bit = (unsigned long)data + 16;
-+ int hwswitch_bit = (unsigned long)data - 1;
-+
-+ get_buffer();
-+ dell_send_request(buffer, 17, 11);
-+ status = buffer->output[1];
-+ release_buffer();
-+
-+ rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
-+
-+ if (hwswitch_state & (BIT(hwswitch_bit)))
-+ rfkill_set_hw_state(rfkill, !(status & BIT(16)));
-+}
-+
-+static const struct rfkill_ops dell_rfkill_ops = {
-+ .set_block = dell_rfkill_set,
-+ .query = dell_rfkill_query,
-+};
-+
- static struct dentry *dell_laptop_dir;
-
- static int dell_debugfs_show(struct seq_file *s, void *data)
-@@ -424,6 +563,108 @@ static const struct file_operations dell_debugfs_fops = {
- .release = single_release,
- };
-
-+static void dell_update_rfkill(struct work_struct *ignored)
-+{
-+ if (wifi_rfkill)
-+ dell_rfkill_query(wifi_rfkill, (void *)1);
-+ if (bluetooth_rfkill)
-+ dell_rfkill_query(bluetooth_rfkill, (void *)2);
-+ if (wwan_rfkill)
-+ dell_rfkill_query(wwan_rfkill, (void *)3);
-+}
-+static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
-+
-+
-+static int __init dell_setup_rfkill(void)
-+{
-+ int status;
-+ int ret;
-+
-+ if (dmi_check_system(dell_blacklist)) {
-+ pr_info("Blacklisted hardware detected - not enabling rfkill\n");
-+ return 0;
-+ }
-+
-+ get_buffer();
-+ dell_send_request(buffer, 17, 11);
-+ status = buffer->output[1];
-+ buffer->input[0] = 0x2;
-+ dell_send_request(buffer, 17, 11);
-+ hwswitch_state = buffer->output[1];
-+ release_buffer();
-+
-+ if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
-+ wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
-+ RFKILL_TYPE_WLAN,
-+ &dell_rfkill_ops, (void *) 1);
-+ if (!wifi_rfkill) {
-+ ret = -ENOMEM;
-+ goto err_wifi;
-+ }
-+ ret = rfkill_register(wifi_rfkill);
-+ if (ret)
-+ goto err_wifi;
-+ }
-+
-+ if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
-+ bluetooth_rfkill = rfkill_alloc("dell-bluetooth",
-+ &platform_device->dev,
-+ RFKILL_TYPE_BLUETOOTH,
-+ &dell_rfkill_ops, (void *) 2);
-+ if (!bluetooth_rfkill) {
-+ ret = -ENOMEM;
-+ goto err_bluetooth;
-+ }
-+ ret = rfkill_register(bluetooth_rfkill);
-+ if (ret)
-+ goto err_bluetooth;
-+ }
-+
-+ if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
-+ wwan_rfkill = rfkill_alloc("dell-wwan",
-+ &platform_device->dev,
-+ RFKILL_TYPE_WWAN,
-+ &dell_rfkill_ops, (void *) 3);
-+ if (!wwan_rfkill) {
-+ ret = -ENOMEM;
-+ goto err_wwan;
-+ }
-+ ret = rfkill_register(wwan_rfkill);
-+ if (ret)
-+ goto err_wwan;
-+ }
-+
-+ return 0;
-+err_wwan:
-+ rfkill_destroy(wwan_rfkill);
-+ if (bluetooth_rfkill)
-+ rfkill_unregister(bluetooth_rfkill);
-+err_bluetooth:
-+ rfkill_destroy(bluetooth_rfkill);
-+ if (wifi_rfkill)
-+ rfkill_unregister(wifi_rfkill);
-+err_wifi:
-+ rfkill_destroy(wifi_rfkill);
-+
-+ return ret;
-+}
-+
-+static void dell_cleanup_rfkill(void)
-+{
-+ if (wifi_rfkill) {
-+ rfkill_unregister(wifi_rfkill);
-+ rfkill_destroy(wifi_rfkill);
-+ }
-+ if (bluetooth_rfkill) {
-+ rfkill_unregister(bluetooth_rfkill);
-+ rfkill_destroy(bluetooth_rfkill);
-+ }
-+ if (wwan_rfkill) {
-+ rfkill_unregister(wwan_rfkill);
-+ rfkill_destroy(wwan_rfkill);
-+ }
-+}
-+
- static int dell_send_intensity(struct backlight_device *bd)
- {
- int ret = 0;
-@@ -515,6 +756,30 @@ static void touchpad_led_exit(void)
- led_classdev_unregister(&touchpad_led);
- }
-
-+static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
-+ struct serio *port)
-+{
-+ static bool extended;
-+
-+ if (str & 0x20)
-+ return false;
-+
-+ if (unlikely(data == 0xe0)) {
-+ extended = true;
-+ return false;
-+ } else if (unlikely(extended)) {
-+ switch (data) {
-+ case 0x8:
-+ schedule_delayed_work(&dell_rfkill_work,
-+ round_jiffies_relative(HZ));
-+ break;
-+ }
-+ extended = false;
-+ }
-+
-+ return false;
-+}
-+
- static int __init dell_init(void)
- {
- int max_intensity = 0;
-@@ -557,10 +822,26 @@ static int __init dell_init(void)
- }
- buffer = page_address(bufferpage);
-
-+ ret = dell_setup_rfkill();
-+
-+ if (ret) {
-+ pr_warn("Unable to setup rfkill\n");
-+ goto fail_rfkill;
-+ }
-+
-+ ret = i8042_install_filter(dell_laptop_i8042_filter);
-+ if (ret) {
-+ pr_warn("Unable to install key filter\n");
-+ goto fail_filter;
-+ }
-+
- if (quirks && quirks->touchpad_led)
- touchpad_led_init(&platform_device->dev);
-
- dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
-+ if (dell_laptop_dir != NULL)
-+ debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
-+ &dell_debugfs_fops);
-
- #ifdef CONFIG_ACPI
- /* In the event of an ACPI backlight being available, don't
-@@ -603,6 +884,11 @@ static int __init dell_init(void)
- return 0;
-
- fail_backlight:
-+ i8042_remove_filter(dell_laptop_i8042_filter);
-+ cancel_delayed_work_sync(&dell_rfkill_work);
-+fail_filter:
-+ dell_cleanup_rfkill();
-+fail_rfkill:
- free_page((unsigned long)bufferpage);
- fail_buffer:
- platform_device_del(platform_device);
-@@ -620,7 +906,10 @@ static void __exit dell_exit(void)
- debugfs_remove_recursive(dell_laptop_dir);
- if (quirks && quirks->touchpad_led)
- touchpad_led_exit();
-+ i8042_remove_filter(dell_laptop_i8042_filter);
-+ cancel_delayed_work_sync(&dell_rfkill_work);
- backlight_device_unregister(dell_backlight_device);
-+ dell_cleanup_rfkill();
- if (platform_device) {
- platform_device_unregister(platform_device);
- platform_driver_unregister(&platform_driver);
---
-1.8.3.1
-
-
-From 2a92551845bbbc8421ba908cd14bbdf065e0f454 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:17 +0100
-Subject: [PATCH 02/12] dell-laptop: Only enable rfkill on Latitudes
-
-The rfkill functionality was removed from the dell-laptop driver because it
-was causing problems on various non Latitude models, and the blacklist kept
-growing and growing. In the thread discussing this Dell mentioned that they
-only QA the rfkill acpi interface on Latitudes and indeed there have been
-no blacklist entries for Latitudes.
-
-Note that the blacklist contained no Vostros either, and most Vostros have
-a hardware switch too, so we could consider supporting Vostros with a
-hardware switch too.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 57 +++++---------------------------------
- 1 file changed, 7 insertions(+), 50 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 55f75a2..bae932b 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -119,53 +119,6 @@ static const struct dmi_system_id dell_device_table[] __initconst = {
- };
- MODULE_DEVICE_TABLE(dmi, dell_device_table);
-
--static struct dmi_system_id dell_blacklist[] = {
-- /* Supported by compal-laptop */
-- {
-- .ident = "Dell Mini 9",
-- .matches = {
-- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 910"),
-- },
-- },
-- {
-- .ident = "Dell Mini 10",
-- .matches = {
-- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1010"),
-- },
-- },
-- {
-- .ident = "Dell Mini 10v",
-- .matches = {
-- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1011"),
-- },
-- },
-- {
-- .ident = "Dell Mini 1012",
-- .matches = {
-- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
-- },
-- },
-- {
-- .ident = "Dell Inspiron 11z",
-- .matches = {
-- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1110"),
-- },
-- },
-- {
-- .ident = "Dell Mini 12",
-- .matches = {
-- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-- DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1210"),
-- },
-- },
-- {}
--};
--
- static struct dmi_system_id dell_quirks[] = {
- {
- .callback = dmi_matched,
-@@ -579,11 +532,15 @@ static int __init dell_setup_rfkill(void)
- {
- int status;
- int ret;
-+ const char *product;
-
-- if (dmi_check_system(dell_blacklist)) {
-- pr_info("Blacklisted hardware detected - not enabling rfkill\n");
-+ /*
-+ * rfkill causes trouble on various non Latitudes, according to Dell
-+ * actually testing the rfkill functionality is only done on Latitudes.
-+ */
-+ product = dmi_get_system_info(DMI_PRODUCT_NAME);
-+ if (!product || strncmp(product, "Latitude", 8))
- return 0;
-- }
-
- get_buffer();
- dell_send_request(buffer, 17, 11);
---
-1.8.3.1
-
-
-From ddde708217af6d5fe43c0086247c05ed317076b4 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:18 +0100
-Subject: [PATCH 03/12] dell-laptop: If there is no hwswitch, then clear all
- hw-controlled bits
-
-To ensure we don't enter any hw-switch related code paths on machines without
-a hw-switch.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index bae932b..48fabf6 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -548,6 +548,9 @@ static int __init dell_setup_rfkill(void)
- buffer->input[0] = 0x2;
- dell_send_request(buffer, 17, 11);
- hwswitch_state = buffer->output[1];
-+ /* If there is no hwswitch, then clear all hw-controlled bits */
-+ if (!(status & BIT(0)))
-+ hwswitch_state &= ~7;
- release_buffer();
-
- if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
---
-1.8.3.1
-
-
-From d038880efd9dd222c67fd31fbfca3440d0db3a06 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:19 +0100
-Subject: [PATCH 04/12] dell-laptop: Only get status from BIOS once when
- updating
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 28 +++++++++++++++++++---------
- 1 file changed, 19 insertions(+), 9 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 48fabf6..06f281b 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -425,21 +425,24 @@ out:
- return ret;
- }
-
-+static void dell_rfkill_update(struct rfkill *rfkill, int radio, int status)
-+{
-+ rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
-+
-+ if (hwswitch_state & (BIT(radio - 1)))
-+ rfkill_set_hw_state(rfkill, !(status & BIT(16)));
-+}
-+
- static void dell_rfkill_query(struct rfkill *rfkill, void *data)
- {
- int status;
-- int bit = (unsigned long)data + 16;
-- int hwswitch_bit = (unsigned long)data - 1;
-
- get_buffer();
- dell_send_request(buffer, 17, 11);
- status = buffer->output[1];
- release_buffer();
-
-- rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
--
-- if (hwswitch_state & (BIT(hwswitch_bit)))
-- rfkill_set_hw_state(rfkill, !(status & BIT(16)));
-+ dell_rfkill_update(rfkill, (unsigned long)data, status);
- }
-
- static const struct rfkill_ops dell_rfkill_ops = {
-@@ -518,12 +521,19 @@ static const struct file_operations dell_debugfs_fops = {
-
- static void dell_update_rfkill(struct work_struct *ignored)
- {
-+ int status;
-+
-+ get_buffer();
-+ dell_send_request(buffer, 17, 11);
-+ status = buffer->output[1];
-+ release_buffer();
-+
- if (wifi_rfkill)
-- dell_rfkill_query(wifi_rfkill, (void *)1);
-+ dell_rfkill_update(wifi_rfkill, 1, status);
- if (bluetooth_rfkill)
-- dell_rfkill_query(bluetooth_rfkill, (void *)2);
-+ dell_rfkill_update(bluetooth_rfkill, 2, status);
- if (wwan_rfkill)
-- dell_rfkill_query(wwan_rfkill, (void *)3);
-+ dell_rfkill_update(wwan_rfkill, 3, status);
- }
- static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
-
---
-1.8.3.1
-
-
-From 33f9359abb9f6ded3e7b6dc98b1468c83404af49 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:20 +0100
-Subject: [PATCH 05/12] dell-laptop: Don't set sw_state from the query callback
-
-The query callback should only update the hw_state, see the comment in
-net/rfkill/core.c in rfkill_set_block, which is its only caller.
-
-rfkill_set_block will modify the sw_state directly after calling query so
-calling set_sw_state is an expensive NOP.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 27 +++++++++++++++++++--------
- 1 file changed, 19 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 06f281b..7f47396 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -425,10 +425,15 @@ out:
- return ret;
- }
-
--static void dell_rfkill_update(struct rfkill *rfkill, int radio, int status)
-+static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
-+ int status)
- {
- rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
-+}
-
-+static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
-+ int status)
-+{
- if (hwswitch_state & (BIT(radio - 1)))
- rfkill_set_hw_state(rfkill, !(status & BIT(16)));
- }
-@@ -442,7 +447,7 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data)
- status = buffer->output[1];
- release_buffer();
-
-- dell_rfkill_update(rfkill, (unsigned long)data, status);
-+ dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status);
- }
-
- static const struct rfkill_ops dell_rfkill_ops = {
-@@ -528,12 +533,18 @@ static void dell_update_rfkill(struct work_struct *ignored)
- status = buffer->output[1];
- release_buffer();
-
-- if (wifi_rfkill)
-- dell_rfkill_update(wifi_rfkill, 1, status);
-- if (bluetooth_rfkill)
-- dell_rfkill_update(bluetooth_rfkill, 2, status);
-- if (wwan_rfkill)
-- dell_rfkill_update(wwan_rfkill, 3, status);
-+ if (wifi_rfkill) {
-+ dell_rfkill_update_hw_state(wifi_rfkill, 1, status);
-+ dell_rfkill_update_sw_state(wifi_rfkill, 1, status);
-+ }
-+ if (bluetooth_rfkill) {
-+ dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status);
-+ dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status);
-+ }
-+ if (wwan_rfkill) {
-+ dell_rfkill_update_hw_state(wwan_rfkill, 3, status);
-+ dell_rfkill_update_sw_state(wwan_rfkill, 3, status);
-+ }
- }
- static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
-
---
-1.8.3.1
-
-
-From 3f56588a79a06a0499db0077cad6675762ddc40e Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:21 +0100
-Subject: [PATCH 06/12] dell-laptop: Don't read-back sw_state on machines with
- a hardware switch
-
-On machines with a hardware switch, the blocking settings can not be changed
-through a Fn + wireless-key combo, so there is no reason to read back the
-blocking state from the BIOS.
-
-Reading back is not only not necessary it is actually harmful, since on some
-machines the blocking state will be cleared to all 0 after a wireless switch
-toggle, even for radios not controlled by the hw-switch (yeah firmware bugs).
-
-This causes "magic" changes to the sw_state. This is inconsistent with other
-rfkill drivers which preserve the sw_state over a hw kill on / off.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 7f47396..80de0cc 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -428,7 +428,10 @@ out:
- static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
- int status)
- {
-- rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
-+ if (!(status & BIT(0))) {
-+ /* No hw-switch, sync BIOS state to sw_state */
-+ rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
-+ }
- }
-
- static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
---
-1.8.3.1
-
-
-From 4d39d88ceb83e88953a76df8b1fa10f43f328038 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:22 +0100
-Subject: [PATCH 07/12] dell-laptop: Allow changing the sw_state while the
- radio is blocked by hw
-
-This makes dell-laptop's rfkill code consistent with other drivers which
-allow sw_state changes while hw blocked.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 80de0cc..834f499 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -404,7 +404,6 @@ static int dell_rfkill_set(void *data, bool blocked)
- int disable = blocked ? 1 : 0;
- unsigned long radio = (unsigned long)data;
- int hwswitch_bit = (unsigned long)data - 1;
-- int ret = 0;
-
- get_buffer();
- dell_send_request(buffer, 17, 11);
-@@ -412,17 +411,15 @@ static int dell_rfkill_set(void *data, bool blocked)
- /* If the hardware switch controls this radio, and the hardware
- switch is disabled, don't allow changing the software state */
- if ((hwswitch_state & BIT(hwswitch_bit)) &&
-- !(buffer->output[1] & BIT(16))) {
-- ret = -EINVAL;
-+ !(buffer->output[1] & BIT(16)))
- goto out;
-- }
-
- buffer->input[0] = (1 | (radio<<8) | (disable << 16));
- dell_send_request(buffer, 17, 11);
-
- out:
- release_buffer();
-- return ret;
-+ return 0;
- }
-
- static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
---
-1.8.3.1
-
-
-From 04c9a3a06c47b337b90a91e458716262cc45b103 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:23 +0100
-Subject: [PATCH 08/12] dell-laptop: Sync current block state to BIOS on hw
- switch change
-
-This is necessary for 3 reasons:
-1) To apply sw_state changes made while hw-blocked
-2) To set all the blocked bits for hw-switch controlled radios to 1 when the
- switch gets changed to off, this is necessary on some models to actually
- turn the radio status LEDs off.
-3) On some models non hw-switch controlled radios will have their block bit
- cleared (potentially undoing a soft-block) on hw-switch toggle, this
- restores the sw-block in this case.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 14 +++++++++++---
- 1 file changed, 11 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 834f499..7f59624 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -422,10 +422,16 @@ out:
- return 0;
- }
-
-+/* Must be called with the buffer held */
- static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
- int status)
- {
-- if (!(status & BIT(0))) {
-+ if (status & BIT(0)) {
-+ /* Has hw-switch, sync sw_state to BIOS */
-+ int block = rfkill_blocked(rfkill);
-+ buffer->input[0] = (1 | (radio << 8) | (block << 16));
-+ dell_send_request(buffer, 17, 11);
-+ } else {
- /* No hw-switch, sync BIOS state to sw_state */
- rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
- }
-@@ -445,9 +451,10 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data)
- get_buffer();
- dell_send_request(buffer, 17, 11);
- status = buffer->output[1];
-- release_buffer();
-
- dell_rfkill_update_hw_state(rfkill, (unsigned long)data, status);
-+
-+ release_buffer();
- }
-
- static const struct rfkill_ops dell_rfkill_ops = {
-@@ -531,7 +538,6 @@ static void dell_update_rfkill(struct work_struct *ignored)
- get_buffer();
- dell_send_request(buffer, 17, 11);
- status = buffer->output[1];
-- release_buffer();
-
- if (wifi_rfkill) {
- dell_rfkill_update_hw_state(wifi_rfkill, 1, status);
-@@ -545,6 +551,8 @@ static void dell_update_rfkill(struct work_struct *ignored)
- dell_rfkill_update_hw_state(wwan_rfkill, 3, status);
- dell_rfkill_update_sw_state(wwan_rfkill, 3, status);
- }
-+
-+ release_buffer();
- }
- static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
-
---
-1.8.3.1
-
-
-From ed1128989ab242f44664b446702a512e5695c4b7 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:24 +0100
-Subject: [PATCH 09/12] dell-laptop: Do not skip setting blocked bit rfkill_set
- while hw-blocked
-
-Instead when hw-blocked always write 1 to the blocked bit for the radio in
-question. This is necessary to properly set all the blocked bits for hw-switch
-controlled radios to 1 after power-on and resume.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index 7f59624..b33b779 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -409,15 +409,14 @@ static int dell_rfkill_set(void *data, bool blocked)
- dell_send_request(buffer, 17, 11);
-
- /* If the hardware switch controls this radio, and the hardware
-- switch is disabled, don't allow changing the software state */
-+ switch is disabled, always disable the radio */
- if ((hwswitch_state & BIT(hwswitch_bit)) &&
- !(buffer->output[1] & BIT(16)))
-- goto out;
-+ disable = 1;
-
- buffer->input[0] = (1 | (radio<<8) | (disable << 16));
- dell_send_request(buffer, 17, 11);
-
--out:
- release_buffer();
- return 0;
- }
---
-1.8.3.1
-
-
-From 26c22d63a70f62e0832c6d9f2a2690ab0155d584 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:25 +0100
-Subject: [PATCH 10/12] dell-laptop: Wait less long before updating rfkill
- after an rfkill keypress
-
-Some time is needed for the BIOS to do its work, but 250ms should be plenty.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index b33b779..fe20f67 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -759,7 +759,7 @@ static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
- switch (data) {
- case 0x8:
- schedule_delayed_work(&dell_rfkill_work,
-- round_jiffies_relative(HZ));
-+ round_jiffies_relative(HZ / 4));
- break;
- }
- extended = false;
---
-1.8.3.1
-
-
-From 8e0e668d0aa09d2eb0a7a260b6c7801796e01bd3 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:26 +0100
-Subject: [PATCH 11/12] dell-laptop: Add a force_rfkill module parameter
-
-Setting force_rfkill will cause the dell-laptop rfkill code to skip its
-whitelist checks, this will allow individual users to override the whitelist,
-as well as to gather info from users to improve the checks.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index fe20f67..bd67c89 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -93,6 +93,10 @@ static struct backlight_device *dell_backlight_device;
- static struct rfkill *wifi_rfkill;
- static struct rfkill *bluetooth_rfkill;
- static struct rfkill *wwan_rfkill;
-+static bool force_rfkill;
-+
-+module_param(force_rfkill, bool, 0444);
-+MODULE_PARM_DESC(force_rfkill, "enable rfkill on non whitelisted models");
-
- static const struct dmi_system_id dell_device_table[] __initconst = {
- {
-@@ -567,7 +571,7 @@ static int __init dell_setup_rfkill(void)
- * actually testing the rfkill functionality is only done on Latitudes.
- */
- product = dmi_get_system_info(DMI_PRODUCT_NAME);
-- if (!product || strncmp(product, "Latitude", 8))
-+ if (!force_rfkill && (!product || strncmp(product, "Latitude", 8)))
- return 0;
-
- get_buffer();
---
-1.8.3.1
-
-
-From 2bd4ac139259bb605fc0325a7dda33e2fbb67ae3 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Sun, 17 Nov 2013 14:00:27 +0100
-Subject: [PATCH 12/12] dell-laptop: Only enable rfkill functionality on
- laptops with a hw killswitch
-
-All my testing has been on laptops with a hw killswitch, so to be on the
-safe side disable rfkill functionality on models without a hw killswitch for
-now. Once we gather some feedback on laptops without a hw killswitch this
-decision maybe reconsidered.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
----
- drivers/platform/x86/dell-laptop.c | 13 ++++++++++---
- 1 file changed, 10 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
-index bd67c89..c608b1d 100644
---- a/drivers/platform/x86/dell-laptop.c
-+++ b/drivers/platform/x86/dell-laptop.c
-@@ -580,11 +580,18 @@ static int __init dell_setup_rfkill(void)
- buffer->input[0] = 0x2;
- dell_send_request(buffer, 17, 11);
- hwswitch_state = buffer->output[1];
-- /* If there is no hwswitch, then clear all hw-controlled bits */
-- if (!(status & BIT(0)))
-- hwswitch_state &= ~7;
- release_buffer();
-
-+ if (!(status & BIT(0))) {
-+ if (force_rfkill) {
-+ /* No hwsitch, clear all hw-controlled bits */
-+ hwswitch_state &= ~7;
-+ } else {
-+ /* rfkill is only tested on laptops with a hwswitch */
-+ return 0;
-+ }
-+ }
-+
- if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
- wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
- RFKILL_TYPE_WLAN,
---
-1.8.3.1
-
diff --git a/dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch b/dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch
deleted file mode 100644
index 494f4af04..000000000
--- a/dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-Bugzilla: 993744
-Upstream-status: Still pending upstream
-
-diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c
-index cab6dd2..ec79c8f 100644
---- a/drivers/md/dm-cache-policy-mq.c
-+++ b/drivers/md/dm-cache-policy-mq.c
-@@ -868,7 +868,7 @@ static void mq_destroy(struct dm_cache_policy *p)
- struct mq_policy *mq = to_mq_policy(p);
-
- free_bitset(mq->allocation_bitset);
-- kfree(mq->table);
-+ vfree(mq->table);
- free_entries(mq);
- kfree(mq);
- }
-@@ -1189,7 +1189,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
-
- mq->nr_buckets = next_power(from_cblock(cache_size) / 2, 16);
- mq->hash_bits = ffs(mq->nr_buckets) - 1;
-- mq->table = kzalloc(sizeof(*mq->table) * mq->nr_buckets, GFP_KERNEL);
-+ mq->table = vzalloc(sizeof(*mq->table) * mq->nr_buckets);
- if (!mq->table)
- goto bad_alloc_table;
-
-@@ -1200,7 +1200,7 @@ static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
- return &mq->policy;
-
- bad_alloc_bitset:
-- kfree(mq->table);
-+ vfree(mq->table);
- bad_alloc_table:
- free_entries(mq);
- bad_cache_alloc:
diff --git a/drm-i915-dp-stfu.patch b/drm-i915-dp-stfu.patch
deleted file mode 100644
index fb2e58ee9..000000000
--- a/drm-i915-dp-stfu.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
-index fb2fbc1..0aaf67d 100644
---- a/drivers/gpu/drm/i915/intel_dp.c
-+++ b/drivers/gpu/drm/i915/intel_dp.c
-@@ -283,7 +283,7 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
-
- if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
-- WARN(1, "eDP powered off while attempting aux channel communication.\n");
-+ DRM_ERROR("eDP powered off while attempting aux channel communication.\n");
- DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
- I915_READ(pp_stat_reg),
- I915_READ(pp_ctrl_reg));
-@@ -376,7 +376,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
- }
-
- if (try == 3) {
-- WARN(1, "dp_aux_ch not started status 0x%08x\n",
-+ DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
- I915_READ(ch_ctl));
- ret = -EBUSY;
- goto out;
-@@ -995,8 +995,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
- return;
- DRM_DEBUG_KMS("Turn eDP VDD on\n");
-
-- WARN(intel_dp->want_panel_vdd,
-- "eDP VDD already requested on\n");
-+ if (intel_dp->want_panel_vdd)
-+ DRM_ERROR("eDP VDD already requested on\n");
-
- intel_dp->want_panel_vdd = true;
-
-@@ -1070,7 +1070,8 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
- return;
-
- DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
-- WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
-+ if (!intel_dp->want_panel_vdd)
-+ DRM_ERROR("eDP VDD not forced on");
-
- intel_dp->want_panel_vdd = false;
-
-@@ -1144,7 +1145,8 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
-
- DRM_DEBUG_KMS("Turn eDP power off\n");
-
-- WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
-+ if (!intel_dp->want_panel_vdd)
-+ DRM_ERROR("Need VDD to turn off panel\n");
-
- pp = ironlake_get_pp_control(intel_dp);
- /* We need to switch off panel power _and_ force vdd, for otherwise some
diff --git a/drm-i915-hush-check-crtc-state.patch b/drm-i915-hush-check-crtc-state.patch
new file mode 100644
index 000000000..295cad7b7
--- /dev/null
+++ b/drm-i915-hush-check-crtc-state.patch
@@ -0,0 +1,20 @@
+Bugzilla: 1027037 1028785
+Upstream-status: http://lists.freedesktop.org/archives/intel-gfx/2013-November/035948.html
+
+This is _by far_ the most common backtrace for i915 on retrace.fp.o, and
+it's mostly useless noise. There's not enough context when it's generated
+to know if something actually went wrong. Downgrade the message to
+KMS debugging so we can still get it if we want it.
+
+diff -up linux-3.13.0-0.rc0.git2.1.fc21.x86_64/drivers/gpu/drm/i915/intel_display.c.jx linux-3.13.0-0.rc0.git2.1.fc21.x86_64/drivers/gpu/drm/i915/intel_display.c
+--- linux-3.13.0-0.rc0.git2.1.fc21.x86_64/drivers/gpu/drm/i915/intel_display.c.jx 2013-11-03 18:41:51.000000000 -0500
++++ linux-3.13.0-0.rc0.git2.1.fc21.x86_64/drivers/gpu/drm/i915/intel_display.c 2013-11-13 10:12:05.781301624 -0500
+@@ -8803,7 +8803,7 @@ check_crtc_state(struct drm_device *dev)
+
+ if (active &&
+ !intel_pipe_config_compare(dev, &crtc->config, &pipe_config)) {
+- WARN(1, "pipe state doesn't match!\n");
++ DRM_DEBUG_KMS("pipe state doesn't match!\n");
+ intel_dump_pipe_config(crtc, &pipe_config,
+ "[hw state]");
+ intel_dump_pipe_config(crtc, &crtc->config,
diff --git a/drm-qxl-backport-fixes-for-Fedora.patch b/drm-qxl-backport-fixes-for-Fedora.patch
deleted file mode 100644
index 04848b529..000000000
--- a/drm-qxl-backport-fixes-for-Fedora.patch
+++ /dev/null
@@ -1,213 +0,0 @@
-Bugzilla: N/A
-Upstream-status: Queued for 3.13
-
-From db8edc33193879f39c1b52521e20f4d6eb4e9858 Mon Sep 17 00:00:00 2001
-From: Dave Airlie <airlied@redhat.com>
-Date: Fri, 08 Nov 2013 06:36:45 +0000
-Subject: drm/qxl: backport fixes for Fedora
-
-This pulls these changes from drm-next back into Fedora.
-
-drm/qxl: prefer the monitor config resolution (b080742393e2c1)
-drm/qxl: remove unnecessary check (a40a60d912a101e8dfb08ee1)
-drm/qxl: fix disabling extra monitors from client (5cab51cb3381157)
-qxl: avoid an oops in the deferred io code. (cc87509d87696d7cd39)
-drm/qxl: support 64bit surface bar (35541782dcc1e502)
-qxl: add a connector property to denote hotplug should rescan modes. (4695b03970df37)
-
-Signed-off-by: Dave Airlie <airlied@redhat.com>
----
-diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
-index 835caba..1d975eb 100644
---- a/drivers/gpu/drm/qxl/qxl_display.c
-+++ b/drivers/gpu/drm/qxl/qxl_display.c
-@@ -110,7 +110,9 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
- drm_helper_hpd_irq_event(qdev->ddev);
- }
-
--static int qxl_add_monitors_config_modes(struct drm_connector *connector)
-+static int qxl_add_monitors_config_modes(struct drm_connector *connector,
-+ unsigned *pwidth,
-+ unsigned *pheight)
- {
- struct drm_device *dev = connector->dev;
- struct qxl_device *qdev = dev->dev_private;
-@@ -126,11 +128,15 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector)
- mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
- false);
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-+ *pwidth = head->width;
-+ *pheight = head->height;
- drm_mode_probed_add(connector, mode);
- return 1;
- }
-
--static int qxl_add_common_modes(struct drm_connector *connector)
-+static int qxl_add_common_modes(struct drm_connector *connector,
-+ unsigned pwidth,
-+ unsigned pheight)
- {
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *mode = NULL;
-@@ -159,12 +165,9 @@ static int qxl_add_common_modes(struct drm_connector *connector)
- };
-
- for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
-- if (common_modes[i].w < 320 || common_modes[i].h < 200)
-- continue;
--
- mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
- 60, false, false, false);
-- if (common_modes[i].w == 1024 && common_modes[i].h == 768)
-+ if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
- mode->type |= DRM_MODE_TYPE_PREFERRED;
- drm_mode_probed_add(connector, mode);
- }
-@@ -720,16 +723,18 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
- {
- int ret = 0;
- struct qxl_device *qdev = connector->dev->dev_private;
-+ unsigned pwidth = 1024;
-+ unsigned pheight = 768;
-
- DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config);
- /* TODO: what should we do here? only show the configured modes for the
- * device, or allow the full list, or both? */
- if (qdev->monitors_config && qdev->monitors_config->count) {
-- ret = qxl_add_monitors_config_modes(connector);
-+ ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
- if (ret < 0)
- return ret;
- }
-- ret += qxl_add_common_modes(connector);
-+ ret += qxl_add_common_modes(connector, pwidth, pheight);
- return ret;
- }
-
-@@ -793,7 +798,10 @@ static enum drm_connector_status qxl_conn_detect(
- qdev->client_monitors_config->count > output->index &&
- qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]));
-
-- DRM_DEBUG("\n");
-+ DRM_DEBUG("#%d connected: %d\n", output->index, connected);
-+ if (!connected)
-+ qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0);
-+
- return connected ? connector_status_connected
- : connector_status_disconnected;
- }
-@@ -835,8 +843,21 @@ static const struct drm_encoder_funcs qxl_enc_funcs = {
- .destroy = qxl_enc_destroy,
- };
-
-+static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
-+{
-+ if (qdev->hotplug_mode_update_property)
-+ return 0;
-+
-+ qdev->hotplug_mode_update_property =
-+ drm_property_create_range(qdev->ddev, DRM_MODE_PROP_IMMUTABLE,
-+ "hotplug_mode_update", 0, 1);
-+
-+ return 0;
-+}
-+
- static int qdev_output_init(struct drm_device *dev, int num_output)
- {
-+ struct qxl_device *qdev = dev->dev_private;
- struct qxl_output *qxl_output;
- struct drm_connector *connector;
- struct drm_encoder *encoder;
-@@ -863,6 +884,8 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
- drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
- drm_connector_helper_add(connector, &qxl_connector_helper_funcs);
-
-+ drm_object_attach_property(&connector->base,
-+ qdev->hotplug_mode_update_property, 0);
- drm_sysfs_connector_add(connector);
- return 0;
- }
-@@ -975,6 +998,9 @@ int qxl_modeset_init(struct qxl_device *qdev)
- qdev->ddev->mode_config.max_height = 8192;
-
- qdev->ddev->mode_config.fb_base = qdev->vram_base;
-+
-+ qxl_mode_create_hotplug_mode_update_property(qdev);
-+
- for (i = 0 ; i < qxl_num_crtc; ++i) {
- qdev_crtc_init(qdev->ddev, i);
- qdev_output_init(qdev->ddev, i);
-diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
-index 7e96f4f..18c599d 100644
---- a/drivers/gpu/drm/qxl/qxl_drv.h
-+++ b/drivers/gpu/drm/qxl/qxl_drv.h
-@@ -323,6 +323,8 @@ struct qxl_device {
- struct work_struct gc_work;
-
- struct work_struct fb_work;
-+
-+ struct drm_property *hotplug_mode_update_property;
- };
-
- /* forward declaration for QXL_INFO_IO */
-diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
-index 9e8da9e..e0ddd5b 100644
---- a/drivers/gpu/drm/qxl/qxl_kms.c
-+++ b/drivers/gpu/drm/qxl/qxl_kms.c
-@@ -120,7 +120,7 @@ int qxl_device_init(struct qxl_device *qdev,
- struct pci_dev *pdev,
- unsigned long flags)
- {
-- int r;
-+ int r, sb;
-
- qdev->dev = &pdev->dev;
- qdev->ddev = ddev;
-@@ -136,21 +136,39 @@ int qxl_device_init(struct qxl_device *qdev,
- qdev->rom_base = pci_resource_start(pdev, 2);
- qdev->rom_size = pci_resource_len(pdev, 2);
- qdev->vram_base = pci_resource_start(pdev, 0);
-- qdev->surfaceram_base = pci_resource_start(pdev, 1);
-- qdev->surfaceram_size = pci_resource_len(pdev, 1);
- qdev->io_base = pci_resource_start(pdev, 3);
-
- qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
-- qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size);
-- DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk)\n",
-+
-+ if (pci_resource_len(pdev, 4) > 0) {
-+ /* 64bit surface bar present */
-+ sb = 4;
-+ qdev->surfaceram_base = pci_resource_start(pdev, sb);
-+ qdev->surfaceram_size = pci_resource_len(pdev, sb);
-+ qdev->surface_mapping =
-+ io_mapping_create_wc(qdev->surfaceram_base,
-+ qdev->surfaceram_size);
-+ }
-+ if (qdev->surface_mapping == NULL) {
-+ /* 64bit surface bar not present (or mapping failed) */
-+ sb = 1;
-+ qdev->surfaceram_base = pci_resource_start(pdev, sb);
-+ qdev->surfaceram_size = pci_resource_len(pdev, sb);
-+ qdev->surface_mapping =
-+ io_mapping_create_wc(qdev->surfaceram_base,
-+ qdev->surfaceram_size);
-+ }
-+
-+ DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n",
- (unsigned long long)qdev->vram_base,
- (unsigned long long)pci_resource_end(pdev, 0),
- (int)pci_resource_len(pdev, 0) / 1024 / 1024,
- (int)pci_resource_len(pdev, 0) / 1024,
- (unsigned long long)qdev->surfaceram_base,
-- (unsigned long long)pci_resource_end(pdev, 1),
-+ (unsigned long long)pci_resource_end(pdev, sb),
- (int)qdev->surfaceram_size / 1024 / 1024,
-- (int)qdev->surfaceram_size / 1024);
-+ (int)qdev->surfaceram_size / 1024,
-+ (sb == 4) ? "64bit" : "32bit");
-
- qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);
- if (!qdev->rom) {
---
-cgit v0.9.0.2-2-gbebe
diff --git a/elantech-Properly-differentiate-between-clickpads-an.patch b/elantech-Properly-differentiate-between-clickpads-an.patch
deleted file mode 100644
index 3fc49980b..000000000
--- a/elantech-Properly-differentiate-between-clickpads-an.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-Bugzilla: 1030802
-Upstream-status: http://www.mail-archive.com/linux-input@vger.kernel.org/msg07220.html
-
-From e1c7fa5fbb6688bd464658ff8a93bdf23c442065 Mon Sep 17 00:00:00 2001
-From: Hans de Goede <hdegoede@redhat.com>
-Date: Mon, 9 Dec 2013 15:18:04 +0100
-Subject: [PATCH v2] elantech: Properly differentiate between clickpads and
- normal touchpads
-
-The current assumption in the elantech driver that hw version 3 touchpads are
-never clickpads and hw version 4 touchpads are always clickpads is wrong.
-
-There are several bug reports for this, ie:
-https://bugzilla.redhat.com/show_bug.cgi?id=1030802
-http://superuser.com/questions/619582/right-elantech-touchpad-button-not-working-in-linux
-
-I've spend a couple of hours wading through various bugzillas,
-launchpads and forum posts to create a list of fw-versions and capabilities
-for different laptop models to find a good method to differentiate between
-clickpads and versions with separate hardware buttons.
-
-Which shows that a device being a clickpad is reliable indicated by bit 12
-being set in the fw_version. I've included the gathered list inside the driver,
-so that we've this info at hand if we need to revisit this later.
-
-Signed-off-by: Hans de Goede <hdegoede@redhat.com>
----
- drivers/input/mouse/elantech.c | 45 +++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 42 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
-index 597e9b8..ef1cf52 100644
---- a/drivers/input/mouse/elantech.c
-+++ b/drivers/input/mouse/elantech.c
-@@ -486,6 +486,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse)
- unsigned char *packet = psmouse->packet;
-
- input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
-+ input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
- input_mt_report_pointer_emulation(dev, true);
- input_sync(dev);
- }
-@@ -984,6 +985,44 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
- }
-
- /*
-+ * Advertise INPUT_PROP_BUTTONPAD for clickpads. The testing of bit 12 in
-+ * fw_version for this is based on the following fw_version & caps table:
-+ *
-+ * Laptop-model: fw_version: caps: buttons:
-+ * Acer S3 0x461f00 10, 13, 0e clickpad
-+ * Acer S7-392 0x581f01 50, 17, 0d clickpad
-+ * Acer V5-131 0x461f02 01, 16, 0c clickpad
-+ * Acer V5-551 0x461f00 ? clickpad
-+ * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons
-+ * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons
-+ * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons
-+ * Asus UX31 0x361f00 20, 15, 0e clickpad
-+ * Asus UX32VD 0x361f02 00, 15, 0e clickpad
-+ * Avatar AVIU-145A2 0x361f00 ? clickpad
-+ * Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
-+ * Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
-+ * Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
-+ * Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
-+ * Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
-+ * Samsung NP900X3E-A02 0x575f03 ? clickpad
-+ * Samsung NP-QX410 0x851b00 19, 14, 0c clickpad
-+ * Samsung RC512 0x450f00 08, 15, 0c 2 hw buttons
-+ * Samsung RF710 0x450f00 ? 2 hw buttons
-+ * System76 Pangolin 0x250f01 ? 2 hw buttons
-+ * (*) + 3 trackpoint buttons
-+ */
-+static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
-+{
-+ struct input_dev *dev = psmouse->dev;
-+ struct elantech_data *etd = psmouse->private;
-+
-+ if (etd->fw_version & 0x001000) {
-+ __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
-+ __clear_bit(BTN_RIGHT, dev->keybit);
-+ }
-+}
-+
-+/*
- * Set the appropriate event bits for the input subsystem
- */
- static int elantech_set_input_params(struct psmouse *psmouse)
-@@ -1026,6 +1065,8 @@ static int elantech_set_input_params(struct psmouse *psmouse)
- __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
- /* fall through */
- case 3:
-+ if (etd->hw_version == 3)
-+ elantech_set_buttonpad_prop(psmouse);
- input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
- input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
- if (etd->reports_pressure) {
-@@ -1047,9 +1088,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
- */
- psmouse_warn(psmouse, "couldn't query resolution data.\n");
- }
-- /* v4 is clickpad, with only one button. */
-- __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
-- __clear_bit(BTN_RIGHT, dev->keybit);
-+ elantech_set_buttonpad_prop(psmouse);
- __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
- /* For X to recognize me as touchpad. */
- input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
---
-1.8.4.2
-
diff --git a/fs-proc-devtree-remove_proc_entry.patch b/fs-proc-devtree-remove_proc_entry.patch
deleted file mode 100644
index c32e79e6e..000000000
--- a/fs-proc-devtree-remove_proc_entry.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
-index 927cbd1..f060f28 100644
---- a/fs/proc/proc_devtree.c
-+++ b/fs/proc/proc_devtree.c
-@@ -233,6 +233,7 @@ void __init proc_device_tree_init(void)
- return;
- root = of_find_node_by_path("/");
- if (root == NULL) {
-+ remove_proc_entry("device-tree", NULL);
- pr_debug("/proc/device-tree: can't find root\n");
- return;
- }
diff --git a/iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch b/iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
new file mode 100644
index 000000000..ee06d9f09
--- /dev/null
+++ b/iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
@@ -0,0 +1,48 @@
+Bugzilla: 1046495
+Upstream-status: Sent for 3.14 http://marc.info/?l=linux-wireless&m=139453882510796&w=2
+
+From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+
+There is a flow in which we send the host command in SYNC
+mode, but we don't take priv->mutex.
+
+Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1046495
+
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+---
+ drivers/net/wireless/iwlwifi/dvm/main.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
+index ba1b1ea..ea7e70c 100644
+--- a/drivers/net/wireless/iwlwifi/dvm/main.c
++++ b/drivers/net/wireless/iwlwifi/dvm/main.c
+@@ -252,13 +252,17 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
+ struct iwl_priv *priv =
+ container_of(work, struct iwl_priv, bt_runtime_config);
+
++ mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+- return;
++ goto out;
+
+ /* dont send host command if rf-kill is on */
+ if (!iwl_is_ready_rf(priv))
+- return;
++ goto out;
++
+ iwlagn_send_advance_bt_config(priv);
++out:
++ mutex_unlock(&priv->mutex);
+ }
+
+ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
+--
+1.8.3.2
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/kernel.spec b/kernel.spec
index 51b94e487..3333cab13 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -68,13 +68,13 @@ Summary: The Linux kernel
# base_sublevel is the kernel version we're starting with and patching
# on top of -- for example, 3.1-rc7-git1 starts with a 3.0 base,
# which yields a base_sublevel of 0.
-%define base_sublevel 12
+%define base_sublevel 14
## If this is a released kernel ##
%if 0%{?released_kernel}
# Do we have a -stable update to apply?
-%define stable_update 5
+%define stable_update 0
# Is it a -stable RC?
%define stable_rc 0
# Set rpm version accordingly
@@ -394,7 +394,7 @@ Summary: The Linux kernel
%endif
%ifarch aarch64
-%define all_arch_configs kernel-%{version}-arm64.config
+%define all_arch_configs kernel-%{version}-aarch64*.config
%define asmarch arm64
%define hdrarch arm64
%define make_target Image.gz
@@ -493,11 +493,11 @@ BuildRequires: xmlto, asciidoc
BuildRequires: sparse
%endif
%if %{with_perf}
-BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) bison
+BuildRequires: elfutils-devel zlib-devel binutils-devel newt-devel python-devel perl(ExtUtils::Embed) bison flex
BuildRequires: audit-libs-devel
%endif
%if %{with_tools}
-BuildRequires: pciutils-devel gettext
+BuildRequires: pciutils-devel gettext ncurses-devel
%endif
BuildConflicts: rhbuildsys(DiskFree) < 500Mb
%if %{with_debuginfo}
@@ -613,7 +613,6 @@ Patch09: upstream-reverts.patch
# Standalone patches
Patch390: defaults-acpi-video.patch
-Patch396: acpi-sony-nonvs-blacklist.patch
Patch450: input-kill-stupid-messages.patch
Patch452: no-pcspkr-modalias.patch
@@ -625,18 +624,15 @@ Patch470: die-floppy-die.patch
Patch510: silence-noise.patch
Patch530: silence-fbcon-logo.patch
-Patch600: x86-allow-1024-cpus.patch
+Patch600: 0001-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
+
+#rhbz 917708
+Patch700: Revert-userns-Allow-unprivileged-users-to-create-use.patch
Patch800: crash-driver.patch
# crypto/
-# keys
-Patch900: keys-expand-keyring.patch
-Patch901: keys-krb-support.patch
-Patch902: keys-x509-improv.patch
-Patch903: keys-fixes.patch
-
# secure boot
Patch1000: secure-modules.patch
Patch1001: modsign-uefi.patch
@@ -649,18 +645,15 @@ Patch1003: sysrq-secure-boot.patch
# nouveau + drm fixes
# intel drm is all merged upstream
-Patch1825: drm-i915-dp-stfu.patch
-
+Patch1826: drm-i915-hush-check-crtc-state.patch
# Quiet boot fixes
-# silence the ACPI blacklist code
-Patch2802: silence-acpi-blacklist.patch
# fs fixes
# NFSv4
# patches headed upstream
-Patch10000: fs-proc-devtree-remove_proc_entry.patch
+Patch12015: 3.14.1-rc1.patch
Patch12016: disable-i8042-check-on-apple-mac.patch
@@ -684,18 +677,14 @@ Patch21010: arm-omap-load-tfp410.patch
# ARM tegra
Patch21020: arm-tegra-usb-no-reset-linux33.patch
+# Add panel support for tegra paz00
+# Backported from linux-next scheduled for 3.15
+Patch21021: arm-tegra-paz00-panel-dts.patch
+
# ARM i.MX6
# http://www.spinics.net/lists/devicetree/msg08276.html
Patch21025: arm-imx6-utilite.patch
-# am33xx (BeagleBone)
-# https://github.com/beagleboard/kernel
-# Pulled primarily from the above git repo. First patch is all in arm-soc
-# scheduled for 3.13. The others should be landing via other trees
-Patch21030: arm-am33xx-arm-soc-upstream.patch
-Patch21031: arm-am33xx-bblack.patch
-Patch21032: arm-am33xx-cpsw.patch
-
#rhbz 754518
Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
@@ -709,46 +698,20 @@ Patch22000: weird-root-dentry-name-debug.patch
Patch25047: drm-radeon-Disable-writeback-by-default-on-ppc.patch
-#rhbz 896695
-Patch25127: 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch
-
-#rhbz 993744
-Patch25128: dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch
-
-#rhbz 1000439
-Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch
-
-Patch25140: drm-qxl-backport-fixes-for-Fedora.patch
-
-#rhbz 1011362
-Patch25148: alx-Reset-phy-speed-after-resume.patch
-
-# Fix 15sec NFS mount delay
-Patch25152: sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch
-Patch25153: sunrpc-replace-gssd_running-with-more-reliable-check.patch
-Patch25154: nfs-check-gssd-running-before-krb5i-auth.patch
-
-#CVE-2013-6382 rhbz 1033603 1034670
-Patch25157: xfs-underflow-bug-in-xfs_attrlist_by_handle.patch
+#rhbz 1051748
+Patch25035: Bluetooth-allocate-static-minor-for-vhci.patch
-#rhbz 958826
-Patch25164: dell-laptop.patch
+#rhbz 1046495
+Patch25044: iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
-#rhbz 1030802
-Patch25170: Input-elantech-add-support-for-newer-August-2013-dev.patch
-Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch
+#CVE-2014-0155 rhbz 1081589 1085016
+Patch25036: KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch
-#CVE-2013-6367 rhbz 1032207 1042081
-Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.patch
+#rhbz 1048314
+Patch25062: 0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.patch
-#CVE-2013-6368 rhbz 1032210 1042090
-Patch25173: KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
-
-#CVE-2013-6376 rhbz 1033106 1042099
-Patch25174: KVM-x86-fix-guest-initiated-crash-with-x2apic.patch
-
-#CVE-2013-4587 rhbz 1030986 1042071
-Patch25175: KVM-Improve-create-VCPU-parameter.patch
+#rhbz 1074235
+Patch25055: lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch
# END OF PATCH DEFINITIONS
@@ -899,7 +862,7 @@ This package provides debug information for package kernel-tools.
# symlinks because of the trailing nonmatching alternation and
# the leading .*, because of find-debuginfo.sh's buggy handling
# of matching the pattern against the symlinks file.
-%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|.*%%{_bindir}/turbostat(\.debug)?|.*%%{_bindir}/x86_energy_perf_policy(\.debug)?|XXX' -o kernel-tools-debuginfo.list}
+%{expand:%%global debuginfo_args %{?debuginfo_args} -p '.*%%{_bindir}/centrino-decode(\.debug)?|.*%%{_bindir}/powernow-k8-decode(\.debug)?|.*%%{_bindir}/cpupower(\.debug)?|.*%%{_libdir}/libcpupower.*|.*%%{_bindir}/turbostat(\.debug)?|.*%%{_bindir}/x86_energy_perf_policy(\.debug)?|.*%%{_bindir}/tmon(\.debug)?|XXX' -o kernel-tools-debuginfo.list}
%endif # with_tools
@@ -950,10 +913,10 @@ against the %{?2:%{2} }kernel package.\
Summary: Extra kernel modules to match the %{?2:%{2} }kernel\
Group: System Environment/Kernel\
Provides: kernel%{?1:-%{1}}-modules-extra-%{_target_cpu} = %{version}-%{release}\
-Provides: kernel-modules-extra-%{_target_cpu} = %{version}-%{release}%{?1:+%{1}}\
-Provides: kernel-modules-extra = %{version}-%{release}%{?1:+%{1}}\
+Provides: kernel%{?1:-%{1}}-modules-extra-%{_target_cpu} = %{version}-%{release}%{?1:+%{1}}\
+Provides: kernel%{?1:-%{1}}-modules-extra = %{version}-%{release}%{?1:+%{1}}\
Provides: installonlypkg(kernel-module)\
-Provides: kernel-modules-extra-uname-r = %{KVERREL}%{?1:+%{1}}\
+Provides: kernel%{?1:-%{1}}-modules-extra-uname-r = %{KVERREL}%{?1:+%{1}}\
Requires: kernel-uname-r = %{KVERREL}%{?1:+%{1}}\
AutoReqProv: no\
%description -n kernel%{?variant}%{?1:-%{1}}-modules-extra\
@@ -1186,7 +1149,7 @@ if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then
done
if [[ ! -z $sharedir && -d $sharedir/vanilla-%{kversion} ]] ; then
%setup -q -n kernel-%{kversion}%{?dist} -c -T
- cp -rl $sharedir/vanilla-%{kversion} .
+ cp -al $sharedir/vanilla-%{kversion} .
else
%setup -q -n kernel-%{kversion}%{?dist} -c
mv linux-%{kversion} vanilla-%{kversion}
@@ -1203,12 +1166,12 @@ if [ ! -d kernel-%{kversion}%{?dist}/vanilla-%{vanillaversion} ]; then
done
if [[ ! -z $sharedir && -d $sharedir/vanilla-%{vanillaversion} ]] ; then
- cp -rl $sharedir/vanilla-%{vanillaversion} .
+ cp -al $sharedir/vanilla-%{vanillaversion} .
else
# Need to apply patches to the base vanilla version.
- cp -rl vanilla-%{kversion} vanilla-%{vanillaversion}
+ cp -al vanilla-%{kversion} vanilla-%{vanillaversion}
cd vanilla-%{vanillaversion}
# Update vanilla to the latest upstream.
@@ -1239,7 +1202,7 @@ else
fi
# Now build the fedora kernel tree.
-cp -rl vanilla-%{vanillaversion} linux-%{KVERREL}
+cp -al vanilla-%{vanillaversion} linux-%{KVERREL}
cd linux-%{KVERREL}
@@ -1271,7 +1234,7 @@ make -f %{SOURCE19} config-release
make -f %{SOURCE20} VERSION=%{version} configs
# Merge in any user-provided local config option changes
-for i in kernel-%{version}-*.config
+for i in %{all_arch_configs}
do
mv $i $i.tmp
./merge.pl %{SOURCE1000} $i.tmp > $i
@@ -1292,7 +1255,7 @@ ApplyOptionalPatch upstream-reverts.patch -R
# Architecture patches
# x86(-64)
-ApplyPatch x86-allow-1024-cpus.patch
+ApplyPatch 0001-lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
# ARM64
@@ -1303,11 +1266,9 @@ ApplyPatch arm-lpae-ax88796.patch
ApplyPatch arm-sound-soc-samsung-dma-avoid-another-64bit-division.patch
ApplyPatch arm-omap-load-tfp410.patch
ApplyPatch arm-tegra-usb-no-reset-linux33.patch
+ApplyPatch arm-tegra-paz00-panel-dts.patch
ApplyPatch arm-imx6-utilite.patch
-ApplyPatch arm-am33xx-arm-soc-upstream.patch
-ApplyPatch arm-am33xx-bblack.patch
-ApplyPatch arm-am33xx-cpsw.patch
#
# bugfixes to drivers and filesystems
@@ -1329,7 +1290,6 @@ ApplyPatch arm-am33xx-cpsw.patch
# ACPI
ApplyPatch defaults-acpi-video.patch
-ApplyPatch acpi-sony-nonvs-blacklist.patch
#
# PCI
@@ -1365,18 +1325,14 @@ ApplyPatch silence-fbcon-logo.patch
# Changes to upstream defaults.
+#rhbz 917708
+ApplyPatch Revert-userns-Allow-unprivileged-users-to-create-use.patch
# /dev/crash driver.
ApplyPatch crash-driver.patch
# crypto/
-# keys
-ApplyPatch keys-expand-keyring.patch
-ApplyPatch keys-krb-support.patch
-ApplyPatch keys-x509-improv.patch
-ApplyPatch keys-fixes.patch
-
# secure boot
ApplyPatch secure-modules.patch
ApplyPatch modsign-uefi.patch
@@ -1390,15 +1346,12 @@ ApplyPatch sysrq-secure-boot.patch
# Nouveau DRM
# Intel DRM
-ApplyPatch drm-i915-dp-stfu.patch
+ApplyPatch drm-i915-hush-check-crtc-state.patch
# Radeon DRM
-# silence the ACPI blacklist code
-ApplyPatch silence-acpi-blacklist.patch
-
# Patches headed upstream
-ApplyPatch fs-proc-devtree-remove_proc_entry.patch
+ApplyPatch 3.14.1-rc1.patch
ApplyPatch disable-i8042-check-on-apple-mac.patch
@@ -1423,46 +1376,20 @@ ApplyPatch ath9k_rx_dma_stop_check.patch
ApplyPatch drm-radeon-Disable-writeback-by-default-on-ppc.patch
-#rhbz 896695
-ApplyPatch 0002-iwlwifi-don-t-WARN-on-bad-firmware-state.patch
-
-#rhbz 993744
-ApplyPatch dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch
-
-#rhbz 1000439
-ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch
-
-ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch
-
-#rhbz 1011362
-ApplyPatch alx-Reset-phy-speed-after-resume.patch
-
-# Fix 15sec NFS mount delay
-ApplyPatch sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch
-ApplyPatch sunrpc-replace-gssd_running-with-more-reliable-check.patch
-ApplyPatch nfs-check-gssd-running-before-krb5i-auth.patch
-
-#CVE-2013-6382 rhbz 1033603 1034670
-ApplyPatch xfs-underflow-bug-in-xfs_attrlist_by_handle.patch
-
-#rhbz 958826
-ApplyPatch dell-laptop.patch
-
-#rhbz 1030802
-ApplyPatch Input-elantech-add-support-for-newer-August-2013-dev.patch
-ApplyPatch elantech-Properly-differentiate-between-clickpads-an.patch
+#rhbz 1051748
+ApplyPatch Bluetooth-allocate-static-minor-for-vhci.patch
-#CVE-2013-6367 rhbz 1032207 1042081
-ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch
+#rhbz 1046495
+ApplyPatch iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
-#CVE-2013-6368 rhbz 1032210 1042090
-ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch
+#CVE-2014-0155 rhbz 1081589 1085016
+ApplyPatch KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch
-#CVE-2013-6376 rhbz 1033106 1042099
-ApplyPatch KVM-x86-fix-guest-initiated-crash-with-x2apic.patch
+#rhbz 1048314
+ApplyPatch 0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.patch
-#CVE-2013-4587 rhbz 1030986 1042071
-ApplyPatch KVM-Improve-create-VCPU-parameter.patch
+#rhbz 1074235
+ApplyPatch lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch
# END OF PATCH APPLICATIONS
@@ -1848,6 +1775,9 @@ chmod +x tools/power/cpupower/utils/version-gen.sh
popd
%endif #turbostat/x86_energy_perf_policy
%endif
+pushd tools/thermal/tmon/
+%{make}
+popd
%endif
%if %{with_doc}
@@ -1961,13 +1891,15 @@ find $RPM_BUILD_ROOT/usr/include \
%if %{with_perf}
# perf tool binary and supporting scripts/binaries
-%{perf_make} DESTDIR=$RPM_BUILD_ROOT install
+%{perf_make} DESTDIR=$RPM_BUILD_ROOT install-bin
+# remove the 'trace' symlink.
+rm -f %{buildroot}%{_bindir}/trace
# python-perf extension
%{perf_make} DESTDIR=$RPM_BUILD_ROOT install-python_ext
# perf man pages (note: implicit rpm magic compresses them later)
-%{perf_make} DESTDIR=$RPM_BUILD_ROOT install-man || %{doc_build_fail}
+%{perf_make} DESTDIR=$RPM_BUILD_ROOT try-install-man || %{doc_build_fail}
%endif
%if %{with_tools}
@@ -2002,6 +1934,9 @@ install -m644 %{SOURCE2001} %{buildroot}%{_sysconfdir}/sysconfig/cpupower
make DESTDIR=%{buildroot} install
popd
%endif #turbostat/x86_energy_perf_policy
+pushd tools/thermal/tmon
+make INSTALL_ROOT=%{buildroot} install
+popd
%endif
%if %{with_bootwrapper}
@@ -2180,6 +2115,7 @@ fi
%{_bindir}/turbostat
%{_mandir}/man8/turbostat*
%endif
+%{_bindir}/tmon
%endif
%if %{with_debuginfo}
diff --git a/keys-expand-keyring.patch b/keys-expand-keyring.patch
deleted file mode 100644
index 75618243b..000000000
--- a/keys-expand-keyring.patch
+++ /dev/null
@@ -1,6834 +0,0 @@
-From 96dcf8e91389e509021448ffd798cc68471fcf0f Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:50 +0100
-Subject: [PATCH 01/10] KEYS: Skip key state checks when checking for
- possession
-
-Skip key state checks (invalidation, revocation and expiration) when checking
-for possession. Without this, keys that have been marked invalid, revoked
-keys and expired keys are not given a possession attribute - which means the
-possessor is not granted any possession permits and cannot do anything with
-them unless they also have one a user, group or other permit.
-
-This causes failures in the keyutils test suite's revocation and expiration
-tests now that commit 96b5c8fea6c0861621051290d705ec2e971963f1 reduced the
-initial permissions granted to a key.
-
-The failures are due to accesses to revoked and expired keys being given
-EACCES instead of EKEYREVOKED or EKEYEXPIRED.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/internal.h | 1 +
- security/keys/process_keys.c | 8 +++++---
- security/keys/request_key.c | 6 ++++--
- security/keys/request_key_auth.c | 2 +-
- 4 files changed, 11 insertions(+), 6 deletions(-)
-
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index d4f1468..df971fe 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -124,6 +124,7 @@ extern key_ref_t search_my_process_keyrings(struct key_type *type,
- extern key_ref_t search_process_keyrings(struct key_type *type,
- const void *description,
- key_match_func_t match,
-+ bool no_state_check,
- const struct cred *cred);
-
- extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
-diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
-index 42defae..a3410d6 100644
---- a/security/keys/process_keys.c
-+++ b/security/keys/process_keys.c
-@@ -440,6 +440,7 @@ found:
- key_ref_t search_process_keyrings(struct key_type *type,
- const void *description,
- key_match_func_t match,
-+ bool no_state_check,
- const struct cred *cred)
- {
- struct request_key_auth *rka;
-@@ -448,7 +449,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
- might_sleep();
-
- key_ref = search_my_process_keyrings(type, description, match,
-- false, cred);
-+ no_state_check, cred);
- if (!IS_ERR(key_ref))
- goto found;
- err = key_ref;
-@@ -468,7 +469,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
- rka = cred->request_key_auth->payload.data;
-
- key_ref = search_process_keyrings(type, description,
-- match, rka->cred);
-+ match, no_state_check,
-+ rka->cred);
-
- up_read(&cred->request_key_auth->sem);
-
-@@ -675,7 +677,7 @@ try_again:
- /* check to see if we possess the key */
- skey_ref = search_process_keyrings(key->type, key,
- lookup_user_key_possessed,
-- cred);
-+ true, cred);
-
- if (!IS_ERR(skey_ref)) {
- key_put(key);
-diff --git a/security/keys/request_key.c b/security/keys/request_key.c
-index c411f9b..172115b 100644
---- a/security/keys/request_key.c
-+++ b/security/keys/request_key.c
-@@ -390,7 +390,8 @@ static int construct_alloc_key(struct key_type *type,
- * waited for locks */
- mutex_lock(&key_construction_mutex);
-
-- key_ref = search_process_keyrings(type, description, type->match, cred);
-+ key_ref = search_process_keyrings(type, description, type->match,
-+ false, cred);
- if (!IS_ERR(key_ref))
- goto key_already_present;
-
-@@ -539,7 +540,8 @@ struct key *request_key_and_link(struct key_type *type,
- dest_keyring, flags);
-
- /* search all the process keyrings for a key */
-- key_ref = search_process_keyrings(type, description, type->match, cred);
-+ key_ref = search_process_keyrings(type, description, type->match,
-+ false, cred);
-
- if (!IS_ERR(key_ref)) {
- key = key_ref_to_ptr(key_ref);
-diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
-index 85730d5..92077de 100644
---- a/security/keys/request_key_auth.c
-+++ b/security/keys/request_key_auth.c
-@@ -247,7 +247,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
- &key_type_request_key_auth,
- (void *) (unsigned long) target_id,
- key_get_instantiation_authkey_match,
-- cred);
-+ false, cred);
-
- if (IS_ERR(authkey_ref)) {
- authkey = ERR_CAST(authkey_ref);
---
-1.8.3.1
-
-
-From 9b1294158dd1fbca78541b5d55c057e46b1a9ca2 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:51 +0100
-Subject: [PATCH 02/10] KEYS: Use bool in make_key_ref() and is_key_possessed()
-
-Make make_key_ref() take a bool possession parameter and make
-is_key_possessed() return a bool.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/security/keys.txt | 7 +++----
- include/linux/key.h | 4 ++--
- security/keys/keyring.c | 5 +++--
- 3 files changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
-index 7b4145d..9ede670 100644
---- a/Documentation/security/keys.txt
-+++ b/Documentation/security/keys.txt
-@@ -865,15 +865,14 @@ encountered:
- calling processes has a searchable link to the key from one of its
- keyrings. There are three functions for dealing with these:
-
-- key_ref_t make_key_ref(const struct key *key,
-- unsigned long possession);
-+ key_ref_t make_key_ref(const struct key *key, bool possession);
-
- struct key *key_ref_to_ptr(const key_ref_t key_ref);
-
-- unsigned long is_key_possessed(const key_ref_t key_ref);
-+ bool is_key_possessed(const key_ref_t key_ref);
-
- The first function constructs a key reference from a key pointer and
-- possession information (which must be 0 or 1 and not any other value).
-+ possession information (which must be true or false).
-
- The second function retrieves the key pointer from a reference and the
- third retrieves the possession flag.
-diff --git a/include/linux/key.h b/include/linux/key.h
-index 4dfde11..51bce29 100644
---- a/include/linux/key.h
-+++ b/include/linux/key.h
-@@ -99,7 +99,7 @@ struct keyring_name;
- typedef struct __key_reference_with_attributes *key_ref_t;
-
- static inline key_ref_t make_key_ref(const struct key *key,
-- unsigned long possession)
-+ bool possession)
- {
- return (key_ref_t) ((unsigned long) key | possession);
- }
-@@ -109,7 +109,7 @@ static inline struct key *key_ref_to_ptr(const key_ref_t key_ref)
- return (struct key *) ((unsigned long) key_ref & ~1UL);
- }
-
--static inline unsigned long is_key_possessed(const key_ref_t key_ref)
-+static inline bool is_key_possessed(const key_ref_t key_ref)
- {
- return (unsigned long) key_ref & 1UL;
- }
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 6ece7f2..f784063 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -329,9 +329,10 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-
- struct keyring_list *keylist;
- struct timespec now;
-- unsigned long possessed, kflags;
-+ unsigned long kflags;
- struct key *keyring, *key;
- key_ref_t key_ref;
-+ bool possessed;
- long err;
- int sp, nkeys, kix;
-
-@@ -542,8 +543,8 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
- key_perm_t perm)
- {
- struct keyring_list *klist;
-- unsigned long possessed;
- struct key *keyring, *key;
-+ bool possessed;
- int nkeys, loop;
-
- keyring = key_ref_to_ptr(keyring_ref);
---
-1.8.3.1
-
-
-From 4a7e7536b9b728f1d912d0e4c047c885c95e13a1 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:51 +0100
-Subject: [PATCH 03/10] KEYS: key_is_dead() should take a const key pointer
- argument
-
-key_is_dead() should take a const key pointer argument as it doesn't modify
-what it points to.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/internal.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index df971fe..490aef5 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -203,7 +203,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
- /*
- * Determine whether a key is dead.
- */
--static inline bool key_is_dead(struct key *key, time_t limit)
-+static inline bool key_is_dead(const struct key *key, time_t limit)
- {
- return
- key->flags & ((1 << KEY_FLAG_DEAD) |
---
-1.8.3.1
-
-
-From 9007a0a7f8c135f0085e46db277de0cf7b944403 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:52 +0100
-Subject: [PATCH 04/10] KEYS: Consolidate the concept of an 'index key' for key
- access
-
-Consolidate the concept of an 'index key' for accessing keys. The index key
-is the search term needed to find a key directly - basically the key type and
-the key description. We can add to that the description length.
-
-This will be useful when turning a keyring into an associative array rather
-than just a pointer block.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/key.h | 21 +++++++++----
- security/keys/internal.h | 8 ++---
- security/keys/key.c | 72 +++++++++++++++++++++++----------------------
- security/keys/keyring.c | 37 +++++++++++------------
- security/keys/request_key.c | 12 +++++---
- 5 files changed, 83 insertions(+), 67 deletions(-)
-
-diff --git a/include/linux/key.h b/include/linux/key.h
-index 51bce29..d573e82 100644
---- a/include/linux/key.h
-+++ b/include/linux/key.h
-@@ -82,6 +82,12 @@ struct key_owner;
- struct keyring_list;
- struct keyring_name;
-
-+struct keyring_index_key {
-+ struct key_type *type;
-+ const char *description;
-+ size_t desc_len;
-+};
-+
- /*****************************************************************************/
- /*
- * key reference with possession attribute handling
-@@ -129,7 +135,6 @@ struct key {
- struct list_head graveyard_link;
- struct rb_node serial_node;
- };
-- struct key_type *type; /* type of key */
- struct rw_semaphore sem; /* change vs change sem */
- struct key_user *user; /* owner of this key */
- void *security; /* security data for this key */
-@@ -163,12 +168,18 @@ struct key {
- #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */
- #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
-
-- /* the description string
-- * - this is used to match a key against search criteria
-- * - this should be a printable string
-+ /* the key type and key description string
-+ * - the desc is used to match a key against search criteria
-+ * - it should be a printable string
- * - eg: for krb5 AFS, this might be "afs@REDHAT.COM"
- */
-- char *description;
-+ union {
-+ struct keyring_index_key index_key;
-+ struct {
-+ struct key_type *type; /* type of key */
-+ char *description;
-+ };
-+ };
-
- /* type specific data
- * - this is used by the keyring type to index the name
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index 490aef5..77441dd 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -89,19 +89,17 @@ extern struct key_type *key_type_lookup(const char *type);
- extern void key_type_put(struct key_type *ktype);
-
- extern int __key_link_begin(struct key *keyring,
-- const struct key_type *type,
-- const char *description,
-+ const struct keyring_index_key *index_key,
- unsigned long *_prealloc);
- extern int __key_link_check_live_key(struct key *keyring, struct key *key);
- extern void __key_link(struct key *keyring, struct key *key,
- unsigned long *_prealloc);
- extern void __key_link_end(struct key *keyring,
-- struct key_type *type,
-+ const struct keyring_index_key *index_key,
- unsigned long prealloc);
-
- extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
-- const struct key_type *type,
-- const char *description,
-+ const struct keyring_index_key *index_key,
- key_perm_t perm);
-
- extern struct key *keyring_search_instkey(struct key *keyring,
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 8fb7c7b..7e6bc39 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -242,8 +242,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
- }
- }
-
-- desclen = strlen(desc) + 1;
-- quotalen = desclen + type->def_datalen;
-+ desclen = strlen(desc);
-+ quotalen = desclen + 1 + type->def_datalen;
-
- /* get hold of the key tracking for this user */
- user = key_user_lookup(uid);
-@@ -277,7 +277,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
- goto no_memory_2;
-
- if (desc) {
-- key->description = kmemdup(desc, desclen, GFP_KERNEL);
-+ key->index_key.desc_len = desclen;
-+ key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL);
- if (!key->description)
- goto no_memory_3;
- }
-@@ -285,7 +286,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
- atomic_set(&key->usage, 1);
- init_rwsem(&key->sem);
- lockdep_set_class(&key->sem, &type->lock_class);
-- key->type = type;
-+ key->index_key.type = type;
- key->user = user;
- key->quotalen = quotalen;
- key->datalen = type->def_datalen;
-@@ -489,8 +490,7 @@ int key_instantiate_and_link(struct key *key,
- }
-
- if (keyring) {
-- ret = __key_link_begin(keyring, key->type, key->description,
-- &prealloc);
-+ ret = __key_link_begin(keyring, &key->index_key, &prealloc);
- if (ret < 0)
- goto error_free_preparse;
- }
-@@ -499,7 +499,7 @@ int key_instantiate_and_link(struct key *key,
- &prealloc);
-
- if (keyring)
-- __key_link_end(keyring, key->type, prealloc);
-+ __key_link_end(keyring, &key->index_key, prealloc);
-
- error_free_preparse:
- if (key->type->preparse)
-@@ -548,8 +548,7 @@ int key_reject_and_link(struct key *key,
- ret = -EBUSY;
-
- if (keyring)
-- link_ret = __key_link_begin(keyring, key->type,
-- key->description, &prealloc);
-+ link_ret = __key_link_begin(keyring, &key->index_key, &prealloc);
-
- mutex_lock(&key_construction_mutex);
-
-@@ -581,7 +580,7 @@ int key_reject_and_link(struct key *key,
- mutex_unlock(&key_construction_mutex);
-
- if (keyring)
-- __key_link_end(keyring, key->type, prealloc);
-+ __key_link_end(keyring, &key->index_key, prealloc);
-
- /* wake up anyone waiting for a key to be constructed */
- if (awaken)
-@@ -780,25 +779,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- key_perm_t perm,
- unsigned long flags)
- {
-- unsigned long prealloc;
-+ struct keyring_index_key index_key = {
-+ .description = description,
-+ };
- struct key_preparsed_payload prep;
- const struct cred *cred = current_cred();
-- struct key_type *ktype;
-+ unsigned long prealloc;
- struct key *keyring, *key = NULL;
- key_ref_t key_ref;
- int ret;
-
- /* look up the key type to see if it's one of the registered kernel
- * types */
-- ktype = key_type_lookup(type);
-- if (IS_ERR(ktype)) {
-+ index_key.type = key_type_lookup(type);
-+ if (IS_ERR(index_key.type)) {
- key_ref = ERR_PTR(-ENODEV);
- goto error;
- }
-
- key_ref = ERR_PTR(-EINVAL);
-- if (!ktype->match || !ktype->instantiate ||
-- (!description && !ktype->preparse))
-+ if (!index_key.type->match || !index_key.type->instantiate ||
-+ (!index_key.description && !index_key.type->preparse))
- goto error_put_type;
-
- keyring = key_ref_to_ptr(keyring_ref);
-@@ -812,21 +813,22 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- memset(&prep, 0, sizeof(prep));
- prep.data = payload;
- prep.datalen = plen;
-- prep.quotalen = ktype->def_datalen;
-- if (ktype->preparse) {
-- ret = ktype->preparse(&prep);
-+ prep.quotalen = index_key.type->def_datalen;
-+ if (index_key.type->preparse) {
-+ ret = index_key.type->preparse(&prep);
- if (ret < 0) {
- key_ref = ERR_PTR(ret);
- goto error_put_type;
- }
-- if (!description)
-- description = prep.description;
-+ if (!index_key.description)
-+ index_key.description = prep.description;
- key_ref = ERR_PTR(-EINVAL);
-- if (!description)
-+ if (!index_key.description)
- goto error_free_prep;
- }
-+ index_key.desc_len = strlen(index_key.description);
-
-- ret = __key_link_begin(keyring, ktype, description, &prealloc);
-+ ret = __key_link_begin(keyring, &index_key, &prealloc);
- if (ret < 0) {
- key_ref = ERR_PTR(ret);
- goto error_free_prep;
-@@ -844,9 +846,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- * key of the same type and description in the destination keyring and
- * update that instead if possible
- */
-- if (ktype->update) {
-- key_ref = __keyring_search_one(keyring_ref, ktype, description,
-- 0);
-+ if (index_key.type->update) {
-+ key_ref = __keyring_search_one(keyring_ref, &index_key, 0);
- if (!IS_ERR(key_ref))
- goto found_matching_key;
- }
-@@ -856,16 +857,17 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
- perm |= KEY_USR_VIEW;
-
-- if (ktype->read)
-+ if (index_key.type->read)
- perm |= KEY_POS_READ;
-
-- if (ktype == &key_type_keyring || ktype->update)
-+ if (index_key.type == &key_type_keyring ||
-+ index_key.type->update)
- perm |= KEY_POS_WRITE;
- }
-
- /* allocate a new key */
-- key = key_alloc(ktype, description, cred->fsuid, cred->fsgid, cred,
-- perm, flags);
-+ key = key_alloc(index_key.type, index_key.description,
-+ cred->fsuid, cred->fsgid, cred, perm, flags);
- if (IS_ERR(key)) {
- key_ref = ERR_CAST(key);
- goto error_link_end;
-@@ -882,12 +884,12 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
-
- error_link_end:
-- __key_link_end(keyring, ktype, prealloc);
-+ __key_link_end(keyring, &index_key, prealloc);
- error_free_prep:
-- if (ktype->preparse)
-- ktype->free_preparse(&prep);
-+ if (index_key.type->preparse)
-+ index_key.type->free_preparse(&prep);
- error_put_type:
-- key_type_put(ktype);
-+ key_type_put(index_key.type);
- error:
- return key_ref;
-
-@@ -895,7 +897,7 @@ error:
- /* we found a matching key, so we're going to try to update it
- * - we can drop the locks first as we have the key pinned
- */
-- __key_link_end(keyring, ktype, prealloc);
-+ __key_link_end(keyring, &index_key, prealloc);
-
- key_ref = __key_update(key_ref, &prep);
- goto error_free_prep;
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index f784063..c7f59f9 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -538,8 +538,7 @@ EXPORT_SYMBOL(keyring_search);
- * to the returned key reference.
- */
- key_ref_t __keyring_search_one(key_ref_t keyring_ref,
-- const struct key_type *ktype,
-- const char *description,
-+ const struct keyring_index_key *index_key,
- key_perm_t perm)
- {
- struct keyring_list *klist;
-@@ -558,9 +557,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
- smp_rmb();
- for (loop = 0; loop < nkeys ; loop++) {
- key = rcu_dereference(klist->keys[loop]);
-- if (key->type == ktype &&
-+ if (key->type == index_key->type &&
- (!key->type->match ||
-- key->type->match(key, description)) &&
-+ key->type->match(key, index_key->description)) &&
- key_permission(make_key_ref(key, possessed),
- perm) == 0 &&
- !(key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-@@ -747,8 +746,8 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
- /*
- * Preallocate memory so that a key can be linked into to a keyring.
- */
--int __key_link_begin(struct key *keyring, const struct key_type *type,
-- const char *description, unsigned long *_prealloc)
-+int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key,
-+ unsigned long *_prealloc)
- __acquires(&keyring->sem)
- __acquires(&keyring_serialise_link_sem)
- {
-@@ -759,7 +758,8 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
- size_t size;
- int loop, lru, ret;
-
-- kenter("%d,%s,%s,", key_serial(keyring), type->name, description);
-+ kenter("%d,%s,%s,",
-+ key_serial(keyring), index_key->type->name, index_key->description);
-
- if (keyring->type != &key_type_keyring)
- return -ENOTDIR;
-@@ -772,7 +772,7 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
-
- /* serialise link/link calls to prevent parallel calls causing a cycle
- * when linking two keyring in opposite orders */
-- if (type == &key_type_keyring)
-+ if (index_key->type == &key_type_keyring)
- down_write(&keyring_serialise_link_sem);
-
- klist = rcu_dereference_locked_keyring(keyring);
-@@ -784,8 +784,8 @@ int __key_link_begin(struct key *keyring, const struct key_type *type,
- for (loop = klist->nkeys - 1; loop >= 0; loop--) {
- struct key *key = rcu_deref_link_locked(klist, loop,
- keyring);
-- if (key->type == type &&
-- strcmp(key->description, description) == 0) {
-+ if (key->type == index_key->type &&
-+ strcmp(key->description, index_key->description) == 0) {
- /* Found a match - we'll replace the link with
- * one to the new key. We record the slot
- * position.
-@@ -865,7 +865,7 @@ error_quota:
- key_payload_reserve(keyring,
- keyring->datalen - KEYQUOTA_LINK_BYTES);
- error_sem:
-- if (type == &key_type_keyring)
-+ if (index_key->type == &key_type_keyring)
- up_write(&keyring_serialise_link_sem);
- error_krsem:
- up_write(&keyring->sem);
-@@ -957,16 +957,17 @@ void __key_link(struct key *keyring, struct key *key,
- *
- * Must be called with __key_link_begin() having being called.
- */
--void __key_link_end(struct key *keyring, struct key_type *type,
-+void __key_link_end(struct key *keyring,
-+ const struct keyring_index_key *index_key,
- unsigned long prealloc)
- __releases(&keyring->sem)
- __releases(&keyring_serialise_link_sem)
- {
-- BUG_ON(type == NULL);
-- BUG_ON(type->name == NULL);
-- kenter("%d,%s,%lx", keyring->serial, type->name, prealloc);
-+ BUG_ON(index_key->type == NULL);
-+ BUG_ON(index_key->type->name == NULL);
-+ kenter("%d,%s,%lx", keyring->serial, index_key->type->name, prealloc);
-
-- if (type == &key_type_keyring)
-+ if (index_key->type == &key_type_keyring)
- up_write(&keyring_serialise_link_sem);
-
- if (prealloc) {
-@@ -1007,12 +1008,12 @@ int key_link(struct key *keyring, struct key *key)
- key_check(keyring);
- key_check(key);
-
-- ret = __key_link_begin(keyring, key->type, key->description, &prealloc);
-+ ret = __key_link_begin(keyring, &key->index_key, &prealloc);
- if (ret == 0) {
- ret = __key_link_check_live_key(keyring, key);
- if (ret == 0)
- __key_link(keyring, key, &prealloc);
-- __key_link_end(keyring, key->type, prealloc);
-+ __key_link_end(keyring, &key->index_key, prealloc);
- }
-
- return ret;
-diff --git a/security/keys/request_key.c b/security/keys/request_key.c
-index 172115b..586cb79 100644
---- a/security/keys/request_key.c
-+++ b/security/keys/request_key.c
-@@ -352,6 +352,11 @@ static int construct_alloc_key(struct key_type *type,
- struct key_user *user,
- struct key **_key)
- {
-+ const struct keyring_index_key index_key = {
-+ .type = type,
-+ .description = description,
-+ .desc_len = strlen(description),
-+ };
- const struct cred *cred = current_cred();
- unsigned long prealloc;
- struct key *key;
-@@ -379,8 +384,7 @@ static int construct_alloc_key(struct key_type *type,
- set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
-
- if (dest_keyring) {
-- ret = __key_link_begin(dest_keyring, type, description,
-- &prealloc);
-+ ret = __key_link_begin(dest_keyring, &index_key, &prealloc);
- if (ret < 0)
- goto link_prealloc_failed;
- }
-@@ -400,7 +404,7 @@ static int construct_alloc_key(struct key_type *type,
-
- mutex_unlock(&key_construction_mutex);
- if (dest_keyring)
-- __key_link_end(dest_keyring, type, prealloc);
-+ __key_link_end(dest_keyring, &index_key, prealloc);
- mutex_unlock(&user->cons_lock);
- *_key = key;
- kleave(" = 0 [%d]", key_serial(key));
-@@ -416,7 +420,7 @@ key_already_present:
- ret = __key_link_check_live_key(dest_keyring, key);
- if (ret == 0)
- __key_link(dest_keyring, key, &prealloc);
-- __key_link_end(dest_keyring, type, prealloc);
-+ __key_link_end(dest_keyring, &index_key, prealloc);
- if (ret < 0)
- goto link_check_failed;
- }
---
-1.8.3.1
-
-
-From eca8dad5cd291d2baf2d20372fcb0af9e75e25ea Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:52 +0100
-Subject: [PATCH 05/10] KEYS: Introduce a search context structure
-
-Search functions pass around a bunch of arguments, each of which gets copied
-with each call. Introduce a search context structure to hold these.
-
-Whilst we're at it, create a search flag that indicates whether the search
-should be directly to the description or whether it should iterate through all
-keys looking for a non-description match.
-
-This will be useful when keyrings use a generic data struct with generic
-routines to manage their content as the search terms can just be passed
-through to the iterator callback function.
-
-Also, for future use, the data to be supplied to the match function is
-separated from the description pointer in the search context. This makes it
-clear which is being supplied.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/linux/key-type.h | 5 ++
- security/keys/internal.h | 40 +++++++------
- security/keys/keyring.c | 70 +++++++++++------------
- security/keys/proc.c | 17 ++++--
- security/keys/process_keys.c | 117 +++++++++++++++++++--------------------
- security/keys/request_key.c | 56 +++++++++----------
- security/keys/request_key_auth.c | 14 +++--
- security/keys/user_defined.c | 18 +++---
- 8 files changed, 179 insertions(+), 158 deletions(-)
-
-diff --git a/include/linux/key-type.h b/include/linux/key-type.h
-index 518a53a..f58737b 100644
---- a/include/linux/key-type.h
-+++ b/include/linux/key-type.h
-@@ -63,6 +63,11 @@ struct key_type {
- */
- size_t def_datalen;
-
-+ /* Default key search algorithm. */
-+ unsigned def_lookup_type;
-+#define KEYRING_SEARCH_LOOKUP_DIRECT 0x0000 /* Direct lookup by description. */
-+#define KEYRING_SEARCH_LOOKUP_ITERATE 0x0001 /* Iterative search. */
-+
- /* vet a description */
- int (*vet_description)(const char *description);
-
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index 77441dd..f4bf938 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -107,23 +107,31 @@ extern struct key *keyring_search_instkey(struct key *keyring,
-
- typedef int (*key_match_func_t)(const struct key *, const void *);
-
-+struct keyring_search_context {
-+ struct keyring_index_key index_key;
-+ const struct cred *cred;
-+ key_match_func_t match;
-+ const void *match_data;
-+ unsigned flags;
-+#define KEYRING_SEARCH_LOOKUP_TYPE 0x0001 /* [as type->def_lookup_type] */
-+#define KEYRING_SEARCH_NO_STATE_CHECK 0x0002 /* Skip state checks */
-+#define KEYRING_SEARCH_DO_STATE_CHECK 0x0004 /* Override NO_STATE_CHECK */
-+#define KEYRING_SEARCH_NO_UPDATE_TIME 0x0008 /* Don't update times */
-+#define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */
-+#define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */
-+
-+ /* Internal stuff */
-+ int skipped_ret;
-+ bool possessed;
-+ key_ref_t result;
-+ struct timespec now;
-+};
-+
- extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-- const struct cred *cred,
-- struct key_type *type,
-- const void *description,
-- key_match_func_t match,
-- bool no_state_check);
--
--extern key_ref_t search_my_process_keyrings(struct key_type *type,
-- const void *description,
-- key_match_func_t match,
-- bool no_state_check,
-- const struct cred *cred);
--extern key_ref_t search_process_keyrings(struct key_type *type,
-- const void *description,
-- key_match_func_t match,
-- bool no_state_check,
-- const struct cred *cred);
-+ struct keyring_search_context *ctx);
-+
-+extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx);
-+extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx);
-
- extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
-
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index c7f59f9..b42f2d4 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -280,11 +280,7 @@ EXPORT_SYMBOL(keyring_alloc);
- /**
- * keyring_search_aux - Search a keyring tree for a key matching some criteria
- * @keyring_ref: A pointer to the keyring with possession indicator.
-- * @cred: The credentials to use for permissions checks.
-- * @type: The type of key to search for.
-- * @description: Parameter for @match.
-- * @match: Function to rule on whether or not a key is the one required.
-- * @no_state_check: Don't check if a matching key is bad
-+ * @ctx: The keyring search context.
- *
- * Search the supplied keyring tree for a key that matches the criteria given.
- * The root keyring and any linked keyrings must grant Search permission to the
-@@ -314,11 +310,7 @@ EXPORT_SYMBOL(keyring_alloc);
- * @keyring_ref is propagated to the returned key reference.
- */
- key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-- const struct cred *cred,
-- struct key_type *type,
-- const void *description,
-- key_match_func_t match,
-- bool no_state_check)
-+ struct keyring_search_context *ctx)
- {
- struct {
- /* Need a separate keylist pointer for RCU purposes */
-@@ -328,20 +320,18 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
- } stack[KEYRING_SEARCH_MAX_DEPTH];
-
- struct keyring_list *keylist;
-- struct timespec now;
- unsigned long kflags;
- struct key *keyring, *key;
- key_ref_t key_ref;
-- bool possessed;
- long err;
- int sp, nkeys, kix;
-
- keyring = key_ref_to_ptr(keyring_ref);
-- possessed = is_key_possessed(keyring_ref);
-+ ctx->possessed = is_key_possessed(keyring_ref);
- key_check(keyring);
-
- /* top keyring must have search permission to begin the search */
-- err = key_task_permission(keyring_ref, cred, KEY_SEARCH);
-+ err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
- if (err < 0) {
- key_ref = ERR_PTR(err);
- goto error;
-@@ -353,7 +343,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-
- rcu_read_lock();
-
-- now = current_kernel_time();
-+ ctx->now = current_kernel_time();
- err = -EAGAIN;
- sp = 0;
-
-@@ -361,16 +351,17 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
- * are looking for */
- key_ref = ERR_PTR(-EAGAIN);
- kflags = keyring->flags;
-- if (keyring->type == type && match(keyring, description)) {
-+ if (keyring->type == ctx->index_key.type &&
-+ ctx->match(keyring, ctx->match_data)) {
- key = keyring;
-- if (no_state_check)
-+ if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
- goto found;
-
- /* check it isn't negative and hasn't expired or been
- * revoked */
- if (kflags & (1 << KEY_FLAG_REVOKED))
- goto error_2;
-- if (key->expiry && now.tv_sec >= key->expiry)
-+ if (key->expiry && ctx->now.tv_sec >= key->expiry)
- goto error_2;
- key_ref = ERR_PTR(key->type_data.reject_error);
- if (kflags & (1 << KEY_FLAG_NEGATIVE))
-@@ -384,7 +375,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
- if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
- (1 << KEY_FLAG_REVOKED) |
- (1 << KEY_FLAG_NEGATIVE)) ||
-- (keyring->expiry && now.tv_sec >= keyring->expiry))
-+ (keyring->expiry && ctx->now.tv_sec >= keyring->expiry))
- goto error_2;
-
- /* start processing a new keyring */
-@@ -406,29 +397,29 @@ descend:
- kflags = key->flags;
-
- /* ignore keys not of this type */
-- if (key->type != type)
-+ if (key->type != ctx->index_key.type)
- continue;
-
- /* skip invalidated, revoked and expired keys */
-- if (!no_state_check) {
-+ if (!(ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)) {
- if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
- (1 << KEY_FLAG_REVOKED)))
- continue;
-
-- if (key->expiry && now.tv_sec >= key->expiry)
-+ if (key->expiry && ctx->now.tv_sec >= key->expiry)
- continue;
- }
-
- /* keys that don't match */
-- if (!match(key, description))
-+ if (!ctx->match(key, ctx->match_data))
- continue;
-
- /* key must have search permissions */
-- if (key_task_permission(make_key_ref(key, possessed),
-- cred, KEY_SEARCH) < 0)
-+ if (key_task_permission(make_key_ref(key, ctx->possessed),
-+ ctx->cred, KEY_SEARCH) < 0)
- continue;
-
-- if (no_state_check)
-+ if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
- goto found;
-
- /* we set a different error code if we pass a negative key */
-@@ -456,8 +447,8 @@ ascend:
- if (sp >= KEYRING_SEARCH_MAX_DEPTH)
- continue;
-
-- if (key_task_permission(make_key_ref(key, possessed),
-- cred, KEY_SEARCH) < 0)
-+ if (key_task_permission(make_key_ref(key, ctx->possessed),
-+ ctx->cred, KEY_SEARCH) < 0)
- continue;
-
- /* stack the current position */
-@@ -489,12 +480,12 @@ not_this_keyring:
- /* we found a viable match */
- found:
- atomic_inc(&key->usage);
-- key->last_used_at = now.tv_sec;
-- keyring->last_used_at = now.tv_sec;
-+ key->last_used_at = ctx->now.tv_sec;
-+ keyring->last_used_at = ctx->now.tv_sec;
- while (sp > 0)
-- stack[--sp].keyring->last_used_at = now.tv_sec;
-+ stack[--sp].keyring->last_used_at = ctx->now.tv_sec;
- key_check(key);
-- key_ref = make_key_ref(key, possessed);
-+ key_ref = make_key_ref(key, ctx->possessed);
- error_2:
- rcu_read_unlock();
- error:
-@@ -514,11 +505,20 @@ key_ref_t keyring_search(key_ref_t keyring,
- struct key_type *type,
- const char *description)
- {
-- if (!type->match)
-+ struct keyring_search_context ctx = {
-+ .index_key.type = type,
-+ .index_key.description = description,
-+ .cred = current_cred(),
-+ .match = type->match,
-+ .match_data = description,
-+ .flags = (type->def_lookup_type |
-+ KEYRING_SEARCH_DO_STATE_CHECK),
-+ };
-+
-+ if (!ctx.match)
- return ERR_PTR(-ENOKEY);
-
-- return keyring_search_aux(keyring, current->cred,
-- type, description, type->match, false);
-+ return keyring_search_aux(keyring, &ctx);
- }
- EXPORT_SYMBOL(keyring_search);
-
-diff --git a/security/keys/proc.c b/security/keys/proc.c
-index 217b685..88e9a46 100644
---- a/security/keys/proc.c
-+++ b/security/keys/proc.c
-@@ -182,7 +182,6 @@ static void proc_keys_stop(struct seq_file *p, void *v)
-
- static int proc_keys_show(struct seq_file *m, void *v)
- {
-- const struct cred *cred = current_cred();
- struct rb_node *_p = v;
- struct key *key = rb_entry(_p, struct key, serial_node);
- struct timespec now;
-@@ -191,15 +190,23 @@ static int proc_keys_show(struct seq_file *m, void *v)
- char xbuf[12];
- int rc;
-
-+ struct keyring_search_context ctx = {
-+ .index_key.type = key->type,
-+ .index_key.description = key->description,
-+ .cred = current_cred(),
-+ .match = lookup_user_key_possessed,
-+ .match_data = key,
-+ .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
-+ KEYRING_SEARCH_LOOKUP_DIRECT),
-+ };
-+
- key_ref = make_key_ref(key, 0);
-
- /* determine if the key is possessed by this process (a test we can
- * skip if the key does not indicate the possessor can view it
- */
- if (key->perm & KEY_POS_VIEW) {
-- skey_ref = search_my_process_keyrings(key->type, key,
-- lookup_user_key_possessed,
-- true, cred);
-+ skey_ref = search_my_process_keyrings(&ctx);
- if (!IS_ERR(skey_ref)) {
- key_ref_put(skey_ref);
- key_ref = make_key_ref(key, 1);
-@@ -211,7 +218,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
- * - the caller holds a spinlock, and thus the RCU read lock, making our
- * access to __current_cred() safe
- */
-- rc = key_task_permission(key_ref, cred, KEY_VIEW);
-+ rc = key_task_permission(key_ref, ctx.cred, KEY_VIEW);
- if (rc < 0)
- return 0;
-
-diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
-index a3410d6..e68a3e0 100644
---- a/security/keys/process_keys.c
-+++ b/security/keys/process_keys.c
-@@ -319,11 +319,7 @@ void key_fsgid_changed(struct task_struct *tsk)
- * In the case of a successful return, the possession attribute is set on the
- * returned key reference.
- */
--key_ref_t search_my_process_keyrings(struct key_type *type,
-- const void *description,
-- key_match_func_t match,
-- bool no_state_check,
-- const struct cred *cred)
-+key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx)
- {
- key_ref_t key_ref, ret, err;
-
-@@ -339,10 +335,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
- err = ERR_PTR(-EAGAIN);
-
- /* search the thread keyring first */
-- if (cred->thread_keyring) {
-+ if (ctx->cred->thread_keyring) {
- key_ref = keyring_search_aux(
-- make_key_ref(cred->thread_keyring, 1),
-- cred, type, description, match, no_state_check);
-+ make_key_ref(ctx->cred->thread_keyring, 1), ctx);
- if (!IS_ERR(key_ref))
- goto found;
-
-@@ -358,10 +353,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
- }
-
- /* search the process keyring second */
-- if (cred->process_keyring) {
-+ if (ctx->cred->process_keyring) {
- key_ref = keyring_search_aux(
-- make_key_ref(cred->process_keyring, 1),
-- cred, type, description, match, no_state_check);
-+ make_key_ref(ctx->cred->process_keyring, 1), ctx);
- if (!IS_ERR(key_ref))
- goto found;
-
-@@ -379,11 +373,11 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
- }
-
- /* search the session keyring */
-- if (cred->session_keyring) {
-+ if (ctx->cred->session_keyring) {
- rcu_read_lock();
- key_ref = keyring_search_aux(
-- make_key_ref(rcu_dereference(cred->session_keyring), 1),
-- cred, type, description, match, no_state_check);
-+ make_key_ref(rcu_dereference(ctx->cred->session_keyring), 1),
-+ ctx);
- rcu_read_unlock();
-
- if (!IS_ERR(key_ref))
-@@ -402,10 +396,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type,
- }
- }
- /* or search the user-session keyring */
-- else if (cred->user->session_keyring) {
-+ else if (ctx->cred->user->session_keyring) {
- key_ref = keyring_search_aux(
-- make_key_ref(cred->user->session_keyring, 1),
-- cred, type, description, match, no_state_check);
-+ make_key_ref(ctx->cred->user->session_keyring, 1),
-+ ctx);
- if (!IS_ERR(key_ref))
- goto found;
-
-@@ -437,19 +431,14 @@ found:
- *
- * Return same as search_my_process_keyrings().
- */
--key_ref_t search_process_keyrings(struct key_type *type,
-- const void *description,
-- key_match_func_t match,
-- bool no_state_check,
-- const struct cred *cred)
-+key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
- {
- struct request_key_auth *rka;
- key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
-
- might_sleep();
-
-- key_ref = search_my_process_keyrings(type, description, match,
-- no_state_check, cred);
-+ key_ref = search_my_process_keyrings(ctx);
- if (!IS_ERR(key_ref))
- goto found;
- err = key_ref;
-@@ -458,19 +447,21 @@ key_ref_t search_process_keyrings(struct key_type *type,
- * search the keyrings of the process mentioned there
- * - we don't permit access to request_key auth keys via this method
- */
-- if (cred->request_key_auth &&
-- cred == current_cred() &&
-- type != &key_type_request_key_auth
-+ if (ctx->cred->request_key_auth &&
-+ ctx->cred == current_cred() &&
-+ ctx->index_key.type != &key_type_request_key_auth
- ) {
-+ const struct cred *cred = ctx->cred;
-+
- /* defend against the auth key being revoked */
- down_read(&cred->request_key_auth->sem);
-
-- if (key_validate(cred->request_key_auth) == 0) {
-- rka = cred->request_key_auth->payload.data;
-+ if (key_validate(ctx->cred->request_key_auth) == 0) {
-+ rka = ctx->cred->request_key_auth->payload.data;
-
-- key_ref = search_process_keyrings(type, description,
-- match, no_state_check,
-- rka->cred);
-+ ctx->cred = rka->cred;
-+ key_ref = search_process_keyrings(ctx);
-+ ctx->cred = cred;
-
- up_read(&cred->request_key_auth->sem);
-
-@@ -524,19 +515,23 @@ int lookup_user_key_possessed(const struct key *key, const void *target)
- key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
- key_perm_t perm)
- {
-+ struct keyring_search_context ctx = {
-+ .match = lookup_user_key_possessed,
-+ .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
-+ KEYRING_SEARCH_LOOKUP_DIRECT),
-+ };
- struct request_key_auth *rka;
-- const struct cred *cred;
- struct key *key;
- key_ref_t key_ref, skey_ref;
- int ret;
-
- try_again:
-- cred = get_current_cred();
-+ ctx.cred = get_current_cred();
- key_ref = ERR_PTR(-ENOKEY);
-
- switch (id) {
- case KEY_SPEC_THREAD_KEYRING:
-- if (!cred->thread_keyring) {
-+ if (!ctx.cred->thread_keyring) {
- if (!(lflags & KEY_LOOKUP_CREATE))
- goto error;
-
-@@ -548,13 +543,13 @@ try_again:
- goto reget_creds;
- }
-
-- key = cred->thread_keyring;
-+ key = ctx.cred->thread_keyring;
- atomic_inc(&key->usage);
- key_ref = make_key_ref(key, 1);
- break;
-
- case KEY_SPEC_PROCESS_KEYRING:
-- if (!cred->process_keyring) {
-+ if (!ctx.cred->process_keyring) {
- if (!(lflags & KEY_LOOKUP_CREATE))
- goto error;
-
-@@ -566,13 +561,13 @@ try_again:
- goto reget_creds;
- }
-
-- key = cred->process_keyring;
-+ key = ctx.cred->process_keyring;
- atomic_inc(&key->usage);
- key_ref = make_key_ref(key, 1);
- break;
-
- case KEY_SPEC_SESSION_KEYRING:
-- if (!cred->session_keyring) {
-+ if (!ctx.cred->session_keyring) {
- /* always install a session keyring upon access if one
- * doesn't exist yet */
- ret = install_user_keyrings();
-@@ -582,13 +577,13 @@ try_again:
- ret = join_session_keyring(NULL);
- else
- ret = install_session_keyring(
-- cred->user->session_keyring);
-+ ctx.cred->user->session_keyring);
-
- if (ret < 0)
- goto error;
- goto reget_creds;
-- } else if (cred->session_keyring ==
-- cred->user->session_keyring &&
-+ } else if (ctx.cred->session_keyring ==
-+ ctx.cred->user->session_keyring &&
- lflags & KEY_LOOKUP_CREATE) {
- ret = join_session_keyring(NULL);
- if (ret < 0)
-@@ -597,32 +592,32 @@ try_again:
- }
-
- rcu_read_lock();
-- key = rcu_dereference(cred->session_keyring);
-+ key = rcu_dereference(ctx.cred->session_keyring);
- atomic_inc(&key->usage);
- rcu_read_unlock();
- key_ref = make_key_ref(key, 1);
- break;
-
- case KEY_SPEC_USER_KEYRING:
-- if (!cred->user->uid_keyring) {
-+ if (!ctx.cred->user->uid_keyring) {
- ret = install_user_keyrings();
- if (ret < 0)
- goto error;
- }
-
-- key = cred->user->uid_keyring;
-+ key = ctx.cred->user->uid_keyring;
- atomic_inc(&key->usage);
- key_ref = make_key_ref(key, 1);
- break;
-
- case KEY_SPEC_USER_SESSION_KEYRING:
-- if (!cred->user->session_keyring) {
-+ if (!ctx.cred->user->session_keyring) {
- ret = install_user_keyrings();
- if (ret < 0)
- goto error;
- }
-
-- key = cred->user->session_keyring;
-+ key = ctx.cred->user->session_keyring;
- atomic_inc(&key->usage);
- key_ref = make_key_ref(key, 1);
- break;
-@@ -633,7 +628,7 @@ try_again:
- goto error;
-
- case KEY_SPEC_REQKEY_AUTH_KEY:
-- key = cred->request_key_auth;
-+ key = ctx.cred->request_key_auth;
- if (!key)
- goto error;
-
-@@ -642,20 +637,20 @@ try_again:
- break;
-
- case KEY_SPEC_REQUESTOR_KEYRING:
-- if (!cred->request_key_auth)
-+ if (!ctx.cred->request_key_auth)
- goto error;
-
-- down_read(&cred->request_key_auth->sem);
-+ down_read(&ctx.cred->request_key_auth->sem);
- if (test_bit(KEY_FLAG_REVOKED,
-- &cred->request_key_auth->flags)) {
-+ &ctx.cred->request_key_auth->flags)) {
- key_ref = ERR_PTR(-EKEYREVOKED);
- key = NULL;
- } else {
-- rka = cred->request_key_auth->payload.data;
-+ rka = ctx.cred->request_key_auth->payload.data;
- key = rka->dest_keyring;
- atomic_inc(&key->usage);
- }
-- up_read(&cred->request_key_auth->sem);
-+ up_read(&ctx.cred->request_key_auth->sem);
- if (!key)
- goto error;
- key_ref = make_key_ref(key, 1);
-@@ -675,9 +670,13 @@ try_again:
- key_ref = make_key_ref(key, 0);
-
- /* check to see if we possess the key */
-- skey_ref = search_process_keyrings(key->type, key,
-- lookup_user_key_possessed,
-- true, cred);
-+ ctx.index_key.type = key->type;
-+ ctx.index_key.description = key->description;
-+ ctx.index_key.desc_len = strlen(key->description);
-+ ctx.match_data = key;
-+ kdebug("check possessed");
-+ skey_ref = search_process_keyrings(&ctx);
-+ kdebug("possessed=%p", skey_ref);
-
- if (!IS_ERR(skey_ref)) {
- key_put(key);
-@@ -717,14 +716,14 @@ try_again:
- goto invalid_key;
-
- /* check the permissions */
-- ret = key_task_permission(key_ref, cred, perm);
-+ ret = key_task_permission(key_ref, ctx.cred, perm);
- if (ret < 0)
- goto invalid_key;
-
- key->last_used_at = current_kernel_time().tv_sec;
-
- error:
-- put_cred(cred);
-+ put_cred(ctx.cred);
- return key_ref;
-
- invalid_key:
-@@ -735,7 +734,7 @@ invalid_key:
- /* if we attempted to install a keyring, then it may have caused new
- * creds to be installed */
- reget_creds:
-- put_cred(cred);
-+ put_cred(ctx.cred);
- goto try_again;
- }
-
-diff --git a/security/keys/request_key.c b/security/keys/request_key.c
-index 586cb79..ab75df4 100644
---- a/security/keys/request_key.c
-+++ b/security/keys/request_key.c
-@@ -345,38 +345,34 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
- * May return a key that's already under construction instead if there was a
- * race between two thread calling request_key().
- */
--static int construct_alloc_key(struct key_type *type,
-- const char *description,
-+static int construct_alloc_key(struct keyring_search_context *ctx,
- struct key *dest_keyring,
- unsigned long flags,
- struct key_user *user,
- struct key **_key)
- {
-- const struct keyring_index_key index_key = {
-- .type = type,
-- .description = description,
-- .desc_len = strlen(description),
-- };
-- const struct cred *cred = current_cred();
- unsigned long prealloc;
- struct key *key;
- key_perm_t perm;
- key_ref_t key_ref;
- int ret;
-
-- kenter("%s,%s,,,", type->name, description);
-+ kenter("%s,%s,,,",
-+ ctx->index_key.type->name, ctx->index_key.description);
-
- *_key = NULL;
- mutex_lock(&user->cons_lock);
-
- perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
- perm |= KEY_USR_VIEW;
-- if (type->read)
-+ if (ctx->index_key.type->read)
- perm |= KEY_POS_READ;
-- if (type == &key_type_keyring || type->update)
-+ if (ctx->index_key.type == &key_type_keyring ||
-+ ctx->index_key.type->update)
- perm |= KEY_POS_WRITE;
-
-- key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
-+ key = key_alloc(ctx->index_key.type, ctx->index_key.description,
-+ ctx->cred->fsuid, ctx->cred->fsgid, ctx->cred,
- perm, flags);
- if (IS_ERR(key))
- goto alloc_failed;
-@@ -384,7 +380,7 @@ static int construct_alloc_key(struct key_type *type,
- set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
-
- if (dest_keyring) {
-- ret = __key_link_begin(dest_keyring, &index_key, &prealloc);
-+ ret = __key_link_begin(dest_keyring, &ctx->index_key, &prealloc);
- if (ret < 0)
- goto link_prealloc_failed;
- }
-@@ -394,8 +390,7 @@ static int construct_alloc_key(struct key_type *type,
- * waited for locks */
- mutex_lock(&key_construction_mutex);
-
-- key_ref = search_process_keyrings(type, description, type->match,
-- false, cred);
-+ key_ref = search_process_keyrings(ctx);
- if (!IS_ERR(key_ref))
- goto key_already_present;
-
-@@ -404,7 +399,7 @@ static int construct_alloc_key(struct key_type *type,
-
- mutex_unlock(&key_construction_mutex);
- if (dest_keyring)
-- __key_link_end(dest_keyring, &index_key, prealloc);
-+ __key_link_end(dest_keyring, &ctx->index_key, prealloc);
- mutex_unlock(&user->cons_lock);
- *_key = key;
- kleave(" = 0 [%d]", key_serial(key));
-@@ -420,7 +415,7 @@ key_already_present:
- ret = __key_link_check_live_key(dest_keyring, key);
- if (ret == 0)
- __key_link(dest_keyring, key, &prealloc);
-- __key_link_end(dest_keyring, &index_key, prealloc);
-+ __key_link_end(dest_keyring, &ctx->index_key, prealloc);
- if (ret < 0)
- goto link_check_failed;
- }
-@@ -449,8 +444,7 @@ alloc_failed:
- /*
- * Commence key construction.
- */
--static struct key *construct_key_and_link(struct key_type *type,
-- const char *description,
-+static struct key *construct_key_and_link(struct keyring_search_context *ctx,
- const char *callout_info,
- size_t callout_len,
- void *aux,
-@@ -469,8 +463,7 @@ static struct key *construct_key_and_link(struct key_type *type,
-
- construct_get_dest_keyring(&dest_keyring);
-
-- ret = construct_alloc_key(type, description, dest_keyring, flags, user,
-- &key);
-+ ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key);
- key_user_put(user);
-
- if (ret == 0) {
-@@ -534,18 +527,24 @@ struct key *request_key_and_link(struct key_type *type,
- struct key *dest_keyring,
- unsigned long flags)
- {
-- const struct cred *cred = current_cred();
-+ struct keyring_search_context ctx = {
-+ .index_key.type = type,
-+ .index_key.description = description,
-+ .cred = current_cred(),
-+ .match = type->match,
-+ .match_data = description,
-+ .flags = KEYRING_SEARCH_LOOKUP_DIRECT,
-+ };
- struct key *key;
- key_ref_t key_ref;
- int ret;
-
- kenter("%s,%s,%p,%zu,%p,%p,%lx",
-- type->name, description, callout_info, callout_len, aux,
-- dest_keyring, flags);
-+ ctx.index_key.type->name, ctx.index_key.description,
-+ callout_info, callout_len, aux, dest_keyring, flags);
-
- /* search all the process keyrings for a key */
-- key_ref = search_process_keyrings(type, description, type->match,
-- false, cred);
-+ key_ref = search_process_keyrings(&ctx);
-
- if (!IS_ERR(key_ref)) {
- key = key_ref_to_ptr(key_ref);
-@@ -568,9 +567,8 @@ struct key *request_key_and_link(struct key_type *type,
- if (!callout_info)
- goto error;
-
-- key = construct_key_and_link(type, description, callout_info,
-- callout_len, aux, dest_keyring,
-- flags);
-+ key = construct_key_and_link(&ctx, callout_info, callout_len,
-+ aux, dest_keyring, flags);
- }
-
- error:
-diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
-index 92077de..8d09852 100644
---- a/security/keys/request_key_auth.c
-+++ b/security/keys/request_key_auth.c
-@@ -239,15 +239,17 @@ static int key_get_instantiation_authkey_match(const struct key *key,
- */
- struct key *key_get_instantiation_authkey(key_serial_t target_id)
- {
-- const struct cred *cred = current_cred();
-+ struct keyring_search_context ctx = {
-+ .index_key.type = &key_type_request_key_auth,
-+ .cred = current_cred(),
-+ .match = key_get_instantiation_authkey_match,
-+ .match_data = (void *)(unsigned long)target_id,
-+ .flags = KEYRING_SEARCH_LOOKUP_DIRECT,
-+ };
- struct key *authkey;
- key_ref_t authkey_ref;
-
-- authkey_ref = search_process_keyrings(
-- &key_type_request_key_auth,
-- (void *) (unsigned long) target_id,
-- key_get_instantiation_authkey_match,
-- false, cred);
-+ authkey_ref = search_process_keyrings(&ctx);
-
- if (IS_ERR(authkey_ref)) {
- authkey = ERR_CAST(authkey_ref);
-diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
-index 55dc889..faa2cae 100644
---- a/security/keys/user_defined.c
-+++ b/security/keys/user_defined.c
-@@ -25,14 +25,15 @@ static int logon_vet_description(const char *desc);
- * arbitrary blob of data as the payload
- */
- struct key_type key_type_user = {
-- .name = "user",
-- .instantiate = user_instantiate,
-- .update = user_update,
-- .match = user_match,
-- .revoke = user_revoke,
-- .destroy = user_destroy,
-- .describe = user_describe,
-- .read = user_read,
-+ .name = "user",
-+ .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
-+ .instantiate = user_instantiate,
-+ .update = user_update,
-+ .match = user_match,
-+ .revoke = user_revoke,
-+ .destroy = user_destroy,
-+ .describe = user_describe,
-+ .read = user_read,
- };
-
- EXPORT_SYMBOL_GPL(key_type_user);
-@@ -45,6 +46,7 @@ EXPORT_SYMBOL_GPL(key_type_user);
- */
- struct key_type key_type_logon = {
- .name = "logon",
-+ .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
- .instantiate = user_instantiate,
- .update = user_update,
- .match = user_match,
---
-1.8.3.1
-
-
-From 4dffed72b92a305bcdbb73b719570d8f4ec53f46 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:52 +0100
-Subject: [PATCH 06/10] KEYS: Search for auth-key by name rather than target
- key ID
-
-Search for auth-key by name rather than by target key ID as, in a future
-patch, we'll by searching directly by index key in preference to iteration
-over all keys.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/request_key_auth.c | 21 +++++++--------------
- 1 file changed, 7 insertions(+), 14 deletions(-)
-
-diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
-index 8d09852..7495a93 100644
---- a/security/keys/request_key_auth.c
-+++ b/security/keys/request_key_auth.c
-@@ -18,6 +18,7 @@
- #include <linux/slab.h>
- #include <asm/uaccess.h>
- #include "internal.h"
-+#include <keys/user-type.h>
-
- static int request_key_auth_instantiate(struct key *,
- struct key_preparsed_payload *);
-@@ -222,33 +223,25 @@ error_alloc:
- }
-
- /*
-- * See if an authorisation key is associated with a particular key.
-- */
--static int key_get_instantiation_authkey_match(const struct key *key,
-- const void *_id)
--{
-- struct request_key_auth *rka = key->payload.data;
-- key_serial_t id = (key_serial_t)(unsigned long) _id;
--
-- return rka->target_key->serial == id;
--}
--
--/*
- * Search the current process's keyrings for the authorisation key for
- * instantiation of a key.
- */
- struct key *key_get_instantiation_authkey(key_serial_t target_id)
- {
-+ char description[16];
- struct keyring_search_context ctx = {
- .index_key.type = &key_type_request_key_auth,
-+ .index_key.description = description,
- .cred = current_cred(),
-- .match = key_get_instantiation_authkey_match,
-- .match_data = (void *)(unsigned long)target_id,
-+ .match = user_match,
-+ .match_data = description,
- .flags = KEYRING_SEARCH_LOOKUP_DIRECT,
- };
- struct key *authkey;
- key_ref_t authkey_ref;
-
-+ sprintf(description, "%x", target_id);
-+
- authkey_ref = search_process_keyrings(&ctx);
-
- if (IS_ERR(authkey_ref)) {
---
-1.8.3.1
-
-
-From 5f3c76b0923620ddd5294270ac478819f06f21d1 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:53 +0100
-Subject: [PATCH 07/10] KEYS: Define a __key_get() wrapper to use rather than
- atomic_inc()
-
-Define a __key_get() wrapper to use rather than atomic_inc() on the key usage
-count as this makes it easier to hook in refcount error debugging.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/security/keys.txt | 13 ++++++++-----
- include/linux/key.h | 10 +++++++---
- security/keys/key.c | 2 +-
- security/keys/keyring.c | 6 +++---
- security/keys/process_keys.c | 16 ++++++++--------
- 5 files changed, 27 insertions(+), 20 deletions(-)
-
-diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
-index 9ede670..a4c33f1 100644
---- a/Documentation/security/keys.txt
-+++ b/Documentation/security/keys.txt
-@@ -960,14 +960,17 @@ payload contents" for more information.
- the argument will not be parsed.
-
-
--(*) Extra references can be made to a key by calling the following function:
-+(*) Extra references can be made to a key by calling one of the following
-+ functions:
-
-+ struct key *__key_get(struct key *key);
- struct key *key_get(struct key *key);
-
-- These need to be disposed of by calling key_put() when they've been
-- finished with. The key pointer passed in will be returned. If the pointer
-- is NULL or CONFIG_KEYS is not set then the key will not be dereferenced and
-- no increment will take place.
-+ Keys so references will need to be disposed of by calling key_put() when
-+ they've been finished with. The key pointer passed in will be returned.
-+
-+ In the case of key_get(), if the pointer is NULL or CONFIG_KEYS is not set
-+ then the key will not be dereferenced and no increment will take place.
-
-
- (*) A key's serial number can be obtained by calling:
-diff --git a/include/linux/key.h b/include/linux/key.h
-index d573e82..ef596c7 100644
---- a/include/linux/key.h
-+++ b/include/linux/key.h
-@@ -219,13 +219,17 @@ extern void key_revoke(struct key *key);
- extern void key_invalidate(struct key *key);
- extern void key_put(struct key *key);
-
--static inline struct key *key_get(struct key *key)
-+static inline struct key *__key_get(struct key *key)
- {
-- if (key)
-- atomic_inc(&key->usage);
-+ atomic_inc(&key->usage);
- return key;
- }
-
-+static inline struct key *key_get(struct key *key)
-+{
-+ return key ? __key_get(key) : key;
-+}
-+
- static inline void key_ref_put(key_ref_t key_ref)
- {
- key_put(key_ref_to_ptr(key_ref));
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 7e6bc39..1e23cc2 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -644,7 +644,7 @@ found:
- /* this races with key_put(), but that doesn't matter since key_put()
- * doesn't actually change the key
- */
-- atomic_inc(&key->usage);
-+ __key_get(key);
-
- error:
- spin_unlock(&key_serial_lock);
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index b42f2d4..87eff32 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -479,7 +479,7 @@ not_this_keyring:
-
- /* we found a viable match */
- found:
-- atomic_inc(&key->usage);
-+ __key_get(key);
- key->last_used_at = ctx->now.tv_sec;
- keyring->last_used_at = ctx->now.tv_sec;
- while (sp > 0)
-@@ -573,7 +573,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
- return ERR_PTR(-ENOKEY);
-
- found:
-- atomic_inc(&key->usage);
-+ __key_get(key);
- keyring->last_used_at = key->last_used_at =
- current_kernel_time().tv_sec;
- rcu_read_unlock();
-@@ -909,7 +909,7 @@ void __key_link(struct key *keyring, struct key *key,
-
- klist = rcu_dereference_locked_keyring(keyring);
-
-- atomic_inc(&key->usage);
-+ __key_get(key);
- keyring->last_used_at = key->last_used_at =
- current_kernel_time().tv_sec;
-
-diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
-index e68a3e0..68548ea 100644
---- a/security/keys/process_keys.c
-+++ b/security/keys/process_keys.c
-@@ -235,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
- if (IS_ERR(keyring))
- return PTR_ERR(keyring);
- } else {
-- atomic_inc(&keyring->usage);
-+ __key_get(keyring);
- }
-
- /* install the keyring */
-@@ -544,7 +544,7 @@ try_again:
- }
-
- key = ctx.cred->thread_keyring;
-- atomic_inc(&key->usage);
-+ __key_get(key);
- key_ref = make_key_ref(key, 1);
- break;
-
-@@ -562,7 +562,7 @@ try_again:
- }
-
- key = ctx.cred->process_keyring;
-- atomic_inc(&key->usage);
-+ __key_get(key);
- key_ref = make_key_ref(key, 1);
- break;
-
-@@ -593,7 +593,7 @@ try_again:
-
- rcu_read_lock();
- key = rcu_dereference(ctx.cred->session_keyring);
-- atomic_inc(&key->usage);
-+ __key_get(key);
- rcu_read_unlock();
- key_ref = make_key_ref(key, 1);
- break;
-@@ -606,7 +606,7 @@ try_again:
- }
-
- key = ctx.cred->user->uid_keyring;
-- atomic_inc(&key->usage);
-+ __key_get(key);
- key_ref = make_key_ref(key, 1);
- break;
-
-@@ -618,7 +618,7 @@ try_again:
- }
-
- key = ctx.cred->user->session_keyring;
-- atomic_inc(&key->usage);
-+ __key_get(key);
- key_ref = make_key_ref(key, 1);
- break;
-
-@@ -632,7 +632,7 @@ try_again:
- if (!key)
- goto error;
-
-- atomic_inc(&key->usage);
-+ __key_get(key);
- key_ref = make_key_ref(key, 1);
- break;
-
-@@ -648,7 +648,7 @@ try_again:
- } else {
- rka = ctx.cred->request_key_auth->payload.data;
- key = rka->dest_keyring;
-- atomic_inc(&key->usage);
-+ __key_get(key);
- }
- up_read(&ctx.cred->request_key_auth->sem);
- if (!key)
---
-1.8.3.1
-
-
-From 99b0f3185570bb92a61952673b9933d9c1999508 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:53 +0100
-Subject: [PATCH 08/10] KEYS: Drop the permissions argument from
- __keyring_search_one()
-
-Drop the permissions argument from __keyring_search_one() as the only caller
-passes 0 here - which causes all checks to be skipped.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/internal.h | 3 +--
- security/keys/key.c | 2 +-
- security/keys/keyring.c | 9 +++------
- 3 files changed, 5 insertions(+), 9 deletions(-)
-
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index f4bf938..73950bf 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -99,8 +99,7 @@ extern void __key_link_end(struct key *keyring,
- unsigned long prealloc);
-
- extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
-- const struct keyring_index_key *index_key,
-- key_perm_t perm);
-+ const struct keyring_index_key *index_key);
-
- extern struct key *keyring_search_instkey(struct key *keyring,
- key_serial_t target_id);
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 1e23cc2..7d716b8 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -847,7 +847,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- * update that instead if possible
- */
- if (index_key.type->update) {
-- key_ref = __keyring_search_one(keyring_ref, &index_key, 0);
-+ key_ref = __keyring_search_one(keyring_ref, &index_key);
- if (!IS_ERR(key_ref))
- goto found_matching_key;
- }
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 87eff32..eeef1a0 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -531,15 +531,14 @@ EXPORT_SYMBOL(keyring_search);
- * RCU is used to make it unnecessary to lock the keyring key list here.
- *
- * Returns a pointer to the found key with usage count incremented if
-- * successful and returns -ENOKEY if not found. Revoked keys and keys not
-- * providing the requested permission are skipped over.
-+ * successful and returns -ENOKEY if not found. Revoked and invalidated keys
-+ * are skipped over.
- *
- * If successful, the possession indicator is propagated from the keyring ref
- * to the returned key reference.
- */
- key_ref_t __keyring_search_one(key_ref_t keyring_ref,
-- const struct keyring_index_key *index_key,
-- key_perm_t perm)
-+ const struct keyring_index_key *index_key)
- {
- struct keyring_list *klist;
- struct key *keyring, *key;
-@@ -560,8 +559,6 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
- if (key->type == index_key->type &&
- (!key->type->match ||
- key->type->match(key, index_key->description)) &&
-- key_permission(make_key_ref(key, possessed),
-- perm) == 0 &&
- !(key->flags & ((1 << KEY_FLAG_INVALIDATED) |
- (1 << KEY_FLAG_REVOKED)))
- )
---
-1.8.3.1
-
-
-From cb720b39e41e62d55bf1e5f8243d78643d31154d Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:53 +0100
-Subject: [PATCH 09/10] Add a generic associative array implementation.
-
-Add a generic associative array implementation that can be used as the
-container for keyrings, thereby massively increasing the capacity available
-whilst also speeding up searching in keyrings that contain a lot of keys.
-
-This may also be useful in FS-Cache for tracking cookies.
-
-Documentation is added into Documentation/associative_array.txt
-
-Some of the properties of the implementation are:
-
- (1) Objects are opaque pointers. The implementation does not care where they
- point (if anywhere) or what they point to (if anything).
-
- [!] NOTE: Pointers to objects _must_ be zero in the two least significant
- bits.
-
- (2) Objects do not need to contain linkage blocks for use by the array. This
- permits an object to be located in multiple arrays simultaneously.
- Rather, the array is made up of metadata blocks that point to objects.
-
- (3) Objects are labelled as being one of two types (the type is a bool value).
- This information is stored in the array, but has no consequence to the
- array itself or its algorithms.
-
- (4) Objects require index keys to locate them within the array.
-
- (5) Index keys must be unique. Inserting an object with the same key as one
- already in the array will replace the old object.
-
- (6) Index keys can be of any length and can be of different lengths.
-
- (7) Index keys should encode the length early on, before any variation due to
- length is seen.
-
- (8) Index keys can include a hash to scatter objects throughout the array.
-
- (9) The array can iterated over. The objects will not necessarily come out in
- key order.
-
-(10) The array can be iterated whilst it is being modified, provided the RCU
- readlock is being held by the iterator. Note, however, under these
- circumstances, some objects may be seen more than once. If this is a
- problem, the iterator should lock against modification. Objects will not
- be missed, however, unless deleted.
-
-(11) Objects in the array can be looked up by means of their index key.
-
-(12) Objects can be looked up whilst the array is being modified, provided the
- RCU readlock is being held by the thread doing the look up.
-
-The implementation uses a tree of 16-pointer nodes internally that are indexed
-on each level by nibbles from the index key. To improve memory efficiency,
-shortcuts can be emplaced to skip over what would otherwise be a series of
-single-occupancy nodes. Further, nodes pack leaf object pointers into spare
-space in the node rather than making an extra branch until as such time an
-object needs to be added to a full node.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- Documentation/assoc_array.txt | 574 +++++++++++++
- include/linux/assoc_array.h | 92 ++
- include/linux/assoc_array_priv.h | 182 ++++
- lib/Kconfig | 14 +
- lib/Makefile | 1 +
- lib/assoc_array.c | 1745 ++++++++++++++++++++++++++++++++++++++
- 6 files changed, 2608 insertions(+)
- create mode 100644 Documentation/assoc_array.txt
- create mode 100644 include/linux/assoc_array.h
- create mode 100644 include/linux/assoc_array_priv.h
- create mode 100644 lib/assoc_array.c
-
-diff --git a/Documentation/assoc_array.txt b/Documentation/assoc_array.txt
-new file mode 100644
-index 0000000..f4faec0
---- /dev/null
-+++ b/Documentation/assoc_array.txt
-@@ -0,0 +1,574 @@
-+ ========================================
-+ GENERIC ASSOCIATIVE ARRAY IMPLEMENTATION
-+ ========================================
-+
-+Contents:
-+
-+ - Overview.
-+
-+ - The public API.
-+ - Edit script.
-+ - Operations table.
-+ - Manipulation functions.
-+ - Access functions.
-+ - Index key form.
-+
-+ - Internal workings.
-+ - Basic internal tree layout.
-+ - Shortcuts.
-+ - Splitting and collapsing nodes.
-+ - Non-recursive iteration.
-+ - Simultaneous alteration and iteration.
-+
-+
-+========
-+OVERVIEW
-+========
-+
-+This associative array implementation is an object container with the following
-+properties:
-+
-+ (1) Objects are opaque pointers. The implementation does not care where they
-+ point (if anywhere) or what they point to (if anything).
-+
-+ [!] NOTE: Pointers to objects _must_ be zero in the least significant bit.
-+
-+ (2) Objects do not need to contain linkage blocks for use by the array. This
-+ permits an object to be located in multiple arrays simultaneously.
-+ Rather, the array is made up of metadata blocks that point to objects.
-+
-+ (3) Objects require index keys to locate them within the array.
-+
-+ (4) Index keys must be unique. Inserting an object with the same key as one
-+ already in the array will replace the old object.
-+
-+ (5) Index keys can be of any length and can be of different lengths.
-+
-+ (6) Index keys should encode the length early on, before any variation due to
-+ length is seen.
-+
-+ (7) Index keys can include a hash to scatter objects throughout the array.
-+
-+ (8) The array can iterated over. The objects will not necessarily come out in
-+ key order.
-+
-+ (9) The array can be iterated over whilst it is being modified, provided the
-+ RCU readlock is being held by the iterator. Note, however, under these
-+ circumstances, some objects may be seen more than once. If this is a
-+ problem, the iterator should lock against modification. Objects will not
-+ be missed, however, unless deleted.
-+
-+(10) Objects in the array can be looked up by means of their index key.
-+
-+(11) Objects can be looked up whilst the array is being modified, provided the
-+ RCU readlock is being held by the thread doing the look up.
-+
-+The implementation uses a tree of 16-pointer nodes internally that are indexed
-+on each level by nibbles from the index key in the same manner as in a radix
-+tree. To improve memory efficiency, shortcuts can be emplaced to skip over
-+what would otherwise be a series of single-occupancy nodes. Further, nodes
-+pack leaf object pointers into spare space in the node rather than making an
-+extra branch until as such time an object needs to be added to a full node.
-+
-+
-+==============
-+THE PUBLIC API
-+==============
-+
-+The public API can be found in <linux/assoc_array.h>. The associative array is
-+rooted on the following structure:
-+
-+ struct assoc_array {
-+ ...
-+ };
-+
-+The code is selected by enabling CONFIG_ASSOCIATIVE_ARRAY.
-+
-+
-+EDIT SCRIPT
-+-----------
-+
-+The insertion and deletion functions produce an 'edit script' that can later be
-+applied to effect the changes without risking ENOMEM. This retains the
-+preallocated metadata blocks that will be installed in the internal tree and
-+keeps track of the metadata blocks that will be removed from the tree when the
-+script is applied.
-+
-+This is also used to keep track of dead blocks and dead objects after the
-+script has been applied so that they can be freed later. The freeing is done
-+after an RCU grace period has passed - thus allowing access functions to
-+proceed under the RCU read lock.
-+
-+The script appears as outside of the API as a pointer of the type:
-+
-+ struct assoc_array_edit;
-+
-+There are two functions for dealing with the script:
-+
-+ (1) Apply an edit script.
-+
-+ void assoc_array_apply_edit(struct assoc_array_edit *edit);
-+
-+ This will perform the edit functions, interpolating various write barriers
-+ to permit accesses under the RCU read lock to continue. The edit script
-+ will then be passed to call_rcu() to free it and any dead stuff it points
-+ to.
-+
-+ (2) Cancel an edit script.
-+
-+ void assoc_array_cancel_edit(struct assoc_array_edit *edit);
-+
-+ This frees the edit script and all preallocated memory immediately. If
-+ this was for insertion, the new object is _not_ released by this function,
-+ but must rather be released by the caller.
-+
-+These functions are guaranteed not to fail.
-+
-+
-+OPERATIONS TABLE
-+----------------
-+
-+Various functions take a table of operations:
-+
-+ struct assoc_array_ops {
-+ ...
-+ };
-+
-+This points to a number of methods, all of which need to be provided:
-+
-+ (1) Get a chunk of index key from caller data:
-+
-+ unsigned long (*get_key_chunk)(const void *index_key, int level);
-+
-+ This should return a chunk of caller-supplied index key starting at the
-+ *bit* position given by the level argument. The level argument will be a
-+ multiple of ASSOC_ARRAY_KEY_CHUNK_SIZE and the function should return
-+ ASSOC_ARRAY_KEY_CHUNK_SIZE bits. No error is possible.
-+
-+
-+ (2) Get a chunk of an object's index key.
-+
-+ unsigned long (*get_object_key_chunk)(const void *object, int level);
-+
-+ As the previous function, but gets its data from an object in the array
-+ rather than from a caller-supplied index key.
-+
-+
-+ (3) See if this is the object we're looking for.
-+
-+ bool (*compare_object)(const void *object, const void *index_key);
-+
-+ Compare the object against an index key and return true if it matches and
-+ false if it doesn't.
-+
-+
-+ (4) Diff the index keys of two objects.
-+
-+ int (*diff_objects)(const void *a, const void *b);
-+
-+ Return the bit position at which the index keys of two objects differ or
-+ -1 if they are the same.
-+
-+
-+ (5) Free an object.
-+
-+ void (*free_object)(void *object);
-+
-+ Free the specified object. Note that this may be called an RCU grace
-+ period after assoc_array_apply_edit() was called, so synchronize_rcu() may
-+ be necessary on module unloading.
-+
-+
-+MANIPULATION FUNCTIONS
-+----------------------
-+
-+There are a number of functions for manipulating an associative array:
-+
-+ (1) Initialise an associative array.
-+
-+ void assoc_array_init(struct assoc_array *array);
-+
-+ This initialises the base structure for an associative array. It can't
-+ fail.
-+
-+
-+ (2) Insert/replace an object in an associative array.
-+
-+ struct assoc_array_edit *
-+ assoc_array_insert(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key,
-+ void *object);
-+
-+ This inserts the given object into the array. Note that the least
-+ significant bit of the pointer must be zero as it's used to type-mark
-+ pointers internally.
-+
-+ If an object already exists for that key then it will be replaced with the
-+ new object and the old one will be freed automatically.
-+
-+ The index_key argument should hold index key information and is
-+ passed to the methods in the ops table when they are called.
-+
-+ This function makes no alteration to the array itself, but rather returns
-+ an edit script that must be applied. -ENOMEM is returned in the case of
-+ an out-of-memory error.
-+
-+ The caller should lock exclusively against other modifiers of the array.
-+
-+
-+ (3) Delete an object from an associative array.
-+
-+ struct assoc_array_edit *
-+ assoc_array_delete(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key);
-+
-+ This deletes an object that matches the specified data from the array.
-+
-+ The index_key argument should hold index key information and is
-+ passed to the methods in the ops table when they are called.
-+
-+ This function makes no alteration to the array itself, but rather returns
-+ an edit script that must be applied. -ENOMEM is returned in the case of
-+ an out-of-memory error. NULL will be returned if the specified object is
-+ not found within the array.
-+
-+ The caller should lock exclusively against other modifiers of the array.
-+
-+
-+ (4) Delete all objects from an associative array.
-+
-+ struct assoc_array_edit *
-+ assoc_array_clear(struct assoc_array *array,
-+ const struct assoc_array_ops *ops);
-+
-+ This deletes all the objects from an associative array and leaves it
-+ completely empty.
-+
-+ This function makes no alteration to the array itself, but rather returns
-+ an edit script that must be applied. -ENOMEM is returned in the case of
-+ an out-of-memory error.
-+
-+ The caller should lock exclusively against other modifiers of the array.
-+
-+
-+ (5) Destroy an associative array, deleting all objects.
-+
-+ void assoc_array_destroy(struct assoc_array *array,
-+ const struct assoc_array_ops *ops);
-+
-+ This destroys the contents of the associative array and leaves it
-+ completely empty. It is not permitted for another thread to be traversing
-+ the array under the RCU read lock at the same time as this function is
-+ destroying it as no RCU deferral is performed on memory release -
-+ something that would require memory to be allocated.
-+
-+ The caller should lock exclusively against other modifiers and accessors
-+ of the array.
-+
-+
-+ (6) Garbage collect an associative array.
-+
-+ int assoc_array_gc(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ bool (*iterator)(void *object, void *iterator_data),
-+ void *iterator_data);
-+
-+ This iterates over the objects in an associative array and passes each one
-+ to iterator(). If iterator() returns true, the object is kept. If it
-+ returns false, the object will be freed. If the iterator() function
-+ returns true, it must perform any appropriate refcount incrementing on the
-+ object before returning.
-+
-+ The internal tree will be packed down if possible as part of the iteration
-+ to reduce the number of nodes in it.
-+
-+ The iterator_data is passed directly to iterator() and is otherwise
-+ ignored by the function.
-+
-+ The function will return 0 if successful and -ENOMEM if there wasn't
-+ enough memory.
-+
-+ It is possible for other threads to iterate over or search the array under
-+ the RCU read lock whilst this function is in progress. The caller should
-+ lock exclusively against other modifiers of the array.
-+
-+
-+ACCESS FUNCTIONS
-+----------------
-+
-+There are two functions for accessing an associative array:
-+
-+ (1) Iterate over all the objects in an associative array.
-+
-+ int assoc_array_iterate(const struct assoc_array *array,
-+ int (*iterator)(const void *object,
-+ void *iterator_data),
-+ void *iterator_data);
-+
-+ This passes each object in the array to the iterator callback function.
-+ iterator_data is private data for that function.
-+
-+ This may be used on an array at the same time as the array is being
-+ modified, provided the RCU read lock is held. Under such circumstances,
-+ it is possible for the iteration function to see some objects twice. If
-+ this is a problem, then modification should be locked against. The
-+ iteration algorithm should not, however, miss any objects.
-+
-+ The function will return 0 if no objects were in the array or else it will
-+ return the result of the last iterator function called. Iteration stops
-+ immediately if any call to the iteration function results in a non-zero
-+ return.
-+
-+
-+ (2) Find an object in an associative array.
-+
-+ void *assoc_array_find(const struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key);
-+
-+ This walks through the array's internal tree directly to the object
-+ specified by the index key..
-+
-+ This may be used on an array at the same time as the array is being
-+ modified, provided the RCU read lock is held.
-+
-+ The function will return the object if found (and set *_type to the object
-+ type) or will return NULL if the object was not found.
-+
-+
-+INDEX KEY FORM
-+--------------
-+
-+The index key can be of any form, but since the algorithms aren't told how long
-+the key is, it is strongly recommended that the index key includes its length
-+very early on before any variation due to the length would have an effect on
-+comparisons.
-+
-+This will cause leaves with different length keys to scatter away from each
-+other - and those with the same length keys to cluster together.
-+
-+It is also recommended that the index key begin with a hash of the rest of the
-+key to maximise scattering throughout keyspace.
-+
-+The better the scattering, the wider and lower the internal tree will be.
-+
-+Poor scattering isn't too much of a problem as there are shortcuts and nodes
-+can contain mixtures of leaves and metadata pointers.
-+
-+The index key is read in chunks of machine word. Each chunk is subdivided into
-+one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and
-+on a 64-bit CPU, 16 levels. Unless the scattering is really poor, it is
-+unlikely that more than one word of any particular index key will have to be
-+used.
-+
-+
-+=================
-+INTERNAL WORKINGS
-+=================
-+
-+The associative array data structure has an internal tree. This tree is
-+constructed of two types of metadata blocks: nodes and shortcuts.
-+
-+A node is an array of slots. Each slot can contain one of four things:
-+
-+ (*) A NULL pointer, indicating that the slot is empty.
-+
-+ (*) A pointer to an object (a leaf).
-+
-+ (*) A pointer to a node at the next level.
-+
-+ (*) A pointer to a shortcut.
-+
-+
-+BASIC INTERNAL TREE LAYOUT
-+--------------------------
-+
-+Ignoring shortcuts for the moment, the nodes form a multilevel tree. The index
-+key space is strictly subdivided by the nodes in the tree and nodes occur on
-+fixed levels. For example:
-+
-+ Level: 0 1 2 3
-+ =============== =============== =============== ===============
-+ NODE D
-+ NODE B NODE C +------>+---+
-+ +------>+---+ +------>+---+ | | 0 |
-+ NODE A | | 0 | | | 0 | | +---+
-+ +---+ | +---+ | +---+ | : :
-+ | 0 | | : : | : : | +---+
-+ +---+ | +---+ | +---+ | | f |
-+ | 1 |---+ | 3 |---+ | 7 |---+ +---+
-+ +---+ +---+ +---+
-+ : : : : | 8 |---+
-+ +---+ +---+ +---+ | NODE E
-+ | e |---+ | f | : : +------>+---+
-+ +---+ | +---+ +---+ | 0 |
-+ | f | | | f | +---+
-+ +---+ | +---+ : :
-+ | NODE F +---+
-+ +------>+---+ | f |
-+ | 0 | NODE G +---+
-+ +---+ +------>+---+
-+ : : | | 0 |
-+ +---+ | +---+
-+ | 6 |---+ : :
-+ +---+ +---+
-+ : : | f |
-+ +---+ +---+
-+ | f |
-+ +---+
-+
-+In the above example, there are 7 nodes (A-G), each with 16 slots (0-f).
-+Assuming no other meta data nodes in the tree, the key space is divided thusly:
-+
-+ KEY PREFIX NODE
-+ ========== ====
-+ 137* D
-+ 138* E
-+ 13[0-69-f]* C
-+ 1[0-24-f]* B
-+ e6* G
-+ e[0-57-f]* F
-+ [02-df]* A
-+
-+So, for instance, keys with the following example index keys will be found in
-+the appropriate nodes:
-+
-+ INDEX KEY PREFIX NODE
-+ =============== ======= ====
-+ 13694892892489 13 C
-+ 13795289025897 137 D
-+ 13889dde88793 138 E
-+ 138bbb89003093 138 E
-+ 1394879524789 12 C
-+ 1458952489 1 B
-+ 9431809de993ba - A
-+ b4542910809cd - A
-+ e5284310def98 e F
-+ e68428974237 e6 G
-+ e7fffcbd443 e F
-+ f3842239082 - A
-+
-+To save memory, if a node can hold all the leaves in its portion of keyspace,
-+then the node will have all those leaves in it and will not have any metadata
-+pointers - even if some of those leaves would like to be in the same slot.
-+
-+A node can contain a heterogeneous mix of leaves and metadata pointers.
-+Metadata pointers must be in the slots that match their subdivisions of key
-+space. The leaves can be in any slot not occupied by a metadata pointer. It
-+is guaranteed that none of the leaves in a node will match a slot occupied by a
-+metadata pointer. If the metadata pointer is there, any leaf whose key matches
-+the metadata key prefix must be in the subtree that the metadata pointer points
-+to.
-+
-+In the above example list of index keys, node A will contain:
-+
-+ SLOT CONTENT INDEX KEY (PREFIX)
-+ ==== =============== ==================
-+ 1 PTR TO NODE B 1*
-+ any LEAF 9431809de993ba
-+ any LEAF b4542910809cd
-+ e PTR TO NODE F e*
-+ any LEAF f3842239082
-+
-+and node B:
-+
-+ 3 PTR TO NODE C 13*
-+ any LEAF 1458952489
-+
-+
-+SHORTCUTS
-+---------
-+
-+Shortcuts are metadata records that jump over a piece of keyspace. A shortcut
-+is a replacement for a series of single-occupancy nodes ascending through the
-+levels. Shortcuts exist to save memory and to speed up traversal.
-+
-+It is possible for the root of the tree to be a shortcut - say, for example,
-+the tree contains at least 17 nodes all with key prefix '1111'. The insertion
-+algorithm will insert a shortcut to skip over the '1111' keyspace in a single
-+bound and get to the fourth level where these actually become different.
-+
-+
-+SPLITTING AND COLLAPSING NODES
-+------------------------------
-+
-+Each node has a maximum capacity of 16 leaves and metadata pointers. If the
-+insertion algorithm finds that it is trying to insert a 17th object into a
-+node, that node will be split such that at least two leaves that have a common
-+key segment at that level end up in a separate node rooted on that slot for
-+that common key segment.
-+
-+If the leaves in a full node and the leaf that is being inserted are
-+sufficiently similar, then a shortcut will be inserted into the tree.
-+
-+When the number of objects in the subtree rooted at a node falls to 16 or
-+fewer, then the subtree will be collapsed down to a single node - and this will
-+ripple towards the root if possible.
-+
-+
-+NON-RECURSIVE ITERATION
-+-----------------------
-+
-+Each node and shortcut contains a back pointer to its parent and the number of
-+slot in that parent that points to it. None-recursive iteration uses these to
-+proceed rootwards through the tree, going to the parent node, slot N + 1 to
-+make sure progress is made without the need for a stack.
-+
-+The backpointers, however, make simultaneous alteration and iteration tricky.
-+
-+
-+SIMULTANEOUS ALTERATION AND ITERATION
-+-------------------------------------
-+
-+There are a number of cases to consider:
-+
-+ (1) Simple insert/replace. This involves simply replacing a NULL or old
-+ matching leaf pointer with the pointer to the new leaf after a barrier.
-+ The metadata blocks don't change otherwise. An old leaf won't be freed
-+ until after the RCU grace period.
-+
-+ (2) Simple delete. This involves just clearing an old matching leaf. The
-+ metadata blocks don't change otherwise. The old leaf won't be freed until
-+ after the RCU grace period.
-+
-+ (3) Insertion replacing part of a subtree that we haven't yet entered. This
-+ may involve replacement of part of that subtree - but that won't affect
-+ the iteration as we won't have reached the pointer to it yet and the
-+ ancestry blocks are not replaced (the layout of those does not change).
-+
-+ (4) Insertion replacing nodes that we're actively processing. This isn't a
-+ problem as we've passed the anchoring pointer and won't switch onto the
-+ new layout until we follow the back pointers - at which point we've
-+ already examined the leaves in the replaced node (we iterate over all the
-+ leaves in a node before following any of its metadata pointers).
-+
-+ We might, however, re-see some leaves that have been split out into a new
-+ branch that's in a slot further along than we were at.
-+
-+ (5) Insertion replacing nodes that we're processing a dependent branch of.
-+ This won't affect us until we follow the back pointers. Similar to (4).
-+
-+ (6) Deletion collapsing a branch under us. This doesn't affect us because the
-+ back pointers will get us back to the parent of the new node before we
-+ could see the new node. The entire collapsed subtree is thrown away
-+ unchanged - and will still be rooted on the same slot, so we shouldn't
-+ process it a second time as we'll go back to slot + 1.
-+
-+Note:
-+
-+ (*) Under some circumstances, we need to simultaneously change the parent
-+ pointer and the parent slot pointer on a node (say, for example, we
-+ inserted another node before it and moved it up a level). We cannot do
-+ this without locking against a read - so we have to replace that node too.
-+
-+ However, when we're changing a shortcut into a node this isn't a problem
-+ as shortcuts only have one slot and so the parent slot number isn't used
-+ when traversing backwards over one. This means that it's okay to change
-+ the slot number first - provided suitable barriers are used to make sure
-+ the parent slot number is read after the back pointer.
-+
-+Obsolete blocks and leaves are freed up after an RCU grace period has passed,
-+so as long as anyone doing walking or iteration holds the RCU read lock, the
-+old superstructure should not go away on them.
-diff --git a/include/linux/assoc_array.h b/include/linux/assoc_array.h
-new file mode 100644
-index 0000000..9a193b8
---- /dev/null
-+++ b/include/linux/assoc_array.h
-@@ -0,0 +1,92 @@
-+/* Generic associative array implementation.
-+ *
-+ * See Documentation/assoc_array.txt for information.
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_ASSOC_ARRAY_H
-+#define _LINUX_ASSOC_ARRAY_H
-+
-+#ifdef CONFIG_ASSOCIATIVE_ARRAY
-+
-+#include <linux/types.h>
-+
-+#define ASSOC_ARRAY_KEY_CHUNK_SIZE BITS_PER_LONG /* Key data retrieved in chunks of this size */
-+
-+/*
-+ * Generic associative array.
-+ */
-+struct assoc_array {
-+ struct assoc_array_ptr *root; /* The node at the root of the tree */
-+ unsigned long nr_leaves_on_tree;
-+};
-+
-+/*
-+ * Operations on objects and index keys for use by array manipulation routines.
-+ */
-+struct assoc_array_ops {
-+ /* Method to get a chunk of an index key from caller-supplied data */
-+ unsigned long (*get_key_chunk)(const void *index_key, int level);
-+
-+ /* Method to get a piece of an object's index key */
-+ unsigned long (*get_object_key_chunk)(const void *object, int level);
-+
-+ /* Is this the object we're looking for? */
-+ bool (*compare_object)(const void *object, const void *index_key);
-+
-+ /* How different are two objects, to a bit position in their keys? (or
-+ * -1 if they're the same)
-+ */
-+ int (*diff_objects)(const void *a, const void *b);
-+
-+ /* Method to free an object. */
-+ void (*free_object)(void *object);
-+};
-+
-+/*
-+ * Access and manipulation functions.
-+ */
-+struct assoc_array_edit;
-+
-+static inline void assoc_array_init(struct assoc_array *array)
-+{
-+ array->root = NULL;
-+ array->nr_leaves_on_tree = 0;
-+}
-+
-+extern int assoc_array_iterate(const struct assoc_array *array,
-+ int (*iterator)(const void *object,
-+ void *iterator_data),
-+ void *iterator_data);
-+extern void *assoc_array_find(const struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key);
-+extern void assoc_array_destroy(struct assoc_array *array,
-+ const struct assoc_array_ops *ops);
-+extern struct assoc_array_edit *assoc_array_insert(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key,
-+ void *object);
-+extern void assoc_array_insert_set_object(struct assoc_array_edit *edit,
-+ void *object);
-+extern struct assoc_array_edit *assoc_array_delete(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key);
-+extern struct assoc_array_edit *assoc_array_clear(struct assoc_array *array,
-+ const struct assoc_array_ops *ops);
-+extern void assoc_array_apply_edit(struct assoc_array_edit *edit);
-+extern void assoc_array_cancel_edit(struct assoc_array_edit *edit);
-+extern int assoc_array_gc(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ bool (*iterator)(void *object, void *iterator_data),
-+ void *iterator_data);
-+
-+#endif /* CONFIG_ASSOCIATIVE_ARRAY */
-+#endif /* _LINUX_ASSOC_ARRAY_H */
-diff --git a/include/linux/assoc_array_priv.h b/include/linux/assoc_array_priv.h
-new file mode 100644
-index 0000000..711275e
---- /dev/null
-+++ b/include/linux/assoc_array_priv.h
-@@ -0,0 +1,182 @@
-+/* Private definitions for the generic associative array implementation.
-+ *
-+ * See Documentation/assoc_array.txt for information.
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _LINUX_ASSOC_ARRAY_PRIV_H
-+#define _LINUX_ASSOC_ARRAY_PRIV_H
-+
-+#ifdef CONFIG_ASSOCIATIVE_ARRAY
-+
-+#include <linux/assoc_array.h>
-+
-+#define ASSOC_ARRAY_FAN_OUT 16 /* Number of slots per node */
-+#define ASSOC_ARRAY_FAN_MASK (ASSOC_ARRAY_FAN_OUT - 1)
-+#define ASSOC_ARRAY_LEVEL_STEP (ilog2(ASSOC_ARRAY_FAN_OUT))
-+#define ASSOC_ARRAY_LEVEL_STEP_MASK (ASSOC_ARRAY_LEVEL_STEP - 1)
-+#define ASSOC_ARRAY_KEY_CHUNK_MASK (ASSOC_ARRAY_KEY_CHUNK_SIZE - 1)
-+#define ASSOC_ARRAY_KEY_CHUNK_SHIFT (ilog2(BITS_PER_LONG))
-+
-+/*
-+ * Undefined type representing a pointer with type information in the bottom
-+ * two bits.
-+ */
-+struct assoc_array_ptr;
-+
-+/*
-+ * An N-way node in the tree.
-+ *
-+ * Each slot contains one of four things:
-+ *
-+ * (1) Nothing (NULL).
-+ *
-+ * (2) A leaf object (pointer types 0).
-+ *
-+ * (3) A next-level node (pointer type 1, subtype 0).
-+ *
-+ * (4) A shortcut (pointer type 1, subtype 1).
-+ *
-+ * The tree is optimised for search-by-ID, but permits reasonable iteration
-+ * also.
-+ *
-+ * The tree is navigated by constructing an index key consisting of an array of
-+ * segments, where each segment is ilog2(ASSOC_ARRAY_FAN_OUT) bits in size.
-+ *
-+ * The segments correspond to levels of the tree (the first segment is used at
-+ * level 0, the second at level 1, etc.).
-+ */
-+struct assoc_array_node {
-+ struct assoc_array_ptr *back_pointer;
-+ u8 parent_slot;
-+ struct assoc_array_ptr *slots[ASSOC_ARRAY_FAN_OUT];
-+ unsigned long nr_leaves_on_branch;
-+};
-+
-+/*
-+ * A shortcut through the index space out to where a collection of nodes/leaves
-+ * with the same IDs live.
-+ */
-+struct assoc_array_shortcut {
-+ struct assoc_array_ptr *back_pointer;
-+ int parent_slot;
-+ int skip_to_level;
-+ struct assoc_array_ptr *next_node;
-+ unsigned long index_key[];
-+};
-+
-+/*
-+ * Preallocation cache.
-+ */
-+struct assoc_array_edit {
-+ struct rcu_head rcu;
-+ struct assoc_array *array;
-+ const struct assoc_array_ops *ops;
-+ const struct assoc_array_ops *ops_for_excised_subtree;
-+ struct assoc_array_ptr *leaf;
-+ struct assoc_array_ptr **leaf_p;
-+ struct assoc_array_ptr *dead_leaf;
-+ struct assoc_array_ptr *new_meta[3];
-+ struct assoc_array_ptr *excised_meta[1];
-+ struct assoc_array_ptr *excised_subtree;
-+ struct assoc_array_ptr **set_backpointers[ASSOC_ARRAY_FAN_OUT];
-+ struct assoc_array_ptr *set_backpointers_to;
-+ struct assoc_array_node *adjust_count_on;
-+ long adjust_count_by;
-+ struct {
-+ struct assoc_array_ptr **ptr;
-+ struct assoc_array_ptr *to;
-+ } set[2];
-+ struct {
-+ u8 *p;
-+ u8 to;
-+ } set_parent_slot[1];
-+ u8 segment_cache[ASSOC_ARRAY_FAN_OUT + 1];
-+};
-+
-+/*
-+ * Internal tree member pointers are marked in the bottom one or two bits to
-+ * indicate what type they are so that we don't have to look behind every
-+ * pointer to see what it points to.
-+ *
-+ * We provide functions to test type annotations and to create and translate
-+ * the annotated pointers.
-+ */
-+#define ASSOC_ARRAY_PTR_TYPE_MASK 0x1UL
-+#define ASSOC_ARRAY_PTR_LEAF_TYPE 0x0UL /* Points to leaf (or nowhere) */
-+#define ASSOC_ARRAY_PTR_META_TYPE 0x1UL /* Points to node or shortcut */
-+#define ASSOC_ARRAY_PTR_SUBTYPE_MASK 0x2UL
-+#define ASSOC_ARRAY_PTR_NODE_SUBTYPE 0x0UL
-+#define ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE 0x2UL
-+
-+static inline bool assoc_array_ptr_is_meta(const struct assoc_array_ptr *x)
-+{
-+ return (unsigned long)x & ASSOC_ARRAY_PTR_TYPE_MASK;
-+}
-+static inline bool assoc_array_ptr_is_leaf(const struct assoc_array_ptr *x)
-+{
-+ return !assoc_array_ptr_is_meta(x);
-+}
-+static inline bool assoc_array_ptr_is_shortcut(const struct assoc_array_ptr *x)
-+{
-+ return (unsigned long)x & ASSOC_ARRAY_PTR_SUBTYPE_MASK;
-+}
-+static inline bool assoc_array_ptr_is_node(const struct assoc_array_ptr *x)
-+{
-+ return !assoc_array_ptr_is_shortcut(x);
-+}
-+
-+static inline void *assoc_array_ptr_to_leaf(const struct assoc_array_ptr *x)
-+{
-+ return (void *)((unsigned long)x & ~ASSOC_ARRAY_PTR_TYPE_MASK);
-+}
-+
-+static inline
-+unsigned long __assoc_array_ptr_to_meta(const struct assoc_array_ptr *x)
-+{
-+ return (unsigned long)x &
-+ ~(ASSOC_ARRAY_PTR_SUBTYPE_MASK | ASSOC_ARRAY_PTR_TYPE_MASK);
-+}
-+static inline
-+struct assoc_array_node *assoc_array_ptr_to_node(const struct assoc_array_ptr *x)
-+{
-+ return (struct assoc_array_node *)__assoc_array_ptr_to_meta(x);
-+}
-+static inline
-+struct assoc_array_shortcut *assoc_array_ptr_to_shortcut(const struct assoc_array_ptr *x)
-+{
-+ return (struct assoc_array_shortcut *)__assoc_array_ptr_to_meta(x);
-+}
-+
-+static inline
-+struct assoc_array_ptr *__assoc_array_x_to_ptr(const void *p, unsigned long t)
-+{
-+ return (struct assoc_array_ptr *)((unsigned long)p | t);
-+}
-+static inline
-+struct assoc_array_ptr *assoc_array_leaf_to_ptr(const void *p)
-+{
-+ return __assoc_array_x_to_ptr(p, ASSOC_ARRAY_PTR_LEAF_TYPE);
-+}
-+static inline
-+struct assoc_array_ptr *assoc_array_node_to_ptr(const struct assoc_array_node *p)
-+{
-+ return __assoc_array_x_to_ptr(
-+ p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_NODE_SUBTYPE);
-+}
-+static inline
-+struct assoc_array_ptr *assoc_array_shortcut_to_ptr(const struct assoc_array_shortcut *p)
-+{
-+ return __assoc_array_x_to_ptr(
-+ p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE);
-+}
-+
-+#endif /* CONFIG_ASSOCIATIVE_ARRAY */
-+#endif /* _LINUX_ASSOC_ARRAY_PRIV_H */
-diff --git a/lib/Kconfig b/lib/Kconfig
-index 35da513..b7d3234 100644
---- a/lib/Kconfig
-+++ b/lib/Kconfig
-@@ -312,6 +312,20 @@ config TEXTSEARCH_FSM
- config BTREE
- boolean
-
-+config ASSOCIATIVE_ARRAY
-+ bool
-+ help
-+ Generic associative array. Can be searched and iterated over whilst
-+ it is being modified. It is also reasonably quick to search and
-+ modify. The algorithms are non-recursive, and the trees are highly
-+ capacious.
-+
-+ See:
-+
-+ Documentation/assoc_array.txt
-+
-+ for more information.
-+
- config HAS_IOMEM
- boolean
- depends on !NO_IOMEM
-diff --git a/lib/Makefile b/lib/Makefile
-index 7baccfd..2c59891 100644
---- a/lib/Makefile
-+++ b/lib/Makefile
-@@ -49,6 +49,7 @@ CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
- obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
-
- obj-$(CONFIG_BTREE) += btree.o
-+obj-$(CONFIG_ASSOCIATIVE_ARRAY) += assoc_array.o
- obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
- obj-$(CONFIG_DEBUG_LIST) += list_debug.o
- obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
-diff --git a/lib/assoc_array.c b/lib/assoc_array.c
-new file mode 100644
-index 0000000..a095281
---- /dev/null
-+++ b/lib/assoc_array.c
-@@ -0,0 +1,1745 @@
-+/* Generic associative array implementation.
-+ *
-+ * See Documentation/assoc_array.txt for information.
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+//#define DEBUG
-+#include <linux/slab.h>
-+#include <linux/assoc_array_priv.h>
-+
-+/*
-+ * Iterate over an associative array. The caller must hold the RCU read lock
-+ * or better.
-+ */
-+static int assoc_array_subtree_iterate(const struct assoc_array_ptr *root,
-+ const struct assoc_array_ptr *stop,
-+ int (*iterator)(const void *leaf,
-+ void *iterator_data),
-+ void *iterator_data)
-+{
-+ const struct assoc_array_shortcut *shortcut;
-+ const struct assoc_array_node *node;
-+ const struct assoc_array_ptr *cursor, *ptr, *parent;
-+ unsigned long has_meta;
-+ int slot, ret;
-+
-+ cursor = root;
-+
-+begin_node:
-+ if (assoc_array_ptr_is_shortcut(cursor)) {
-+ /* Descend through a shortcut */
-+ shortcut = assoc_array_ptr_to_shortcut(cursor);
-+ smp_read_barrier_depends();
-+ cursor = ACCESS_ONCE(shortcut->next_node);
-+ }
-+
-+ node = assoc_array_ptr_to_node(cursor);
-+ smp_read_barrier_depends();
-+ slot = 0;
-+
-+ /* We perform two passes of each node.
-+ *
-+ * The first pass does all the leaves in this node. This means we
-+ * don't miss any leaves if the node is split up by insertion whilst
-+ * we're iterating over the branches rooted here (we may, however, see
-+ * some leaves twice).
-+ */
-+ has_meta = 0;
-+ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = ACCESS_ONCE(node->slots[slot]);
-+ has_meta |= (unsigned long)ptr;
-+ if (ptr && assoc_array_ptr_is_leaf(ptr)) {
-+ /* We need a barrier between the read of the pointer
-+ * and dereferencing the pointer - but only if we are
-+ * actually going to dereference it.
-+ */
-+ smp_read_barrier_depends();
-+
-+ /* Invoke the callback */
-+ ret = iterator(assoc_array_ptr_to_leaf(ptr),
-+ iterator_data);
-+ if (ret)
-+ return ret;
-+ }
-+ }
-+
-+ /* The second pass attends to all the metadata pointers. If we follow
-+ * one of these we may find that we don't come back here, but rather go
-+ * back to a replacement node with the leaves in a different layout.
-+ *
-+ * We are guaranteed to make progress, however, as the slot number for
-+ * a particular portion of the key space cannot change - and we
-+ * continue at the back pointer + 1.
-+ */
-+ if (!(has_meta & ASSOC_ARRAY_PTR_META_TYPE))
-+ goto finished_node;
-+ slot = 0;
-+
-+continue_node:
-+ node = assoc_array_ptr_to_node(cursor);
-+ smp_read_barrier_depends();
-+
-+ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = ACCESS_ONCE(node->slots[slot]);
-+ if (assoc_array_ptr_is_meta(ptr)) {
-+ cursor = ptr;
-+ goto begin_node;
-+ }
-+ }
-+
-+finished_node:
-+ /* Move up to the parent (may need to skip back over a shortcut) */
-+ parent = ACCESS_ONCE(node->back_pointer);
-+ slot = node->parent_slot;
-+ if (parent == stop)
-+ return 0;
-+
-+ if (assoc_array_ptr_is_shortcut(parent)) {
-+ shortcut = assoc_array_ptr_to_shortcut(parent);
-+ smp_read_barrier_depends();
-+ cursor = parent;
-+ parent = ACCESS_ONCE(shortcut->back_pointer);
-+ slot = shortcut->parent_slot;
-+ if (parent == stop)
-+ return 0;
-+ }
-+
-+ /* Ascend to next slot in parent node */
-+ cursor = parent;
-+ slot++;
-+ goto continue_node;
-+}
-+
-+/**
-+ * assoc_array_iterate - Pass all objects in the array to a callback
-+ * @array: The array to iterate over.
-+ * @iterator: The callback function.
-+ * @iterator_data: Private data for the callback function.
-+ *
-+ * Iterate over all the objects in an associative array. Each one will be
-+ * presented to the iterator function.
-+ *
-+ * If the array is being modified concurrently with the iteration then it is
-+ * possible that some objects in the array will be passed to the iterator
-+ * callback more than once - though every object should be passed at least
-+ * once. If this is undesirable then the caller must lock against modification
-+ * for the duration of this function.
-+ *
-+ * The function will return 0 if no objects were in the array or else it will
-+ * return the result of the last iterator function called. Iteration stops
-+ * immediately if any call to the iteration function results in a non-zero
-+ * return.
-+ *
-+ * The caller should hold the RCU read lock or better if concurrent
-+ * modification is possible.
-+ */
-+int assoc_array_iterate(const struct assoc_array *array,
-+ int (*iterator)(const void *object,
-+ void *iterator_data),
-+ void *iterator_data)
-+{
-+ struct assoc_array_ptr *root = ACCESS_ONCE(array->root);
-+
-+ if (!root)
-+ return 0;
-+ return assoc_array_subtree_iterate(root, NULL, iterator, iterator_data);
-+}
-+
-+enum assoc_array_walk_status {
-+ assoc_array_walk_tree_empty,
-+ assoc_array_walk_found_terminal_node,
-+ assoc_array_walk_found_wrong_shortcut,
-+} status;
-+
-+struct assoc_array_walk_result {
-+ struct {
-+ struct assoc_array_node *node; /* Node in which leaf might be found */
-+ int level;
-+ int slot;
-+ } terminal_node;
-+ struct {
-+ struct assoc_array_shortcut *shortcut;
-+ int level;
-+ int sc_level;
-+ unsigned long sc_segments;
-+ unsigned long dissimilarity;
-+ } wrong_shortcut;
-+};
-+
-+/*
-+ * Navigate through the internal tree looking for the closest node to the key.
-+ */
-+static enum assoc_array_walk_status
-+assoc_array_walk(const struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key,
-+ struct assoc_array_walk_result *result)
-+{
-+ struct assoc_array_shortcut *shortcut;
-+ struct assoc_array_node *node;
-+ struct assoc_array_ptr *cursor, *ptr;
-+ unsigned long sc_segments, dissimilarity;
-+ unsigned long segments;
-+ int level, sc_level, next_sc_level;
-+ int slot;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ cursor = ACCESS_ONCE(array->root);
-+ if (!cursor)
-+ return assoc_array_walk_tree_empty;
-+
-+ level = 0;
-+
-+ /* Use segments from the key for the new leaf to navigate through the
-+ * internal tree, skipping through nodes and shortcuts that are on
-+ * route to the destination. Eventually we'll come to a slot that is
-+ * either empty or contains a leaf at which point we've found a node in
-+ * which the leaf we're looking for might be found or into which it
-+ * should be inserted.
-+ */
-+jumped:
-+ segments = ops->get_key_chunk(index_key, level);
-+ pr_devel("segments[%d]: %lx\n", level, segments);
-+
-+ if (assoc_array_ptr_is_shortcut(cursor))
-+ goto follow_shortcut;
-+
-+consider_node:
-+ node = assoc_array_ptr_to_node(cursor);
-+ smp_read_barrier_depends();
-+
-+ slot = segments >> (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
-+ slot &= ASSOC_ARRAY_FAN_MASK;
-+ ptr = ACCESS_ONCE(node->slots[slot]);
-+
-+ pr_devel("consider slot %x [ix=%d type=%lu]\n",
-+ slot, level, (unsigned long)ptr & 3);
-+
-+ if (!assoc_array_ptr_is_meta(ptr)) {
-+ /* The node doesn't have a node/shortcut pointer in the slot
-+ * corresponding to the index key that we have to follow.
-+ */
-+ result->terminal_node.node = node;
-+ result->terminal_node.level = level;
-+ result->terminal_node.slot = slot;
-+ pr_devel("<--%s() = terminal_node\n", __func__);
-+ return assoc_array_walk_found_terminal_node;
-+ }
-+
-+ if (assoc_array_ptr_is_node(ptr)) {
-+ /* There is a pointer to a node in the slot corresponding to
-+ * this index key segment, so we need to follow it.
-+ */
-+ cursor = ptr;
-+ level += ASSOC_ARRAY_LEVEL_STEP;
-+ if ((level & ASSOC_ARRAY_KEY_CHUNK_MASK) != 0)
-+ goto consider_node;
-+ goto jumped;
-+ }
-+
-+ /* There is a shortcut in the slot corresponding to the index key
-+ * segment. We follow the shortcut if its partial index key matches
-+ * this leaf's. Otherwise we need to split the shortcut.
-+ */
-+ cursor = ptr;
-+follow_shortcut:
-+ shortcut = assoc_array_ptr_to_shortcut(cursor);
-+ smp_read_barrier_depends();
-+ pr_devel("shortcut to %d\n", shortcut->skip_to_level);
-+ sc_level = level + ASSOC_ARRAY_LEVEL_STEP;
-+ BUG_ON(sc_level > shortcut->skip_to_level);
-+
-+ do {
-+ /* Check the leaf against the shortcut's index key a word at a
-+ * time, trimming the final word (the shortcut stores the index
-+ * key completely from the root to the shortcut's target).
-+ */
-+ if ((sc_level & ASSOC_ARRAY_KEY_CHUNK_MASK) == 0)
-+ segments = ops->get_key_chunk(index_key, sc_level);
-+
-+ sc_segments = shortcut->index_key[sc_level >> ASSOC_ARRAY_KEY_CHUNK_SHIFT];
-+ dissimilarity = segments ^ sc_segments;
-+
-+ if (round_up(sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE) > shortcut->skip_to_level) {
-+ /* Trim segments that are beyond the shortcut */
-+ int shift = shortcut->skip_to_level & ASSOC_ARRAY_KEY_CHUNK_MASK;
-+ dissimilarity &= ~(ULONG_MAX << shift);
-+ next_sc_level = shortcut->skip_to_level;
-+ } else {
-+ next_sc_level = sc_level + ASSOC_ARRAY_KEY_CHUNK_SIZE;
-+ next_sc_level = round_down(next_sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE);
-+ }
-+
-+ if (dissimilarity != 0) {
-+ /* This shortcut points elsewhere */
-+ result->wrong_shortcut.shortcut = shortcut;
-+ result->wrong_shortcut.level = level;
-+ result->wrong_shortcut.sc_level = sc_level;
-+ result->wrong_shortcut.sc_segments = sc_segments;
-+ result->wrong_shortcut.dissimilarity = dissimilarity;
-+ return assoc_array_walk_found_wrong_shortcut;
-+ }
-+
-+ sc_level = next_sc_level;
-+ } while (sc_level < shortcut->skip_to_level);
-+
-+ /* The shortcut matches the leaf's index to this point. */
-+ cursor = ACCESS_ONCE(shortcut->next_node);
-+ if (((level ^ sc_level) & ~ASSOC_ARRAY_KEY_CHUNK_MASK) != 0) {
-+ level = sc_level;
-+ goto jumped;
-+ } else {
-+ level = sc_level;
-+ goto consider_node;
-+ }
-+}
-+
-+/**
-+ * assoc_array_find - Find an object by index key
-+ * @array: The associative array to search.
-+ * @ops: The operations to use.
-+ * @index_key: The key to the object.
-+ *
-+ * Find an object in an associative array by walking through the internal tree
-+ * to the node that should contain the object and then searching the leaves
-+ * there. NULL is returned if the requested object was not found in the array.
-+ *
-+ * The caller must hold the RCU read lock or better.
-+ */
-+void *assoc_array_find(const struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key)
-+{
-+ struct assoc_array_walk_result result;
-+ const struct assoc_array_node *node;
-+ const struct assoc_array_ptr *ptr;
-+ const void *leaf;
-+ int slot;
-+
-+ if (assoc_array_walk(array, ops, index_key, &result) !=
-+ assoc_array_walk_found_terminal_node)
-+ return NULL;
-+
-+ node = result.terminal_node.node;
-+ smp_read_barrier_depends();
-+
-+ /* If the target key is available to us, it's has to be pointed to by
-+ * the terminal node.
-+ */
-+ for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = ACCESS_ONCE(node->slots[slot]);
-+ if (ptr && assoc_array_ptr_is_leaf(ptr)) {
-+ /* We need a barrier between the read of the pointer
-+ * and dereferencing the pointer - but only if we are
-+ * actually going to dereference it.
-+ */
-+ leaf = assoc_array_ptr_to_leaf(ptr);
-+ smp_read_barrier_depends();
-+ if (ops->compare_object(leaf, index_key))
-+ return (void *)leaf;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Destructively iterate over an associative array. The caller must prevent
-+ * other simultaneous accesses.
-+ */
-+static void assoc_array_destroy_subtree(struct assoc_array_ptr *root,
-+ const struct assoc_array_ops *ops)
-+{
-+ struct assoc_array_shortcut *shortcut;
-+ struct assoc_array_node *node;
-+ struct assoc_array_ptr *cursor, *parent = NULL;
-+ int slot = -1;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ cursor = root;
-+ if (!cursor) {
-+ pr_devel("empty\n");
-+ return;
-+ }
-+
-+move_to_meta:
-+ if (assoc_array_ptr_is_shortcut(cursor)) {
-+ /* Descend through a shortcut */
-+ pr_devel("[%d] shortcut\n", slot);
-+ BUG_ON(!assoc_array_ptr_is_shortcut(cursor));
-+ shortcut = assoc_array_ptr_to_shortcut(cursor);
-+ BUG_ON(shortcut->back_pointer != parent);
-+ BUG_ON(slot != -1 && shortcut->parent_slot != slot);
-+ parent = cursor;
-+ cursor = shortcut->next_node;
-+ slot = -1;
-+ BUG_ON(!assoc_array_ptr_is_node(cursor));
-+ }
-+
-+ pr_devel("[%d] node\n", slot);
-+ node = assoc_array_ptr_to_node(cursor);
-+ BUG_ON(node->back_pointer != parent);
-+ BUG_ON(slot != -1 && node->parent_slot != slot);
-+ slot = 0;
-+
-+continue_node:
-+ pr_devel("Node %p [back=%p]\n", node, node->back_pointer);
-+ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ struct assoc_array_ptr *ptr = node->slots[slot];
-+ if (!ptr)
-+ continue;
-+ if (assoc_array_ptr_is_meta(ptr)) {
-+ parent = cursor;
-+ cursor = ptr;
-+ goto move_to_meta;
-+ }
-+
-+ if (ops) {
-+ pr_devel("[%d] free leaf\n", slot);
-+ ops->free_object(assoc_array_ptr_to_leaf(ptr));
-+ }
-+ }
-+
-+ parent = node->back_pointer;
-+ slot = node->parent_slot;
-+ pr_devel("free node\n");
-+ kfree(node);
-+ if (!parent)
-+ return; /* Done */
-+
-+ /* Move back up to the parent (may need to free a shortcut on
-+ * the way up) */
-+ if (assoc_array_ptr_is_shortcut(parent)) {
-+ shortcut = assoc_array_ptr_to_shortcut(parent);
-+ BUG_ON(shortcut->next_node != cursor);
-+ cursor = parent;
-+ parent = shortcut->back_pointer;
-+ slot = shortcut->parent_slot;
-+ pr_devel("free shortcut\n");
-+ kfree(shortcut);
-+ if (!parent)
-+ return;
-+
-+ BUG_ON(!assoc_array_ptr_is_node(parent));
-+ }
-+
-+ /* Ascend to next slot in parent node */
-+ pr_devel("ascend to %p[%d]\n", parent, slot);
-+ cursor = parent;
-+ node = assoc_array_ptr_to_node(cursor);
-+ slot++;
-+ goto continue_node;
-+}
-+
-+/**
-+ * assoc_array_destroy - Destroy an associative array
-+ * @array: The array to destroy.
-+ * @ops: The operations to use.
-+ *
-+ * Discard all metadata and free all objects in an associative array. The
-+ * array will be empty and ready to use again upon completion. This function
-+ * cannot fail.
-+ *
-+ * The caller must prevent all other accesses whilst this takes place as no
-+ * attempt is made to adjust pointers gracefully to permit RCU readlock-holding
-+ * accesses to continue. On the other hand, no memory allocation is required.
-+ */
-+void assoc_array_destroy(struct assoc_array *array,
-+ const struct assoc_array_ops *ops)
-+{
-+ assoc_array_destroy_subtree(array->root, ops);
-+ array->root = NULL;
-+}
-+
-+/*
-+ * Handle insertion into an empty tree.
-+ */
-+static bool assoc_array_insert_in_empty_tree(struct assoc_array_edit *edit)
-+{
-+ struct assoc_array_node *new_n0;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL);
-+ if (!new_n0)
-+ return false;
-+
-+ edit->new_meta[0] = assoc_array_node_to_ptr(new_n0);
-+ edit->leaf_p = &new_n0->slots[0];
-+ edit->adjust_count_on = new_n0;
-+ edit->set[0].ptr = &edit->array->root;
-+ edit->set[0].to = assoc_array_node_to_ptr(new_n0);
-+
-+ pr_devel("<--%s() = ok [no root]\n", __func__);
-+ return true;
-+}
-+
-+/*
-+ * Handle insertion into a terminal node.
-+ */
-+static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key,
-+ struct assoc_array_walk_result *result)
-+{
-+ struct assoc_array_shortcut *shortcut, *new_s0;
-+ struct assoc_array_node *node, *new_n0, *new_n1, *side;
-+ struct assoc_array_ptr *ptr;
-+ unsigned long dissimilarity, base_seg, blank;
-+ size_t keylen;
-+ bool have_meta;
-+ int level, diff;
-+ int slot, next_slot, free_slot, i, j;
-+
-+ node = result->terminal_node.node;
-+ level = result->terminal_node.level;
-+ edit->segment_cache[ASSOC_ARRAY_FAN_OUT] = result->terminal_node.slot;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ /* We arrived at a node which doesn't have an onward node or shortcut
-+ * pointer that we have to follow. This means that (a) the leaf we
-+ * want must go here (either by insertion or replacement) or (b) we
-+ * need to split this node and insert in one of the fragments.
-+ */
-+ free_slot = -1;
-+
-+ /* Firstly, we have to check the leaves in this node to see if there's
-+ * a matching one we should replace in place.
-+ */
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ ptr = node->slots[i];
-+ if (!ptr) {
-+ free_slot = i;
-+ continue;
-+ }
-+ if (ops->compare_object(assoc_array_ptr_to_leaf(ptr), index_key)) {
-+ pr_devel("replace in slot %d\n", i);
-+ edit->leaf_p = &node->slots[i];
-+ edit->dead_leaf = node->slots[i];
-+ pr_devel("<--%s() = ok [replace]\n", __func__);
-+ return true;
-+ }
-+ }
-+
-+ /* If there is a free slot in this node then we can just insert the
-+ * leaf here.
-+ */
-+ if (free_slot >= 0) {
-+ pr_devel("insert in free slot %d\n", free_slot);
-+ edit->leaf_p = &node->slots[free_slot];
-+ edit->adjust_count_on = node;
-+ pr_devel("<--%s() = ok [insert]\n", __func__);
-+ return true;
-+ }
-+
-+ /* The node has no spare slots - so we're either going to have to split
-+ * it or insert another node before it.
-+ *
-+ * Whatever, we're going to need at least two new nodes - so allocate
-+ * those now. We may also need a new shortcut, but we deal with that
-+ * when we need it.
-+ */
-+ new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL);
-+ if (!new_n0)
-+ return false;
-+ edit->new_meta[0] = assoc_array_node_to_ptr(new_n0);
-+ new_n1 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL);
-+ if (!new_n1)
-+ return false;
-+ edit->new_meta[1] = assoc_array_node_to_ptr(new_n1);
-+
-+ /* We need to find out how similar the leaves are. */
-+ pr_devel("no spare slots\n");
-+ have_meta = false;
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ ptr = node->slots[i];
-+ if (assoc_array_ptr_is_meta(ptr)) {
-+ edit->segment_cache[i] = 0xff;
-+ have_meta = true;
-+ continue;
-+ }
-+ base_seg = ops->get_object_key_chunk(
-+ assoc_array_ptr_to_leaf(ptr), level);
-+ base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK;
-+ edit->segment_cache[i] = base_seg & ASSOC_ARRAY_FAN_MASK;
-+ }
-+
-+ if (have_meta) {
-+ pr_devel("have meta\n");
-+ goto split_node;
-+ }
-+
-+ /* The node contains only leaves */
-+ dissimilarity = 0;
-+ base_seg = edit->segment_cache[0];
-+ for (i = 1; i < ASSOC_ARRAY_FAN_OUT; i++)
-+ dissimilarity |= edit->segment_cache[i] ^ base_seg;
-+
-+ pr_devel("only leaves; dissimilarity=%lx\n", dissimilarity);
-+
-+ if ((dissimilarity & ASSOC_ARRAY_FAN_MASK) == 0) {
-+ /* The old leaves all cluster in the same slot. We will need
-+ * to insert a shortcut if the new node wants to cluster with them.
-+ */
-+ if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0)
-+ goto all_leaves_cluster_together;
-+
-+ /* Otherwise we can just insert a new node ahead of the old
-+ * one.
-+ */
-+ goto present_leaves_cluster_but_not_new_leaf;
-+ }
-+
-+split_node:
-+ pr_devel("split node\n");
-+
-+ /* We need to split the current node; we know that the node doesn't
-+ * simply contain a full set of leaves that cluster together (it
-+ * contains meta pointers and/or non-clustering leaves).
-+ *
-+ * We need to expel at least two leaves out of a set consisting of the
-+ * leaves in the node and the new leaf.
-+ *
-+ * We need a new node (n0) to replace the current one and a new node to
-+ * take the expelled nodes (n1).
-+ */
-+ edit->set[0].to = assoc_array_node_to_ptr(new_n0);
-+ new_n0->back_pointer = node->back_pointer;
-+ new_n0->parent_slot = node->parent_slot;
-+ new_n1->back_pointer = assoc_array_node_to_ptr(new_n0);
-+ new_n1->parent_slot = -1; /* Need to calculate this */
-+
-+do_split_node:
-+ pr_devel("do_split_node\n");
-+
-+ new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch;
-+ new_n1->nr_leaves_on_branch = 0;
-+
-+ /* Begin by finding two matching leaves. There have to be at least two
-+ * that match - even if there are meta pointers - because any leaf that
-+ * would match a slot with a meta pointer in it must be somewhere
-+ * behind that meta pointer and cannot be here. Further, given N
-+ * remaining leaf slots, we now have N+1 leaves to go in them.
-+ */
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ slot = edit->segment_cache[i];
-+ if (slot != 0xff)
-+ for (j = i + 1; j < ASSOC_ARRAY_FAN_OUT + 1; j++)
-+ if (edit->segment_cache[j] == slot)
-+ goto found_slot_for_multiple_occupancy;
-+ }
-+found_slot_for_multiple_occupancy:
-+ pr_devel("same slot: %x %x [%02x]\n", i, j, slot);
-+ BUG_ON(i >= ASSOC_ARRAY_FAN_OUT);
-+ BUG_ON(j >= ASSOC_ARRAY_FAN_OUT + 1);
-+ BUG_ON(slot >= ASSOC_ARRAY_FAN_OUT);
-+
-+ new_n1->parent_slot = slot;
-+
-+ /* Metadata pointers cannot change slot */
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++)
-+ if (assoc_array_ptr_is_meta(node->slots[i]))
-+ new_n0->slots[i] = node->slots[i];
-+ else
-+ new_n0->slots[i] = NULL;
-+ BUG_ON(new_n0->slots[slot] != NULL);
-+ new_n0->slots[slot] = assoc_array_node_to_ptr(new_n1);
-+
-+ /* Filter the leaf pointers between the new nodes */
-+ free_slot = -1;
-+ next_slot = 0;
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ if (assoc_array_ptr_is_meta(node->slots[i]))
-+ continue;
-+ if (edit->segment_cache[i] == slot) {
-+ new_n1->slots[next_slot++] = node->slots[i];
-+ new_n1->nr_leaves_on_branch++;
-+ } else {
-+ do {
-+ free_slot++;
-+ } while (new_n0->slots[free_slot] != NULL);
-+ new_n0->slots[free_slot] = node->slots[i];
-+ }
-+ }
-+
-+ pr_devel("filtered: f=%x n=%x\n", free_slot, next_slot);
-+
-+ if (edit->segment_cache[ASSOC_ARRAY_FAN_OUT] != slot) {
-+ do {
-+ free_slot++;
-+ } while (new_n0->slots[free_slot] != NULL);
-+ edit->leaf_p = &new_n0->slots[free_slot];
-+ edit->adjust_count_on = new_n0;
-+ } else {
-+ edit->leaf_p = &new_n1->slots[next_slot++];
-+ edit->adjust_count_on = new_n1;
-+ }
-+
-+ BUG_ON(next_slot <= 1);
-+
-+ edit->set_backpointers_to = assoc_array_node_to_ptr(new_n0);
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ if (edit->segment_cache[i] == 0xff) {
-+ ptr = node->slots[i];
-+ BUG_ON(assoc_array_ptr_is_leaf(ptr));
-+ if (assoc_array_ptr_is_node(ptr)) {
-+ side = assoc_array_ptr_to_node(ptr);
-+ edit->set_backpointers[i] = &side->back_pointer;
-+ } else {
-+ shortcut = assoc_array_ptr_to_shortcut(ptr);
-+ edit->set_backpointers[i] = &shortcut->back_pointer;
-+ }
-+ }
-+ }
-+
-+ ptr = node->back_pointer;
-+ if (!ptr)
-+ edit->set[0].ptr = &edit->array->root;
-+ else if (assoc_array_ptr_is_node(ptr))
-+ edit->set[0].ptr = &assoc_array_ptr_to_node(ptr)->slots[node->parent_slot];
-+ else
-+ edit->set[0].ptr = &assoc_array_ptr_to_shortcut(ptr)->next_node;
-+ edit->excised_meta[0] = assoc_array_node_to_ptr(node);
-+ pr_devel("<--%s() = ok [split node]\n", __func__);
-+ return true;
-+
-+present_leaves_cluster_but_not_new_leaf:
-+ /* All the old leaves cluster in the same slot, but the new leaf wants
-+ * to go into a different slot, so we create a new node to hold the new
-+ * leaf and a pointer to a new node holding all the old leaves.
-+ */
-+ pr_devel("present leaves cluster but not new leaf\n");
-+
-+ new_n0->back_pointer = node->back_pointer;
-+ new_n0->parent_slot = node->parent_slot;
-+ new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch;
-+ new_n1->back_pointer = assoc_array_node_to_ptr(new_n0);
-+ new_n1->parent_slot = edit->segment_cache[0];
-+ new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch;
-+ edit->adjust_count_on = new_n0;
-+
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++)
-+ new_n1->slots[i] = node->slots[i];
-+
-+ new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0);
-+ edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]];
-+
-+ edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot];
-+ edit->set[0].to = assoc_array_node_to_ptr(new_n0);
-+ edit->excised_meta[0] = assoc_array_node_to_ptr(node);
-+ pr_devel("<--%s() = ok [insert node before]\n", __func__);
-+ return true;
-+
-+all_leaves_cluster_together:
-+ /* All the leaves, new and old, want to cluster together in this node
-+ * in the same slot, so we have to replace this node with a shortcut to
-+ * skip over the identical parts of the key and then place a pair of
-+ * nodes, one inside the other, at the end of the shortcut and
-+ * distribute the keys between them.
-+ *
-+ * Firstly we need to work out where the leaves start diverging as a
-+ * bit position into their keys so that we know how big the shortcut
-+ * needs to be.
-+ *
-+ * We only need to make a single pass of N of the N+1 leaves because if
-+ * any keys differ between themselves at bit X then at least one of
-+ * them must also differ with the base key at bit X or before.
-+ */
-+ pr_devel("all leaves cluster together\n");
-+ diff = INT_MAX;
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ int x = ops->diff_objects(assoc_array_ptr_to_leaf(edit->leaf),
-+ assoc_array_ptr_to_leaf(node->slots[i]));
-+ if (x < diff) {
-+ BUG_ON(x < 0);
-+ diff = x;
-+ }
-+ }
-+ BUG_ON(diff == INT_MAX);
-+ BUG_ON(diff < level + ASSOC_ARRAY_LEVEL_STEP);
-+
-+ keylen = round_up(diff, ASSOC_ARRAY_KEY_CHUNK_SIZE);
-+ keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT;
-+
-+ new_s0 = kzalloc(sizeof(struct assoc_array_shortcut) +
-+ keylen * sizeof(unsigned long), GFP_KERNEL);
-+ if (!new_s0)
-+ return false;
-+ edit->new_meta[2] = assoc_array_shortcut_to_ptr(new_s0);
-+
-+ edit->set[0].to = assoc_array_shortcut_to_ptr(new_s0);
-+ new_s0->back_pointer = node->back_pointer;
-+ new_s0->parent_slot = node->parent_slot;
-+ new_s0->next_node = assoc_array_node_to_ptr(new_n0);
-+ new_n0->back_pointer = assoc_array_shortcut_to_ptr(new_s0);
-+ new_n0->parent_slot = 0;
-+ new_n1->back_pointer = assoc_array_node_to_ptr(new_n0);
-+ new_n1->parent_slot = -1; /* Need to calculate this */
-+
-+ new_s0->skip_to_level = level = diff & ~ASSOC_ARRAY_LEVEL_STEP_MASK;
-+ pr_devel("skip_to_level = %d [diff %d]\n", level, diff);
-+ BUG_ON(level <= 0);
-+
-+ for (i = 0; i < keylen; i++)
-+ new_s0->index_key[i] =
-+ ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE);
-+
-+ blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
-+ pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
-+ new_s0->index_key[keylen - 1] &= ~blank;
-+
-+ /* This now reduces to a node splitting exercise for which we'll need
-+ * to regenerate the disparity table.
-+ */
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ ptr = node->slots[i];
-+ base_seg = ops->get_object_key_chunk(assoc_array_ptr_to_leaf(ptr),
-+ level);
-+ base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK;
-+ edit->segment_cache[i] = base_seg & ASSOC_ARRAY_FAN_MASK;
-+ }
-+
-+ base_seg = ops->get_key_chunk(index_key, level);
-+ base_seg >>= level & ASSOC_ARRAY_KEY_CHUNK_MASK;
-+ edit->segment_cache[ASSOC_ARRAY_FAN_OUT] = base_seg & ASSOC_ARRAY_FAN_MASK;
-+ goto do_split_node;
-+}
-+
-+/*
-+ * Handle insertion into the middle of a shortcut.
-+ */
-+static bool assoc_array_insert_mid_shortcut(struct assoc_array_edit *edit,
-+ const struct assoc_array_ops *ops,
-+ struct assoc_array_walk_result *result)
-+{
-+ struct assoc_array_shortcut *shortcut, *new_s0, *new_s1;
-+ struct assoc_array_node *node, *new_n0, *side;
-+ unsigned long sc_segments, dissimilarity, blank;
-+ size_t keylen;
-+ int level, sc_level, diff;
-+ int sc_slot;
-+
-+ shortcut = result->wrong_shortcut.shortcut;
-+ level = result->wrong_shortcut.level;
-+ sc_level = result->wrong_shortcut.sc_level;
-+ sc_segments = result->wrong_shortcut.sc_segments;
-+ dissimilarity = result->wrong_shortcut.dissimilarity;
-+
-+ pr_devel("-->%s(ix=%d dis=%lx scix=%d)\n",
-+ __func__, level, dissimilarity, sc_level);
-+
-+ /* We need to split a shortcut and insert a node between the two
-+ * pieces. Zero-length pieces will be dispensed with entirely.
-+ *
-+ * First of all, we need to find out in which level the first
-+ * difference was.
-+ */
-+ diff = __ffs(dissimilarity);
-+ diff &= ~ASSOC_ARRAY_LEVEL_STEP_MASK;
-+ diff += sc_level & ~ASSOC_ARRAY_KEY_CHUNK_MASK;
-+ pr_devel("diff=%d\n", diff);
-+
-+ if (!shortcut->back_pointer) {
-+ edit->set[0].ptr = &edit->array->root;
-+ } else if (assoc_array_ptr_is_node(shortcut->back_pointer)) {
-+ node = assoc_array_ptr_to_node(shortcut->back_pointer);
-+ edit->set[0].ptr = &node->slots[shortcut->parent_slot];
-+ } else {
-+ BUG();
-+ }
-+
-+ edit->excised_meta[0] = assoc_array_shortcut_to_ptr(shortcut);
-+
-+ /* Create a new node now since we're going to need it anyway */
-+ new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL);
-+ if (!new_n0)
-+ return false;
-+ edit->new_meta[0] = assoc_array_node_to_ptr(new_n0);
-+ edit->adjust_count_on = new_n0;
-+
-+ /* Insert a new shortcut before the new node if this segment isn't of
-+ * zero length - otherwise we just connect the new node directly to the
-+ * parent.
-+ */
-+ level += ASSOC_ARRAY_LEVEL_STEP;
-+ if (diff > level) {
-+ pr_devel("pre-shortcut %d...%d\n", level, diff);
-+ keylen = round_up(diff, ASSOC_ARRAY_KEY_CHUNK_SIZE);
-+ keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT;
-+
-+ new_s0 = kzalloc(sizeof(struct assoc_array_shortcut) +
-+ keylen * sizeof(unsigned long), GFP_KERNEL);
-+ if (!new_s0)
-+ return false;
-+ edit->new_meta[1] = assoc_array_shortcut_to_ptr(new_s0);
-+ edit->set[0].to = assoc_array_shortcut_to_ptr(new_s0);
-+ new_s0->back_pointer = shortcut->back_pointer;
-+ new_s0->parent_slot = shortcut->parent_slot;
-+ new_s0->next_node = assoc_array_node_to_ptr(new_n0);
-+ new_s0->skip_to_level = diff;
-+
-+ new_n0->back_pointer = assoc_array_shortcut_to_ptr(new_s0);
-+ new_n0->parent_slot = 0;
-+
-+ memcpy(new_s0->index_key, shortcut->index_key,
-+ keylen * sizeof(unsigned long));
-+
-+ blank = ULONG_MAX << (diff & ASSOC_ARRAY_KEY_CHUNK_MASK);
-+ pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, diff, blank);
-+ new_s0->index_key[keylen - 1] &= ~blank;
-+ } else {
-+ pr_devel("no pre-shortcut\n");
-+ edit->set[0].to = assoc_array_node_to_ptr(new_n0);
-+ new_n0->back_pointer = shortcut->back_pointer;
-+ new_n0->parent_slot = shortcut->parent_slot;
-+ }
-+
-+ side = assoc_array_ptr_to_node(shortcut->next_node);
-+ new_n0->nr_leaves_on_branch = side->nr_leaves_on_branch;
-+
-+ /* We need to know which slot in the new node is going to take a
-+ * metadata pointer.
-+ */
-+ sc_slot = sc_segments >> (diff & ASSOC_ARRAY_KEY_CHUNK_MASK);
-+ sc_slot &= ASSOC_ARRAY_FAN_MASK;
-+
-+ pr_devel("new slot %lx >> %d -> %d\n",
-+ sc_segments, diff & ASSOC_ARRAY_KEY_CHUNK_MASK, sc_slot);
-+
-+ /* Determine whether we need to follow the new node with a replacement
-+ * for the current shortcut. We could in theory reuse the current
-+ * shortcut if its parent slot number doesn't change - but that's a
-+ * 1-in-16 chance so not worth expending the code upon.
-+ */
-+ level = diff + ASSOC_ARRAY_LEVEL_STEP;
-+ if (level < shortcut->skip_to_level) {
-+ pr_devel("post-shortcut %d...%d\n", level, shortcut->skip_to_level);
-+ keylen = round_up(shortcut->skip_to_level, ASSOC_ARRAY_KEY_CHUNK_SIZE);
-+ keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT;
-+
-+ new_s1 = kzalloc(sizeof(struct assoc_array_shortcut) +
-+ keylen * sizeof(unsigned long), GFP_KERNEL);
-+ if (!new_s1)
-+ return false;
-+ edit->new_meta[2] = assoc_array_shortcut_to_ptr(new_s1);
-+
-+ new_s1->back_pointer = assoc_array_node_to_ptr(new_n0);
-+ new_s1->parent_slot = sc_slot;
-+ new_s1->next_node = shortcut->next_node;
-+ new_s1->skip_to_level = shortcut->skip_to_level;
-+
-+ new_n0->slots[sc_slot] = assoc_array_shortcut_to_ptr(new_s1);
-+
-+ memcpy(new_s1->index_key, shortcut->index_key,
-+ keylen * sizeof(unsigned long));
-+
-+ edit->set[1].ptr = &side->back_pointer;
-+ edit->set[1].to = assoc_array_shortcut_to_ptr(new_s1);
-+ } else {
-+ pr_devel("no post-shortcut\n");
-+
-+ /* We don't have to replace the pointed-to node as long as we
-+ * use memory barriers to make sure the parent slot number is
-+ * changed before the back pointer (the parent slot number is
-+ * irrelevant to the old parent shortcut).
-+ */
-+ new_n0->slots[sc_slot] = shortcut->next_node;
-+ edit->set_parent_slot[0].p = &side->parent_slot;
-+ edit->set_parent_slot[0].to = sc_slot;
-+ edit->set[1].ptr = &side->back_pointer;
-+ edit->set[1].to = assoc_array_node_to_ptr(new_n0);
-+ }
-+
-+ /* Install the new leaf in a spare slot in the new node. */
-+ if (sc_slot == 0)
-+ edit->leaf_p = &new_n0->slots[1];
-+ else
-+ edit->leaf_p = &new_n0->slots[0];
-+
-+ pr_devel("<--%s() = ok [split shortcut]\n", __func__);
-+ return edit;
-+}
-+
-+/**
-+ * assoc_array_insert - Script insertion of an object into an associative array
-+ * @array: The array to insert into.
-+ * @ops: The operations to use.
-+ * @index_key: The key to insert at.
-+ * @object: The object to insert.
-+ *
-+ * Precalculate and preallocate a script for the insertion or replacement of an
-+ * object in an associative array. This results in an edit script that can
-+ * either be applied or cancelled.
-+ *
-+ * The function returns a pointer to an edit script or -ENOMEM.
-+ *
-+ * The caller should lock against other modifications and must continue to hold
-+ * the lock until assoc_array_apply_edit() has been called.
-+ *
-+ * Accesses to the tree may take place concurrently with this function,
-+ * provided they hold the RCU read lock.
-+ */
-+struct assoc_array_edit *assoc_array_insert(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key,
-+ void *object)
-+{
-+ struct assoc_array_walk_result result;
-+ struct assoc_array_edit *edit;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ /* The leaf pointer we're given must not have the bottom bit set as we
-+ * use those for type-marking the pointer. NULL pointers are also not
-+ * allowed as they indicate an empty slot but we have to allow them
-+ * here as they can be updated later.
-+ */
-+ BUG_ON(assoc_array_ptr_is_meta(object));
-+
-+ edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL);
-+ if (!edit)
-+ return ERR_PTR(-ENOMEM);
-+ edit->array = array;
-+ edit->ops = ops;
-+ edit->leaf = assoc_array_leaf_to_ptr(object);
-+ edit->adjust_count_by = 1;
-+
-+ switch (assoc_array_walk(array, ops, index_key, &result)) {
-+ case assoc_array_walk_tree_empty:
-+ /* Allocate a root node if there isn't one yet */
-+ if (!assoc_array_insert_in_empty_tree(edit))
-+ goto enomem;
-+ return edit;
-+
-+ case assoc_array_walk_found_terminal_node:
-+ /* We found a node that doesn't have a node/shortcut pointer in
-+ * the slot corresponding to the index key that we have to
-+ * follow.
-+ */
-+ if (!assoc_array_insert_into_terminal_node(edit, ops, index_key,
-+ &result))
-+ goto enomem;
-+ return edit;
-+
-+ case assoc_array_walk_found_wrong_shortcut:
-+ /* We found a shortcut that didn't match our key in a slot we
-+ * needed to follow.
-+ */
-+ if (!assoc_array_insert_mid_shortcut(edit, ops, &result))
-+ goto enomem;
-+ return edit;
-+ }
-+
-+enomem:
-+ /* Clean up after an out of memory error */
-+ pr_devel("enomem\n");
-+ assoc_array_cancel_edit(edit);
-+ return ERR_PTR(-ENOMEM);
-+}
-+
-+/**
-+ * assoc_array_insert_set_object - Set the new object pointer in an edit script
-+ * @edit: The edit script to modify.
-+ * @object: The object pointer to set.
-+ *
-+ * Change the object to be inserted in an edit script. The object pointed to
-+ * by the old object is not freed. This must be done prior to applying the
-+ * script.
-+ */
-+void assoc_array_insert_set_object(struct assoc_array_edit *edit, void *object)
-+{
-+ BUG_ON(!object);
-+ edit->leaf = assoc_array_leaf_to_ptr(object);
-+}
-+
-+struct assoc_array_delete_collapse_context {
-+ struct assoc_array_node *node;
-+ const void *skip_leaf;
-+ int slot;
-+};
-+
-+/*
-+ * Subtree collapse to node iterator.
-+ */
-+static int assoc_array_delete_collapse_iterator(const void *leaf,
-+ void *iterator_data)
-+{
-+ struct assoc_array_delete_collapse_context *collapse = iterator_data;
-+
-+ if (leaf == collapse->skip_leaf)
-+ return 0;
-+
-+ BUG_ON(collapse->slot >= ASSOC_ARRAY_FAN_OUT);
-+
-+ collapse->node->slots[collapse->slot++] = assoc_array_leaf_to_ptr(leaf);
-+ return 0;
-+}
-+
-+/**
-+ * assoc_array_delete - Script deletion of an object from an associative array
-+ * @array: The array to search.
-+ * @ops: The operations to use.
-+ * @index_key: The key to the object.
-+ *
-+ * Precalculate and preallocate a script for the deletion of an object from an
-+ * associative array. This results in an edit script that can either be
-+ * applied or cancelled.
-+ *
-+ * The function returns a pointer to an edit script if the object was found,
-+ * NULL if the object was not found or -ENOMEM.
-+ *
-+ * The caller should lock against other modifications and must continue to hold
-+ * the lock until assoc_array_apply_edit() has been called.
-+ *
-+ * Accesses to the tree may take place concurrently with this function,
-+ * provided they hold the RCU read lock.
-+ */
-+struct assoc_array_edit *assoc_array_delete(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ const void *index_key)
-+{
-+ struct assoc_array_delete_collapse_context collapse;
-+ struct assoc_array_walk_result result;
-+ struct assoc_array_node *node, *new_n0;
-+ struct assoc_array_edit *edit;
-+ struct assoc_array_ptr *ptr;
-+ bool has_meta;
-+ int slot, i;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL);
-+ if (!edit)
-+ return ERR_PTR(-ENOMEM);
-+ edit->array = array;
-+ edit->ops = ops;
-+ edit->adjust_count_by = -1;
-+
-+ switch (assoc_array_walk(array, ops, index_key, &result)) {
-+ case assoc_array_walk_found_terminal_node:
-+ /* We found a node that should contain the leaf we've been
-+ * asked to remove - *if* it's in the tree.
-+ */
-+ pr_devel("terminal_node\n");
-+ node = result.terminal_node.node;
-+
-+ for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = node->slots[slot];
-+ if (ptr &&
-+ assoc_array_ptr_is_leaf(ptr) &&
-+ ops->compare_object(assoc_array_ptr_to_leaf(ptr),
-+ index_key))
-+ goto found_leaf;
-+ }
-+ case assoc_array_walk_tree_empty:
-+ case assoc_array_walk_found_wrong_shortcut:
-+ default:
-+ assoc_array_cancel_edit(edit);
-+ pr_devel("not found\n");
-+ return NULL;
-+ }
-+
-+found_leaf:
-+ BUG_ON(array->nr_leaves_on_tree <= 0);
-+
-+ /* In the simplest form of deletion we just clear the slot and release
-+ * the leaf after a suitable interval.
-+ */
-+ edit->dead_leaf = node->slots[slot];
-+ edit->set[0].ptr = &node->slots[slot];
-+ edit->set[0].to = NULL;
-+ edit->adjust_count_on = node;
-+
-+ /* If that concludes erasure of the last leaf, then delete the entire
-+ * internal array.
-+ */
-+ if (array->nr_leaves_on_tree == 1) {
-+ edit->set[1].ptr = &array->root;
-+ edit->set[1].to = NULL;
-+ edit->adjust_count_on = NULL;
-+ edit->excised_subtree = array->root;
-+ pr_devel("all gone\n");
-+ return edit;
-+ }
-+
-+ /* However, we'd also like to clear up some metadata blocks if we
-+ * possibly can.
-+ *
-+ * We go for a simple algorithm of: if this node has FAN_OUT or fewer
-+ * leaves in it, then attempt to collapse it - and attempt to
-+ * recursively collapse up the tree.
-+ *
-+ * We could also try and collapse in partially filled subtrees to take
-+ * up space in this node.
-+ */
-+ if (node->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT + 1) {
-+ struct assoc_array_node *parent, *grandparent;
-+ struct assoc_array_ptr *ptr;
-+
-+ /* First of all, we need to know if this node has metadata so
-+ * that we don't try collapsing if all the leaves are already
-+ * here.
-+ */
-+ has_meta = false;
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ ptr = node->slots[i];
-+ if (assoc_array_ptr_is_meta(ptr)) {
-+ has_meta = true;
-+ break;
-+ }
-+ }
-+
-+ pr_devel("leaves: %ld [m=%d]\n",
-+ node->nr_leaves_on_branch - 1, has_meta);
-+
-+ /* Look further up the tree to see if we can collapse this node
-+ * into a more proximal node too.
-+ */
-+ parent = node;
-+ collapse_up:
-+ pr_devel("collapse subtree: %ld\n", parent->nr_leaves_on_branch);
-+
-+ ptr = parent->back_pointer;
-+ if (!ptr)
-+ goto do_collapse;
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ struct assoc_array_shortcut *s = assoc_array_ptr_to_shortcut(ptr);
-+ ptr = s->back_pointer;
-+ if (!ptr)
-+ goto do_collapse;
-+ }
-+
-+ grandparent = assoc_array_ptr_to_node(ptr);
-+ if (grandparent->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT + 1) {
-+ parent = grandparent;
-+ goto collapse_up;
-+ }
-+
-+ do_collapse:
-+ /* There's no point collapsing if the original node has no meta
-+ * pointers to discard and if we didn't merge into one of that
-+ * node's ancestry.
-+ */
-+ if (has_meta || parent != node) {
-+ node = parent;
-+
-+ /* Create a new node to collapse into */
-+ new_n0 = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL);
-+ if (!new_n0)
-+ goto enomem;
-+ edit->new_meta[0] = assoc_array_node_to_ptr(new_n0);
-+
-+ new_n0->back_pointer = node->back_pointer;
-+ new_n0->parent_slot = node->parent_slot;
-+ new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch;
-+ edit->adjust_count_on = new_n0;
-+
-+ collapse.node = new_n0;
-+ collapse.skip_leaf = assoc_array_ptr_to_leaf(edit->dead_leaf);
-+ collapse.slot = 0;
-+ assoc_array_subtree_iterate(assoc_array_node_to_ptr(node),
-+ node->back_pointer,
-+ assoc_array_delete_collapse_iterator,
-+ &collapse);
-+ pr_devel("collapsed %d,%lu\n", collapse.slot, new_n0->nr_leaves_on_branch);
-+ BUG_ON(collapse.slot != new_n0->nr_leaves_on_branch - 1);
-+
-+ if (!node->back_pointer) {
-+ edit->set[1].ptr = &array->root;
-+ } else if (assoc_array_ptr_is_leaf(node->back_pointer)) {
-+ BUG();
-+ } else if (assoc_array_ptr_is_node(node->back_pointer)) {
-+ struct assoc_array_node *p =
-+ assoc_array_ptr_to_node(node->back_pointer);
-+ edit->set[1].ptr = &p->slots[node->parent_slot];
-+ } else if (assoc_array_ptr_is_shortcut(node->back_pointer)) {
-+ struct assoc_array_shortcut *s =
-+ assoc_array_ptr_to_shortcut(node->back_pointer);
-+ edit->set[1].ptr = &s->next_node;
-+ }
-+ edit->set[1].to = assoc_array_node_to_ptr(new_n0);
-+ edit->excised_subtree = assoc_array_node_to_ptr(node);
-+ }
-+ }
-+
-+ return edit;
-+
-+enomem:
-+ /* Clean up after an out of memory error */
-+ pr_devel("enomem\n");
-+ assoc_array_cancel_edit(edit);
-+ return ERR_PTR(-ENOMEM);
-+}
-+
-+/**
-+ * assoc_array_clear - Script deletion of all objects from an associative array
-+ * @array: The array to clear.
-+ * @ops: The operations to use.
-+ *
-+ * Precalculate and preallocate a script for the deletion of all the objects
-+ * from an associative array. This results in an edit script that can either
-+ * be applied or cancelled.
-+ *
-+ * The function returns a pointer to an edit script if there are objects to be
-+ * deleted, NULL if there are no objects in the array or -ENOMEM.
-+ *
-+ * The caller should lock against other modifications and must continue to hold
-+ * the lock until assoc_array_apply_edit() has been called.
-+ *
-+ * Accesses to the tree may take place concurrently with this function,
-+ * provided they hold the RCU read lock.
-+ */
-+struct assoc_array_edit *assoc_array_clear(struct assoc_array *array,
-+ const struct assoc_array_ops *ops)
-+{
-+ struct assoc_array_edit *edit;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ if (!array->root)
-+ return NULL;
-+
-+ edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL);
-+ if (!edit)
-+ return ERR_PTR(-ENOMEM);
-+ edit->array = array;
-+ edit->ops = ops;
-+ edit->set[1].ptr = &array->root;
-+ edit->set[1].to = NULL;
-+ edit->excised_subtree = array->root;
-+ edit->ops_for_excised_subtree = ops;
-+ pr_devel("all gone\n");
-+ return edit;
-+}
-+
-+/*
-+ * Handle the deferred destruction after an applied edit.
-+ */
-+static void assoc_array_rcu_cleanup(struct rcu_head *head)
-+{
-+ struct assoc_array_edit *edit =
-+ container_of(head, struct assoc_array_edit, rcu);
-+ int i;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ if (edit->dead_leaf)
-+ edit->ops->free_object(assoc_array_ptr_to_leaf(edit->dead_leaf));
-+ for (i = 0; i < ARRAY_SIZE(edit->excised_meta); i++)
-+ if (edit->excised_meta[i])
-+ kfree(assoc_array_ptr_to_node(edit->excised_meta[i]));
-+
-+ if (edit->excised_subtree) {
-+ BUG_ON(assoc_array_ptr_is_leaf(edit->excised_subtree));
-+ if (assoc_array_ptr_is_node(edit->excised_subtree)) {
-+ struct assoc_array_node *n =
-+ assoc_array_ptr_to_node(edit->excised_subtree);
-+ n->back_pointer = NULL;
-+ } else {
-+ struct assoc_array_shortcut *s =
-+ assoc_array_ptr_to_shortcut(edit->excised_subtree);
-+ s->back_pointer = NULL;
-+ }
-+ assoc_array_destroy_subtree(edit->excised_subtree,
-+ edit->ops_for_excised_subtree);
-+ }
-+
-+ kfree(edit);
-+}
-+
-+/**
-+ * assoc_array_apply_edit - Apply an edit script to an associative array
-+ * @edit: The script to apply.
-+ *
-+ * Apply an edit script to an associative array to effect an insertion,
-+ * deletion or clearance. As the edit script includes preallocated memory,
-+ * this is guaranteed not to fail.
-+ *
-+ * The edit script, dead objects and dead metadata will be scheduled for
-+ * destruction after an RCU grace period to permit those doing read-only
-+ * accesses on the array to continue to do so under the RCU read lock whilst
-+ * the edit is taking place.
-+ */
-+void assoc_array_apply_edit(struct assoc_array_edit *edit)
-+{
-+ struct assoc_array_shortcut *shortcut;
-+ struct assoc_array_node *node;
-+ struct assoc_array_ptr *ptr;
-+ int i;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ smp_wmb();
-+ if (edit->leaf_p)
-+ *edit->leaf_p = edit->leaf;
-+
-+ smp_wmb();
-+ for (i = 0; i < ARRAY_SIZE(edit->set_parent_slot); i++)
-+ if (edit->set_parent_slot[i].p)
-+ *edit->set_parent_slot[i].p = edit->set_parent_slot[i].to;
-+
-+ smp_wmb();
-+ for (i = 0; i < ARRAY_SIZE(edit->set_backpointers); i++)
-+ if (edit->set_backpointers[i])
-+ *edit->set_backpointers[i] = edit->set_backpointers_to;
-+
-+ smp_wmb();
-+ for (i = 0; i < ARRAY_SIZE(edit->set); i++)
-+ if (edit->set[i].ptr)
-+ *edit->set[i].ptr = edit->set[i].to;
-+
-+ if (edit->array->root == NULL) {
-+ edit->array->nr_leaves_on_tree = 0;
-+ } else if (edit->adjust_count_on) {
-+ node = edit->adjust_count_on;
-+ for (;;) {
-+ node->nr_leaves_on_branch += edit->adjust_count_by;
-+
-+ ptr = node->back_pointer;
-+ if (!ptr)
-+ break;
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ shortcut = assoc_array_ptr_to_shortcut(ptr);
-+ ptr = shortcut->back_pointer;
-+ if (!ptr)
-+ break;
-+ }
-+ BUG_ON(!assoc_array_ptr_is_node(ptr));
-+ node = assoc_array_ptr_to_node(ptr);
-+ }
-+
-+ edit->array->nr_leaves_on_tree += edit->adjust_count_by;
-+ }
-+
-+ call_rcu(&edit->rcu, assoc_array_rcu_cleanup);
-+}
-+
-+/**
-+ * assoc_array_cancel_edit - Discard an edit script.
-+ * @edit: The script to discard.
-+ *
-+ * Free an edit script and all the preallocated data it holds without making
-+ * any changes to the associative array it was intended for.
-+ *
-+ * NOTE! In the case of an insertion script, this does _not_ release the leaf
-+ * that was to be inserted. That is left to the caller.
-+ */
-+void assoc_array_cancel_edit(struct assoc_array_edit *edit)
-+{
-+ struct assoc_array_ptr *ptr;
-+ int i;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ /* Clean up after an out of memory error */
-+ for (i = 0; i < ARRAY_SIZE(edit->new_meta); i++) {
-+ ptr = edit->new_meta[i];
-+ if (ptr) {
-+ if (assoc_array_ptr_is_node(ptr))
-+ kfree(assoc_array_ptr_to_node(ptr));
-+ else
-+ kfree(assoc_array_ptr_to_shortcut(ptr));
-+ }
-+ }
-+ kfree(edit);
-+}
-+
-+/**
-+ * assoc_array_gc - Garbage collect an associative array.
-+ * @array: The array to clean.
-+ * @ops: The operations to use.
-+ * @iterator: A callback function to pass judgement on each object.
-+ * @iterator_data: Private data for the callback function.
-+ *
-+ * Collect garbage from an associative array and pack down the internal tree to
-+ * save memory.
-+ *
-+ * The iterator function is asked to pass judgement upon each object in the
-+ * array. If it returns false, the object is discard and if it returns true,
-+ * the object is kept. If it returns true, it must increment the object's
-+ * usage count (or whatever it needs to do to retain it) before returning.
-+ *
-+ * This function returns 0 if successful or -ENOMEM if out of memory. In the
-+ * latter case, the array is not changed.
-+ *
-+ * The caller should lock against other modifications and must continue to hold
-+ * the lock until assoc_array_apply_edit() has been called.
-+ *
-+ * Accesses to the tree may take place concurrently with this function,
-+ * provided they hold the RCU read lock.
-+ */
-+int assoc_array_gc(struct assoc_array *array,
-+ const struct assoc_array_ops *ops,
-+ bool (*iterator)(void *object, void *iterator_data),
-+ void *iterator_data)
-+{
-+ struct assoc_array_shortcut *shortcut, *new_s;
-+ struct assoc_array_node *node, *new_n;
-+ struct assoc_array_edit *edit;
-+ struct assoc_array_ptr *cursor, *ptr;
-+ struct assoc_array_ptr *new_root, *new_parent, **new_ptr_pp;
-+ unsigned long nr_leaves_on_tree;
-+ int keylen, slot, nr_free, next_slot, i;
-+
-+ pr_devel("-->%s()\n", __func__);
-+
-+ if (!array->root)
-+ return 0;
-+
-+ edit = kzalloc(sizeof(struct assoc_array_edit), GFP_KERNEL);
-+ if (!edit)
-+ return -ENOMEM;
-+ edit->array = array;
-+ edit->ops = ops;
-+ edit->ops_for_excised_subtree = ops;
-+ edit->set[0].ptr = &array->root;
-+ edit->excised_subtree = array->root;
-+
-+ new_root = new_parent = NULL;
-+ new_ptr_pp = &new_root;
-+ cursor = array->root;
-+
-+descend:
-+ /* If this point is a shortcut, then we need to duplicate it and
-+ * advance the target cursor.
-+ */
-+ if (assoc_array_ptr_is_shortcut(cursor)) {
-+ shortcut = assoc_array_ptr_to_shortcut(cursor);
-+ keylen = round_up(shortcut->skip_to_level, ASSOC_ARRAY_KEY_CHUNK_SIZE);
-+ keylen >>= ASSOC_ARRAY_KEY_CHUNK_SHIFT;
-+ new_s = kmalloc(sizeof(struct assoc_array_shortcut) +
-+ keylen * sizeof(unsigned long), GFP_KERNEL);
-+ if (!new_s)
-+ goto enomem;
-+ pr_devel("dup shortcut %p -> %p\n", shortcut, new_s);
-+ memcpy(new_s, shortcut, (sizeof(struct assoc_array_shortcut) +
-+ keylen * sizeof(unsigned long)));
-+ new_s->back_pointer = new_parent;
-+ new_s->parent_slot = shortcut->parent_slot;
-+ *new_ptr_pp = new_parent = assoc_array_shortcut_to_ptr(new_s);
-+ new_ptr_pp = &new_s->next_node;
-+ cursor = shortcut->next_node;
-+ }
-+
-+ /* Duplicate the node at this position */
-+ node = assoc_array_ptr_to_node(cursor);
-+ new_n = kzalloc(sizeof(struct assoc_array_node), GFP_KERNEL);
-+ if (!new_n)
-+ goto enomem;
-+ pr_devel("dup node %p -> %p\n", node, new_n);
-+ new_n->back_pointer = new_parent;
-+ new_n->parent_slot = node->parent_slot;
-+ *new_ptr_pp = new_parent = assoc_array_node_to_ptr(new_n);
-+ new_ptr_pp = NULL;
-+ slot = 0;
-+
-+continue_node:
-+ /* Filter across any leaves and gc any subtrees */
-+ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = node->slots[slot];
-+ if (!ptr)
-+ continue;
-+
-+ if (assoc_array_ptr_is_leaf(ptr)) {
-+ if (iterator(assoc_array_ptr_to_leaf(ptr),
-+ iterator_data))
-+ /* The iterator will have done any reference
-+ * counting on the object for us.
-+ */
-+ new_n->slots[slot] = ptr;
-+ continue;
-+ }
-+
-+ new_ptr_pp = &new_n->slots[slot];
-+ cursor = ptr;
-+ goto descend;
-+ }
-+
-+ pr_devel("-- compress node %p --\n", new_n);
-+
-+ /* Count up the number of empty slots in this node and work out the
-+ * subtree leaf count.
-+ */
-+ new_n->nr_leaves_on_branch = 0;
-+ nr_free = 0;
-+ for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = new_n->slots[slot];
-+ if (!ptr)
-+ nr_free++;
-+ else if (assoc_array_ptr_is_leaf(ptr))
-+ new_n->nr_leaves_on_branch++;
-+ }
-+ pr_devel("free=%d, leaves=%lu\n", nr_free, new_n->nr_leaves_on_branch);
-+
-+ /* See what we can fold in */
-+ next_slot = 0;
-+ for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ struct assoc_array_shortcut *s;
-+ struct assoc_array_node *child;
-+
-+ ptr = new_n->slots[slot];
-+ if (!ptr || assoc_array_ptr_is_leaf(ptr))
-+ continue;
-+
-+ s = NULL;
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ s = assoc_array_ptr_to_shortcut(ptr);
-+ ptr = s->next_node;
-+ }
-+
-+ child = assoc_array_ptr_to_node(ptr);
-+ new_n->nr_leaves_on_branch += child->nr_leaves_on_branch;
-+
-+ if (child->nr_leaves_on_branch <= nr_free + 1) {
-+ /* Fold the child node into this one */
-+ pr_devel("[%d] fold node %lu/%d [nx %d]\n",
-+ slot, child->nr_leaves_on_branch, nr_free + 1,
-+ next_slot);
-+
-+ /* We would already have reaped an intervening shortcut
-+ * on the way back up the tree.
-+ */
-+ BUG_ON(s);
-+
-+ new_n->slots[slot] = NULL;
-+ nr_free++;
-+ if (slot < next_slot)
-+ next_slot = slot;
-+ for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-+ struct assoc_array_ptr *p = child->slots[i];
-+ if (!p)
-+ continue;
-+ BUG_ON(assoc_array_ptr_is_meta(p));
-+ while (new_n->slots[next_slot])
-+ next_slot++;
-+ BUG_ON(next_slot >= ASSOC_ARRAY_FAN_OUT);
-+ new_n->slots[next_slot++] = p;
-+ nr_free--;
-+ }
-+ kfree(child);
-+ } else {
-+ pr_devel("[%d] retain node %lu/%d [nx %d]\n",
-+ slot, child->nr_leaves_on_branch, nr_free + 1,
-+ next_slot);
-+ }
-+ }
-+
-+ pr_devel("after: %lu\n", new_n->nr_leaves_on_branch);
-+
-+ nr_leaves_on_tree = new_n->nr_leaves_on_branch;
-+
-+ /* Excise this node if it is singly occupied by a shortcut */
-+ if (nr_free == ASSOC_ARRAY_FAN_OUT - 1) {
-+ for (slot = 0; slot < ASSOC_ARRAY_FAN_OUT; slot++)
-+ if ((ptr = new_n->slots[slot]))
-+ break;
-+
-+ if (assoc_array_ptr_is_meta(ptr) &&
-+ assoc_array_ptr_is_shortcut(ptr)) {
-+ pr_devel("excise node %p with 1 shortcut\n", new_n);
-+ new_s = assoc_array_ptr_to_shortcut(ptr);
-+ new_parent = new_n->back_pointer;
-+ slot = new_n->parent_slot;
-+ kfree(new_n);
-+ if (!new_parent) {
-+ new_s->back_pointer = NULL;
-+ new_s->parent_slot = 0;
-+ new_root = ptr;
-+ goto gc_complete;
-+ }
-+
-+ if (assoc_array_ptr_is_shortcut(new_parent)) {
-+ /* We can discard any preceding shortcut also */
-+ struct assoc_array_shortcut *s =
-+ assoc_array_ptr_to_shortcut(new_parent);
-+
-+ pr_devel("excise preceding shortcut\n");
-+
-+ new_parent = new_s->back_pointer = s->back_pointer;
-+ slot = new_s->parent_slot = s->parent_slot;
-+ kfree(s);
-+ if (!new_parent) {
-+ new_s->back_pointer = NULL;
-+ new_s->parent_slot = 0;
-+ new_root = ptr;
-+ goto gc_complete;
-+ }
-+ }
-+
-+ new_s->back_pointer = new_parent;
-+ new_s->parent_slot = slot;
-+ new_n = assoc_array_ptr_to_node(new_parent);
-+ new_n->slots[slot] = ptr;
-+ goto ascend_old_tree;
-+ }
-+ }
-+
-+ /* Excise any shortcuts we might encounter that point to nodes that
-+ * only contain leaves.
-+ */
-+ ptr = new_n->back_pointer;
-+ if (!ptr)
-+ goto gc_complete;
-+
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ new_s = assoc_array_ptr_to_shortcut(ptr);
-+ new_parent = new_s->back_pointer;
-+ slot = new_s->parent_slot;
-+
-+ if (new_n->nr_leaves_on_branch <= ASSOC_ARRAY_FAN_OUT) {
-+ struct assoc_array_node *n;
-+
-+ pr_devel("excise shortcut\n");
-+ new_n->back_pointer = new_parent;
-+ new_n->parent_slot = slot;
-+ kfree(new_s);
-+ if (!new_parent) {
-+ new_root = assoc_array_node_to_ptr(new_n);
-+ goto gc_complete;
-+ }
-+
-+ n = assoc_array_ptr_to_node(new_parent);
-+ n->slots[slot] = assoc_array_node_to_ptr(new_n);
-+ }
-+ } else {
-+ new_parent = ptr;
-+ }
-+ new_n = assoc_array_ptr_to_node(new_parent);
-+
-+ascend_old_tree:
-+ ptr = node->back_pointer;
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ shortcut = assoc_array_ptr_to_shortcut(ptr);
-+ slot = shortcut->parent_slot;
-+ cursor = shortcut->back_pointer;
-+ } else {
-+ slot = node->parent_slot;
-+ cursor = ptr;
-+ }
-+ BUG_ON(!ptr);
-+ node = assoc_array_ptr_to_node(cursor);
-+ slot++;
-+ goto continue_node;
-+
-+gc_complete:
-+ edit->set[0].to = new_root;
-+ assoc_array_apply_edit(edit);
-+ edit->array->nr_leaves_on_tree = nr_leaves_on_tree;
-+ return 0;
-+
-+enomem:
-+ pr_devel("enomem\n");
-+ assoc_array_destroy_subtree(new_root, edit->ops);
-+ kfree(edit);
-+ return -ENOMEM;
-+}
---
-1.8.3.1
-
-
-From 03ac60b84587fa8e57e7ec5cd3d59b7fa8d97c79 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:54 +0100
-Subject: [PATCH 10/10] KEYS: Expand the capacity of a keyring
-
-Expand the capacity of a keyring to be able to hold a lot more keys by using
-the previously added associative array implementation. Currently the maximum
-capacity is:
-
- (PAGE_SIZE - sizeof(header)) / sizeof(struct key *)
-
-which, on a 64-bit system, is a little more 500. However, since this is being
-used for the NFS uid mapper, we need more than that. The new implementation
-gives us effectively unlimited capacity.
-
-With some alterations, the keyutils testsuite runs successfully to completion
-after this patch is applied. The alterations are because (a) keyrings that
-are simply added to no longer appear ordered and (b) some of the errors have
-changed a bit.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/keys/keyring-type.h | 17 +-
- include/linux/key.h | 13 +-
- lib/assoc_array.c | 1 +
- security/keys/Kconfig | 1 +
- security/keys/gc.c | 33 +-
- security/keys/internal.h | 17 +-
- security/keys/key.c | 35 +-
- security/keys/keyring.c | 1436 ++++++++++++++++++++++---------------------
- security/keys/request_key.c | 12 +-
- 9 files changed, 803 insertions(+), 762 deletions(-)
-
-diff --git a/include/keys/keyring-type.h b/include/keys/keyring-type.h
-index cf49159..fca5c62 100644
---- a/include/keys/keyring-type.h
-+++ b/include/keys/keyring-type.h
-@@ -1,6 +1,6 @@
- /* Keyring key type
- *
-- * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
-+ * Copyright (C) 2008, 2013 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
-@@ -13,19 +13,6 @@
- #define _KEYS_KEYRING_TYPE_H
-
- #include <linux/key.h>
--#include <linux/rcupdate.h>
--
--/*
-- * the keyring payload contains a list of the keys to which the keyring is
-- * subscribed
-- */
--struct keyring_list {
-- struct rcu_head rcu; /* RCU deletion hook */
-- unsigned short maxkeys; /* max keys this list can hold */
-- unsigned short nkeys; /* number of keys currently held */
-- unsigned short delkey; /* key to be unlinked by RCU */
-- struct key __rcu *keys[0];
--};
--
-+#include <linux/assoc_array.h>
-
- #endif /* _KEYS_KEYRING_TYPE_H */
-diff --git a/include/linux/key.h b/include/linux/key.h
-index ef596c7..2417f78 100644
---- a/include/linux/key.h
-+++ b/include/linux/key.h
-@@ -22,6 +22,7 @@
- #include <linux/sysctl.h>
- #include <linux/rwsem.h>
- #include <linux/atomic.h>
-+#include <linux/assoc_array.h>
-
- #ifdef __KERNEL__
- #include <linux/uidgid.h>
-@@ -196,11 +197,13 @@ struct key {
- * whatever
- */
- union {
-- unsigned long value;
-- void __rcu *rcudata;
-- void *data;
-- struct keyring_list __rcu *subscriptions;
-- } payload;
-+ union {
-+ unsigned long value;
-+ void __rcu *rcudata;
-+ void *data;
-+ } payload;
-+ struct assoc_array keys;
-+ };
- };
-
- extern struct key *key_alloc(struct key_type *type,
-diff --git a/lib/assoc_array.c b/lib/assoc_array.c
-index a095281..17edeaf 100644
---- a/lib/assoc_array.c
-+++ b/lib/assoc_array.c
-@@ -12,6 +12,7 @@
- */
- //#define DEBUG
- #include <linux/slab.h>
-+#include <linux/err.h>
- #include <linux/assoc_array_priv.h>
-
- /*
-diff --git a/security/keys/Kconfig b/security/keys/Kconfig
-index a90d6d3..15e0dfe 100644
---- a/security/keys/Kconfig
-+++ b/security/keys/Kconfig
-@@ -4,6 +4,7 @@
-
- config KEYS
- bool "Enable access key retention support"
-+ select ASSOCIATIVE_ARRAY
- help
- This option provides support for retaining authentication tokens and
- access keys in the kernel.
-diff --git a/security/keys/gc.c b/security/keys/gc.c
-index d67c97b..cce621c 100644
---- a/security/keys/gc.c
-+++ b/security/keys/gc.c
-@@ -130,6 +130,13 @@ void key_gc_keytype(struct key_type *ktype)
- kleave("");
- }
-
-+static int key_gc_keyring_func(const void *object, void *iterator_data)
-+{
-+ const struct key *key = object;
-+ time_t *limit = iterator_data;
-+ return key_is_dead(key, *limit);
-+}
-+
- /*
- * Garbage collect pointers from a keyring.
- *
-@@ -138,10 +145,9 @@ void key_gc_keytype(struct key_type *ktype)
- */
- static void key_gc_keyring(struct key *keyring, time_t limit)
- {
-- struct keyring_list *klist;
-- int loop;
-+ int result;
-
-- kenter("%x", key_serial(keyring));
-+ kenter("%x{%s}", keyring->serial, keyring->description ?: "");
-
- if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
- (1 << KEY_FLAG_REVOKED)))
-@@ -149,27 +155,17 @@ static void key_gc_keyring(struct key *keyring, time_t limit)
-
- /* scan the keyring looking for dead keys */
- rcu_read_lock();
-- klist = rcu_dereference(keyring->payload.subscriptions);
-- if (!klist)
-- goto unlock_dont_gc;
--
-- loop = klist->nkeys;
-- smp_rmb();
-- for (loop--; loop >= 0; loop--) {
-- struct key *key = rcu_dereference(klist->keys[loop]);
-- if (key_is_dead(key, limit))
-- goto do_gc;
-- }
--
--unlock_dont_gc:
-+ result = assoc_array_iterate(&keyring->keys,
-+ key_gc_keyring_func, &limit);
- rcu_read_unlock();
-+ if (result == true)
-+ goto do_gc;
-+
- dont_gc:
- kleave(" [no gc]");
- return;
-
- do_gc:
-- rcu_read_unlock();
--
- keyring_gc(keyring, limit);
- kleave(" [gc]");
- }
-@@ -392,7 +388,6 @@ found_unreferenced_key:
- */
- found_keyring:
- spin_unlock(&key_serial_lock);
-- kdebug("scan keyring %d", key->serial);
- key_gc_keyring(key, limit);
- goto maybe_resched;
-
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index 73950bf..581c6f6 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -90,20 +90,23 @@ extern void key_type_put(struct key_type *ktype);
-
- extern int __key_link_begin(struct key *keyring,
- const struct keyring_index_key *index_key,
-- unsigned long *_prealloc);
-+ struct assoc_array_edit **_edit);
- extern int __key_link_check_live_key(struct key *keyring, struct key *key);
--extern void __key_link(struct key *keyring, struct key *key,
-- unsigned long *_prealloc);
-+extern void __key_link(struct key *key, struct assoc_array_edit **_edit);
- extern void __key_link_end(struct key *keyring,
- const struct keyring_index_key *index_key,
-- unsigned long prealloc);
-+ struct assoc_array_edit *edit);
-
--extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
-- const struct keyring_index_key *index_key);
-+extern key_ref_t find_key_to_update(key_ref_t keyring_ref,
-+ const struct keyring_index_key *index_key);
-
- extern struct key *keyring_search_instkey(struct key *keyring,
- key_serial_t target_id);
-
-+extern int iterate_over_keyring(const struct key *keyring,
-+ int (*func)(const struct key *key, void *data),
-+ void *data);
-+
- typedef int (*key_match_func_t)(const struct key *, const void *);
-
- struct keyring_search_context {
-@@ -119,6 +122,8 @@ struct keyring_search_context {
- #define KEYRING_SEARCH_NO_CHECK_PERM 0x0010 /* Don't check permissions */
- #define KEYRING_SEARCH_DETECT_TOO_DEEP 0x0020 /* Give an error on excessive depth */
-
-+ int (*iterator)(const void *object, void *iterator_data);
-+
- /* Internal stuff */
- int skipped_ret;
- bool possessed;
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 7d716b8..a819b5c 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -409,7 +409,7 @@ static int __key_instantiate_and_link(struct key *key,
- struct key_preparsed_payload *prep,
- struct key *keyring,
- struct key *authkey,
-- unsigned long *_prealloc)
-+ struct assoc_array_edit **_edit)
- {
- int ret, awaken;
-
-@@ -436,7 +436,7 @@ static int __key_instantiate_and_link(struct key *key,
-
- /* and link it into the destination keyring */
- if (keyring)
-- __key_link(keyring, key, _prealloc);
-+ __key_link(key, _edit);
-
- /* disable the authorisation key */
- if (authkey)
-@@ -476,7 +476,7 @@ int key_instantiate_and_link(struct key *key,
- struct key *authkey)
- {
- struct key_preparsed_payload prep;
-- unsigned long prealloc;
-+ struct assoc_array_edit *edit;
- int ret;
-
- memset(&prep, 0, sizeof(prep));
-@@ -490,16 +490,15 @@ int key_instantiate_and_link(struct key *key,
- }
-
- if (keyring) {
-- ret = __key_link_begin(keyring, &key->index_key, &prealloc);
-+ ret = __key_link_begin(keyring, &key->index_key, &edit);
- if (ret < 0)
- goto error_free_preparse;
- }
-
-- ret = __key_instantiate_and_link(key, &prep, keyring, authkey,
-- &prealloc);
-+ ret = __key_instantiate_and_link(key, &prep, keyring, authkey, &edit);
-
- if (keyring)
-- __key_link_end(keyring, &key->index_key, prealloc);
-+ __key_link_end(keyring, &key->index_key, edit);
-
- error_free_preparse:
- if (key->type->preparse)
-@@ -537,7 +536,7 @@ int key_reject_and_link(struct key *key,
- struct key *keyring,
- struct key *authkey)
- {
-- unsigned long prealloc;
-+ struct assoc_array_edit *edit;
- struct timespec now;
- int ret, awaken, link_ret = 0;
-
-@@ -548,7 +547,7 @@ int key_reject_and_link(struct key *key,
- ret = -EBUSY;
-
- if (keyring)
-- link_ret = __key_link_begin(keyring, &key->index_key, &prealloc);
-+ link_ret = __key_link_begin(keyring, &key->index_key, &edit);
-
- mutex_lock(&key_construction_mutex);
-
-@@ -570,7 +569,7 @@ int key_reject_and_link(struct key *key,
-
- /* and link it into the destination keyring */
- if (keyring && link_ret == 0)
-- __key_link(keyring, key, &prealloc);
-+ __key_link(key, &edit);
-
- /* disable the authorisation key */
- if (authkey)
-@@ -580,7 +579,7 @@ int key_reject_and_link(struct key *key,
- mutex_unlock(&key_construction_mutex);
-
- if (keyring)
-- __key_link_end(keyring, &key->index_key, prealloc);
-+ __key_link_end(keyring, &key->index_key, edit);
-
- /* wake up anyone waiting for a key to be constructed */
- if (awaken)
-@@ -783,8 +782,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- .description = description,
- };
- struct key_preparsed_payload prep;
-+ struct assoc_array_edit *edit;
- const struct cred *cred = current_cred();
-- unsigned long prealloc;
- struct key *keyring, *key = NULL;
- key_ref_t key_ref;
- int ret;
-@@ -828,7 +827,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- }
- index_key.desc_len = strlen(index_key.description);
-
-- ret = __key_link_begin(keyring, &index_key, &prealloc);
-+ ret = __key_link_begin(keyring, &index_key, &edit);
- if (ret < 0) {
- key_ref = ERR_PTR(ret);
- goto error_free_prep;
-@@ -847,8 +846,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- * update that instead if possible
- */
- if (index_key.type->update) {
-- key_ref = __keyring_search_one(keyring_ref, &index_key);
-- if (!IS_ERR(key_ref))
-+ key_ref = find_key_to_update(keyring_ref, &index_key);
-+ if (key_ref)
- goto found_matching_key;
- }
-
-@@ -874,7 +873,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- }
-
- /* instantiate it and link it into the target keyring */
-- ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc);
-+ ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &edit);
- if (ret < 0) {
- key_put(key);
- key_ref = ERR_PTR(ret);
-@@ -884,7 +883,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- key_ref = make_key_ref(key, is_key_possessed(keyring_ref));
-
- error_link_end:
-- __key_link_end(keyring, &index_key, prealloc);
-+ __key_link_end(keyring, &index_key, edit);
- error_free_prep:
- if (index_key.type->preparse)
- index_key.type->free_preparse(&prep);
-@@ -897,7 +896,7 @@ error:
- /* we found a matching key, so we're going to try to update it
- * - we can drop the locks first as we have the key pinned
- */
-- __key_link_end(keyring, &index_key, prealloc);
-+ __key_link_end(keyring, &index_key, edit);
-
- key_ref = __key_update(key_ref, &prep);
- goto error_free_prep;
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index eeef1a0..f7cdea2 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -1,6 +1,6 @@
- /* Keyring handling
- *
-- * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
-+ * Copyright (C) 2004-2005, 2008, 2013 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
-@@ -17,25 +17,11 @@
- #include <linux/seq_file.h>
- #include <linux/err.h>
- #include <keys/keyring-type.h>
-+#include <keys/user-type.h>
-+#include <linux/assoc_array_priv.h>
- #include <linux/uaccess.h>
- #include "internal.h"
-
--#define rcu_dereference_locked_keyring(keyring) \
-- (rcu_dereference_protected( \
-- (keyring)->payload.subscriptions, \
-- rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
--
--#define rcu_deref_link_locked(klist, index, keyring) \
-- (rcu_dereference_protected( \
-- (klist)->keys[index], \
-- rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
--
--#define MAX_KEYRING_LINKS \
-- min_t(size_t, USHRT_MAX - 1, \
-- ((PAGE_SIZE - sizeof(struct keyring_list)) / sizeof(struct key *)))
--
--#define KEY_LINK_FIXQUOTA 1UL
--
- /*
- * When plumbing the depths of the key tree, this sets a hard limit
- * set on how deep we're willing to go.
-@@ -47,6 +33,28 @@
- */
- #define KEYRING_NAME_HASH_SIZE (1 << 5)
-
-+/*
-+ * We mark pointers we pass to the associative array with bit 1 set if
-+ * they're keyrings and clear otherwise.
-+ */
-+#define KEYRING_PTR_SUBTYPE 0x2UL
-+
-+static inline bool keyring_ptr_is_keyring(const struct assoc_array_ptr *x)
-+{
-+ return (unsigned long)x & KEYRING_PTR_SUBTYPE;
-+}
-+static inline struct key *keyring_ptr_to_key(const struct assoc_array_ptr *x)
-+{
-+ void *object = assoc_array_ptr_to_leaf(x);
-+ return (struct key *)((unsigned long)object & ~KEYRING_PTR_SUBTYPE);
-+}
-+static inline void *keyring_key_to_ptr(struct key *key)
-+{
-+ if (key->type == &key_type_keyring)
-+ return (void *)((unsigned long)key | KEYRING_PTR_SUBTYPE);
-+ return key;
-+}
-+
- static struct list_head keyring_name_hash[KEYRING_NAME_HASH_SIZE];
- static DEFINE_RWLOCK(keyring_name_lock);
-
-@@ -67,7 +75,6 @@ static inline unsigned keyring_hash(const char *desc)
- */
- static int keyring_instantiate(struct key *keyring,
- struct key_preparsed_payload *prep);
--static int keyring_match(const struct key *keyring, const void *criterion);
- static void keyring_revoke(struct key *keyring);
- static void keyring_destroy(struct key *keyring);
- static void keyring_describe(const struct key *keyring, struct seq_file *m);
-@@ -76,9 +83,9 @@ static long keyring_read(const struct key *keyring,
-
- struct key_type key_type_keyring = {
- .name = "keyring",
-- .def_datalen = sizeof(struct keyring_list),
-+ .def_datalen = 0,
- .instantiate = keyring_instantiate,
-- .match = keyring_match,
-+ .match = user_match,
- .revoke = keyring_revoke,
- .destroy = keyring_destroy,
- .describe = keyring_describe,
-@@ -127,6 +134,7 @@ static int keyring_instantiate(struct key *keyring,
-
- ret = -EINVAL;
- if (prep->datalen == 0) {
-+ assoc_array_init(&keyring->keys);
- /* make the keyring available by name if it has one */
- keyring_publish_name(keyring);
- ret = 0;
-@@ -136,15 +144,226 @@ static int keyring_instantiate(struct key *keyring,
- }
-
- /*
-- * Match keyrings on their name
-+ * Multiply 64-bits by 32-bits to 96-bits and fold back to 64-bit. Ideally we'd
-+ * fold the carry back too, but that requires inline asm.
-+ */
-+static u64 mult_64x32_and_fold(u64 x, u32 y)
-+{
-+ u64 hi = (u64)(u32)(x >> 32) * y;
-+ u64 lo = (u64)(u32)(x) * y;
-+ return lo + ((u64)(u32)hi << 32) + (u32)(hi >> 32);
-+}
-+
-+/*
-+ * Hash a key type and description.
-+ */
-+static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key)
-+{
-+ const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;
-+ const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK;
-+ const char *description = index_key->description;
-+ unsigned long hash, type;
-+ u32 piece;
-+ u64 acc;
-+ int n, desc_len = index_key->desc_len;
-+
-+ type = (unsigned long)index_key->type;
-+
-+ acc = mult_64x32_and_fold(type, desc_len + 13);
-+ acc = mult_64x32_and_fold(acc, 9207);
-+ for (;;) {
-+ n = desc_len;
-+ if (n <= 0)
-+ break;
-+ if (n > 4)
-+ n = 4;
-+ piece = 0;
-+ memcpy(&piece, description, n);
-+ description += n;
-+ desc_len -= n;
-+ acc = mult_64x32_and_fold(acc, piece);
-+ acc = mult_64x32_and_fold(acc, 9207);
-+ }
-+
-+ /* Fold the hash down to 32 bits if need be. */
-+ hash = acc;
-+ if (ASSOC_ARRAY_KEY_CHUNK_SIZE == 32)
-+ hash ^= acc >> 32;
-+
-+ /* Squidge all the keyrings into a separate part of the tree to
-+ * ordinary keys by making sure the lowest level segment in the hash is
-+ * zero for keyrings and non-zero otherwise.
-+ */
-+ if (index_key->type != &key_type_keyring && (hash & level_mask) == 0)
-+ return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1;
-+ if (index_key->type == &key_type_keyring && (hash & level_mask) != 0)
-+ return (hash + (hash << level_shift)) & ~level_mask;
-+ return hash;
-+}
-+
-+/*
-+ * Build the next index key chunk.
-+ *
-+ * On 32-bit systems the index key is laid out as:
-+ *
-+ * 0 4 5 9...
-+ * hash desclen typeptr desc[]
-+ *
-+ * On 64-bit systems:
-+ *
-+ * 0 8 9 17...
-+ * hash desclen typeptr desc[]
-+ *
-+ * We return it one word-sized chunk at a time.
- */
--static int keyring_match(const struct key *keyring, const void *description)
-+static unsigned long keyring_get_key_chunk(const void *data, int level)
-+{
-+ const struct keyring_index_key *index_key = data;
-+ unsigned long chunk = 0;
-+ long offset = 0;
-+ int desc_len = index_key->desc_len, n = sizeof(chunk);
-+
-+ level /= ASSOC_ARRAY_KEY_CHUNK_SIZE;
-+ switch (level) {
-+ case 0:
-+ return hash_key_type_and_desc(index_key);
-+ case 1:
-+ return ((unsigned long)index_key->type << 8) | desc_len;
-+ case 2:
-+ if (desc_len == 0)
-+ return (u8)((unsigned long)index_key->type >>
-+ (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8));
-+ n--;
-+ offset = 1;
-+ default:
-+ offset += sizeof(chunk) - 1;
-+ offset += (level - 3) * sizeof(chunk);
-+ if (offset >= desc_len)
-+ return 0;
-+ desc_len -= offset;
-+ if (desc_len > n)
-+ desc_len = n;
-+ offset += desc_len;
-+ do {
-+ chunk <<= 8;
-+ chunk |= ((u8*)index_key->description)[--offset];
-+ } while (--desc_len > 0);
-+
-+ if (level == 2) {
-+ chunk <<= 8;
-+ chunk |= (u8)((unsigned long)index_key->type >>
-+ (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8));
-+ }
-+ return chunk;
-+ }
-+}
-+
-+static unsigned long keyring_get_object_key_chunk(const void *object, int level)
-+{
-+ const struct key *key = keyring_ptr_to_key(object);
-+ return keyring_get_key_chunk(&key->index_key, level);
-+}
-+
-+static bool keyring_compare_object(const void *object, const void *data)
- {
-- return keyring->description &&
-- strcmp(keyring->description, description) == 0;
-+ const struct keyring_index_key *index_key = data;
-+ const struct key *key = keyring_ptr_to_key(object);
-+
-+ return key->index_key.type == index_key->type &&
-+ key->index_key.desc_len == index_key->desc_len &&
-+ memcmp(key->index_key.description, index_key->description,
-+ index_key->desc_len) == 0;
- }
-
- /*
-+ * Compare the index keys of a pair of objects and determine the bit position
-+ * at which they differ - if they differ.
-+ */
-+static int keyring_diff_objects(const void *_a, const void *_b)
-+{
-+ const struct key *key_a = keyring_ptr_to_key(_a);
-+ const struct key *key_b = keyring_ptr_to_key(_b);
-+ const struct keyring_index_key *a = &key_a->index_key;
-+ const struct keyring_index_key *b = &key_b->index_key;
-+ unsigned long seg_a, seg_b;
-+ int level, i;
-+
-+ level = 0;
-+ seg_a = hash_key_type_and_desc(a);
-+ seg_b = hash_key_type_and_desc(b);
-+ if ((seg_a ^ seg_b) != 0)
-+ goto differ;
-+
-+ /* The number of bits contributed by the hash is controlled by a
-+ * constant in the assoc_array headers. Everything else thereafter we
-+ * can deal with as being machine word-size dependent.
-+ */
-+ level += ASSOC_ARRAY_KEY_CHUNK_SIZE / 8;
-+ seg_a = a->desc_len;
-+ seg_b = b->desc_len;
-+ if ((seg_a ^ seg_b) != 0)
-+ goto differ;
-+
-+ /* The next bit may not work on big endian */
-+ level++;
-+ seg_a = (unsigned long)a->type;
-+ seg_b = (unsigned long)b->type;
-+ if ((seg_a ^ seg_b) != 0)
-+ goto differ;
-+
-+ level += sizeof(unsigned long);
-+ if (a->desc_len == 0)
-+ goto same;
-+
-+ i = 0;
-+ if (((unsigned long)a->description | (unsigned long)b->description) &
-+ (sizeof(unsigned long) - 1)) {
-+ do {
-+ seg_a = *(unsigned long *)(a->description + i);
-+ seg_b = *(unsigned long *)(b->description + i);
-+ if ((seg_a ^ seg_b) != 0)
-+ goto differ_plus_i;
-+ i += sizeof(unsigned long);
-+ } while (i < (a->desc_len & (sizeof(unsigned long) - 1)));
-+ }
-+
-+ for (; i < a->desc_len; i++) {
-+ seg_a = *(unsigned char *)(a->description + i);
-+ seg_b = *(unsigned char *)(b->description + i);
-+ if ((seg_a ^ seg_b) != 0)
-+ goto differ_plus_i;
-+ }
-+
-+same:
-+ return -1;
-+
-+differ_plus_i:
-+ level += i;
-+differ:
-+ i = level * 8 + __ffs(seg_a ^ seg_b);
-+ return i;
-+}
-+
-+/*
-+ * Free an object after stripping the keyring flag off of the pointer.
-+ */
-+static void keyring_free_object(void *object)
-+{
-+ key_put(keyring_ptr_to_key(object));
-+}
-+
-+/*
-+ * Operations for keyring management by the index-tree routines.
-+ */
-+static const struct assoc_array_ops keyring_assoc_array_ops = {
-+ .get_key_chunk = keyring_get_key_chunk,
-+ .get_object_key_chunk = keyring_get_object_key_chunk,
-+ .compare_object = keyring_compare_object,
-+ .diff_objects = keyring_diff_objects,
-+ .free_object = keyring_free_object,
-+};
-+
-+/*
- * Clean up a keyring when it is destroyed. Unpublish its name if it had one
- * and dispose of its data.
- *
-@@ -155,9 +374,6 @@ static int keyring_match(const struct key *keyring, const void *description)
- */
- static void keyring_destroy(struct key *keyring)
- {
-- struct keyring_list *klist;
-- int loop;
--
- if (keyring->description) {
- write_lock(&keyring_name_lock);
-
-@@ -168,12 +384,7 @@ static void keyring_destroy(struct key *keyring)
- write_unlock(&keyring_name_lock);
- }
-
-- klist = rcu_access_pointer(keyring->payload.subscriptions);
-- if (klist) {
-- for (loop = klist->nkeys - 1; loop >= 0; loop--)
-- key_put(rcu_access_pointer(klist->keys[loop]));
-- kfree(klist);
-- }
-+ assoc_array_destroy(&keyring->keys, &keyring_assoc_array_ops);
- }
-
- /*
-@@ -181,76 +392,88 @@ static void keyring_destroy(struct key *keyring)
- */
- static void keyring_describe(const struct key *keyring, struct seq_file *m)
- {
-- struct keyring_list *klist;
--
- if (keyring->description)
- seq_puts(m, keyring->description);
- else
- seq_puts(m, "[anon]");
-
- if (key_is_instantiated(keyring)) {
-- rcu_read_lock();
-- klist = rcu_dereference(keyring->payload.subscriptions);
-- if (klist)
-- seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
-+ if (keyring->keys.nr_leaves_on_tree != 0)
-+ seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree);
- else
- seq_puts(m, ": empty");
-- rcu_read_unlock();
- }
- }
-
-+struct keyring_read_iterator_context {
-+ size_t qty;
-+ size_t count;
-+ key_serial_t __user *buffer;
-+};
-+
-+static int keyring_read_iterator(const void *object, void *data)
-+{
-+ struct keyring_read_iterator_context *ctx = data;
-+ const struct key *key = keyring_ptr_to_key(object);
-+ int ret;
-+
-+ kenter("{%s,%d},,{%zu/%zu}",
-+ key->type->name, key->serial, ctx->count, ctx->qty);
-+
-+ if (ctx->count >= ctx->qty)
-+ return 1;
-+
-+ ret = put_user(key->serial, ctx->buffer);
-+ if (ret < 0)
-+ return ret;
-+ ctx->buffer++;
-+ ctx->count += sizeof(key->serial);
-+ return 0;
-+}
-+
- /*
- * Read a list of key IDs from the keyring's contents in binary form
- *
-- * The keyring's semaphore is read-locked by the caller.
-+ * The keyring's semaphore is read-locked by the caller. This prevents someone
-+ * from modifying it under us - which could cause us to read key IDs multiple
-+ * times.
- */
- static long keyring_read(const struct key *keyring,
- char __user *buffer, size_t buflen)
- {
-- struct keyring_list *klist;
-- struct key *key;
-- size_t qty, tmp;
-- int loop, ret;
-+ struct keyring_read_iterator_context ctx;
-+ unsigned long nr_keys;
-+ int ret;
-
-- ret = 0;
-- klist = rcu_dereference_locked_keyring(keyring);
-- if (klist) {
-- /* calculate how much data we could return */
-- qty = klist->nkeys * sizeof(key_serial_t);
--
-- if (buffer && buflen > 0) {
-- if (buflen > qty)
-- buflen = qty;
--
-- /* copy the IDs of the subscribed keys into the
-- * buffer */
-- ret = -EFAULT;
--
-- for (loop = 0; loop < klist->nkeys; loop++) {
-- key = rcu_deref_link_locked(klist, loop,
-- keyring);
--
-- tmp = sizeof(key_serial_t);
-- if (tmp > buflen)
-- tmp = buflen;
--
-- if (copy_to_user(buffer,
-- &key->serial,
-- tmp) != 0)
-- goto error;
--
-- buflen -= tmp;
-- if (buflen == 0)
-- break;
-- buffer += tmp;
-- }
-- }
-+ kenter("{%d},,%zu", key_serial(keyring), buflen);
-+
-+ if (buflen & (sizeof(key_serial_t) - 1))
-+ return -EINVAL;
-+
-+ nr_keys = keyring->keys.nr_leaves_on_tree;
-+ if (nr_keys == 0)
-+ return 0;
-
-- ret = qty;
-+ /* Calculate how much data we could return */
-+ ctx.qty = nr_keys * sizeof(key_serial_t);
-+
-+ if (!buffer || !buflen)
-+ return ctx.qty;
-+
-+ if (buflen > ctx.qty)
-+ ctx.qty = buflen;
-+
-+ /* Copy the IDs of the subscribed keys into the buffer */
-+ ctx.buffer = (key_serial_t __user *)buffer;
-+ ctx.count = 0;
-+ ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
-+ if (ret < 0) {
-+ kleave(" = %d [iterate]", ret);
-+ return ret;
- }
-
--error:
-- return ret;
-+ kleave(" = %zu [ok]", ctx.count);
-+ return ctx.count;
- }
-
- /*
-@@ -277,219 +500,360 @@ struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
- }
- EXPORT_SYMBOL(keyring_alloc);
-
--/**
-- * keyring_search_aux - Search a keyring tree for a key matching some criteria
-- * @keyring_ref: A pointer to the keyring with possession indicator.
-- * @ctx: The keyring search context.
-- *
-- * Search the supplied keyring tree for a key that matches the criteria given.
-- * The root keyring and any linked keyrings must grant Search permission to the
-- * caller to be searchable and keys can only be found if they too grant Search
-- * to the caller. The possession flag on the root keyring pointer controls use
-- * of the possessor bits in permissions checking of the entire tree. In
-- * addition, the LSM gets to forbid keyring searches and key matches.
-- *
-- * The search is performed as a breadth-then-depth search up to the prescribed
-- * limit (KEYRING_SEARCH_MAX_DEPTH).
-- *
-- * Keys are matched to the type provided and are then filtered by the match
-- * function, which is given the description to use in any way it sees fit. The
-- * match function may use any attributes of a key that it wishes to to
-- * determine the match. Normally the match function from the key type would be
-- * used.
-- *
-- * RCU is used to prevent the keyring key lists from disappearing without the
-- * need to take lots of locks.
-- *
-- * Returns a pointer to the found key and increments the key usage count if
-- * successful; -EAGAIN if no matching keys were found, or if expired or revoked
-- * keys were found; -ENOKEY if only negative keys were found; -ENOTDIR if the
-- * specified keyring wasn't a keyring.
-- *
-- * In the case of a successful return, the possession attribute from
-- * @keyring_ref is propagated to the returned key reference.
-+/*
-+ * Iteration function to consider each key found.
- */
--key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-- struct keyring_search_context *ctx)
-+static int keyring_search_iterator(const void *object, void *iterator_data)
- {
-- struct {
-- /* Need a separate keylist pointer for RCU purposes */
-- struct key *keyring;
-- struct keyring_list *keylist;
-- int kix;
-- } stack[KEYRING_SEARCH_MAX_DEPTH];
--
-- struct keyring_list *keylist;
-- unsigned long kflags;
-- struct key *keyring, *key;
-- key_ref_t key_ref;
-- long err;
-- int sp, nkeys, kix;
-+ struct keyring_search_context *ctx = iterator_data;
-+ const struct key *key = keyring_ptr_to_key(object);
-+ unsigned long kflags = key->flags;
-
-- keyring = key_ref_to_ptr(keyring_ref);
-- ctx->possessed = is_key_possessed(keyring_ref);
-- key_check(keyring);
-+ kenter("{%d}", key->serial);
-
-- /* top keyring must have search permission to begin the search */
-- err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
-- if (err < 0) {
-- key_ref = ERR_PTR(err);
-- goto error;
-+ /* ignore keys not of this type */
-+ if (key->type != ctx->index_key.type) {
-+ kleave(" = 0 [!type]");
-+ return 0;
- }
-
-- key_ref = ERR_PTR(-ENOTDIR);
-- if (keyring->type != &key_type_keyring)
-- goto error;
-+ /* skip invalidated, revoked and expired keys */
-+ if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
-+ if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
-+ (1 << KEY_FLAG_REVOKED))) {
-+ ctx->result = ERR_PTR(-EKEYREVOKED);
-+ kleave(" = %d [invrev]", ctx->skipped_ret);
-+ goto skipped;
-+ }
-
-- rcu_read_lock();
-+ if (key->expiry && ctx->now.tv_sec >= key->expiry) {
-+ ctx->result = ERR_PTR(-EKEYEXPIRED);
-+ kleave(" = %d [expire]", ctx->skipped_ret);
-+ goto skipped;
-+ }
-+ }
-
-- ctx->now = current_kernel_time();
-- err = -EAGAIN;
-- sp = 0;
--
-- /* firstly we should check to see if this top-level keyring is what we
-- * are looking for */
-- key_ref = ERR_PTR(-EAGAIN);
-- kflags = keyring->flags;
-- if (keyring->type == ctx->index_key.type &&
-- ctx->match(keyring, ctx->match_data)) {
-- key = keyring;
-- if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
-- goto found;
-+ /* keys that don't match */
-+ if (!ctx->match(key, ctx->match_data)) {
-+ kleave(" = 0 [!match]");
-+ return 0;
-+ }
-
-- /* check it isn't negative and hasn't expired or been
-- * revoked */
-- if (kflags & (1 << KEY_FLAG_REVOKED))
-- goto error_2;
-- if (key->expiry && ctx->now.tv_sec >= key->expiry)
-- goto error_2;
-- key_ref = ERR_PTR(key->type_data.reject_error);
-- if (kflags & (1 << KEY_FLAG_NEGATIVE))
-- goto error_2;
-- goto found;
-+ /* key must have search permissions */
-+ if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) &&
-+ key_task_permission(make_key_ref(key, ctx->possessed),
-+ ctx->cred, KEY_SEARCH) < 0) {
-+ ctx->result = ERR_PTR(-EACCES);
-+ kleave(" = %d [!perm]", ctx->skipped_ret);
-+ goto skipped;
- }
-
-- /* otherwise, the top keyring must not be revoked, expired, or
-- * negatively instantiated if we are to search it */
-- key_ref = ERR_PTR(-EAGAIN);
-- if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
-- (1 << KEY_FLAG_REVOKED) |
-- (1 << KEY_FLAG_NEGATIVE)) ||
-- (keyring->expiry && ctx->now.tv_sec >= keyring->expiry))
-- goto error_2;
--
-- /* start processing a new keyring */
--descend:
-- kflags = keyring->flags;
-- if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
-- (1 << KEY_FLAG_REVOKED)))
-- goto not_this_keyring;
-+ if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
-+ /* we set a different error code if we pass a negative key */
-+ if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
-+ ctx->result = ERR_PTR(key->type_data.reject_error);
-+ kleave(" = %d [neg]", ctx->skipped_ret);
-+ goto skipped;
-+ }
-+ }
-
-- keylist = rcu_dereference(keyring->payload.subscriptions);
-- if (!keylist)
-- goto not_this_keyring;
-+ /* Found */
-+ ctx->result = make_key_ref(key, ctx->possessed);
-+ kleave(" = 1 [found]");
-+ return 1;
-
-- /* iterate through the keys in this keyring first */
-- nkeys = keylist->nkeys;
-- smp_rmb();
-- for (kix = 0; kix < nkeys; kix++) {
-- key = rcu_dereference(keylist->keys[kix]);
-- kflags = key->flags;
-+skipped:
-+ return ctx->skipped_ret;
-+}
-
-- /* ignore keys not of this type */
-- if (key->type != ctx->index_key.type)
-- continue;
-+/*
-+ * Search inside a keyring for a key. We can search by walking to it
-+ * directly based on its index-key or we can iterate over the entire
-+ * tree looking for it, based on the match function.
-+ */
-+static int search_keyring(struct key *keyring, struct keyring_search_context *ctx)
-+{
-+ if ((ctx->flags & KEYRING_SEARCH_LOOKUP_TYPE) ==
-+ KEYRING_SEARCH_LOOKUP_DIRECT) {
-+ const void *object;
-+
-+ object = assoc_array_find(&keyring->keys,
-+ &keyring_assoc_array_ops,
-+ &ctx->index_key);
-+ return object ? ctx->iterator(object, ctx) : 0;
-+ }
-+ return assoc_array_iterate(&keyring->keys, ctx->iterator, ctx);
-+}
-
-- /* skip invalidated, revoked and expired keys */
-- if (!(ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)) {
-- if (kflags & ((1 << KEY_FLAG_INVALIDATED) |
-- (1 << KEY_FLAG_REVOKED)))
-- continue;
-+/*
-+ * Search a tree of keyrings that point to other keyrings up to the maximum
-+ * depth.
-+ */
-+static bool search_nested_keyrings(struct key *keyring,
-+ struct keyring_search_context *ctx)
-+{
-+ struct {
-+ struct key *keyring;
-+ struct assoc_array_node *node;
-+ int slot;
-+ } stack[KEYRING_SEARCH_MAX_DEPTH];
-
-- if (key->expiry && ctx->now.tv_sec >= key->expiry)
-- continue;
-- }
-+ struct assoc_array_shortcut *shortcut;
-+ struct assoc_array_node *node;
-+ struct assoc_array_ptr *ptr;
-+ struct key *key;
-+ int sp = 0, slot;
-
-- /* keys that don't match */
-- if (!ctx->match(key, ctx->match_data))
-- continue;
-+ kenter("{%d},{%s,%s}",
-+ keyring->serial,
-+ ctx->index_key.type->name,
-+ ctx->index_key.description);
-
-- /* key must have search permissions */
-- if (key_task_permission(make_key_ref(key, ctx->possessed),
-- ctx->cred, KEY_SEARCH) < 0)
-- continue;
-+ if (ctx->index_key.description)
-+ ctx->index_key.desc_len = strlen(ctx->index_key.description);
-
-- if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
-+ /* Check to see if this top-level keyring is what we are looking for
-+ * and whether it is valid or not.
-+ */
-+ if (ctx->flags & KEYRING_SEARCH_LOOKUP_ITERATE ||
-+ keyring_compare_object(keyring, &ctx->index_key)) {
-+ ctx->skipped_ret = 2;
-+ ctx->flags |= KEYRING_SEARCH_DO_STATE_CHECK;
-+ switch (ctx->iterator(keyring_key_to_ptr(keyring), ctx)) {
-+ case 1:
- goto found;
--
-- /* we set a different error code if we pass a negative key */
-- if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
-- err = key->type_data.reject_error;
-- continue;
-+ case 2:
-+ return false;
-+ default:
-+ break;
- }
-+ }
-
-+ ctx->skipped_ret = 0;
-+ if (ctx->flags & KEYRING_SEARCH_NO_STATE_CHECK)
-+ ctx->flags &= ~KEYRING_SEARCH_DO_STATE_CHECK;
-+
-+ /* Start processing a new keyring */
-+descend_to_keyring:
-+ kdebug("descend to %d", keyring->serial);
-+ if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
-+ (1 << KEY_FLAG_REVOKED)))
-+ goto not_this_keyring;
-+
-+ /* Search through the keys in this keyring before its searching its
-+ * subtrees.
-+ */
-+ if (search_keyring(keyring, ctx))
- goto found;
-- }
-
-- /* search through the keyrings nested in this one */
-- kix = 0;
--ascend:
-- nkeys = keylist->nkeys;
-- smp_rmb();
-- for (; kix < nkeys; kix++) {
-- key = rcu_dereference(keylist->keys[kix]);
-- if (key->type != &key_type_keyring)
-- continue;
-+ /* Then manually iterate through the keyrings nested in this one.
-+ *
-+ * Start from the root node of the index tree. Because of the way the
-+ * hash function has been set up, keyrings cluster on the leftmost
-+ * branch of the root node (root slot 0) or in the root node itself.
-+ * Non-keyrings avoid the leftmost branch of the root entirely (root
-+ * slots 1-15).
-+ */
-+ ptr = ACCESS_ONCE(keyring->keys.root);
-+ if (!ptr)
-+ goto not_this_keyring;
-
-- /* recursively search nested keyrings
-- * - only search keyrings for which we have search permission
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ /* If the root is a shortcut, either the keyring only contains
-+ * keyring pointers (everything clusters behind root slot 0) or
-+ * doesn't contain any keyring pointers.
- */
-- if (sp >= KEYRING_SEARCH_MAX_DEPTH)
-+ shortcut = assoc_array_ptr_to_shortcut(ptr);
-+ smp_read_barrier_depends();
-+ if ((shortcut->index_key[0] & ASSOC_ARRAY_FAN_MASK) != 0)
-+ goto not_this_keyring;
-+
-+ ptr = ACCESS_ONCE(shortcut->next_node);
-+ node = assoc_array_ptr_to_node(ptr);
-+ goto begin_node;
-+ }
-+
-+ node = assoc_array_ptr_to_node(ptr);
-+ smp_read_barrier_depends();
-+
-+ ptr = node->slots[0];
-+ if (!assoc_array_ptr_is_meta(ptr))
-+ goto begin_node;
-+
-+descend_to_node:
-+ /* Descend to a more distal node in this keyring's content tree and go
-+ * through that.
-+ */
-+ kdebug("descend");
-+ if (assoc_array_ptr_is_shortcut(ptr)) {
-+ shortcut = assoc_array_ptr_to_shortcut(ptr);
-+ smp_read_barrier_depends();
-+ ptr = ACCESS_ONCE(shortcut->next_node);
-+ BUG_ON(!assoc_array_ptr_is_node(ptr));
-+ node = assoc_array_ptr_to_node(ptr);
-+ }
-+
-+begin_node:
-+ kdebug("begin_node");
-+ smp_read_barrier_depends();
-+ slot = 0;
-+ascend_to_node:
-+ /* Go through the slots in a node */
-+ for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-+ ptr = ACCESS_ONCE(node->slots[slot]);
-+
-+ if (assoc_array_ptr_is_meta(ptr) && node->back_pointer)
-+ goto descend_to_node;
-+
-+ if (!keyring_ptr_is_keyring(ptr))
- continue;
-
-- if (key_task_permission(make_key_ref(key, ctx->possessed),
-+ key = keyring_ptr_to_key(ptr);
-+
-+ if (sp >= KEYRING_SEARCH_MAX_DEPTH) {
-+ if (ctx->flags & KEYRING_SEARCH_DETECT_TOO_DEEP) {
-+ ctx->result = ERR_PTR(-ELOOP);
-+ return false;
-+ }
-+ goto not_this_keyring;
-+ }
-+
-+ /* Search a nested keyring */
-+ if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) &&
-+ key_task_permission(make_key_ref(key, ctx->possessed),
- ctx->cred, KEY_SEARCH) < 0)
- continue;
-
- /* stack the current position */
- stack[sp].keyring = keyring;
-- stack[sp].keylist = keylist;
-- stack[sp].kix = kix;
-+ stack[sp].node = node;
-+ stack[sp].slot = slot;
- sp++;
-
- /* begin again with the new keyring */
- keyring = key;
-- goto descend;
-+ goto descend_to_keyring;
-+ }
-+
-+ /* We've dealt with all the slots in the current node, so now we need
-+ * to ascend to the parent and continue processing there.
-+ */
-+ ptr = ACCESS_ONCE(node->back_pointer);
-+ slot = node->parent_slot;
-+
-+ if (ptr && assoc_array_ptr_is_shortcut(ptr)) {
-+ shortcut = assoc_array_ptr_to_shortcut(ptr);
-+ smp_read_barrier_depends();
-+ ptr = ACCESS_ONCE(shortcut->back_pointer);
-+ slot = shortcut->parent_slot;
-+ }
-+ if (!ptr)
-+ goto not_this_keyring;
-+ node = assoc_array_ptr_to_node(ptr);
-+ smp_read_barrier_depends();
-+ slot++;
-+
-+ /* If we've ascended to the root (zero backpointer), we must have just
-+ * finished processing the leftmost branch rather than the root slots -
-+ * so there can't be any more keyrings for us to find.
-+ */
-+ if (node->back_pointer) {
-+ kdebug("ascend %d", slot);
-+ goto ascend_to_node;
- }
-
-- /* the keyring we're looking at was disqualified or didn't contain a
-- * matching key */
-+ /* The keyring we're looking at was disqualified or didn't contain a
-+ * matching key.
-+ */
- not_this_keyring:
-- if (sp > 0) {
-- /* resume the processing of a keyring higher up in the tree */
-- sp--;
-- keyring = stack[sp].keyring;
-- keylist = stack[sp].keylist;
-- kix = stack[sp].kix + 1;
-- goto ascend;
-+ kdebug("not_this_keyring %d", sp);
-+ if (sp <= 0) {
-+ kleave(" = false");
-+ return false;
- }
-
-- key_ref = ERR_PTR(err);
-- goto error_2;
-+ /* Resume the processing of a keyring higher up in the tree */
-+ sp--;
-+ keyring = stack[sp].keyring;
-+ node = stack[sp].node;
-+ slot = stack[sp].slot + 1;
-+ kdebug("ascend to %d [%d]", keyring->serial, slot);
-+ goto ascend_to_node;
-
-- /* we found a viable match */
-+ /* We found a viable match */
- found:
-- __key_get(key);
-- key->last_used_at = ctx->now.tv_sec;
-- keyring->last_used_at = ctx->now.tv_sec;
-- while (sp > 0)
-- stack[--sp].keyring->last_used_at = ctx->now.tv_sec;
-+ key = key_ref_to_ptr(ctx->result);
- key_check(key);
-- key_ref = make_key_ref(key, ctx->possessed);
--error_2:
-+ if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) {
-+ key->last_used_at = ctx->now.tv_sec;
-+ keyring->last_used_at = ctx->now.tv_sec;
-+ while (sp > 0)
-+ stack[--sp].keyring->last_used_at = ctx->now.tv_sec;
-+ }
-+ kleave(" = true");
-+ return true;
-+}
-+
-+/**
-+ * keyring_search_aux - Search a keyring tree for a key matching some criteria
-+ * @keyring_ref: A pointer to the keyring with possession indicator.
-+ * @ctx: The keyring search context.
-+ *
-+ * Search the supplied keyring tree for a key that matches the criteria given.
-+ * The root keyring and any linked keyrings must grant Search permission to the
-+ * caller to be searchable and keys can only be found if they too grant Search
-+ * to the caller. The possession flag on the root keyring pointer controls use
-+ * of the possessor bits in permissions checking of the entire tree. In
-+ * addition, the LSM gets to forbid keyring searches and key matches.
-+ *
-+ * The search is performed as a breadth-then-depth search up to the prescribed
-+ * limit (KEYRING_SEARCH_MAX_DEPTH).
-+ *
-+ * Keys are matched to the type provided and are then filtered by the match
-+ * function, which is given the description to use in any way it sees fit. The
-+ * match function may use any attributes of a key that it wishes to to
-+ * determine the match. Normally the match function from the key type would be
-+ * used.
-+ *
-+ * RCU can be used to prevent the keyring key lists from disappearing without
-+ * the need to take lots of locks.
-+ *
-+ * Returns a pointer to the found key and increments the key usage count if
-+ * successful; -EAGAIN if no matching keys were found, or if expired or revoked
-+ * keys were found; -ENOKEY if only negative keys were found; -ENOTDIR if the
-+ * specified keyring wasn't a keyring.
-+ *
-+ * In the case of a successful return, the possession attribute from
-+ * @keyring_ref is propagated to the returned key reference.
-+ */
-+key_ref_t keyring_search_aux(key_ref_t keyring_ref,
-+ struct keyring_search_context *ctx)
-+{
-+ struct key *keyring;
-+ long err;
-+
-+ ctx->iterator = keyring_search_iterator;
-+ ctx->possessed = is_key_possessed(keyring_ref);
-+ ctx->result = ERR_PTR(-EAGAIN);
-+
-+ keyring = key_ref_to_ptr(keyring_ref);
-+ key_check(keyring);
-+
-+ if (keyring->type != &key_type_keyring)
-+ return ERR_PTR(-ENOTDIR);
-+
-+ if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM)) {
-+ err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
-+ if (err < 0)
-+ return ERR_PTR(err);
-+ }
-+
-+ rcu_read_lock();
-+ ctx->now = current_kernel_time();
-+ if (search_nested_keyrings(keyring, ctx))
-+ __key_get(key_ref_to_ptr(ctx->result));
- rcu_read_unlock();
--error:
-- return key_ref;
-+ return ctx->result;
- }
-
- /**
-@@ -499,7 +863,7 @@ error:
- * @description: The name of the keyring we want to find.
- *
- * As keyring_search_aux() above, but using the current task's credentials and
-- * type's default matching function.
-+ * type's default matching function and preferred search method.
- */
- key_ref_t keyring_search(key_ref_t keyring,
- struct key_type *type,
-@@ -523,58 +887,49 @@ key_ref_t keyring_search(key_ref_t keyring,
- EXPORT_SYMBOL(keyring_search);
-
- /*
-- * Search the given keyring only (no recursion).
-+ * Search the given keyring for a key that might be updated.
- *
- * The caller must guarantee that the keyring is a keyring and that the
-- * permission is granted to search the keyring as no check is made here.
-- *
-- * RCU is used to make it unnecessary to lock the keyring key list here.
-+ * permission is granted to modify the keyring as no check is made here. The
-+ * caller must also hold a lock on the keyring semaphore.
- *
- * Returns a pointer to the found key with usage count incremented if
-- * successful and returns -ENOKEY if not found. Revoked and invalidated keys
-- * are skipped over.
-+ * successful and returns NULL if not found. Revoked and invalidated keys are
-+ * skipped over.
- *
- * If successful, the possession indicator is propagated from the keyring ref
- * to the returned key reference.
- */
--key_ref_t __keyring_search_one(key_ref_t keyring_ref,
-- const struct keyring_index_key *index_key)
-+key_ref_t find_key_to_update(key_ref_t keyring_ref,
-+ const struct keyring_index_key *index_key)
- {
-- struct keyring_list *klist;
- struct key *keyring, *key;
-- bool possessed;
-- int nkeys, loop;
-+ const void *object;
-
- keyring = key_ref_to_ptr(keyring_ref);
-- possessed = is_key_possessed(keyring_ref);
-
-- rcu_read_lock();
-+ kenter("{%d},{%s,%s}",
-+ keyring->serial, index_key->type->name, index_key->description);
-
-- klist = rcu_dereference(keyring->payload.subscriptions);
-- if (klist) {
-- nkeys = klist->nkeys;
-- smp_rmb();
-- for (loop = 0; loop < nkeys ; loop++) {
-- key = rcu_dereference(klist->keys[loop]);
-- if (key->type == index_key->type &&
-- (!key->type->match ||
-- key->type->match(key, index_key->description)) &&
-- !(key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-- (1 << KEY_FLAG_REVOKED)))
-- )
-- goto found;
-- }
-- }
-+ object = assoc_array_find(&keyring->keys, &keyring_assoc_array_ops,
-+ index_key);
-
-- rcu_read_unlock();
-- return ERR_PTR(-ENOKEY);
-+ if (object)
-+ goto found;
-+
-+ kleave(" = NULL");
-+ return NULL;
-
- found:
-+ key = keyring_ptr_to_key(object);
-+ if (key->flags & ((1 << KEY_FLAG_INVALIDATED) |
-+ (1 << KEY_FLAG_REVOKED))) {
-+ kleave(" = NULL [x]");
-+ return NULL;
-+ }
- __key_get(key);
-- keyring->last_used_at = key->last_used_at =
-- current_kernel_time().tv_sec;
-- rcu_read_unlock();
-- return make_key_ref(key, possessed);
-+ kleave(" = {%d}", key->serial);
-+ return make_key_ref(key, is_key_possessed(keyring_ref));
- }
-
- /*
-@@ -637,6 +992,19 @@ out:
- return keyring;
- }
-
-+static int keyring_detect_cycle_iterator(const void *object,
-+ void *iterator_data)
-+{
-+ struct keyring_search_context *ctx = iterator_data;
-+ const struct key *key = keyring_ptr_to_key(object);
-+
-+ kenter("{%d}", key->serial);
-+
-+ BUG_ON(key != ctx->match_data);
-+ ctx->result = ERR_PTR(-EDEADLK);
-+ return 1;
-+}
-+
- /*
- * See if a cycle will will be created by inserting acyclic tree B in acyclic
- * tree A at the topmost level (ie: as a direct child of A).
-@@ -646,117 +1014,39 @@ out:
- */
- static int keyring_detect_cycle(struct key *A, struct key *B)
- {
-- struct {
-- struct keyring_list *keylist;
-- int kix;
-- } stack[KEYRING_SEARCH_MAX_DEPTH];
--
-- struct keyring_list *keylist;
-- struct key *subtree, *key;
-- int sp, nkeys, kix, ret;
-+ struct keyring_search_context ctx = {
-+ .index_key = A->index_key,
-+ .match_data = A,
-+ .iterator = keyring_detect_cycle_iterator,
-+ .flags = (KEYRING_SEARCH_LOOKUP_DIRECT |
-+ KEYRING_SEARCH_NO_STATE_CHECK |
-+ KEYRING_SEARCH_NO_UPDATE_TIME |
-+ KEYRING_SEARCH_NO_CHECK_PERM |
-+ KEYRING_SEARCH_DETECT_TOO_DEEP),
-+ };
-
- rcu_read_lock();
--
-- ret = -EDEADLK;
-- if (A == B)
-- goto cycle_detected;
--
-- subtree = B;
-- sp = 0;
--
-- /* start processing a new keyring */
--descend:
-- if (test_bit(KEY_FLAG_REVOKED, &subtree->flags))
-- goto not_this_keyring;
--
-- keylist = rcu_dereference(subtree->payload.subscriptions);
-- if (!keylist)
-- goto not_this_keyring;
-- kix = 0;
--
--ascend:
-- /* iterate through the remaining keys in this keyring */
-- nkeys = keylist->nkeys;
-- smp_rmb();
-- for (; kix < nkeys; kix++) {
-- key = rcu_dereference(keylist->keys[kix]);
--
-- if (key == A)
-- goto cycle_detected;
--
-- /* recursively check nested keyrings */
-- if (key->type == &key_type_keyring) {
-- if (sp >= KEYRING_SEARCH_MAX_DEPTH)
-- goto too_deep;
--
-- /* stack the current position */
-- stack[sp].keylist = keylist;
-- stack[sp].kix = kix;
-- sp++;
--
-- /* begin again with the new keyring */
-- subtree = key;
-- goto descend;
-- }
-- }
--
-- /* the keyring we're looking at was disqualified or didn't contain a
-- * matching key */
--not_this_keyring:
-- if (sp > 0) {
-- /* resume the checking of a keyring higher up in the tree */
-- sp--;
-- keylist = stack[sp].keylist;
-- kix = stack[sp].kix + 1;
-- goto ascend;
-- }
--
-- ret = 0; /* no cycles detected */
--
--error:
-+ search_nested_keyrings(B, &ctx);
- rcu_read_unlock();
-- return ret;
--
--too_deep:
-- ret = -ELOOP;
-- goto error;
--
--cycle_detected:
-- ret = -EDEADLK;
-- goto error;
--}
--
--/*
-- * Dispose of a keyring list after the RCU grace period, freeing the unlinked
-- * key
-- */
--static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
--{
-- struct keyring_list *klist =
-- container_of(rcu, struct keyring_list, rcu);
--
-- if (klist->delkey != USHRT_MAX)
-- key_put(rcu_access_pointer(klist->keys[klist->delkey]));
-- kfree(klist);
-+ return PTR_ERR(ctx.result) == -EAGAIN ? 0 : PTR_ERR(ctx.result);
- }
-
- /*
- * Preallocate memory so that a key can be linked into to a keyring.
- */
--int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_key,
-- unsigned long *_prealloc)
-+int __key_link_begin(struct key *keyring,
-+ const struct keyring_index_key *index_key,
-+ struct assoc_array_edit **_edit)
- __acquires(&keyring->sem)
- __acquires(&keyring_serialise_link_sem)
- {
-- struct keyring_list *klist, *nklist;
-- unsigned long prealloc;
-- unsigned max;
-- time_t lowest_lru;
-- size_t size;
-- int loop, lru, ret;
-+ struct assoc_array_edit *edit;
-+ int ret;
-
- kenter("%d,%s,%s,",
-- key_serial(keyring), index_key->type->name, index_key->description);
-+ keyring->serial, index_key->type->name, index_key->description);
-+
-+ BUG_ON(index_key->desc_len == 0);
-
- if (keyring->type != &key_type_keyring)
- return -ENOTDIR;
-@@ -772,88 +1062,25 @@ int __key_link_begin(struct key *keyring, const struct keyring_index_key *index_
- if (index_key->type == &key_type_keyring)
- down_write(&keyring_serialise_link_sem);
-
-- klist = rcu_dereference_locked_keyring(keyring);
--
-- /* see if there's a matching key we can displace */
-- lru = -1;
-- if (klist && klist->nkeys > 0) {
-- lowest_lru = TIME_T_MAX;
-- for (loop = klist->nkeys - 1; loop >= 0; loop--) {
-- struct key *key = rcu_deref_link_locked(klist, loop,
-- keyring);
-- if (key->type == index_key->type &&
-- strcmp(key->description, index_key->description) == 0) {
-- /* Found a match - we'll replace the link with
-- * one to the new key. We record the slot
-- * position.
-- */
-- klist->delkey = loop;
-- prealloc = 0;
-- goto done;
-- }
-- if (key->last_used_at < lowest_lru) {
-- lowest_lru = key->last_used_at;
-- lru = loop;
-- }
-- }
-- }
--
-- /* If the keyring is full then do an LRU discard */
-- if (klist &&
-- klist->nkeys == klist->maxkeys &&
-- klist->maxkeys >= MAX_KEYRING_LINKS) {
-- kdebug("LRU discard %d\n", lru);
-- klist->delkey = lru;
-- prealloc = 0;
-- goto done;
-- }
--
- /* check that we aren't going to overrun the user's quota */
- ret = key_payload_reserve(keyring,
- keyring->datalen + KEYQUOTA_LINK_BYTES);
- if (ret < 0)
- goto error_sem;
-
-- if (klist && klist->nkeys < klist->maxkeys) {
-- /* there's sufficient slack space to append directly */
-- klist->delkey = klist->nkeys;
-- prealloc = KEY_LINK_FIXQUOTA;
-- } else {
-- /* grow the key list */
-- max = 4;
-- if (klist) {
-- max += klist->maxkeys;
-- if (max > MAX_KEYRING_LINKS)
-- max = MAX_KEYRING_LINKS;
-- BUG_ON(max <= klist->maxkeys);
-- }
--
-- size = sizeof(*klist) + sizeof(struct key *) * max;
--
-- ret = -ENOMEM;
-- nklist = kmalloc(size, GFP_KERNEL);
-- if (!nklist)
-- goto error_quota;
--
-- nklist->maxkeys = max;
-- if (klist) {
-- memcpy(nklist->keys, klist->keys,
-- sizeof(struct key *) * klist->nkeys);
-- nklist->delkey = klist->nkeys;
-- nklist->nkeys = klist->nkeys + 1;
-- klist->delkey = USHRT_MAX;
-- } else {
-- nklist->nkeys = 1;
-- nklist->delkey = 0;
-- }
--
-- /* add the key into the new space */
-- RCU_INIT_POINTER(nklist->keys[nklist->delkey], NULL);
-- prealloc = (unsigned long)nklist | KEY_LINK_FIXQUOTA;
-+ /* Create an edit script that will insert/replace the key in the
-+ * keyring tree.
-+ */
-+ edit = assoc_array_insert(&keyring->keys,
-+ &keyring_assoc_array_ops,
-+ index_key,
-+ NULL);
-+ if (IS_ERR(edit)) {
-+ ret = PTR_ERR(edit);
-+ goto error_quota;
- }
-
--done:
-- *_prealloc = prealloc;
-+ *_edit = edit;
- kleave(" = 0");
- return 0;
-
-@@ -893,60 +1120,12 @@ int __key_link_check_live_key(struct key *keyring, struct key *key)
- * holds at most one link to any given key of a particular type+description
- * combination.
- */
--void __key_link(struct key *keyring, struct key *key,
-- unsigned long *_prealloc)
-+void __key_link(struct key *key, struct assoc_array_edit **_edit)
- {
-- struct keyring_list *klist, *nklist;
-- struct key *discard;
--
-- nklist = (struct keyring_list *)(*_prealloc & ~KEY_LINK_FIXQUOTA);
-- *_prealloc = 0;
--
-- kenter("%d,%d,%p", keyring->serial, key->serial, nklist);
--
-- klist = rcu_dereference_locked_keyring(keyring);
--
- __key_get(key);
-- keyring->last_used_at = key->last_used_at =
-- current_kernel_time().tv_sec;
--
-- /* there's a matching key we can displace or an empty slot in a newly
-- * allocated list we can fill */
-- if (nklist) {
-- kdebug("reissue %hu/%hu/%hu",
-- nklist->delkey, nklist->nkeys, nklist->maxkeys);
--
-- RCU_INIT_POINTER(nklist->keys[nklist->delkey], key);
--
-- rcu_assign_pointer(keyring->payload.subscriptions, nklist);
--
-- /* dispose of the old keyring list and, if there was one, the
-- * displaced key */
-- if (klist) {
-- kdebug("dispose %hu/%hu/%hu",
-- klist->delkey, klist->nkeys, klist->maxkeys);
-- call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
-- }
-- } else if (klist->delkey < klist->nkeys) {
-- kdebug("replace %hu/%hu/%hu",
-- klist->delkey, klist->nkeys, klist->maxkeys);
--
-- discard = rcu_dereference_protected(
-- klist->keys[klist->delkey],
-- rwsem_is_locked(&keyring->sem));
-- rcu_assign_pointer(klist->keys[klist->delkey], key);
-- /* The garbage collector will take care of RCU
-- * synchronisation */
-- key_put(discard);
-- } else {
-- /* there's sufficient slack space to append directly */
-- kdebug("append %hu/%hu/%hu",
-- klist->delkey, klist->nkeys, klist->maxkeys);
--
-- RCU_INIT_POINTER(klist->keys[klist->delkey], key);
-- smp_wmb();
-- klist->nkeys++;
-- }
-+ assoc_array_insert_set_object(*_edit, keyring_key_to_ptr(key));
-+ assoc_array_apply_edit(*_edit);
-+ *_edit = NULL;
- }
-
- /*
-@@ -956,23 +1135,20 @@ void __key_link(struct key *keyring, struct key *key,
- */
- void __key_link_end(struct key *keyring,
- const struct keyring_index_key *index_key,
-- unsigned long prealloc)
-+ struct assoc_array_edit *edit)
- __releases(&keyring->sem)
- __releases(&keyring_serialise_link_sem)
- {
- BUG_ON(index_key->type == NULL);
-- BUG_ON(index_key->type->name == NULL);
-- kenter("%d,%s,%lx", keyring->serial, index_key->type->name, prealloc);
-+ kenter("%d,%s,", keyring->serial, index_key->type->name);
-
- if (index_key->type == &key_type_keyring)
- up_write(&keyring_serialise_link_sem);
-
-- if (prealloc) {
-- if (prealloc & KEY_LINK_FIXQUOTA)
-- key_payload_reserve(keyring,
-- keyring->datalen -
-- KEYQUOTA_LINK_BYTES);
-- kfree((struct keyring_list *)(prealloc & ~KEY_LINK_FIXQUOTA));
-+ if (edit) {
-+ key_payload_reserve(keyring,
-+ keyring->datalen - KEYQUOTA_LINK_BYTES);
-+ assoc_array_cancel_edit(edit);
- }
- up_write(&keyring->sem);
- }
-@@ -999,20 +1175,24 @@ void __key_link_end(struct key *keyring,
- */
- int key_link(struct key *keyring, struct key *key)
- {
-- unsigned long prealloc;
-+ struct assoc_array_edit *edit;
- int ret;
-
-+ kenter("{%d,%d}", keyring->serial, atomic_read(&keyring->usage));
-+
- key_check(keyring);
- key_check(key);
-
-- ret = __key_link_begin(keyring, &key->index_key, &prealloc);
-+ ret = __key_link_begin(keyring, &key->index_key, &edit);
- if (ret == 0) {
-+ kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage));
- ret = __key_link_check_live_key(keyring, key);
- if (ret == 0)
-- __key_link(keyring, key, &prealloc);
-- __key_link_end(keyring, &key->index_key, prealloc);
-+ __key_link(key, &edit);
-+ __key_link_end(keyring, &key->index_key, edit);
- }
-
-+ kleave(" = %d {%d,%d}", ret, keyring->serial, atomic_read(&keyring->usage));
- return ret;
- }
- EXPORT_SYMBOL(key_link);
-@@ -1036,90 +1216,36 @@ EXPORT_SYMBOL(key_link);
- */
- int key_unlink(struct key *keyring, struct key *key)
- {
-- struct keyring_list *klist, *nklist;
-- int loop, ret;
-+ struct assoc_array_edit *edit;
-+ int ret;
-
- key_check(keyring);
- key_check(key);
-
-- ret = -ENOTDIR;
- if (keyring->type != &key_type_keyring)
-- goto error;
-+ return -ENOTDIR;
-
- down_write(&keyring->sem);
-
-- klist = rcu_dereference_locked_keyring(keyring);
-- if (klist) {
-- /* search the keyring for the key */
-- for (loop = 0; loop < klist->nkeys; loop++)
-- if (rcu_access_pointer(klist->keys[loop]) == key)
-- goto key_is_present;
-+ edit = assoc_array_delete(&keyring->keys, &keyring_assoc_array_ops,
-+ &key->index_key);
-+ if (IS_ERR(edit)) {
-+ ret = PTR_ERR(edit);
-+ goto error;
- }
--
-- up_write(&keyring->sem);
- ret = -ENOENT;
-- goto error;
--
--key_is_present:
-- /* we need to copy the key list for RCU purposes */
-- nklist = kmalloc(sizeof(*klist) +
-- sizeof(struct key *) * klist->maxkeys,
-- GFP_KERNEL);
-- if (!nklist)
-- goto nomem;
-- nklist->maxkeys = klist->maxkeys;
-- nklist->nkeys = klist->nkeys - 1;
--
-- if (loop > 0)
-- memcpy(&nklist->keys[0],
-- &klist->keys[0],
-- loop * sizeof(struct key *));
--
-- if (loop < nklist->nkeys)
-- memcpy(&nklist->keys[loop],
-- &klist->keys[loop + 1],
-- (nklist->nkeys - loop) * sizeof(struct key *));
--
-- /* adjust the user's quota */
-- key_payload_reserve(keyring,
-- keyring->datalen - KEYQUOTA_LINK_BYTES);
--
-- rcu_assign_pointer(keyring->payload.subscriptions, nklist);
--
-- up_write(&keyring->sem);
--
-- /* schedule for later cleanup */
-- klist->delkey = loop;
-- call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
-+ if (edit == NULL)
-+ goto error;
-
-+ assoc_array_apply_edit(edit);
- ret = 0;
-
- error:
-- return ret;
--nomem:
-- ret = -ENOMEM;
- up_write(&keyring->sem);
-- goto error;
-+ return ret;
- }
- EXPORT_SYMBOL(key_unlink);
-
--/*
-- * Dispose of a keyring list after the RCU grace period, releasing the keys it
-- * links to.
-- */
--static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
--{
-- struct keyring_list *klist;
-- int loop;
--
-- klist = container_of(rcu, struct keyring_list, rcu);
--
-- for (loop = klist->nkeys - 1; loop >= 0; loop--)
-- key_put(rcu_access_pointer(klist->keys[loop]));
--
-- kfree(klist);
--}
--
- /**
- * keyring_clear - Clear a keyring
- * @keyring: The keyring to clear.
-@@ -1130,33 +1256,25 @@ static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
- */
- int keyring_clear(struct key *keyring)
- {
-- struct keyring_list *klist;
-+ struct assoc_array_edit *edit;
- int ret;
-
-- ret = -ENOTDIR;
-- if (keyring->type == &key_type_keyring) {
-- /* detach the pointer block with the locks held */
-- down_write(&keyring->sem);
--
-- klist = rcu_dereference_locked_keyring(keyring);
-- if (klist) {
-- /* adjust the quota */
-- key_payload_reserve(keyring,
-- sizeof(struct keyring_list));
--
-- rcu_assign_pointer(keyring->payload.subscriptions,
-- NULL);
-- }
--
-- up_write(&keyring->sem);
-+ if (keyring->type != &key_type_keyring)
-+ return -ENOTDIR;
-
-- /* free the keys after the locks have been dropped */
-- if (klist)
-- call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
-+ down_write(&keyring->sem);
-
-+ edit = assoc_array_clear(&keyring->keys, &keyring_assoc_array_ops);
-+ if (IS_ERR(edit)) {
-+ ret = PTR_ERR(edit);
-+ } else {
-+ if (edit)
-+ assoc_array_apply_edit(edit);
-+ key_payload_reserve(keyring, 0);
- ret = 0;
- }
-
-+ up_write(&keyring->sem);
- return ret;
- }
- EXPORT_SYMBOL(keyring_clear);
-@@ -1168,17 +1286,25 @@ EXPORT_SYMBOL(keyring_clear);
- */
- static void keyring_revoke(struct key *keyring)
- {
-- struct keyring_list *klist;
-+ struct assoc_array_edit *edit;
-
-- klist = rcu_dereference_locked_keyring(keyring);
-+ edit = assoc_array_clear(&keyring->keys, &keyring_assoc_array_ops);
-+ if (!IS_ERR(edit)) {
-+ if (edit)
-+ assoc_array_apply_edit(edit);
-+ key_payload_reserve(keyring, 0);
-+ }
-+}
-
-- /* adjust the quota */
-- key_payload_reserve(keyring, 0);
-+static bool gc_iterator(void *object, void *iterator_data)
-+{
-+ struct key *key = keyring_ptr_to_key(object);
-+ time_t *limit = iterator_data;
-
-- if (klist) {
-- rcu_assign_pointer(keyring->payload.subscriptions, NULL);
-- call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
-- }
-+ if (key_is_dead(key, *limit))
-+ return false;
-+ key_get(key);
-+ return true;
- }
-
- /*
-@@ -1191,88 +1317,12 @@ static void keyring_revoke(struct key *keyring)
- */
- void keyring_gc(struct key *keyring, time_t limit)
- {
-- struct keyring_list *klist, *new;
-- struct key *key;
-- int loop, keep, max;
--
- kenter("{%x,%s}", key_serial(keyring), keyring->description);
-
- down_write(&keyring->sem);
--
-- klist = rcu_dereference_locked_keyring(keyring);
-- if (!klist)
-- goto no_klist;
--
-- /* work out how many subscriptions we're keeping */
-- keep = 0;
-- for (loop = klist->nkeys - 1; loop >= 0; loop--)
-- if (!key_is_dead(rcu_deref_link_locked(klist, loop, keyring),
-- limit))
-- keep++;
--
-- if (keep == klist->nkeys)
-- goto just_return;
--
-- /* allocate a new keyring payload */
-- max = roundup(keep, 4);
-- new = kmalloc(sizeof(struct keyring_list) + max * sizeof(struct key *),
-- GFP_KERNEL);
-- if (!new)
-- goto nomem;
-- new->maxkeys = max;
-- new->nkeys = 0;
-- new->delkey = 0;
--
-- /* install the live keys
-- * - must take care as expired keys may be updated back to life
-- */
-- keep = 0;
-- for (loop = klist->nkeys - 1; loop >= 0; loop--) {
-- key = rcu_deref_link_locked(klist, loop, keyring);
-- if (!key_is_dead(key, limit)) {
-- if (keep >= max)
-- goto discard_new;
-- RCU_INIT_POINTER(new->keys[keep++], key_get(key));
-- }
-- }
-- new->nkeys = keep;
--
-- /* adjust the quota */
-- key_payload_reserve(keyring,
-- sizeof(struct keyring_list) +
-- KEYQUOTA_LINK_BYTES * keep);
--
-- if (keep == 0) {
-- rcu_assign_pointer(keyring->payload.subscriptions, NULL);
-- kfree(new);
-- } else {
-- rcu_assign_pointer(keyring->payload.subscriptions, new);
-- }
--
-- up_write(&keyring->sem);
--
-- call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
-- kleave(" [yes]");
-- return;
--
--discard_new:
-- new->nkeys = keep;
-- keyring_clear_rcu_disposal(&new->rcu);
-+ assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops,
-+ gc_iterator, &limit);
- up_write(&keyring->sem);
-- kleave(" [discard]");
-- return;
-
--just_return:
-- up_write(&keyring->sem);
-- kleave(" [no dead]");
-- return;
--
--no_klist:
-- up_write(&keyring->sem);
-- kleave(" [no_klist]");
-- return;
--
--nomem:
-- up_write(&keyring->sem);
-- kleave(" [oom]");
-+ kleave("");
- }
-diff --git a/security/keys/request_key.c b/security/keys/request_key.c
-index ab75df4..df94827 100644
---- a/security/keys/request_key.c
-+++ b/security/keys/request_key.c
-@@ -351,7 +351,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
- struct key_user *user,
- struct key **_key)
- {
-- unsigned long prealloc;
-+ struct assoc_array_edit *edit;
- struct key *key;
- key_perm_t perm;
- key_ref_t key_ref;
-@@ -380,7 +380,7 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
- set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
-
- if (dest_keyring) {
-- ret = __key_link_begin(dest_keyring, &ctx->index_key, &prealloc);
-+ ret = __key_link_begin(dest_keyring, &ctx->index_key, &edit);
- if (ret < 0)
- goto link_prealloc_failed;
- }
-@@ -395,11 +395,11 @@ static int construct_alloc_key(struct keyring_search_context *ctx,
- goto key_already_present;
-
- if (dest_keyring)
-- __key_link(dest_keyring, key, &prealloc);
-+ __key_link(key, &edit);
-
- mutex_unlock(&key_construction_mutex);
- if (dest_keyring)
-- __key_link_end(dest_keyring, &ctx->index_key, prealloc);
-+ __key_link_end(dest_keyring, &ctx->index_key, edit);
- mutex_unlock(&user->cons_lock);
- *_key = key;
- kleave(" = 0 [%d]", key_serial(key));
-@@ -414,8 +414,8 @@ key_already_present:
- if (dest_keyring) {
- ret = __key_link_check_live_key(dest_keyring, key);
- if (ret == 0)
-- __key_link(dest_keyring, key, &prealloc);
-- __key_link_end(dest_keyring, &ctx->index_key, prealloc);
-+ __key_link(key, &edit);
-+ __key_link_end(dest_keyring, &ctx->index_key, edit);
- if (ret < 0)
- goto link_check_failed;
- }
---
-1.8.3.1
-
diff --git a/keys-fixes.patch b/keys-fixes.patch
deleted file mode 100644
index 96c98221e..000000000
--- a/keys-fixes.patch
+++ /dev/null
@@ -1,1025 +0,0 @@
-Bugzilla: 1035000
-Upstream-status: 3.13 and submitted for 3.13
-
-From adb466891c981db26df5b23ae5a7062e47dfd323 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Wed, 30 Oct 2013 11:15:24 +0000
-Subject: [PATCH 01/10] KEYS: Fix a race between negating a key and reading the
- error set
-
-key_reject_and_link() marking a key as negative and setting the error with
-which it was negated races with keyring searches and other things that read
-that error.
-
-The fix is to switch the order in which the assignments are done in
-key_reject_and_link() and to use memory barriers.
-
-Kudos to Dave Wysochanski <dwysocha@redhat.com> and Scott Mayhew
-<smayhew@redhat.com> for tracking this down.
-
-This may be the cause of:
-
-BUG: unable to handle kernel NULL pointer dereference at 0000000000000070
-IP: [<ffffffff81219011>] wait_for_key_construction+0x31/0x80
-PGD c6b2c3067 PUD c59879067 PMD 0
-Oops: 0000 [#1] SMP
-last sysfs file: /sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_map
-CPU 0
-Modules linked in: ...
-
-Pid: 13359, comm: amqzxma0 Not tainted 2.6.32-358.20.1.el6.x86_64 #1 IBM System x3650 M3 -[7945PSJ]-/00J6159
-RIP: 0010:[<ffffffff81219011>] wait_for_key_construction+0x31/0x80
-RSP: 0018:ffff880c6ab33758 EFLAGS: 00010246
-RAX: ffffffff81219080 RBX: 0000000000000000 RCX: 0000000000000002
-RDX: ffffffff81219060 RSI: 0000000000000000 RDI: 0000000000000000
-RBP: ffff880c6ab33768 R08: 0000000000000000 R09: 0000000000000000
-R10: 0000000000000001 R11: 0000000000000000 R12: ffff880adfcbce40
-R13: ffffffffa03afb84 R14: ffff880adfcbce40 R15: ffff880adfcbce43
-FS: 00007f29b8042700(0000) GS:ffff880028200000(0000) knlGS:0000000000000000
-CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
-CR2: 0000000000000070 CR3: 0000000c613dc000 CR4: 00000000000007f0
-DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
-DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
-Process amqzxma0 (pid: 13359, threadinfo ffff880c6ab32000, task ffff880c610deae0)
-Stack:
- ffff880adfcbce40 0000000000000000 ffff880c6ab337b8 ffffffff81219695
-<d> 0000000000000000 ffff880a000000d0 ffff880c6ab337a8 000000000000000f
-<d> ffffffffa03afb93 000000000000000f ffff88186c7882c0 0000000000000014
-Call Trace:
- [<ffffffff81219695>] request_key+0x65/0xa0
- [<ffffffffa03a0885>] nfs_idmap_request_key+0xc5/0x170 [nfs]
- [<ffffffffa03a0eb4>] nfs_idmap_lookup_id+0x34/0x80 [nfs]
- [<ffffffffa03a1255>] nfs_map_group_to_gid+0x75/0xa0 [nfs]
- [<ffffffffa039a9ad>] decode_getfattr_attrs+0xbdd/0xfb0 [nfs]
- [<ffffffff81057310>] ? __dequeue_entity+0x30/0x50
- [<ffffffff8100988e>] ? __switch_to+0x26e/0x320
- [<ffffffffa039ae03>] decode_getfattr+0x83/0xe0 [nfs]
- [<ffffffffa039b610>] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs]
- [<ffffffffa039b69f>] nfs4_xdr_dec_getattr+0x8f/0xa0 [nfs]
- [<ffffffffa02dada4>] rpcauth_unwrap_resp+0x84/0xb0 [sunrpc]
- [<ffffffffa039b610>] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs]
- [<ffffffffa02cf923>] call_decode+0x1b3/0x800 [sunrpc]
- [<ffffffff81096de0>] ? wake_bit_function+0x0/0x50
- [<ffffffffa02cf770>] ? call_decode+0x0/0x800 [sunrpc]
- [<ffffffffa02d99a7>] __rpc_execute+0x77/0x350 [sunrpc]
- [<ffffffff81096c67>] ? bit_waitqueue+0x17/0xd0
- [<ffffffffa02d9ce1>] rpc_execute+0x61/0xa0 [sunrpc]
- [<ffffffffa02d03a5>] rpc_run_task+0x75/0x90 [sunrpc]
- [<ffffffffa02d04c2>] rpc_call_sync+0x42/0x70 [sunrpc]
- [<ffffffffa038ff80>] _nfs4_call_sync+0x30/0x40 [nfs]
- [<ffffffffa038836c>] _nfs4_proc_getattr+0xac/0xc0 [nfs]
- [<ffffffff810aac87>] ? futex_wait+0x227/0x380
- [<ffffffffa038b856>] nfs4_proc_getattr+0x56/0x80 [nfs]
- [<ffffffffa0371403>] __nfs_revalidate_inode+0xe3/0x220 [nfs]
- [<ffffffffa037158e>] nfs_revalidate_mapping+0x4e/0x170 [nfs]
- [<ffffffffa036f147>] nfs_file_read+0x77/0x130 [nfs]
- [<ffffffff811811aa>] do_sync_read+0xfa/0x140
- [<ffffffff81096da0>] ? autoremove_wake_function+0x0/0x40
- [<ffffffff8100bb8e>] ? apic_timer_interrupt+0xe/0x20
- [<ffffffff8100b9ce>] ? common_interrupt+0xe/0x13
- [<ffffffff81228ffb>] ? selinux_file_permission+0xfb/0x150
- [<ffffffff8121bed6>] ? security_file_permission+0x16/0x20
- [<ffffffff81181a95>] vfs_read+0xb5/0x1a0
- [<ffffffff81181bd1>] sys_read+0x51/0x90
- [<ffffffff810dc685>] ? __audit_syscall_exit+0x265/0x290
- [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-cc: Dave Wysochanski <dwysocha@redhat.com>
-cc: Scott Mayhew <smayhew@redhat.com>
----
- security/keys/key.c | 3 ++-
- security/keys/keyring.c | 1 +
- security/keys/request_key.c | 4 +++-
- 3 files changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/security/keys/key.c b/security/keys/key.c
-index d331ea9..55d110f 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -557,9 +557,10 @@ int key_reject_and_link(struct key *key,
- if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
- /* mark the key as being negatively instantiated */
- atomic_inc(&key->user->nikeys);
-+ key->type_data.reject_error = -error;
-+ smp_wmb();
- set_bit(KEY_FLAG_NEGATIVE, &key->flags);
- set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
-- key->type_data.reject_error = -error;
- now = current_kernel_time();
- key->expiry = now.tv_sec + timeout;
- key_schedule_gc(key->expiry + key_gc_delay);
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 9b6f6e0..8c05ebd 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -551,6 +551,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
- if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) {
- /* we set a different error code if we pass a negative key */
- if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
-+ smp_rmb();
- ctx->result = ERR_PTR(key->type_data.reject_error);
- kleave(" = %d [neg]", ctx->skipped_ret);
- goto skipped;
-diff --git a/security/keys/request_key.c b/security/keys/request_key.c
-index df94827..3814119 100644
---- a/security/keys/request_key.c
-+++ b/security/keys/request_key.c
-@@ -596,8 +596,10 @@ int wait_for_key_construction(struct key *key, bool intr)
- intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
- if (ret < 0)
- return ret;
-- if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
-+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
-+ smp_rmb();
- return key->type_data.reject_error;
-+ }
- return key_validate(key);
- }
- EXPORT_SYMBOL(wait_for_key_construction);
---
-1.8.3.1
-
-
-From 3a35b12cb5167463dd6061bb29da9116fc08625b Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Wed, 30 Oct 2013 11:15:24 +0000
-Subject: [PATCH 02/10] KEYS: Fix keyring quota misaccounting on key
- replacement and unlink
-
-If a key is displaced from a keyring by a matching one, then four more bytes
-of quota are allocated to the keyring - despite the fact that the keyring does
-not change in size.
-
-Further, when a key is unlinked from a keyring, the four bytes of quota
-allocated the link isn't recovered and returned to the user's pool.
-
-The first can be tested by repeating:
-
- keyctl add big_key a fred @s
- cat /proc/key-users
-
-(Don't put it in a shell loop otherwise the garbage collector won't have time
-to clear the displaced keys, thus affecting the result).
-
-This was causing the kerberos keyring to run out of room fairly quickly.
-
-The second can be tested by:
-
- cat /proc/key-users
- a=`keyctl add user a a @s`
- cat /proc/key-users
- keyctl unlink $a
- sleep 1 # Give RCU a chance to delete the key
- cat /proc/key-users
-
-assuming no system activity that otherwise adds/removes keys, the amount of
-key data allocated should go up (say 40/20000 -> 47/20000) and then return to
-the original value at the end.
-
-Reported-by: Stephen Gallagher <sgallagh@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/keyring.c | 27 +++++++++++++++------------
- 1 file changed, 15 insertions(+), 12 deletions(-)
-
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 8c05ebd..d80311e 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -1063,12 +1063,6 @@ int __key_link_begin(struct key *keyring,
- if (index_key->type == &key_type_keyring)
- down_write(&keyring_serialise_link_sem);
-
-- /* check that we aren't going to overrun the user's quota */
-- ret = key_payload_reserve(keyring,
-- keyring->datalen + KEYQUOTA_LINK_BYTES);
-- if (ret < 0)
-- goto error_sem;
--
- /* Create an edit script that will insert/replace the key in the
- * keyring tree.
- */
-@@ -1078,17 +1072,25 @@ int __key_link_begin(struct key *keyring,
- NULL);
- if (IS_ERR(edit)) {
- ret = PTR_ERR(edit);
-- goto error_quota;
-+ goto error_sem;
-+ }
-+
-+ /* If we're not replacing a link in-place then we're going to need some
-+ * extra quota.
-+ */
-+ if (!edit->dead_leaf) {
-+ ret = key_payload_reserve(keyring,
-+ keyring->datalen + KEYQUOTA_LINK_BYTES);
-+ if (ret < 0)
-+ goto error_cancel;
- }
-
- *_edit = edit;
- kleave(" = 0");
- return 0;
-
--error_quota:
-- /* undo the quota changes */
-- key_payload_reserve(keyring,
-- keyring->datalen - KEYQUOTA_LINK_BYTES);
-+error_cancel:
-+ assoc_array_cancel_edit(edit);
- error_sem:
- if (index_key->type == &key_type_keyring)
- up_write(&keyring_serialise_link_sem);
-@@ -1146,7 +1148,7 @@ void __key_link_end(struct key *keyring,
- if (index_key->type == &key_type_keyring)
- up_write(&keyring_serialise_link_sem);
-
-- if (edit) {
-+ if (edit && !edit->dead_leaf) {
- key_payload_reserve(keyring,
- keyring->datalen - KEYQUOTA_LINK_BYTES);
- assoc_array_cancel_edit(edit);
-@@ -1243,6 +1245,7 @@ int key_unlink(struct key *keyring, struct key *key)
- goto error;
-
- assoc_array_apply_edit(edit);
-+ key_payload_reserve(keyring, keyring->datalen - KEYQUOTA_LINK_BYTES);
- ret = 0;
-
- error:
---
-1.8.3.1
-
-
-From 196d3798421b8e331a538a5ea9b4ce7789c0f048 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Thu, 14 Nov 2013 13:02:31 +0000
-Subject: [PATCH 03/10] KEYS: Fix keyring content gc scanner
-
-Key pointers stored in the keyring are marked in bit 1 to indicate if they
-point to a keyring. We need to strip off this bit before using the pointer
-when iterating over the keyring for the purpose of looking for links to garbage
-collect.
-
-This means that expirable keyrings aren't correctly expiring because the
-checker is seeing their key pointer with 2 added to it.
-
-Since the fix for this involves knowing about the internals of the keyring,
-key_gc_keyring() is moved to keyring.c and merged into keyring_gc().
-
-This can be tested by:
-
- echo 2 >/proc/sys/kernel/keys/gc_delay
- keyctl timeout `keyctl add keyring qwerty "" @s` 2
- cat /proc/keys
- sleep 5; cat /proc/keys
-
-which should see a keyring called "qwerty" appear in the session keyring and
-then disappear after it expires, and:
-
- echo 2 >/proc/sys/kernel/keys/gc_delay
- a=`keyctl get_persistent @s`
- b=`keyctl add keyring 0 "" $a`
- keyctl add user a a $b
- keyctl timeout $b 2
- cat /proc/keys
- sleep 5; cat /proc/keys
-
-which should see a keyring called "0" with a key called "a" in it appear in the
-user's persistent keyring (which will be attached to the session keyring) and
-then both the "0" keyring and the "a" key should disappear when the "0" keyring
-expires.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Acked-by: Simo Sorce <simo@redhat.com>
----
- security/keys/gc.c | 42 +-----------------------------------------
- security/keys/keyring.c | 45 +++++++++++++++++++++++++++++++++++----------
- 2 files changed, 36 insertions(+), 51 deletions(-)
-
-diff --git a/security/keys/gc.c b/security/keys/gc.c
-index cce621c..d3222b6 100644
---- a/security/keys/gc.c
-+++ b/security/keys/gc.c
-@@ -130,46 +130,6 @@ void key_gc_keytype(struct key_type *ktype)
- kleave("");
- }
-
--static int key_gc_keyring_func(const void *object, void *iterator_data)
--{
-- const struct key *key = object;
-- time_t *limit = iterator_data;
-- return key_is_dead(key, *limit);
--}
--
--/*
-- * Garbage collect pointers from a keyring.
-- *
-- * Not called with any locks held. The keyring's key struct will not be
-- * deallocated under us as only our caller may deallocate it.
-- */
--static void key_gc_keyring(struct key *keyring, time_t limit)
--{
-- int result;
--
-- kenter("%x{%s}", keyring->serial, keyring->description ?: "");
--
-- if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
-- (1 << KEY_FLAG_REVOKED)))
-- goto dont_gc;
--
-- /* scan the keyring looking for dead keys */
-- rcu_read_lock();
-- result = assoc_array_iterate(&keyring->keys,
-- key_gc_keyring_func, &limit);
-- rcu_read_unlock();
-- if (result == true)
-- goto do_gc;
--
--dont_gc:
-- kleave(" [no gc]");
-- return;
--
--do_gc:
-- keyring_gc(keyring, limit);
-- kleave(" [gc]");
--}
--
- /*
- * Garbage collect a list of unreferenced, detached keys
- */
-@@ -388,7 +348,7 @@ found_unreferenced_key:
- */
- found_keyring:
- spin_unlock(&key_serial_lock);
-- key_gc_keyring(key, limit);
-+ keyring_gc(key, limit);
- goto maybe_resched;
-
- /* We found a dead key that is still referenced. Reset its type and
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index d80311e..69f0cb7 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -1304,7 +1304,7 @@ static void keyring_revoke(struct key *keyring)
- }
- }
-
--static bool gc_iterator(void *object, void *iterator_data)
-+static bool keyring_gc_select_iterator(void *object, void *iterator_data)
- {
- struct key *key = keyring_ptr_to_key(object);
- time_t *limit = iterator_data;
-@@ -1315,22 +1315,47 @@ static bool gc_iterator(void *object, void *iterator_data)
- return true;
- }
-
-+static int keyring_gc_check_iterator(const void *object, void *iterator_data)
-+{
-+ const struct key *key = keyring_ptr_to_key(object);
-+ time_t *limit = iterator_data;
-+
-+ key_check(key);
-+ return key_is_dead(key, *limit);
-+}
-+
- /*
-- * Collect garbage from the contents of a keyring, replacing the old list with
-- * a new one with the pointers all shuffled down.
-+ * Garbage collect pointers from a keyring.
- *
-- * Dead keys are classed as oned that are flagged as being dead or are revoked,
-- * expired or negative keys that were revoked or expired before the specified
-- * limit.
-+ * Not called with any locks held. The keyring's key struct will not be
-+ * deallocated under us as only our caller may deallocate it.
- */
- void keyring_gc(struct key *keyring, time_t limit)
- {
-- kenter("{%x,%s}", key_serial(keyring), keyring->description);
-+ int result;
-+
-+ kenter("%x{%s}", keyring->serial, keyring->description ?: "");
-
-+ if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
-+ (1 << KEY_FLAG_REVOKED)))
-+ goto dont_gc;
-+
-+ /* scan the keyring looking for dead keys */
-+ rcu_read_lock();
-+ result = assoc_array_iterate(&keyring->keys,
-+ keyring_gc_check_iterator, &limit);
-+ rcu_read_unlock();
-+ if (result == true)
-+ goto do_gc;
-+
-+dont_gc:
-+ kleave(" [no gc]");
-+ return;
-+
-+do_gc:
- down_write(&keyring->sem);
- assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops,
-- gc_iterator, &limit);
-+ keyring_gc_select_iterator, &limit);
- up_write(&keyring->sem);
--
-- kleave("");
-+ kleave(" [gc]");
- }
---
-1.8.3.1
-
-
-From 49fbad9064d603b093ee3e101463ccf6756f5120 Mon Sep 17 00:00:00 2001
-From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
-Date: Wed, 30 Oct 2013 11:23:02 +0800
-Subject: [PATCH 04/10] KEYS: fix error return code in big_key_instantiate()
-
-Fix to return a negative error code from the error handling
-case instead of 0, as done elsewhere in this function.
-
-Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/big_key.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/security/keys/big_key.c b/security/keys/big_key.c
-index 5f9defc..2cf5e62 100644
---- a/security/keys/big_key.c
-+++ b/security/keys/big_key.c
-@@ -71,8 +71,10 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
- * TODO: Encrypt the stored data with a temporary key.
- */
- file = shmem_file_setup("", datalen, 0);
-- if (IS_ERR(file))
-+ if (IS_ERR(file)) {
-+ ret = PTR_ERR(file);
- goto err_quota;
-+ }
-
- written = kernel_write(file, prep->data, prep->datalen, 0);
- if (written != datalen) {
---
-1.8.3.1
-
-
-From 2900f2b4200258a1be949a5e3644e7d4b55c4e82 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Wed, 13 Nov 2013 16:51:06 +0000
-Subject: [PATCH 05/10] KEYS: Fix error handling in big_key instantiation
-
-In the big_key_instantiate() function we return 0 if kernel_write() returns us
-an error rather than returning an error. This can potentially lead to
-dentry_open() giving a BUG when called from big_key_read() with an unset
-tmpfile path.
-
- ------------[ cut here ]------------
- kernel BUG at fs/open.c:798!
- ...
- RIP: 0010:[<ffffffff8119bbd1>] dentry_open+0xd1/0xe0
- ...
- Call Trace:
- [<ffffffff812350c5>] big_key_read+0x55/0x100
- [<ffffffff81231084>] keyctl_read_key+0xb4/0xe0
- [<ffffffff81231e58>] SyS_keyctl+0xf8/0x1d0
- [<ffffffff815bb799>] system_call_fastpath+0x16/0x1b
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Stephen Gallagher <sgallagh@redhat.com>
----
- security/keys/big_key.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/security/keys/big_key.c b/security/keys/big_key.c
-index 2cf5e62..7f44c32 100644
---- a/security/keys/big_key.c
-+++ b/security/keys/big_key.c
-@@ -78,6 +78,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-
- written = kernel_write(file, prep->data, prep->datalen, 0);
- if (written != datalen) {
-+ ret = written;
- if (written >= 0)
- ret = -ENOMEM;
- goto err_fput;
---
-1.8.3.1
-
-
-From b6b0e230e3d26b31ab075455c2ebdde9b194f8f5 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Mon, 2 Dec 2013 11:24:18 +0000
-Subject: [PATCH 06/10] KEYS: Pre-clear struct key on allocation
-
-The second word of key->payload does not get initialised in key_alloc(), but
-the big_key type is relying on it having been cleared. The problem comes when
-big_key fails to instantiate a large key and doesn't then set the payload. The
-big_key_destroy() op is called from the garbage collector and this assumes that
-the dentry pointer stored in the second word will be NULL if instantiation did
-not complete.
-
-Therefore just pre-clear the entire struct key on allocation rather than trying
-to be clever and only initialising to 0 only those bits that aren't otherwise
-initialised.
-
-The lack of initialisation can lead to a bug report like the following if
-big_key failed to initialise its file:
-
- general protection fault: 0000 [#1] SMP
- Modules linked in: ...
- CPU: 0 PID: 51 Comm: kworker/0:1 Not tainted 3.10.0-53.el7.x86_64 #1
- Hardware name: Dell Inc. PowerEdge 1955/0HC513, BIOS 1.4.4 12/09/2008
- Workqueue: events key_garbage_collector
- task: ffff8801294f5680 ti: ffff8801296e2000 task.ti: ffff8801296e2000
- RIP: 0010:[<ffffffff811b4a51>] dput+0x21/0x2d0
- ...
- Call Trace:
- [<ffffffff811a7b06>] path_put+0x16/0x30
- [<ffffffff81235604>] big_key_destroy+0x44/0x60
- [<ffffffff8122dc4b>] key_gc_unused_keys.constprop.2+0x5b/0xe0
- [<ffffffff8122df2f>] key_garbage_collector+0x1df/0x3c0
- [<ffffffff8107759b>] process_one_work+0x17b/0x460
- [<ffffffff8107834b>] worker_thread+0x11b/0x400
- [<ffffffff81078230>] ? rescuer_thread+0x3e0/0x3e0
- [<ffffffff8107eb00>] kthread+0xc0/0xd0
- [<ffffffff8107ea40>] ? kthread_create_on_node+0x110/0x110
- [<ffffffff815c4bec>] ret_from_fork+0x7c/0xb0
- [<ffffffff8107ea40>] ? kthread_create_on_node+0x110/0x110
-
-Reported-by: Patrik Kis <pkis@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Stephen Gallagher <sgallagh@redhat.com>
----
- security/keys/key.c | 8 +-------
- 1 file changed, 1 insertion(+), 7 deletions(-)
-
-diff --git a/security/keys/key.c b/security/keys/key.c
-index 55d110f..6e21c11 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -272,7 +272,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
- }
-
- /* allocate and initialise the key and its description */
-- key = kmem_cache_alloc(key_jar, GFP_KERNEL);
-+ key = kmem_cache_zalloc(key_jar, GFP_KERNEL);
- if (!key)
- goto no_memory_2;
-
-@@ -293,18 +293,12 @@ struct key *key_alloc(struct key_type *type, const char *desc,
- key->uid = uid;
- key->gid = gid;
- key->perm = perm;
-- key->flags = 0;
-- key->expiry = 0;
-- key->payload.data = NULL;
-- key->security = NULL;
-
- if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
- key->flags |= 1 << KEY_FLAG_IN_QUOTA;
- if (flags & KEY_ALLOC_TRUSTED)
- key->flags |= 1 << KEY_FLAG_TRUSTED;
-
-- memset(&key->type_data, 0, sizeof(key->type_data));
--
- #ifdef KEY_DEBUGGING
- key->magic = KEY_DEBUG_MAGIC;
- #endif
---
-1.8.3.1
-
-
-From 505f63b47ecea475750c45ad3ba3e3ba73872509 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Mon, 2 Dec 2013 11:24:18 +0000
-Subject: [PATCH 07/10] KEYS: Fix the keyring hash function
-
-The keyring hash function (used by the associative array) is supposed to clear
-the bottommost nibble of the index key (where the hash value resides) for
-keyrings and make sure it is non-zero for non-keyrings. This is done to make
-keyrings cluster together on one branch of the tree separately to other keys.
-
-Unfortunately, the wrong mask is used, so only the bottom two bits are
-examined and cleared and not the whole bottom nibble. This means that keys
-and keyrings can still be successfully searched for under most circumstances
-as the hash is consistent in its miscalculation, but if a keyring's
-associative array bottom node gets filled up then approx 75% of the keyrings
-will not be put into the 0 branch.
-
-The consequence of this is that a key in a keyring linked to by another
-keyring, ie.
-
- keyring A -> keyring B -> key
-
-may not be found if the search starts at keyring A and then descends into
-keyring B because search_nested_keyrings() only searches up the 0 branch (as it
-"knows" all keyrings must be there and not elsewhere in the tree).
-
-The fix is to use the right mask.
-
-This can be tested with:
-
- r=`keyctl newring sandbox @s`
- for ((i=0; i<=16; i++)); do keyctl newring ring$i $r; done
- for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done
- for ((i=0; i<=16; i++)); do keyctl search $r user a$i; done
-
-This creates a sandbox keyring, then creates 17 keyrings therein (labelled
-ring0..ring16). This causes the root node of the sandbox's associative array
-to overflow and for the tree to have extra nodes inserted.
-
-Each keyring then is given a user key (labelled aN for ringN) for us to search
-for.
-
-We then search for the user keys we added, starting from the sandbox. If
-working correctly, it should return the same ordered list of key IDs as
-for...keyctl add... did. Without this patch, it reports ENOKEY "Required key
-not available" for some of the keys. Just which keys get this depends as the
-kernel pointer to the key type forms part of the hash function.
-
-Reported-by: Nalin Dahyabhai <nalin@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
-Tested-by: Stephen Gallagher <sgallagh@redhat.com>
----
- security/keys/keyring.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 69f0cb7..0adbc77 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -160,7 +160,7 @@ static u64 mult_64x32_and_fold(u64 x, u32 y)
- static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key)
- {
- const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP;
-- const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK;
-+ const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK;
- const char *description = index_key->description;
- unsigned long hash, type;
- u32 piece;
-@@ -194,10 +194,10 @@ static unsigned long hash_key_type_and_desc(const struct keyring_index_key *inde
- * ordinary keys by making sure the lowest level segment in the hash is
- * zero for keyrings and non-zero otherwise.
- */
-- if (index_key->type != &key_type_keyring && (hash & level_mask) == 0)
-+ if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0)
- return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1;
-- if (index_key->type == &key_type_keyring && (hash & level_mask) != 0)
-- return (hash + (hash << level_shift)) & ~level_mask;
-+ if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0)
-+ return (hash + (hash << level_shift)) & ~fan_mask;
- return hash;
- }
-
---
-1.8.3.1
-
-
-From cc72a3bd65c6e4594669fea8ac94966e570ec6aa Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Mon, 2 Dec 2013 11:24:18 +0000
-Subject: [PATCH 08/10] KEYS: Fix multiple key add into associative array
-
-If sufficient keys (or keyrings) are added into a keyring such that a node in
-the associative array's tree overflows (each node has a capacity N, currently
-16) and such that all N+1 keys have the same index key segment for that level
-of the tree (the level'th nibble of the index key), then assoc_array_insert()
-calls ops->diff_objects() to indicate at which bit position the two index keys
-vary.
-
-However, __key_link_begin() passes a NULL object to assoc_array_insert() with
-the intention of supplying the correct pointer later before we commit the
-change. This means that keyring_diff_objects() is given a NULL pointer as one
-of its arguments which it does not expect. This results in an oops like the
-attached.
-
-With the previous patch to fix the keyring hash function, this can be forced
-much more easily by creating a keyring and only adding keyrings to it. Add any
-other sort of key and a different insertion path is taken - all 16+1 objects
-must want to cluster in the same node slot.
-
-This can be tested by:
-
- r=`keyctl newring sandbox @s`
- for ((i=0; i<=16; i++)); do keyctl newring ring$i $r; done
-
-This should work fine, but oopses when the 17th keyring is added.
-
-Since ops->diff_objects() is always called with the first pointer pointing to
-the object to be inserted (ie. the NULL pointer), we can fix the problem by
-changing the to-be-inserted object pointer to point to the index key passed
-into assoc_array_insert() instead.
-
-Whilst we're at it, we also switch the arguments so that they are the same as
-for ->compare_object().
-
-BUG: unable to handle kernel NULL pointer dereference at 0000000000000088
-IP: [<ffffffff81191ee4>] hash_key_type_and_desc+0x18/0xb0
-...
-RIP: 0010:[<ffffffff81191ee4>] hash_key_type_and_desc+0x18/0xb0
-...
-Call Trace:
- [<ffffffff81191f9d>] keyring_diff_objects+0x21/0xd2
- [<ffffffff811f09ef>] assoc_array_insert+0x3b6/0x908
- [<ffffffff811929a7>] __key_link_begin+0x78/0xe5
- [<ffffffff81191a2e>] key_create_or_update+0x17d/0x36a
- [<ffffffff81192e0a>] SyS_add_key+0x123/0x183
- [<ffffffff81400ddb>] tracesys+0xdd/0xe2
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Tested-by: Stephen Gallagher <sgallagh@redhat.com>
----
- Documentation/assoc_array.txt | 6 +++---
- include/linux/assoc_array.h | 6 +++---
- lib/assoc_array.c | 4 ++--
- security/keys/keyring.c | 7 +++----
- 4 files changed, 11 insertions(+), 12 deletions(-)
-
-diff --git a/Documentation/assoc_array.txt b/Documentation/assoc_array.txt
-index f4faec0..2f2c6cd 100644
---- a/Documentation/assoc_array.txt
-+++ b/Documentation/assoc_array.txt
-@@ -164,10 +164,10 @@ This points to a number of methods, all of which need to be provided:
-
- (4) Diff the index keys of two objects.
-
-- int (*diff_objects)(const void *a, const void *b);
-+ int (*diff_objects)(const void *object, const void *index_key);
-
-- Return the bit position at which the index keys of two objects differ or
-- -1 if they are the same.
-+ Return the bit position at which the index key of the specified object
-+ differs from the given index key or -1 if they are the same.
-
-
- (5) Free an object.
-diff --git a/include/linux/assoc_array.h b/include/linux/assoc_array.h
-index 9a193b8..a89df3b 100644
---- a/include/linux/assoc_array.h
-+++ b/include/linux/assoc_array.h
-@@ -41,10 +41,10 @@ struct assoc_array_ops {
- /* Is this the object we're looking for? */
- bool (*compare_object)(const void *object, const void *index_key);
-
-- /* How different are two objects, to a bit position in their keys? (or
-- * -1 if they're the same)
-+ /* How different is an object from an index key, to a bit position in
-+ * their keys? (or -1 if they're the same)
- */
-- int (*diff_objects)(const void *a, const void *b);
-+ int (*diff_objects)(const void *object, const void *index_key);
-
- /* Method to free an object. */
- void (*free_object)(void *object);
-diff --git a/lib/assoc_array.c b/lib/assoc_array.c
-index 17edeaf..1b6a44f 100644
---- a/lib/assoc_array.c
-+++ b/lib/assoc_array.c
-@@ -759,8 +759,8 @@ all_leaves_cluster_together:
- pr_devel("all leaves cluster together\n");
- diff = INT_MAX;
- for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++) {
-- int x = ops->diff_objects(assoc_array_ptr_to_leaf(edit->leaf),
-- assoc_array_ptr_to_leaf(node->slots[i]));
-+ int x = ops->diff_objects(assoc_array_ptr_to_leaf(node->slots[i]),
-+ index_key);
- if (x < diff) {
- BUG_ON(x < 0);
- diff = x;
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 0adbc77..3dd8445 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -279,12 +279,11 @@ static bool keyring_compare_object(const void *object, const void *data)
- * Compare the index keys of a pair of objects and determine the bit position
- * at which they differ - if they differ.
- */
--static int keyring_diff_objects(const void *_a, const void *_b)
-+static int keyring_diff_objects(const void *object, const void *data)
- {
-- const struct key *key_a = keyring_ptr_to_key(_a);
-- const struct key *key_b = keyring_ptr_to_key(_b);
-+ const struct key *key_a = keyring_ptr_to_key(object);
- const struct keyring_index_key *a = &key_a->index_key;
-- const struct keyring_index_key *b = &key_b->index_key;
-+ const struct keyring_index_key *b = data;
- unsigned long seg_a, seg_b;
- int level, i;
-
---
-1.8.3.1
-
-
-From 6d2303664c4dd852c49fe68140b308d5b0c4a082 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Mon, 2 Dec 2013 11:24:19 +0000
-Subject: [PATCH 09/10] KEYS: Fix searching of nested keyrings
-
-If a keyring contains more than 16 keyrings (the capacity of a single node in
-the associative array) then those keyrings are split over multiple nodes
-arranged as a tree.
-
-If search_nested_keyrings() is called to search the keyring then it will
-attempt to manually walk over just the 0 branch of the associative array tree
-where all the keyring links are stored. This works provided the key is found
-before the algorithm steps from one node containing keyrings to a child node
-or if there are sufficiently few keyring links that the keyrings are all in
-one node.
-
-However, if the algorithm does need to step from a node to a child node, it
-doesn't change the node pointer unless a shortcut also gets transited. This
-means that the algorithm will keep scanning the same node over and over again
-without terminating and without returning.
-
-To fix this, move the internal-pointer-to-node translation from inside the
-shortcut transit handler so that it applies it to node arrival as well.
-
-This can be tested by:
-
- r=`keyctl newring sandbox @s`
- for ((i=0; i<=16; i++)); do keyctl newring ring$i $r; done
- for ((i=0; i<=16; i++)); do keyctl add user a$i a %:ring$i; done
- for ((i=0; i<=16; i++)); do keyctl search $r user a$i; done
- for ((i=17; i<=20; i++)); do keyctl search $r user a$i; done
-
-The searches should all complete successfully (or with an error for 17-20),
-but instead one or more of them will hang.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Tested-by: Stephen Gallagher <sgallagh@redhat.com>
----
- security/keys/keyring.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index 3dd8445..d46cbc5 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -690,8 +690,8 @@ descend_to_node:
- smp_read_barrier_depends();
- ptr = ACCESS_ONCE(shortcut->next_node);
- BUG_ON(!assoc_array_ptr_is_node(ptr));
-- node = assoc_array_ptr_to_node(ptr);
- }
-+ node = assoc_array_ptr_to_node(ptr);
-
- begin_node:
- kdebug("begin_node");
---
-1.8.3.1
-
-
-From 6a57d6a93f0d17b3e23134fec556aea585cb5392 Mon Sep 17 00:00:00 2001
-From: Eric Paris <eparis@redhat.com>
-Date: Mon, 2 Dec 2013 11:24:19 +0000
-Subject: [PATCH 10/10] security: shmem: implement kernel private shmem inodes
-
-We have a problem where the big_key key storage implementation uses a
-shmem backed inode to hold the key contents. Because of this detail of
-implementation LSM checks are being done between processes trying to
-read the keys and the tmpfs backed inode. The LSM checks are already
-being handled on the key interface level and should not be enforced at
-the inode level (since the inode is an implementation detail, not a
-part of the security model)
-
-This patch implements a new function shmem_kernel_file_setup() which
-returns the equivalent to shmem_file_setup() only the underlying inode
-has S_PRIVATE set. This means that all LSM checks for the inode in
-question are skipped. It should only be used for kernel internal
-operations where the inode is not exposed to userspace without proper
-LSM checking. It is possible that some other users of
-shmem_file_setup() should use the new interface, but this has not been
-explored.
-
-Reproducing this bug is a little bit difficult. The steps I used on
-Fedora are:
-
- (1) Turn off selinux enforcing:
-
- setenforce 0
-
- (2) Create a huge key
-
- k=`dd if=/dev/zero bs=8192 count=1 | keyctl padd big_key test-key @s`
-
- (3) Access the key in another context:
-
- runcon system_u:system_r:httpd_t:s0-s0:c0.c1023 keyctl print $k >/dev/null
-
- (4) Examine the audit logs:
-
- ausearch -m AVC -i --subject httpd_t | audit2allow
-
-If the last command's output includes a line that looks like:
-
- allow httpd_t user_tmpfs_t:file { open read };
-
-There was an inode check between httpd and the tmpfs filesystem. With
-this patch no such denial will be seen. (NOTE! you should clear your
-audit log if you have tested for this previously)
-
-(Please return you box to enforcing)
-
-Signed-off-by: Eric Paris <eparis@redhat.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
-cc: Hugh Dickins <hughd@google.com>
-cc: linux-mm@kvack.org
----
- include/linux/shmem_fs.h | 2 ++
- mm/shmem.c | 36 +++++++++++++++++++++++++++++-------
- security/keys/big_key.c | 2 +-
- 3 files changed, 32 insertions(+), 8 deletions(-)
-
-diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
-index 30aa0dc..9d55438 100644
---- a/include/linux/shmem_fs.h
-+++ b/include/linux/shmem_fs.h
-@@ -47,6 +47,8 @@ extern int shmem_init(void);
- extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
- extern struct file *shmem_file_setup(const char *name,
- loff_t size, unsigned long flags);
-+extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
-+ unsigned long flags);
- extern int shmem_zero_setup(struct vm_area_struct *);
- extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
- extern void shmem_unlock_mapping(struct address_space *mapping);
-diff --git a/mm/shmem.c b/mm/shmem.c
-index e43dc55..1c4124e 100644
---- a/mm/shmem.c
-+++ b/mm/shmem.c
-@@ -2913,13 +2913,8 @@ static struct dentry_operations anon_ops = {
- .d_dname = simple_dname
- };
-
--/**
-- * shmem_file_setup - get an unlinked file living in tmpfs
-- * @name: name for dentry (to be seen in /proc/<pid>/maps
-- * @size: size to be set for the file
-- * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
-- */
--struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
-+static struct file *__shmem_file_setup(const char *name, loff_t size,
-+ unsigned long flags, unsigned int i_flags)
- {
- struct file *res;
- struct inode *inode;
-@@ -2952,6 +2947,7 @@ struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags
- if (!inode)
- goto put_dentry;
-
-+ inode->i_flags |= i_flags;
- d_instantiate(path.dentry, inode);
- inode->i_size = size;
- clear_nlink(inode); /* It is unlinked */
-@@ -2972,6 +2968,32 @@ put_memory:
- shmem_unacct_size(flags, size);
- return res;
- }
-+
-+/**
-+ * shmem_kernel_file_setup - get an unlinked file living in tmpfs which must be
-+ * kernel internal. There will be NO LSM permission checks against the
-+ * underlying inode. So users of this interface must do LSM checks at a
-+ * higher layer. The one user is the big_key implementation. LSM checks
-+ * are provided at the key level rather than the inode level.
-+ * @name: name for dentry (to be seen in /proc/<pid>/maps
-+ * @size: size to be set for the file
-+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
-+ */
-+struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags)
-+{
-+ return __shmem_file_setup(name, size, flags, S_PRIVATE);
-+}
-+
-+/**
-+ * shmem_file_setup - get an unlinked file living in tmpfs
-+ * @name: name for dentry (to be seen in /proc/<pid>/maps
-+ * @size: size to be set for the file
-+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
-+ */
-+struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
-+{
-+ return __shmem_file_setup(name, size, flags, 0);
-+}
- EXPORT_SYMBOL_GPL(shmem_file_setup);
-
- /**
-diff --git a/security/keys/big_key.c b/security/keys/big_key.c
-index 7f44c32..8137b27 100644
---- a/security/keys/big_key.c
-+++ b/security/keys/big_key.c
-@@ -70,7 +70,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
- *
- * TODO: Encrypt the stored data with a temporary key.
- */
-- file = shmem_file_setup("", datalen, 0);
-+ file = shmem_kernel_file_setup("", datalen, 0);
- if (IS_ERR(file)) {
- ret = PTR_ERR(file);
- goto err_quota;
---
-1.8.3.1
-
diff --git a/keys-krb-support.patch b/keys-krb-support.patch
deleted file mode 100644
index 8bffaae8b..000000000
--- a/keys-krb-support.patch
+++ /dev/null
@@ -1,748 +0,0 @@
-From d7ccdaa17aab12a49f5e9e327b55167c4af26bf8 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:54 +0100
-Subject: [PATCH 1/2] KEYS: Implement a big key type that can save to tmpfs
-
-Implement a big key type that can save its contents to tmpfs and thus
-swapspace when memory is tight. This is useful for Kerberos ticket caches.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Tested-by: Simo Sorce <simo@redhat.com>
----
- include/keys/big_key-type.h | 25 ++++++
- include/linux/key.h | 1 +
- security/keys/Kconfig | 11 +++
- security/keys/Makefile | 1 +
- security/keys/big_key.c | 204 ++++++++++++++++++++++++++++++++++++++++++++
- 5 files changed, 242 insertions(+)
- create mode 100644 include/keys/big_key-type.h
- create mode 100644 security/keys/big_key.c
-
-diff --git a/include/keys/big_key-type.h b/include/keys/big_key-type.h
-new file mode 100644
-index 0000000..d69bc8a
---- /dev/null
-+++ b/include/keys/big_key-type.h
-@@ -0,0 +1,25 @@
-+/* Big capacity key type.
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+
-+#ifndef _KEYS_BIG_KEY_TYPE_H
-+#define _KEYS_BIG_KEY_TYPE_H
-+
-+#include <linux/key-type.h>
-+
-+extern struct key_type key_type_big_key;
-+
-+extern int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep);
-+extern void big_key_revoke(struct key *key);
-+extern void big_key_destroy(struct key *key);
-+extern void big_key_describe(const struct key *big_key, struct seq_file *m);
-+extern long big_key_read(const struct key *key, char __user *buffer, size_t buflen);
-+
-+#endif /* _KEYS_BIG_KEY_TYPE_H */
-diff --git a/include/linux/key.h b/include/linux/key.h
-index 2417f78..010dbb6 100644
---- a/include/linux/key.h
-+++ b/include/linux/key.h
-@@ -201,6 +201,7 @@ struct key {
- unsigned long value;
- void __rcu *rcudata;
- void *data;
-+ void *data2[2];
- } payload;
- struct assoc_array keys;
- };
-diff --git a/security/keys/Kconfig b/security/keys/Kconfig
-index 15e0dfe..b563622 100644
---- a/security/keys/Kconfig
-+++ b/security/keys/Kconfig
-@@ -20,6 +20,17 @@ config KEYS
-
- If you are unsure as to whether this is required, answer N.
-
-+config BIG_KEYS
-+ tristate "Large payload keys"
-+ depends on KEYS
-+ depends on TMPFS
-+ help
-+ This option provides support for holding large keys within the kernel
-+ (for example Kerberos ticket caches). The data may be stored out to
-+ swapspace by tmpfs.
-+
-+ If you are unsure as to whether this is required, answer N.
-+
- config TRUSTED_KEYS
- tristate "TRUSTED KEYS"
- depends on KEYS && TCG_TPM
-diff --git a/security/keys/Makefile b/security/keys/Makefile
-index 504aaa0..c487c77 100644
---- a/security/keys/Makefile
-+++ b/security/keys/Makefile
-@@ -22,5 +22,6 @@ obj-$(CONFIG_SYSCTL) += sysctl.o
- #
- # Key types
- #
-+obj-$(CONFIG_BIG_KEYS) += big_key.o
- obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
- obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
-diff --git a/security/keys/big_key.c b/security/keys/big_key.c
-new file mode 100644
-index 0000000..5f9defc
---- /dev/null
-+++ b/security/keys/big_key.c
-@@ -0,0 +1,204 @@
-+/* Large capacity key type
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/seq_file.h>
-+#include <linux/file.h>
-+#include <linux/shmem_fs.h>
-+#include <linux/err.h>
-+#include <keys/user-type.h>
-+#include <keys/big_key-type.h>
-+
-+MODULE_LICENSE("GPL");
-+
-+/*
-+ * If the data is under this limit, there's no point creating a shm file to
-+ * hold it as the permanently resident metadata for the shmem fs will be at
-+ * least as large as the data.
-+ */
-+#define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))
-+
-+/*
-+ * big_key defined keys take an arbitrary string as the description and an
-+ * arbitrary blob of data as the payload
-+ */
-+struct key_type key_type_big_key = {
-+ .name = "big_key",
-+ .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
-+ .instantiate = big_key_instantiate,
-+ .match = user_match,
-+ .revoke = big_key_revoke,
-+ .destroy = big_key_destroy,
-+ .describe = big_key_describe,
-+ .read = big_key_read,
-+};
-+
-+/*
-+ * Instantiate a big key
-+ */
-+int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
-+{
-+ struct path *path = (struct path *)&key->payload.data2;
-+ struct file *file;
-+ ssize_t written;
-+ size_t datalen = prep->datalen;
-+ int ret;
-+
-+ ret = -EINVAL;
-+ if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
-+ goto error;
-+
-+ /* Set an arbitrary quota */
-+ ret = key_payload_reserve(key, 16);
-+ if (ret < 0)
-+ goto error;
-+
-+ key->type_data.x[1] = datalen;
-+
-+ if (datalen > BIG_KEY_FILE_THRESHOLD) {
-+ /* Create a shmem file to store the data in. This will permit the data
-+ * to be swapped out if needed.
-+ *
-+ * TODO: Encrypt the stored data with a temporary key.
-+ */
-+ file = shmem_file_setup("", datalen, 0);
-+ if (IS_ERR(file))
-+ goto err_quota;
-+
-+ written = kernel_write(file, prep->data, prep->datalen, 0);
-+ if (written != datalen) {
-+ if (written >= 0)
-+ ret = -ENOMEM;
-+ goto err_fput;
-+ }
-+
-+ /* Pin the mount and dentry to the key so that we can open it again
-+ * later
-+ */
-+ *path = file->f_path;
-+ path_get(path);
-+ fput(file);
-+ } else {
-+ /* Just store the data in a buffer */
-+ void *data = kmalloc(datalen, GFP_KERNEL);
-+ if (!data) {
-+ ret = -ENOMEM;
-+ goto err_quota;
-+ }
-+
-+ key->payload.data = memcpy(data, prep->data, prep->datalen);
-+ }
-+ return 0;
-+
-+err_fput:
-+ fput(file);
-+err_quota:
-+ key_payload_reserve(key, 0);
-+error:
-+ return ret;
-+}
-+
-+/*
-+ * dispose of the links from a revoked keyring
-+ * - called with the key sem write-locked
-+ */
-+void big_key_revoke(struct key *key)
-+{
-+ struct path *path = (struct path *)&key->payload.data2;
-+
-+ /* clear the quota */
-+ key_payload_reserve(key, 0);
-+ if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD)
-+ vfs_truncate(path, 0);
-+}
-+
-+/*
-+ * dispose of the data dangling from the corpse of a big_key key
-+ */
-+void big_key_destroy(struct key *key)
-+{
-+ if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) {
-+ struct path *path = (struct path *)&key->payload.data2;
-+ path_put(path);
-+ path->mnt = NULL;
-+ path->dentry = NULL;
-+ } else {
-+ kfree(key->payload.data);
-+ key->payload.data = NULL;
-+ }
-+}
-+
-+/*
-+ * describe the big_key key
-+ */
-+void big_key_describe(const struct key *key, struct seq_file *m)
-+{
-+ unsigned long datalen = key->type_data.x[1];
-+
-+ seq_puts(m, key->description);
-+
-+ if (key_is_instantiated(key))
-+ seq_printf(m, ": %lu [%s]",
-+ datalen,
-+ datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
-+}
-+
-+/*
-+ * read the key data
-+ * - the key's semaphore is read-locked
-+ */
-+long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
-+{
-+ unsigned long datalen = key->type_data.x[1];
-+ long ret;
-+
-+ if (!buffer || buflen < datalen)
-+ return datalen;
-+
-+ if (datalen > BIG_KEY_FILE_THRESHOLD) {
-+ struct path *path = (struct path *)&key->payload.data2;
-+ struct file *file;
-+ loff_t pos;
-+
-+ file = dentry_open(path, O_RDONLY, current_cred());
-+ if (IS_ERR(file))
-+ return PTR_ERR(file);
-+
-+ pos = 0;
-+ ret = vfs_read(file, buffer, datalen, &pos);
-+ fput(file);
-+ if (ret >= 0 && ret != datalen)
-+ ret = -EIO;
-+ } else {
-+ ret = datalen;
-+ if (copy_to_user(buffer, key->payload.data, datalen) != 0)
-+ ret = -EFAULT;
-+ }
-+
-+ return ret;
-+}
-+
-+/*
-+ * Module stuff
-+ */
-+static int __init big_key_init(void)
-+{
-+ return register_key_type(&key_type_big_key);
-+}
-+
-+static void __exit big_key_cleanup(void)
-+{
-+ unregister_key_type(&key_type_big_key);
-+}
-+
-+module_init(big_key_init);
-+module_exit(big_key_cleanup);
---
-1.8.3.1
-
-
-From 862e98313b10123fa4352117b0b0c0f5a530cefb Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 15:37:54 +0100
-Subject: [PATCH 2/2] KEYS: Add per-user_namespace registers for persistent
- per-UID kerberos caches
-
-Add support for per-user_namespace registers of persistent per-UID kerberos
-caches held within the kernel.
-
-This allows the kerberos cache to be retained beyond the life of all a user's
-processes so that the user's cron jobs can work.
-
-The kerberos cache is envisioned as a keyring/key tree looking something like:
-
- struct user_namespace
- \___ .krb_cache keyring - The register
- \___ _krb.0 keyring - Root's Kerberos cache
- \___ _krb.5000 keyring - User 5000's Kerberos cache
- \___ _krb.5001 keyring - User 5001's Kerberos cache
- \___ tkt785 big_key - A ccache blob
- \___ tkt12345 big_key - Another ccache blob
-
-Or possibly:
-
- struct user_namespace
- \___ .krb_cache keyring - The register
- \___ _krb.0 keyring - Root's Kerberos cache
- \___ _krb.5000 keyring - User 5000's Kerberos cache
- \___ _krb.5001 keyring - User 5001's Kerberos cache
- \___ tkt785 keyring - A ccache
- \___ krbtgt/REDHAT.COM@REDHAT.COM big_key
- \___ http/REDHAT.COM@REDHAT.COM user
- \___ afs/REDHAT.COM@REDHAT.COM user
- \___ nfs/REDHAT.COM@REDHAT.COM user
- \___ krbtgt/KERNEL.ORG@KERNEL.ORG big_key
- \___ http/KERNEL.ORG@KERNEL.ORG big_key
-
-What goes into a particular Kerberos cache is entirely up to userspace. Kernel
-support is limited to giving you the Kerberos cache keyring that you want.
-
-The user asks for their Kerberos cache by:
-
- krb_cache = keyctl_get_krbcache(uid, dest_keyring);
-
-The uid is -1 or the user's own UID for the user's own cache or the uid of some
-other user's cache (requires CAP_SETUID). This permits rpc.gssd or whatever to
-mess with the cache.
-
-The cache returned is a keyring named "_krb.<uid>" that the possessor can read,
-search, clear, invalidate, unlink from and add links to. Active LSMs get a
-chance to rule on whether the caller is permitted to make a link.
-
-Each uid's cache keyring is created when it first accessed and is given a
-timeout that is extended each time this function is called so that the keyring
-goes away after a while. The timeout is configurable by sysctl but defaults to
-three days.
-
-Each user_namespace struct gets a lazily-created keyring that serves as the
-register. The cache keyrings are added to it. This means that standard key
-search and garbage collection facilities are available.
-
-The user_namespace struct's register goes away when it does and anything left
-in it is then automatically gc'd.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Tested-by: Simo Sorce <simo@redhat.com>
-cc: Serge E. Hallyn <serge.hallyn@ubuntu.com>
-cc: Eric W. Biederman <ebiederm@xmission.com>
----
- include/linux/user_namespace.h | 7 ++
- include/uapi/linux/keyctl.h | 1 +
- kernel/user.c | 4 +
- kernel/user_namespace.c | 6 ++
- security/keys/Kconfig | 17 +++++
- security/keys/Makefile | 1 +
- security/keys/compat.c | 3 +
- security/keys/internal.h | 9 +++
- security/keys/keyctl.c | 3 +
- security/keys/persistent.c | 169 +++++++++++++++++++++++++++++++++++++++++
- security/keys/sysctl.c | 11 +++
- 11 files changed, 231 insertions(+)
- create mode 100644 security/keys/persistent.c
-
-diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
-index 4db2985..bb0639d 100644
---- a/include/linux/user_namespace.h
-+++ b/include/linux/user_namespace.h
-@@ -27,6 +27,13 @@ struct user_namespace {
- kuid_t owner;
- kgid_t group;
- unsigned int proc_inum;
-+
-+ /* Register of per-UID persistent keyrings for this namespace */
-+#ifdef CONFIG_PERSISTENT_KEYRINGS
-+ struct key *persistent_keyring_register;
-+ struct rw_semaphore persistent_keyring_register_sem;
-+#endif
-+
- };
-
- extern struct user_namespace init_user_ns;
-diff --git a/include/uapi/linux/keyctl.h b/include/uapi/linux/keyctl.h
-index c9b7f4fa..840cb99 100644
---- a/include/uapi/linux/keyctl.h
-+++ b/include/uapi/linux/keyctl.h
-@@ -56,5 +56,6 @@
- #define KEYCTL_REJECT 19 /* reject a partially constructed key */
- #define KEYCTL_INSTANTIATE_IOV 20 /* instantiate a partially constructed key */
- #define KEYCTL_INVALIDATE 21 /* invalidate a key */
-+#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */
-
- #endif /* _LINUX_KEYCTL_H */
-diff --git a/kernel/user.c b/kernel/user.c
-index 5bbb919..a3a0dbf 100644
---- a/kernel/user.c
-+++ b/kernel/user.c
-@@ -51,6 +51,10 @@ struct user_namespace init_user_ns = {
- .owner = GLOBAL_ROOT_UID,
- .group = GLOBAL_ROOT_GID,
- .proc_inum = PROC_USER_INIT_INO,
-+#ifdef CONFIG_KEYS_KERBEROS_CACHE
-+ .krb_cache_register_sem =
-+ __RWSEM_INITIALIZER(init_user_ns.krb_cache_register_sem),
-+#endif
- };
- EXPORT_SYMBOL_GPL(init_user_ns);
-
-diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
-index 13fb113..2dbc299 100644
---- a/kernel/user_namespace.c
-+++ b/kernel/user_namespace.c
-@@ -101,6 +101,9 @@ int create_user_ns(struct cred *new)
-
- set_cred_user_ns(new, ns);
-
-+#ifdef CONFIG_PERSISTENT_KEYRINGS
-+ rwsem_init(&ns->persistent_keyring_register_sem);
-+#endif
- return 0;
- }
-
-@@ -130,6 +133,9 @@ void free_user_ns(struct user_namespace *ns)
-
- do {
- parent = ns->parent;
-+#ifdef CONFIG_PERSISTENT_KEYRINGS
-+ key_put(ns->persistent_keyring_register);
-+#endif
- proc_free_inum(ns->proc_inum);
- kmem_cache_free(user_ns_cachep, ns);
- ns = parent;
-diff --git a/security/keys/Kconfig b/security/keys/Kconfig
-index b563622..53d8748 100644
---- a/security/keys/Kconfig
-+++ b/security/keys/Kconfig
-@@ -20,6 +20,23 @@ config KEYS
-
- If you are unsure as to whether this is required, answer N.
-
-+config PERSISTENT_KEYRINGS
-+ bool "Enable register of persistent per-UID keyrings"
-+ depends on KEYS
-+ help
-+ This option provides a register of persistent per-UID keyrings,
-+ primarily aimed at Kerberos key storage. The keyrings are persistent
-+ in the sense that they stay around after all processes of that UID
-+ have exited, not that they survive the machine being rebooted.
-+
-+ A particular keyring may be accessed by either the user whose keyring
-+ it is or by a process with administrative privileges. The active
-+ LSMs gets to rule on which admin-level processes get to access the
-+ cache.
-+
-+ Keyrings are created and added into the register upon demand and get
-+ removed if they expire (a default timeout is set upon creation).
-+
- config BIG_KEYS
- tristate "Large payload keys"
- depends on KEYS
-diff --git a/security/keys/Makefile b/security/keys/Makefile
-index c487c77..dfb3a7b 100644
---- a/security/keys/Makefile
-+++ b/security/keys/Makefile
-@@ -18,6 +18,7 @@ obj-y := \
- obj-$(CONFIG_KEYS_COMPAT) += compat.o
- obj-$(CONFIG_PROC_FS) += proc.o
- obj-$(CONFIG_SYSCTL) += sysctl.o
-+obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
-
- #
- # Key types
-diff --git a/security/keys/compat.c b/security/keys/compat.c
-index d65fa7f..bbd32c7 100644
---- a/security/keys/compat.c
-+++ b/security/keys/compat.c
-@@ -138,6 +138,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
- case KEYCTL_INVALIDATE:
- return keyctl_invalidate_key(arg2);
-
-+ case KEYCTL_GET_PERSISTENT:
-+ return keyctl_get_persistent(arg2, arg3);
-+
- default:
- return -EOPNOTSUPP;
- }
-diff --git a/security/keys/internal.h b/security/keys/internal.h
-index 581c6f6..80b2aac 100644
---- a/security/keys/internal.h
-+++ b/security/keys/internal.h
-@@ -255,6 +255,15 @@ extern long keyctl_invalidate_key(key_serial_t);
- extern long keyctl_instantiate_key_common(key_serial_t,
- const struct iovec *,
- unsigned, size_t, key_serial_t);
-+#ifdef CONFIG_PERSISTENT_KEYRINGS
-+extern long keyctl_get_persistent(uid_t, key_serial_t);
-+extern unsigned persistent_keyring_expiry;
-+#else
-+static inline long keyctl_get_persistent(uid_t uid, key_serial_t destring)
-+{
-+ return -EOPNOTSUPP;
-+}
-+#endif
-
- /*
- * Debugging key validation
-diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
-index 33cfd27..cee72ce 100644
---- a/security/keys/keyctl.c
-+++ b/security/keys/keyctl.c
-@@ -1667,6 +1667,9 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
- case KEYCTL_INVALIDATE:
- return keyctl_invalidate_key((key_serial_t) arg2);
-
-+ case KEYCTL_GET_PERSISTENT:
-+ return keyctl_get_persistent((uid_t)arg2, (key_serial_t)arg3);
-+
- default:
- return -EOPNOTSUPP;
- }
-diff --git a/security/keys/persistent.c b/security/keys/persistent.c
-new file mode 100644
-index 0000000..631a022
---- /dev/null
-+++ b/security/keys/persistent.c
-@@ -0,0 +1,169 @@
-+/* General persistent per-UID keyrings register
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/user_namespace.h>
-+#include "internal.h"
-+
-+unsigned persistent_keyring_expiry = 3 * 24 * 3600; /* Expire after 3 days of non-use */
-+
-+/*
-+ * Create the persistent keyring register for the current user namespace.
-+ *
-+ * Called with the namespace's sem locked for writing.
-+ */
-+static int key_create_persistent_register(struct user_namespace *ns)
-+{
-+ struct key *reg = keyring_alloc(".persistent_register",
-+ KUIDT_INIT(0), KGIDT_INIT(0),
-+ current_cred(),
-+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+ KEY_USR_VIEW | KEY_USR_READ),
-+ KEY_ALLOC_NOT_IN_QUOTA, NULL);
-+ if (IS_ERR(reg))
-+ return PTR_ERR(reg);
-+
-+ ns->persistent_keyring_register = reg;
-+ return 0;
-+}
-+
-+/*
-+ * Create the persistent keyring for the specified user.
-+ *
-+ * Called with the namespace's sem locked for writing.
-+ */
-+static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid,
-+ struct keyring_index_key *index_key)
-+{
-+ struct key *persistent;
-+ key_ref_t reg_ref, persistent_ref;
-+
-+ if (!ns->persistent_keyring_register) {
-+ long err = key_create_persistent_register(ns);
-+ if (err < 0)
-+ return ERR_PTR(err);
-+ } else {
-+ reg_ref = make_key_ref(ns->persistent_keyring_register, true);
-+ persistent_ref = find_key_to_update(reg_ref, index_key);
-+ if (persistent_ref)
-+ return persistent_ref;
-+ }
-+
-+ persistent = keyring_alloc(index_key->description,
-+ uid, INVALID_GID, current_cred(),
-+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+ KEY_USR_VIEW | KEY_USR_READ),
-+ KEY_ALLOC_NOT_IN_QUOTA,
-+ ns->persistent_keyring_register);
-+ if (IS_ERR(persistent))
-+ return ERR_CAST(persistent);
-+
-+ return make_key_ref(persistent, true);
-+}
-+
-+/*
-+ * Get the persistent keyring for a specific UID and link it to the nominated
-+ * keyring.
-+ */
-+static long key_get_persistent(struct user_namespace *ns, kuid_t uid,
-+ key_ref_t dest_ref)
-+{
-+ struct keyring_index_key index_key;
-+ struct key *persistent;
-+ key_ref_t reg_ref, persistent_ref;
-+ char buf[32];
-+ long ret;
-+
-+ /* Look in the register if it exists */
-+ index_key.type = &key_type_keyring;
-+ index_key.description = buf;
-+ index_key.desc_len = sprintf(buf, "_persistent.%u", from_kuid(ns, uid));
-+
-+ if (ns->persistent_keyring_register) {
-+ reg_ref = make_key_ref(ns->persistent_keyring_register, true);
-+ down_read(&ns->persistent_keyring_register_sem);
-+ persistent_ref = find_key_to_update(reg_ref, &index_key);
-+ up_read(&ns->persistent_keyring_register_sem);
-+
-+ if (persistent_ref)
-+ goto found;
-+ }
-+
-+ /* It wasn't in the register, so we'll need to create it. We might
-+ * also need to create the register.
-+ */
-+ down_write(&ns->persistent_keyring_register_sem);
-+ persistent_ref = key_create_persistent(ns, uid, &index_key);
-+ up_write(&ns->persistent_keyring_register_sem);
-+ if (!IS_ERR(persistent_ref))
-+ goto found;
-+
-+ return PTR_ERR(persistent_ref);
-+
-+found:
-+ ret = key_task_permission(persistent_ref, current_cred(), KEY_LINK);
-+ if (ret == 0) {
-+ persistent = key_ref_to_ptr(persistent_ref);
-+ ret = key_link(key_ref_to_ptr(dest_ref), persistent);
-+ if (ret == 0) {
-+ key_set_timeout(persistent, persistent_keyring_expiry);
-+ ret = persistent->serial;
-+ }
-+ }
-+
-+ key_ref_put(persistent_ref);
-+ return ret;
-+}
-+
-+/*
-+ * Get the persistent keyring for a specific UID and link it to the nominated
-+ * keyring.
-+ */
-+long keyctl_get_persistent(uid_t _uid, key_serial_t destid)
-+{
-+ struct user_namespace *ns = current_user_ns();
-+ key_ref_t dest_ref;
-+ kuid_t uid;
-+ long ret;
-+
-+ /* -1 indicates the current user */
-+ if (_uid == (uid_t)-1) {
-+ uid = current_uid();
-+ } else {
-+ uid = make_kuid(ns, _uid);
-+ if (!uid_valid(uid))
-+ return -EINVAL;
-+
-+ /* You can only see your own persistent cache if you're not
-+ * sufficiently privileged.
-+ */
-+ if (uid != current_uid() &&
-+ uid != current_suid() &&
-+ uid != current_euid() &&
-+ uid != current_fsuid() &&
-+ !ns_capable(ns, CAP_SETUID))
-+ return -EPERM;
-+ }
-+
-+ /* There must be a destination keyring */
-+ dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_WRITE);
-+ if (IS_ERR(dest_ref))
-+ return PTR_ERR(dest_ref);
-+ if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) {
-+ ret = -ENOTDIR;
-+ goto out_put_dest;
-+ }
-+
-+ ret = key_get_persistent(ns, uid, dest_ref);
-+
-+out_put_dest:
-+ key_ref_put(dest_ref);
-+ return ret;
-+}
-diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c
-index ee32d18..8c0af08 100644
---- a/security/keys/sysctl.c
-+++ b/security/keys/sysctl.c
-@@ -61,5 +61,16 @@ ctl_table key_sysctls[] = {
- .extra1 = (void *) &zero,
- .extra2 = (void *) &max,
- },
-+#ifdef CONFIG_PERSISTENT_KEYRINGS
-+ {
-+ .procname = "persistent_keyring_expiry",
-+ .data = &persistent_keyring_expiry,
-+ .maxlen = sizeof(unsigned),
-+ .mode = 0644,
-+ .proc_handler = proc_dointvec_minmax,
-+ .extra1 = (void *) &zero,
-+ .extra2 = (void *) &max,
-+ },
-+#endif
- { }
- };
---
-1.8.3.1
-
diff --git a/keys-x509-improv.patch b/keys-x509-improv.patch
deleted file mode 100644
index db07ea348..000000000
--- a/keys-x509-improv.patch
+++ /dev/null
@@ -1,1808 +0,0 @@
-From 775d395f8bd8ef08971c77f54c38ec7b9355ba4f Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:15:10 +0100
-Subject: [PATCH 01/18] KEYS: Rename public key parameter name arrays
-
-Rename the arrays of public key parameters (public key algorithm names, hash
-algorithm names and ID type names) so that the array name ends in "_name".
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/public_key.c | 14 +++++++-------
- crypto/asymmetric_keys/x509_public_key.c | 8 ++++----
- include/crypto/public_key.h | 6 +++---
- kernel/module_signing.c | 4 ++--
- 4 files changed, 16 insertions(+), 16 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
-index cb2e291..b313df1 100644
---- a/crypto/asymmetric_keys/public_key.c
-+++ b/crypto/asymmetric_keys/public_key.c
-@@ -22,13 +22,13 @@
-
- MODULE_LICENSE("GPL");
-
--const char *const pkey_algo[PKEY_ALGO__LAST] = {
-+const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
- [PKEY_ALGO_DSA] = "DSA",
- [PKEY_ALGO_RSA] = "RSA",
- };
--EXPORT_SYMBOL_GPL(pkey_algo);
-+EXPORT_SYMBOL_GPL(pkey_algo_name);
-
--const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
-+const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = {
- [PKEY_HASH_MD4] = "md4",
- [PKEY_HASH_MD5] = "md5",
- [PKEY_HASH_SHA1] = "sha1",
-@@ -38,13 +38,13 @@ const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
- [PKEY_HASH_SHA512] = "sha512",
- [PKEY_HASH_SHA224] = "sha224",
- };
--EXPORT_SYMBOL_GPL(pkey_hash_algo);
-+EXPORT_SYMBOL_GPL(pkey_hash_algo_name);
-
--const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = {
-+const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
- [PKEY_ID_PGP] = "PGP",
- [PKEY_ID_X509] = "X509",
- };
--EXPORT_SYMBOL_GPL(pkey_id_type);
-+EXPORT_SYMBOL_GPL(pkey_id_type_name);
-
- /*
- * Provide a part of a description of the key for /proc/keys.
-@@ -56,7 +56,7 @@ static void public_key_describe(const struct key *asymmetric_key,
-
- if (key)
- seq_printf(m, "%s.%s",
-- pkey_id_type[key->id_type], key->algo->name);
-+ pkey_id_type_name[key->id_type], key->algo->name);
- }
-
- /*
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index 06007f0..afbbc36 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -49,7 +49,7 @@ static int x509_check_signature(const struct public_key *pub,
- /* Allocate the hashing algorithm we're going to need and find out how
- * big the hash operational data will be.
- */
-- tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0);
-+ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0);
- if (IS_ERR(tfm))
- return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
-
-@@ -117,7 +117,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
-
- pr_devel("Cert Issuer: %s\n", cert->issuer);
- pr_devel("Cert Subject: %s\n", cert->subject);
-- pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]);
-+ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]);
- pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
- cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
- cert->valid_from.tm_mday, cert->valid_from.tm_hour,
-@@ -127,8 +127,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- cert->valid_to.tm_mday, cert->valid_to.tm_hour,
- cert->valid_to.tm_min, cert->valid_to.tm_sec);
- pr_devel("Cert Signature: %s + %s\n",
-- pkey_algo[cert->sig_pkey_algo],
-- pkey_hash_algo[cert->sig_hash_algo]);
-+ pkey_algo_name[cert->sig_pkey_algo],
-+ pkey_hash_algo_name[cert->sig_hash_algo]);
-
- if (!cert->fingerprint || !cert->authority) {
- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
-diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
-index f5b0224..619d570 100644
---- a/include/crypto/public_key.h
-+++ b/include/crypto/public_key.h
-@@ -22,7 +22,7 @@ enum pkey_algo {
- PKEY_ALGO__LAST
- };
-
--extern const char *const pkey_algo[PKEY_ALGO__LAST];
-+extern const char *const pkey_algo_name[PKEY_ALGO__LAST];
-
- enum pkey_hash_algo {
- PKEY_HASH_MD4,
-@@ -36,7 +36,7 @@ enum pkey_hash_algo {
- PKEY_HASH__LAST
- };
-
--extern const char *const pkey_hash_algo[PKEY_HASH__LAST];
-+extern const char *const pkey_hash_algo_name[PKEY_HASH__LAST];
-
- enum pkey_id_type {
- PKEY_ID_PGP, /* OpenPGP generated key ID */
-@@ -44,7 +44,7 @@ enum pkey_id_type {
- PKEY_ID_TYPE__LAST
- };
-
--extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST];
-+extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST];
-
- /*
- * Cryptographic data for the public-key subtype of the asymmetric key type.
-diff --git a/kernel/module_signing.c b/kernel/module_signing.c
-index f2970bd..ee47640 100644
---- a/kernel/module_signing.c
-+++ b/kernel/module_signing.c
-@@ -54,7 +54,7 @@ static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash,
- /* Allocate the hashing algorithm we're going to need and find out how
- * big the hash operational data will be.
- */
-- tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0);
-+ tfm = crypto_alloc_shash(pkey_hash_algo_name[hash], 0, 0);
- if (IS_ERR(tfm))
- return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm);
-
-@@ -217,7 +217,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
- return -ENOPKG;
-
- if (ms.hash >= PKEY_HASH__LAST ||
-- !pkey_hash_algo[ms.hash])
-+ !pkey_hash_algo_name[ms.hash])
- return -ENOPKG;
-
- key = request_asymmetric_key(sig, ms.signer_len,
---
-1.8.3.1
-
-
-From d12f06db05dacb455714f00f070cce844fb3e44c Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:15:18 +0100
-Subject: [PATCH 02/18] KEYS: Move the algorithm pointer array from x509 to
- public_key.c
-
-Move the public-key algorithm pointer array from x509_public_key.c to
-public_key.c as it isn't X.509 specific.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/public_key.c | 8 ++++++++
- crypto/asymmetric_keys/x509_public_key.c | 11 +----------
- include/crypto/public_key.h | 1 +
- 3 files changed, 10 insertions(+), 10 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
-index b313df1..796ce08 100644
---- a/crypto/asymmetric_keys/public_key.c
-+++ b/crypto/asymmetric_keys/public_key.c
-@@ -28,6 +28,14 @@ const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
- };
- EXPORT_SYMBOL_GPL(pkey_algo_name);
-
-+const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
-+#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
-+ defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
-+ [PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
-+#endif
-+};
-+EXPORT_SYMBOL_GPL(pkey_algo);
-+
- const char *const pkey_hash_algo_name[PKEY_HASH__LAST] = {
- [PKEY_HASH_MD4] = "md4",
- [PKEY_HASH_MD5] = "md5",
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index afbbc36..fe38628 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -23,15 +23,6 @@
- #include "public_key.h"
- #include "x509_parser.h"
-
--static const
--struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = {
-- [PKEY_ALGO_DSA] = NULL,
--#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
-- defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
-- [PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
--#endif
--};
--
- /*
- * Check the signature on a certificate using the provided public key
- */
-@@ -174,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- goto error_free_cert;
- }
-
-- cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
-+ cert->pub->algo = pkey_algo[cert->pkey_algo];
- cert->pub->id_type = PKEY_ID_X509;
-
- /* Check the signature on the key */
-diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
-index 619d570..46bde25 100644
---- a/include/crypto/public_key.h
-+++ b/include/crypto/public_key.h
-@@ -23,6 +23,7 @@ enum pkey_algo {
- };
-
- extern const char *const pkey_algo_name[PKEY_ALGO__LAST];
-+extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
-
- enum pkey_hash_algo {
- PKEY_HASH_MD4,
---
-1.8.3.1
-
-
-From 8d2905bce58b356e9b5313a4aaebb5085bb4c151 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:15:24 +0100
-Subject: [PATCH 03/18] KEYS: Store public key algo ID in public_key struct
-
-Store public key algo ID in public_key struct for reference purposes. This
-allows it to be removed from the x509_certificate struct and used to find a
-default in public_key_verify_signature().
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/x509_cert_parser.c | 5 +++--
- crypto/asymmetric_keys/x509_parser.h | 1 -
- crypto/asymmetric_keys/x509_public_key.c | 4 ++--
- include/crypto/public_key.h | 1 +
- 4 files changed, 6 insertions(+), 5 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
-index facbf26..8cc253d 100644
---- a/crypto/asymmetric_keys/x509_cert_parser.c
-+++ b/crypto/asymmetric_keys/x509_cert_parser.c
-@@ -343,8 +343,9 @@ int x509_extract_key_data(void *context, size_t hdrlen,
- if (ctx->last_oid != OID_rsaEncryption)
- return -ENOPKG;
-
-- /* There seems to be an extraneous 0 byte on the front of the data */
-- ctx->cert->pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA;
-+
-+ /* Discard the BIT STRING metadata */
- ctx->key = value + 1;
- ctx->key_size = vlen - 1;
- return 0;
-diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
-index f86dc5f..e583ad0 100644
---- a/crypto/asymmetric_keys/x509_parser.h
-+++ b/crypto/asymmetric_keys/x509_parser.h
-@@ -20,7 +20,6 @@ struct x509_certificate {
- char *authority; /* Authority key fingerprint as hex */
- struct tm valid_from;
- struct tm valid_to;
-- enum pkey_algo pkey_algo : 8; /* Public key algorithm */
- enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */
- enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */
- const void *tbs; /* Signed data */
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index fe38628..fac574c 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -108,7 +108,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
-
- pr_devel("Cert Issuer: %s\n", cert->issuer);
- pr_devel("Cert Subject: %s\n", cert->subject);
-- pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pkey_algo]);
-+ pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
- pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
- cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
- cert->valid_from.tm_mday, cert->valid_from.tm_hour,
-@@ -165,7 +165,7 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- goto error_free_cert;
- }
-
-- cert->pub->algo = pkey_algo[cert->pkey_algo];
-+ cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
- cert->pub->id_type = PKEY_ID_X509;
-
- /* Check the signature on the key */
-diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
-index 46bde25..05778df 100644
---- a/include/crypto/public_key.h
-+++ b/include/crypto/public_key.h
-@@ -60,6 +60,7 @@ struct public_key {
- #define PKEY_CAN_DECRYPT 0x02
- #define PKEY_CAN_SIGN 0x04
- #define PKEY_CAN_VERIFY 0x08
-+ enum pkey_algo pkey_algo : 8;
- enum pkey_id_type id_type : 8;
- union {
- MPI mpi[5];
---
-1.8.3.1
-
-
-From df1662a5b9f37a88c1e112d4052eca79efc8e6fc Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:15:30 +0100
-Subject: [PATCH 04/18] KEYS: Split public_key_verify_signature() and make
- available
-
-Modify public_key_verify_signature() so that it now takes a public_key struct
-rather than a key struct and supply a wrapper that takes a key struct. The
-wrapper is then used by the asymmetric key subtype and the modified function is
-used by X.509 self-signature checking and can be used by other things also.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/public_key.c | 40 +++++++++++++++++++++++++-------
- crypto/asymmetric_keys/public_key.h | 6 +++++
- crypto/asymmetric_keys/x509_public_key.c | 2 +-
- 3 files changed, 39 insertions(+), 9 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
-index 796ce08..49ac8d8 100644
---- a/crypto/asymmetric_keys/public_key.c
-+++ b/crypto/asymmetric_keys/public_key.c
-@@ -86,21 +86,45 @@ EXPORT_SYMBOL_GPL(public_key_destroy);
- /*
- * Verify a signature using a public key.
- */
--static int public_key_verify_signature(const struct key *key,
-- const struct public_key_signature *sig)
-+int public_key_verify_signature(const struct public_key *pk,
-+ const struct public_key_signature *sig)
- {
-- const struct public_key *pk = key->payload.data;
-+ const struct public_key_algorithm *algo;
-+
-+ BUG_ON(!pk);
-+ BUG_ON(!pk->mpi[0]);
-+ BUG_ON(!pk->mpi[1]);
-+ BUG_ON(!sig);
-+ BUG_ON(!sig->digest);
-+ BUG_ON(!sig->mpi[0]);
-+
-+ algo = pk->algo;
-+ if (!algo) {
-+ if (pk->pkey_algo >= PKEY_ALGO__LAST)
-+ return -ENOPKG;
-+ algo = pkey_algo[pk->pkey_algo];
-+ if (!algo)
-+ return -ENOPKG;
-+ }
-
-- if (!pk->algo->verify_signature)
-+ if (!algo->verify_signature)
- return -ENOTSUPP;
-
-- if (sig->nr_mpi != pk->algo->n_sig_mpi) {
-+ if (sig->nr_mpi != algo->n_sig_mpi) {
- pr_debug("Signature has %u MPI not %u\n",
-- sig->nr_mpi, pk->algo->n_sig_mpi);
-+ sig->nr_mpi, algo->n_sig_mpi);
- return -EINVAL;
- }
-
-- return pk->algo->verify_signature(pk, sig);
-+ return algo->verify_signature(pk, sig);
-+}
-+EXPORT_SYMBOL_GPL(public_key_verify_signature);
-+
-+static int public_key_verify_signature_2(const struct key *key,
-+ const struct public_key_signature *sig)
-+{
-+ const struct public_key *pk = key->payload.data;
-+ return public_key_verify_signature(pk, sig);
- }
-
- /*
-@@ -111,6 +135,6 @@ struct asymmetric_key_subtype public_key_subtype = {
- .name = "public_key",
- .describe = public_key_describe,
- .destroy = public_key_destroy,
-- .verify_signature = public_key_verify_signature,
-+ .verify_signature = public_key_verify_signature_2,
- };
- EXPORT_SYMBOL_GPL(public_key_subtype);
-diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h
-index 5e5e356..5c37a22 100644
---- a/crypto/asymmetric_keys/public_key.h
-+++ b/crypto/asymmetric_keys/public_key.h
-@@ -28,3 +28,9 @@ struct public_key_algorithm {
- };
-
- extern const struct public_key_algorithm RSA_public_key_algorithm;
-+
-+/*
-+ * public_key.c
-+ */
-+extern int public_key_verify_signature(const struct public_key *pk,
-+ const struct public_key_signature *sig);
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index fac574c..8cb2f70 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -76,7 +76,7 @@ static int x509_check_signature(const struct public_key *pub,
- if (ret < 0)
- goto error_mpi;
-
-- ret = pub->algo->verify_signature(pub, sig);
-+ ret = public_key_verify_signature(pub, sig);
-
- pr_debug("Cert Verification: %d\n", ret);
-
---
-1.8.3.1
-
-
-From 322d3b7e2debb3c7983dce2b80a5aefa4e7b1bda Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:15:37 +0100
-Subject: [PATCH 05/18] KEYS: Store public key algo ID in public_key_signature
- struct
-
-Store public key algorithm ID in public_key_signature struct for reference
-purposes. This allows a public_key_signature struct to be embedded in
-struct x509_certificate and other places more easily.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- include/crypto/public_key.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
-index 05778df..b34fda4 100644
---- a/include/crypto/public_key.h
-+++ b/include/crypto/public_key.h
-@@ -90,6 +90,7 @@ struct public_key_signature {
- u8 *digest;
- u8 digest_size; /* Number of bytes in digest */
- u8 nr_mpi; /* Occupancy of mpi[] */
-+ enum pkey_algo pkey_algo : 8;
- enum pkey_hash_algo pkey_hash_algo : 8;
- union {
- MPI mpi[2];
---
-1.8.3.1
-
-
-From 743143dd12661df376dcfc916b626b01d8ec84a4 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:16:34 +0100
-Subject: [PATCH 06/18] X.509: struct x509_certificate needs struct tm
- declaring
-
-struct x509_certificate needs struct tm declaring by #inclusion of linux/time.h
-prior to its definition.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/x509_parser.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
-index e583ad0..2d01182 100644
---- a/crypto/asymmetric_keys/x509_parser.h
-+++ b/crypto/asymmetric_keys/x509_parser.h
-@@ -9,6 +9,7 @@
- * 2 of the Licence, or (at your option) any later version.
- */
-
-+#include <linux/time.h>
- #include <crypto/public_key.h>
-
- struct x509_certificate {
---
-1.8.3.1
-
-
-From a326ca89468c73dacb00fa247e92873d09e1387b Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:18:02 +0100
-Subject: [PATCH 07/18] X.509: Embed public_key_signature struct and create
- filler function
-
-Embed a public_key_signature struct in struct x509_certificate, eliminating
-now unnecessary fields, and split x509_check_signature() to create a filler
-function for it that attaches a digest of the signed data and an MPI that
-represents the signature data. x509_free_certificate() is then modified to
-deal with these.
-
-Whilst we're at it, export both x509_check_signature() and the new
-x509_get_sig_params().
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/x509_cert_parser.c | 30 +++++------
- crypto/asymmetric_keys/x509_parser.h | 16 ++++--
- crypto/asymmetric_keys/x509_public_key.c | 83 +++++++++++++++++--------------
- 3 files changed, 74 insertions(+), 55 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
-index 8cc253d..144201c 100644
---- a/crypto/asymmetric_keys/x509_cert_parser.c
-+++ b/crypto/asymmetric_keys/x509_cert_parser.c
-@@ -47,6 +47,8 @@ void x509_free_certificate(struct x509_certificate *cert)
- kfree(cert->subject);
- kfree(cert->fingerprint);
- kfree(cert->authority);
-+ kfree(cert->sig.digest);
-+ mpi_free(cert->sig.rsa.s);
- kfree(cert);
- }
- }
-@@ -152,33 +154,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
- return -ENOPKG; /* Unsupported combination */
-
- case OID_md4WithRSAEncryption:
-- ctx->cert->sig_hash_algo = PKEY_HASH_MD5;
-- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_MD5;
-+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
- break;
-
- case OID_sha1WithRSAEncryption:
-- ctx->cert->sig_hash_algo = PKEY_HASH_SHA1;
-- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA1;
-+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
- break;
-
- case OID_sha256WithRSAEncryption:
-- ctx->cert->sig_hash_algo = PKEY_HASH_SHA256;
-- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA256;
-+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
- break;
-
- case OID_sha384WithRSAEncryption:
-- ctx->cert->sig_hash_algo = PKEY_HASH_SHA384;
-- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA384;
-+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
- break;
-
- case OID_sha512WithRSAEncryption:
-- ctx->cert->sig_hash_algo = PKEY_HASH_SHA512;
-- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA512;
-+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
- break;
-
- case OID_sha224WithRSAEncryption:
-- ctx->cert->sig_hash_algo = PKEY_HASH_SHA224;
-- ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
-+ ctx->cert->sig.pkey_hash_algo = PKEY_HASH_SHA224;
-+ ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
- break;
- }
-
-@@ -203,8 +205,8 @@ int x509_note_signature(void *context, size_t hdrlen,
- return -EINVAL;
- }
-
-- ctx->cert->sig = value;
-- ctx->cert->sig_size = vlen;
-+ ctx->cert->raw_sig = value;
-+ ctx->cert->raw_sig_size = vlen;
- return 0;
- }
-
-diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
-index 2d01182..87d9cc2 100644
---- a/crypto/asymmetric_keys/x509_parser.h
-+++ b/crypto/asymmetric_keys/x509_parser.h
-@@ -21,12 +21,11 @@ struct x509_certificate {
- char *authority; /* Authority key fingerprint as hex */
- struct tm valid_from;
- struct tm valid_to;
-- enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */
-- enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */
- const void *tbs; /* Signed data */
-- size_t tbs_size; /* Size of signed data */
-- const void *sig; /* Signature data */
-- size_t sig_size; /* Size of sigature */
-+ unsigned tbs_size; /* Size of signed data */
-+ unsigned raw_sig_size; /* Size of sigature */
-+ const void *raw_sig; /* Signature data */
-+ struct public_key_signature sig; /* Signature parameters */
- };
-
- /*
-@@ -34,3 +33,10 @@ struct x509_certificate {
- */
- extern void x509_free_certificate(struct x509_certificate *cert);
- extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
-+
-+/*
-+ * x509_public_key.c
-+ */
-+extern int x509_get_sig_params(struct x509_certificate *cert);
-+extern int x509_check_signature(const struct public_key *pub,
-+ struct x509_certificate *cert);
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index 8cb2f70..b7c81d8 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -24,72 +24,83 @@
- #include "x509_parser.h"
-
- /*
-- * Check the signature on a certificate using the provided public key
-+ * Set up the signature parameters in an X.509 certificate. This involves
-+ * digesting the signed data and extracting the signature.
- */
--static int x509_check_signature(const struct public_key *pub,
-- const struct x509_certificate *cert)
-+int x509_get_sig_params(struct x509_certificate *cert)
- {
-- struct public_key_signature *sig;
- struct crypto_shash *tfm;
- struct shash_desc *desc;
- size_t digest_size, desc_size;
-+ void *digest;
- int ret;
-
- pr_devel("==>%s()\n", __func__);
--
-+
-+ if (cert->sig.rsa.s)
-+ return 0;
-+
-+ cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
-+ if (!cert->sig.rsa.s)
-+ return -ENOMEM;
-+ cert->sig.nr_mpi = 1;
-+
- /* Allocate the hashing algorithm we're going to need and find out how
- * big the hash operational data will be.
- */
-- tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig_hash_algo], 0, 0);
-+ tfm = crypto_alloc_shash(pkey_hash_algo_name[cert->sig.pkey_hash_algo], 0, 0);
- if (IS_ERR(tfm))
- return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
-
- desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
- digest_size = crypto_shash_digestsize(tfm);
-
-- /* We allocate the hash operational data storage on the end of our
-- * context data.
-+ /* We allocate the hash operational data storage on the end of the
-+ * digest storage space.
- */
- ret = -ENOMEM;
-- sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL);
-- if (!sig)
-- goto error_no_sig;
-+ digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
-+ if (!digest)
-+ goto error;
-
-- sig->pkey_hash_algo = cert->sig_hash_algo;
-- sig->digest = (u8 *)sig + sizeof(*sig) + desc_size;
-- sig->digest_size = digest_size;
-+ cert->sig.digest = digest;
-+ cert->sig.digest_size = digest_size;
-
-- desc = (void *)sig + sizeof(*sig);
-- desc->tfm = tfm;
-- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-+ desc = digest + digest_size;
-+ desc->tfm = tfm;
-+ desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-
- ret = crypto_shash_init(desc);
- if (ret < 0)
- goto error;
-+ might_sleep();
-+ ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest);
-+error:
-+ crypto_free_shash(tfm);
-+ pr_devel("<==%s() = %d\n", __func__, ret);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(x509_get_sig_params);
-
-- ret = -ENOMEM;
-- sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size);
-- if (!sig->rsa.s)
-- goto error;
-+/*
-+ * Check the signature on a certificate using the provided public key
-+ */
-+int x509_check_signature(const struct public_key *pub,
-+ struct x509_certificate *cert)
-+{
-+ int ret;
-
-- ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
-- if (ret < 0)
-- goto error_mpi;
-+ pr_devel("==>%s()\n", __func__);
-
-- ret = public_key_verify_signature(pub, sig);
-+ ret = x509_get_sig_params(cert);
-+ if (ret < 0)
-+ return ret;
-
-+ ret = public_key_verify_signature(pub, &cert->sig);
- pr_debug("Cert Verification: %d\n", ret);
--
--error_mpi:
-- mpi_free(sig->rsa.s);
--error:
-- kfree(sig);
--error_no_sig:
-- crypto_free_shash(tfm);
--
-- pr_devel("<==%s() = %d\n", __func__, ret);
- return ret;
- }
-+EXPORT_SYMBOL_GPL(x509_check_signature);
-
- /*
- * Attempt to parse a data blob for a key as an X509 certificate.
-@@ -118,8 +129,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- cert->valid_to.tm_mday, cert->valid_to.tm_hour,
- cert->valid_to.tm_min, cert->valid_to.tm_sec);
- pr_devel("Cert Signature: %s + %s\n",
-- pkey_algo_name[cert->sig_pkey_algo],
-- pkey_hash_algo_name[cert->sig_hash_algo]);
-+ pkey_algo_name[cert->sig.pkey_algo],
-+ pkey_hash_algo_name[cert->sig.pkey_hash_algo]);
-
- if (!cert->fingerprint || !cert->authority) {
- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
---
-1.8.3.1
-
-
-From 2857db9154b0fcfb8ba490c12f98cd47cc3f46fc Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:18:15 +0100
-Subject: [PATCH 08/18] X.509: Check the algorithm IDs obtained from parsing an
- X.509 certificate
-
-Check that the algorithm IDs obtained from the ASN.1 parse by OID lookup
-corresponds to algorithms that are available to us.
-
-Reported-by: Kees Cook <keescook@chromium.org>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- crypto/asymmetric_keys/x509_public_key.c | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index b7c81d8..eb368d4 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -119,6 +119,17 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
-
- pr_devel("Cert Issuer: %s\n", cert->issuer);
- pr_devel("Cert Subject: %s\n", cert->subject);
-+
-+ if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
-+ cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
-+ cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
-+ !pkey_algo[cert->pub->pkey_algo] ||
-+ !pkey_algo[cert->sig.pkey_algo] ||
-+ !pkey_hash_algo_name[cert->sig.pkey_hash_algo]) {
-+ ret = -ENOPKG;
-+ goto error_free_cert;
-+ }
-+
- pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]);
- pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n",
- cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1,
---
-1.8.3.1
-
-
-From f78f0e8694517a3b1e5393d6ea0d46084bdc816a Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:18:31 +0100
-Subject: [PATCH 09/18] X.509: Handle certificates that lack an
- authorityKeyIdentifier field
-
-Handle certificates that lack an authorityKeyIdentifier field by assuming
-they're self-signed and checking their signatures against themselves.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
-Reviewed-by: Josh Boyer <jwboyer@redhat.com>
----
- crypto/asymmetric_keys/x509_public_key.c | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index eb368d4..0f55e3b 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -143,8 +143,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- pkey_algo_name[cert->sig.pkey_algo],
- pkey_hash_algo_name[cert->sig.pkey_hash_algo]);
-
-- if (!cert->fingerprint || !cert->authority) {
-- pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n",
-+ if (!cert->fingerprint) {
-+ pr_warn("Cert for '%s' must have a SubjKeyId extension\n",
- cert->subject);
- ret = -EKEYREJECTED;
- goto error_free_cert;
-@@ -190,8 +190,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
- cert->pub->id_type = PKEY_ID_X509;
-
-- /* Check the signature on the key */
-- if (strcmp(cert->fingerprint, cert->authority) == 0) {
-+ /* Check the signature on the key if it appears to be self-signed */
-+ if (!cert->authority ||
-+ strcmp(cert->fingerprint, cert->authority) == 0) {
- ret = x509_check_signature(cert->pub, cert);
- if (ret < 0)
- goto error_free_cert;
---
-1.8.3.1
-
-
-From 33f859fea67ab5307da4049e947fbc23cdd13a27 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:07:13 +0100
-Subject: [PATCH 11/18] KEYS: Load *.x509 files into kernel keyring
-
-Load all the files matching the pattern "*.x509" that are to be found in kernel
-base source dir and base build dir into the module signing keyring.
-
-The "extra_certificates" file is then redundant.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/Makefile | 35 +++++++++++++++++++++++++++++------
- kernel/modsign_certificate.S | 3 +--
- 2 files changed, 30 insertions(+), 8 deletions(-)
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 1ce4755..c34e5f9 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -142,17 +142,40 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
- $(call if_changed,bc)
-
- ifeq ($(CONFIG_MODULE_SIG),y)
-+###############################################################################
- #
--# Pull the signing certificate and any extra certificates into the kernel
-+# Roll all the X.509 certificates that we can find together and pull
-+# them into the kernel.
- #
-+###############################################################################
-+X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
-+X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
-+X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y))
-+
-+ifeq ($(X509_CERTIFICATES),)
-+$(warning *** No X.509 certificates found ***)
-+endif
-+
-+ifneq ($(wildcard $(obj)/.x509.list),)
-+ifneq ($(shell cat $(obj)/.x509.list),$(X509_CERTIFICATES))
-+$(info X.509 certificate list changed)
-+$(shell rm $(obj)/.x509.list)
-+endif
-+endif
-+
-+kernel/modsign_certificate.o: $(obj)/x509_certificate_list
-
--quiet_cmd_touch = TOUCH $@
-- cmd_touch = touch $@
-+quiet_cmd_x509certs = CERTS $@
-+ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@
-+targets += $(obj)/x509_certificate_list
-+$(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
-+ $(call if_changed,x509certs)
-
--extra_certificates:
-- $(call cmd,touch)
-+targets += $(obj)/.x509.list
-+$(obj)/.x509.list:
-+ @echo $(X509_CERTIFICATES) >$@
-
--kernel/modsign_certificate.o: signing_key.x509 extra_certificates
-+clean-files := x509_certificate_list .x509.list
-
- ###############################################################################
- #
-diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S
-index 4a9a86d..6fe03c7 100644
---- a/kernel/modsign_certificate.S
-+++ b/kernel/modsign_certificate.S
-@@ -7,6 +7,5 @@
- .section ".init.data","aw"
-
- GLOBAL(modsign_certificate_list)
-- .incbin "signing_key.x509"
-- .incbin "extra_certificates"
-+ .incbin "kernel/x509_certificate_list"
- GLOBAL(modsign_certificate_list_end)
---
-1.8.3.1
-
-
-From 068606ba7df3206e5a09b544b4b89ed09cd30f44 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 17:13:15 +0100
-Subject: [PATCH 12/18] KEYS: Have make canonicalise the paths of the X.509
- certs better to deduplicate
-
-Have make canonicalise the paths of the X.509 certificates before we sort them
-as this allows $(sort) to better remove duplicates.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/Makefile | 12 +++++++++---
- 1 file changed, 9 insertions(+), 3 deletions(-)
-
-diff --git a/kernel/Makefile b/kernel/Makefile
-index c34e5f9..2c24195 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -144,13 +144,19 @@ $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
- ifeq ($(CONFIG_MODULE_SIG),y)
- ###############################################################################
- #
--# Roll all the X.509 certificates that we can find together and pull
--# them into the kernel.
-+# Roll all the X.509 certificates that we can find together and pull them into
-+# the kernel.
-+#
-+# We look in the source root and the build root for all files whose name ends
-+# in ".x509". Unfortunately, this will generate duplicate filenames, so we
-+# have make canonicalise the pathnames and then sort them to discard the
-+# duplicates.
- #
- ###############################################################################
- X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
- X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
--X509_CERTIFICATES := $(sort $(X509_CERTIFICATES-y))
-+X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
-+ $(or $(realpath $(CERT)),$(CERT))))
-
- ifeq ($(X509_CERTIFICATES),)
- $(warning *** No X.509 certificates found ***)
---
-1.8.3.1
-
-
-From 9006cfbd669e9ba52d1a91db2ffd9482ad8a6090 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:07:30 +0100
-Subject: [PATCH 13/18] KEYS: Separate the kernel signature checking keyring
- from module signing
-
-Separate the kernel signature checking keyring from module signing so that it
-can be used by code other than the module-signing code.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- include/keys/system_keyring.h | 23 ++++++++++
- init/Kconfig | 13 ++++++
- kernel/Makefile | 15 ++++--
- kernel/modsign_certificate.S | 11 -----
- kernel/modsign_pubkey.c | 104 ------------------------------------------
- kernel/module-internal.h | 2 -
- kernel/module_signing.c | 3 +-
- kernel/system_certificates.S | 11 +++++
- kernel/system_keyring.c | 103 +++++++++++++++++++++++++++++++++++++++++
- 9 files changed, 162 insertions(+), 123 deletions(-)
- create mode 100644 include/keys/system_keyring.h
- delete mode 100644 kernel/modsign_certificate.S
- delete mode 100644 kernel/modsign_pubkey.c
- create mode 100644 kernel/system_certificates.S
- create mode 100644 kernel/system_keyring.c
-
-diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
-new file mode 100644
-index 0000000..8dabc39
---- /dev/null
-+++ b/include/keys/system_keyring.h
-@@ -0,0 +1,23 @@
-+/* System keyring containing trusted public keys.
-+ *
-+ * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#ifndef _KEYS_SYSTEM_KEYRING_H
-+#define _KEYS_SYSTEM_KEYRING_H
-+
-+#ifdef CONFIG_SYSTEM_TRUSTED_KEYRING
-+
-+#include <linux/key.h>
-+
-+extern struct key *system_trusted_keyring;
-+
-+#endif
-+
-+#endif /* _KEYS_SYSTEM_KEYRING_H */
-diff --git a/init/Kconfig b/init/Kconfig
-index 18bd9e3..cf14d07 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1668,6 +1668,18 @@ config BASE_SMALL
- default 0 if BASE_FULL
- default 1 if !BASE_FULL
-
-+config SYSTEM_TRUSTED_KEYRING
-+ bool "Provide system-wide ring of trusted keys"
-+ depends on KEYS
-+ help
-+ Provide a system keyring to which trusted keys can be added. Keys in
-+ the keyring are considered to be trusted. Keys may be added at will
-+ by the kernel from compiled-in data and from hardware key stores, but
-+ userspace may only add extra keys if those keys can be verified by
-+ keys already in the keyring.
-+
-+ Keys in this keyring are used by module signature checking.
-+
- menuconfig MODULES
- bool "Enable loadable module support"
- option modules
-@@ -1741,6 +1753,7 @@ config MODULE_SRCVERSION_ALL
- config MODULE_SIG
- bool "Module signature verification"
- depends on MODULES
-+ select SYSTEM_TRUSTED_KEYRING
- select KEYS
- select CRYPTO
- select ASYMMETRIC_KEY_TYPE
-diff --git a/kernel/Makefile b/kernel/Makefile
-index 2c24195..6313698 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -54,8 +54,9 @@ obj-$(CONFIG_SMP) += spinlock.o
- obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
- obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
- obj-$(CONFIG_UID16) += uid16.o
-+obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
- obj-$(CONFIG_MODULES) += module.o
--obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o
-+obj-$(CONFIG_MODULE_SIG) += module_signing.o
- obj-$(CONFIG_KALLSYMS) += kallsyms.o
- obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
- obj-$(CONFIG_KEXEC) += kexec.o
-@@ -141,11 +142,11 @@ targets += timeconst.h
- $(obj)/timeconst.h: $(obj)/hz.bc $(src)/timeconst.bc FORCE
- $(call if_changed,bc)
-
--ifeq ($(CONFIG_MODULE_SIG),y)
- ###############################################################################
- #
- # Roll all the X.509 certificates that we can find together and pull them into
--# the kernel.
-+# the kernel so that they get loaded into the system trusted keyring during
-+# boot.
- #
- # We look in the source root and the build root for all files whose name ends
- # in ".x509". Unfortunately, this will generate duplicate filenames, so we
-@@ -153,6 +154,7 @@ ifeq ($(CONFIG_MODULE_SIG),y)
- # duplicates.
- #
- ###############################################################################
-+ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y)
- X509_CERTIFICATES-y := $(wildcard *.x509) $(wildcard $(srctree)/*.x509)
- X509_CERTIFICATES-$(CONFIG_MODULE_SIG) += signing_key.x509
- X509_CERTIFICATES := $(sort $(foreach CERT,$(X509_CERTIFICATES-y), \
-@@ -169,10 +171,11 @@ $(shell rm $(obj)/.x509.list)
- endif
- endif
-
--kernel/modsign_certificate.o: $(obj)/x509_certificate_list
-+kernel/system_certificates.o: $(obj)/x509_certificate_list
-
- quiet_cmd_x509certs = CERTS $@
-- cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@
-+ cmd_x509certs = cat $(X509_CERTIFICATES) /dev/null >$@ $(foreach X509,$(X509_CERTIFICATES),; echo " - Including cert $(X509)")
-+
- targets += $(obj)/x509_certificate_list
- $(obj)/x509_certificate_list: $(X509_CERTIFICATES) $(obj)/.x509.list
- $(call if_changed,x509certs)
-@@ -182,7 +185,9 @@ $(obj)/.x509.list:
- @echo $(X509_CERTIFICATES) >$@
-
- clean-files := x509_certificate_list .x509.list
-+endif
-
-+ifeq ($(CONFIG_MODULE_SIG),y)
- ###############################################################################
- #
- # If module signing is requested, say by allyesconfig, but a key has not been
-diff --git a/kernel/modsign_certificate.S b/kernel/modsign_certificate.S
-deleted file mode 100644
-index 6fe03c7..0000000
---- a/kernel/modsign_certificate.S
-+++ /dev/null
-@@ -1,11 +0,0 @@
--#include <linux/export.h>
--
--#define GLOBAL(name) \
-- .globl VMLINUX_SYMBOL(name); \
-- VMLINUX_SYMBOL(name):
--
-- .section ".init.data","aw"
--
--GLOBAL(modsign_certificate_list)
-- .incbin "kernel/x509_certificate_list"
--GLOBAL(modsign_certificate_list_end)
-diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
-deleted file mode 100644
-index 7cbd450..0000000
---- a/kernel/modsign_pubkey.c
-+++ /dev/null
-@@ -1,104 +0,0 @@
--/* Public keys for module signature verification
-- *
-- * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-- * Written by David Howells (dhowells@redhat.com)
-- *
-- * This program is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU General Public Licence
-- * as published by the Free Software Foundation; either version
-- * 2 of the Licence, or (at your option) any later version.
-- */
--
--#include <linux/kernel.h>
--#include <linux/sched.h>
--#include <linux/cred.h>
--#include <linux/err.h>
--#include <keys/asymmetric-type.h>
--#include "module-internal.h"
--
--struct key *modsign_keyring;
--
--extern __initconst const u8 modsign_certificate_list[];
--extern __initconst const u8 modsign_certificate_list_end[];
--
--/*
-- * We need to make sure ccache doesn't cache the .o file as it doesn't notice
-- * if modsign.pub changes.
-- */
--static __initconst const char annoy_ccache[] = __TIME__ "foo";
--
--/*
-- * Load the compiled-in keys
-- */
--static __init int module_verify_init(void)
--{
-- pr_notice("Initialise module verification\n");
--
-- modsign_keyring = keyring_alloc(".module_sign",
-- KUIDT_INIT(0), KGIDT_INIT(0),
-- current_cred(),
-- ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-- KEY_USR_VIEW | KEY_USR_READ),
-- KEY_ALLOC_NOT_IN_QUOTA, NULL);
-- if (IS_ERR(modsign_keyring))
-- panic("Can't allocate module signing keyring\n");
--
-- return 0;
--}
--
--/*
-- * Must be initialised before we try and load the keys into the keyring.
-- */
--device_initcall(module_verify_init);
--
--/*
-- * Load the compiled-in keys
-- */
--static __init int load_module_signing_keys(void)
--{
-- key_ref_t key;
-- const u8 *p, *end;
-- size_t plen;
--
-- pr_notice("Loading module verification certificates\n");
--
-- end = modsign_certificate_list_end;
-- p = modsign_certificate_list;
-- while (p < end) {
-- /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
-- * than 256 bytes in size.
-- */
-- if (end - p < 4)
-- goto dodgy_cert;
-- if (p[0] != 0x30 &&
-- p[1] != 0x82)
-- goto dodgy_cert;
-- plen = (p[2] << 8) | p[3];
-- plen += 4;
-- if (plen > end - p)
-- goto dodgy_cert;
--
-- key = key_create_or_update(make_key_ref(modsign_keyring, 1),
-- "asymmetric",
-- NULL,
-- p,
-- plen,
-- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-- KEY_USR_VIEW,
-- KEY_ALLOC_NOT_IN_QUOTA);
-- if (IS_ERR(key))
-- pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n",
-- PTR_ERR(key));
-- else
-- pr_notice("MODSIGN: Loaded cert '%s'\n",
-- key_ref_to_ptr(key)->description);
-- p += plen;
-- }
--
-- return 0;
--
--dodgy_cert:
-- pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n");
-- return 0;
--}
--late_initcall(load_module_signing_keys);
-diff --git a/kernel/module-internal.h b/kernel/module-internal.h
-index 24f9247..915e123 100644
---- a/kernel/module-internal.h
-+++ b/kernel/module-internal.h
-@@ -9,6 +9,4 @@
- * 2 of the Licence, or (at your option) any later version.
- */
-
--extern struct key *modsign_keyring;
--
- extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
-diff --git a/kernel/module_signing.c b/kernel/module_signing.c
-index ee47640..0b6b870 100644
---- a/kernel/module_signing.c
-+++ b/kernel/module_signing.c
-@@ -14,6 +14,7 @@
- #include <crypto/public_key.h>
- #include <crypto/hash.h>
- #include <keys/asymmetric-type.h>
-+#include <keys/system_keyring.h>
- #include "module-internal.h"
-
- /*
-@@ -157,7 +158,7 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
-
- pr_debug("Look up: \"%s\"\n", id);
-
-- key = keyring_search(make_key_ref(modsign_keyring, 1),
-+ key = keyring_search(make_key_ref(system_trusted_keyring, 1),
- &key_type_asymmetric, id);
- if (IS_ERR(key))
- pr_warn("Request for unknown module key '%s' err %ld\n",
-diff --git a/kernel/system_certificates.S b/kernel/system_certificates.S
-new file mode 100644
-index 0000000..5cffe86
---- /dev/null
-+++ b/kernel/system_certificates.S
-@@ -0,0 +1,11 @@
-+#include <linux/export.h>
-+
-+#define GLOBAL(name) \
-+ .globl VMLINUX_SYMBOL(name); \
-+ VMLINUX_SYMBOL(name):
-+
-+ .section ".init.data","aw"
-+
-+GLOBAL(system_certificate_list)
-+ .incbin "kernel/x509_certificate_list"
-+GLOBAL(system_certificate_list_end)
-diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
-new file mode 100644
-index 0000000..51c3514
---- /dev/null
-+++ b/kernel/system_keyring.c
-@@ -0,0 +1,103 @@
-+/* System trusted keyring for trusted public keys
-+ *
-+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
-+ * Written by David Howells (dhowells@redhat.com)
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public Licence
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the Licence, or (at your option) any later version.
-+ */
-+
-+#include <linux/export.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/cred.h>
-+#include <linux/err.h>
-+#include <keys/asymmetric-type.h>
-+#include <keys/system_keyring.h>
-+#include "module-internal.h"
-+
-+struct key *system_trusted_keyring;
-+EXPORT_SYMBOL_GPL(system_trusted_keyring);
-+
-+extern __initconst const u8 system_certificate_list[];
-+extern __initconst const u8 system_certificate_list_end[];
-+
-+/*
-+ * Load the compiled-in keys
-+ */
-+static __init int system_trusted_keyring_init(void)
-+{
-+ pr_notice("Initialise system trusted keyring\n");
-+
-+ system_trusted_keyring =
-+ keyring_alloc(".system_keyring",
-+ KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
-+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+ KEY_USR_VIEW | KEY_USR_READ),
-+ KEY_ALLOC_NOT_IN_QUOTA, NULL);
-+ if (IS_ERR(system_trusted_keyring))
-+ panic("Can't allocate system trusted keyring\n");
-+
-+ return 0;
-+}
-+
-+/*
-+ * Must be initialised before we try and load the keys into the keyring.
-+ */
-+device_initcall(system_trusted_keyring_init);
-+
-+/*
-+ * Load the compiled-in list of X.509 certificates.
-+ */
-+static __init int load_system_certificate_list(void)
-+{
-+ key_ref_t key;
-+ const u8 *p, *end;
-+ size_t plen;
-+
-+ pr_notice("Loading compiled-in X.509 certificates\n");
-+
-+ end = system_certificate_list_end;
-+ p = system_certificate_list;
-+ while (p < end) {
-+ /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
-+ * than 256 bytes in size.
-+ */
-+ if (end - p < 4)
-+ goto dodgy_cert;
-+ if (p[0] != 0x30 &&
-+ p[1] != 0x82)
-+ goto dodgy_cert;
-+ plen = (p[2] << 8) | p[3];
-+ plen += 4;
-+ if (plen > end - p)
-+ goto dodgy_cert;
-+
-+ key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
-+ "asymmetric",
-+ NULL,
-+ p,
-+ plen,
-+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+ KEY_USR_VIEW,
-+ KEY_ALLOC_NOT_IN_QUOTA);
-+ if (IS_ERR(key)) {
-+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
-+ PTR_ERR(key));
-+ } else {
-+ pr_notice("Loaded X.509 cert '%s'\n",
-+ key_ref_to_ptr(key)->description);
-+ key_ref_put(key);
-+ }
-+ p += plen;
-+ }
-+
-+ return 0;
-+
-+dodgy_cert:
-+ pr_err("Problem parsing in-kernel X.509 certificate list\n");
-+ return 0;
-+}
-+late_initcall(load_system_certificate_list);
---
-1.8.3.1
-
-
-From c0522b3236c27359bd61fee0f0b74be9f8e2ad60 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Fri, 30 Aug 2013 16:07:37 +0100
-Subject: [PATCH 14/18] KEYS: Add a 'trusted' flag and a 'trusted only' flag
-
-Add KEY_FLAG_TRUSTED to indicate that a key either comes from a trusted source
-or had a cryptographic signature chain that led back to a trusted key the
-kernel already possessed.
-
-Add KEY_FLAGS_TRUSTED_ONLY to indicate that a keyring will only accept links to
-keys marked with KEY_FLAGS_TRUSTED.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
-Reviewed-by: Kees Cook <keescook@chromium.org>
----
- include/linux/key-type.h | 1 +
- include/linux/key.h | 3 +++
- kernel/system_keyring.c | 4 +++-
- security/keys/key.c | 8 ++++++++
- security/keys/keyring.c | 4 ++++
- 5 files changed, 19 insertions(+), 1 deletion(-)
-
-diff --git a/include/linux/key-type.h b/include/linux/key-type.h
-index f58737b..a74c3a8 100644
---- a/include/linux/key-type.h
-+++ b/include/linux/key-type.h
-@@ -45,6 +45,7 @@ struct key_preparsed_payload {
- const void *data; /* Raw data */
- size_t datalen; /* Raw datalen */
- size_t quotalen; /* Quota length for proposed payload */
-+ bool trusted; /* True if key is trusted */
- };
-
- typedef int (*request_key_actor_t)(struct key_construction *key,
-diff --git a/include/linux/key.h b/include/linux/key.h
-index 010dbb6..80d6774 100644
---- a/include/linux/key.h
-+++ b/include/linux/key.h
-@@ -168,6 +168,8 @@ struct key {
- #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */
- #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */
- #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
-+#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */
-+#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */
-
- /* the key type and key description string
- * - the desc is used to match a key against search criteria
-@@ -218,6 +220,7 @@ extern struct key *key_alloc(struct key_type *type,
- #define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */
- #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
- #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
-+#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
-
- extern void key_revoke(struct key *key);
- extern void key_invalidate(struct key *key);
-diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
-index 51c3514..5296721 100644
---- a/kernel/system_keyring.c
-+++ b/kernel/system_keyring.c
-@@ -40,6 +40,7 @@ static __init int system_trusted_keyring_init(void)
- if (IS_ERR(system_trusted_keyring))
- panic("Can't allocate system trusted keyring\n");
-
-+ set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
- return 0;
- }
-
-@@ -82,7 +83,8 @@ static __init int load_system_certificate_list(void)
- plen,
- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW,
-- KEY_ALLOC_NOT_IN_QUOTA);
-+ KEY_ALLOC_NOT_IN_QUOTA |
-+ KEY_ALLOC_TRUSTED);
- if (IS_ERR(key)) {
- pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
- PTR_ERR(key));
-diff --git a/security/keys/key.c b/security/keys/key.c
-index a819b5c..d331ea9 100644
---- a/security/keys/key.c
-+++ b/security/keys/key.c
-@@ -300,6 +300,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
-
- if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
- key->flags |= 1 << KEY_FLAG_IN_QUOTA;
-+ if (flags & KEY_ALLOC_TRUSTED)
-+ key->flags |= 1 << KEY_FLAG_TRUSTED;
-
- memset(&key->type_data, 0, sizeof(key->type_data));
-
-@@ -813,6 +815,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- prep.data = payload;
- prep.datalen = plen;
- prep.quotalen = index_key.type->def_datalen;
-+ prep.trusted = flags & KEY_ALLOC_TRUSTED;
- if (index_key.type->preparse) {
- ret = index_key.type->preparse(&prep);
- if (ret < 0) {
-@@ -827,6 +830,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
- }
- index_key.desc_len = strlen(index_key.description);
-
-+ key_ref = ERR_PTR(-EPERM);
-+ if (!prep.trusted && test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags))
-+ goto error_free_prep;
-+ flags |= prep.trusted ? KEY_ALLOC_TRUSTED : 0;
-+
- ret = __key_link_begin(keyring, &index_key, &edit);
- if (ret < 0) {
- key_ref = ERR_PTR(ret);
-diff --git a/security/keys/keyring.c b/security/keys/keyring.c
-index f7cdea2..9b6f6e0 100644
---- a/security/keys/keyring.c
-+++ b/security/keys/keyring.c
-@@ -1183,6 +1183,10 @@ int key_link(struct key *keyring, struct key *key)
- key_check(keyring);
- key_check(key);
-
-+ if (test_bit(KEY_FLAG_TRUSTED_ONLY, &keyring->flags) &&
-+ !test_bit(KEY_FLAG_TRUSTED, &key->flags))
-+ return -EPERM;
-+
- ret = __key_link_begin(keyring, &key->index_key, &edit);
- if (ret == 0) {
- kdebug("begun {%d,%d}", keyring->serial, atomic_read(&keyring->usage));
---
-1.8.3.1
-
-
-From e8e9a6af1d2de6aca01751ccaf0475ed46f9bdb2 Mon Sep 17 00:00:00 2001
-From: David Howells <dhowells@redhat.com>
-Date: Wed, 4 Sep 2013 19:28:03 +0100
-Subject: [PATCH 15/18] KEYS: Set the asymmetric-key type default search method
-
-The keyring expansion patches introduces a new search method by which
-key_search() attempts to walk directly to the key that has exactly the same
-description as the requested one.
-
-However, this causes inexact matching of asymmetric keys to fail. The
-solution to this is to select iterative rather than direct search as the
-default search type for asymmetric keys.
-
-As an example, the kernel might have a key like this:
-
- Magrathea: Glacier signing key: 6a2a0f82bad7e396665f465e4e3e1f9bd24b1226
-
-and:
-
- keyctl search <keyring-ID> asymmetric id:d24b1226
-
-should find the key, despite that not being its exact description.
-
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- crypto/asymmetric_keys/asymmetric_type.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
-index cf80765..b77eb53 100644
---- a/crypto/asymmetric_keys/asymmetric_type.c
-+++ b/crypto/asymmetric_keys/asymmetric_type.c
-@@ -209,6 +209,7 @@ struct key_type key_type_asymmetric = {
- .match = asymmetric_key_match,
- .destroy = asymmetric_key_destroy,
- .describe = asymmetric_key_describe,
-+ .def_lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE,
- };
- EXPORT_SYMBOL_GPL(key_type_asymmetric);
-
---
-1.8.3.1
-
-
-From dfb7781ebba28004f95f7af4e039d8b44697c87c Mon Sep 17 00:00:00 2001
-From: Mimi Zohar <zohar@linux.vnet.ibm.com>
-Date: Tue, 20 Aug 2013 14:36:26 -0400
-Subject: [PATCH 16/18] KEYS: Make the system 'trusted' keyring viewable by
- userspace
-
-Give the root user the ability to read the system keyring and put read
-permission on the trusted keys added during boot. The latter is actually more
-theoretical than real for the moment as asymmetric keys do not currently
-provide a read operation.
-
-Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- kernel/system_keyring.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
-index 5296721..564dd93 100644
---- a/kernel/system_keyring.c
-+++ b/kernel/system_keyring.c
-@@ -35,7 +35,7 @@ static __init int system_trusted_keyring_init(void)
- keyring_alloc(".system_keyring",
- KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
- ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-- KEY_USR_VIEW | KEY_USR_READ),
-+ KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
- KEY_ALLOC_NOT_IN_QUOTA, NULL);
- if (IS_ERR(system_trusted_keyring))
- panic("Can't allocate system trusted keyring\n");
-@@ -81,8 +81,8 @@ static __init int load_system_certificate_list(void)
- NULL,
- p,
- plen,
-- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-- KEY_USR_VIEW,
-+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-+ KEY_USR_VIEW | KEY_USR_READ),
- KEY_ALLOC_NOT_IN_QUOTA |
- KEY_ALLOC_TRUSTED);
- if (IS_ERR(key)) {
---
-1.8.3.1
-
-
-From 052744b12209e66ede2a04ec31b9bb7ff40bbc9a Mon Sep 17 00:00:00 2001
-From: Mimi Zohar <zohar@linux.vnet.ibm.com>
-Date: Tue, 20 Aug 2013 14:36:27 -0400
-Subject: [PATCH 17/18] KEYS: verify a certificate is signed by a 'trusted' key
-
-Only public keys, with certificates signed by an existing
-'trusted' key on the system trusted keyring, should be added
-to a trusted keyring. This patch adds support for verifying
-a certificate's signature.
-
-This is derived from David Howells pkcs7_request_asymmetric_key() patch.
-
-Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- crypto/asymmetric_keys/x509_public_key.c | 81 +++++++++++++++++++++++++++++++-
- 1 file changed, 80 insertions(+), 1 deletion(-)
-
-diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
-index c1540e8..8761264 100644
---- a/crypto/asymmetric_keys/x509_public_key.c
-+++ b/crypto/asymmetric_keys/x509_public_key.c
-@@ -18,12 +18,60 @@
- #include <linux/asn1_decoder.h>
- #include <keys/asymmetric-subtype.h>
- #include <keys/asymmetric-parser.h>
-+#include <keys/system_keyring.h>
- #include <crypto/hash.h>
- #include "asymmetric_keys.h"
- #include "public_key.h"
- #include "x509_parser.h"
-
- /*
-+ * Find a key in the given keyring by issuer and authority.
-+ */
-+static struct key *x509_request_asymmetric_key(
-+ struct key *keyring,
-+ const char *signer, size_t signer_len,
-+ const char *authority, size_t auth_len)
-+{
-+ key_ref_t key;
-+ char *id;
-+
-+ /* Construct an identifier. */
-+ id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL);
-+ if (!id)
-+ return ERR_PTR(-ENOMEM);
-+
-+ memcpy(id, signer, signer_len);
-+ id[signer_len + 0] = ':';
-+ id[signer_len + 1] = ' ';
-+ memcpy(id + signer_len + 2, authority, auth_len);
-+ id[signer_len + 2 + auth_len] = 0;
-+
-+ pr_debug("Look up: \"%s\"\n", id);
-+
-+ key = keyring_search(make_key_ref(keyring, 1),
-+ &key_type_asymmetric, id);
-+ if (IS_ERR(key))
-+ pr_debug("Request for module key '%s' err %ld\n",
-+ id, PTR_ERR(key));
-+ kfree(id);
-+
-+ if (IS_ERR(key)) {
-+ switch (PTR_ERR(key)) {
-+ /* Hide some search errors */
-+ case -EACCES:
-+ case -ENOTDIR:
-+ case -EAGAIN:
-+ return ERR_PTR(-ENOKEY);
-+ default:
-+ return ERR_CAST(key);
-+ }
-+ }
-+
-+ pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
-+ return key_ref_to_ptr(key);
-+}
-+
-+/*
- * Set up the signature parameters in an X.509 certificate. This involves
- * digesting the signed data and extracting the signature.
- */
-@@ -103,6 +151,33 @@ int x509_check_signature(const struct public_key *pub,
- EXPORT_SYMBOL_GPL(x509_check_signature);
-
- /*
-+ * Check the new certificate against the ones in the trust keyring. If one of
-+ * those is the signing key and validates the new certificate, then mark the
-+ * new certificate as being trusted.
-+ *
-+ * Return 0 if the new certificate was successfully validated, 1 if we couldn't
-+ * find a matching parent certificate in the trusted list and an error if there
-+ * is a matching certificate but the signature check fails.
-+ */
-+static int x509_validate_trust(struct x509_certificate *cert,
-+ struct key *trust_keyring)
-+{
-+ const struct public_key *pk;
-+ struct key *key;
-+ int ret = 1;
-+
-+ key = x509_request_asymmetric_key(trust_keyring,
-+ cert->issuer, strlen(cert->issuer),
-+ cert->authority,
-+ strlen(cert->authority));
-+ if (!IS_ERR(key)) {
-+ pk = key->payload.data;
-+ ret = x509_check_signature(pk, cert);
-+ }
-+ return ret;
-+}
-+
-+/*
- * Attempt to parse a data blob for a key as an X509 certificate.
- */
- static int x509_key_preparse(struct key_preparsed_payload *prep)
-@@ -155,9 +230,13 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
- /* Check the signature on the key if it appears to be self-signed */
- if (!cert->authority ||
- strcmp(cert->fingerprint, cert->authority) == 0) {
-- ret = x509_check_signature(cert->pub, cert);
-+ ret = x509_check_signature(cert->pub, cert); /* self-signed */
- if (ret < 0)
- goto error_free_cert;
-+ } else {
-+ ret = x509_validate_trust(cert, system_trusted_keyring);
-+ if (!ret)
-+ prep->trusted = 1;
- }
-
- /* Propose a description */
---
-1.8.3.1
-
-
-From 8b39d9a6d9f805f6a2e837bf8b9595f701ea4a1c Mon Sep 17 00:00:00 2001
-From: Mimi Zohar <zohar@linux.vnet.ibm.com>
-Date: Wed, 4 Sep 2013 13:26:22 +0100
-Subject: [PATCH 18/18] KEYS: initialize root uid and session keyrings early
-
-In order to create the integrity keyrings (eg. _evm, _ima), root's
-uid and session keyrings need to be initialized early.
-
-Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
-Signed-off-by: David Howells <dhowells@redhat.com>
----
- security/keys/process_keys.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
-index 68548ea..0cf8a13 100644
---- a/security/keys/process_keys.c
-+++ b/security/keys/process_keys.c
-@@ -857,3 +857,13 @@ void key_change_session_keyring(struct callback_head *twork)
-
- commit_creds(new);
- }
-+
-+/*
-+ * Make sure that root's user and user-session keyrings exist.
-+ */
-+static int __init init_root_keyring(void)
-+{
-+ return install_user_keyrings();
-+}
-+
-+late_initcall(init_root_keyring);
---
-1.8.3.1
-
diff --git a/lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch b/lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch
new file mode 100644
index 000000000..7cc9d9ee3
--- /dev/null
+++ b/lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch
@@ -0,0 +1,63 @@
+Bugzilla: 1074235
+Upstream-status: 3.15 and CC'd to stable
+
+From e39435ce68bb4685288f78b1a7e24311f7ef939f Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@fb.com>
+Date: Tue, 8 Apr 2014 16:04:12 -0700
+Subject: [PATCH] lib/percpu_counter.c: fix bad percpu counter state during
+ suspend
+
+I got a bug report yesterday from Laszlo Ersek in which he states that
+his kvm instance fails to suspend. Laszlo bisected it down to this
+commit 1cf7e9c68fe8 ("virtio_blk: blk-mq support") where virtio-blk is
+converted to use the blk-mq infrastructure.
+
+After digging a bit, it became clear that the issue was with the queue
+drain. blk-mq tracks queue usage in a percpu counter, which is
+incremented on request alloc and decremented when the request is freed.
+The initial hunt was for an inconsistency in blk-mq, but everything
+seemed fine. In fact, the counter only returned crazy values when
+suspend was in progress.
+
+When a CPU is unplugged, the percpu counters merges that CPU state with
+the general state. blk-mq takes care to register a hotcpu notifier with
+the appropriate priority, so we know it runs after the percpu counter
+notifier. However, the percpu counter notifier only merges the state
+when the CPU is fully gone. This leaves a state transition where the
+CPU going away is no longer in the online mask, yet it still holds
+private values. This means that in this state, percpu_counter_sum()
+returns invalid results, and the suspend then hangs waiting for
+abs(dead-cpu-value) requests to complete which of course will never
+happen.
+
+Fix this by clearing the state earlier, so we never have a case where
+the CPU isn't in online mask but still holds private state. This bug
+has been there since forever, I guess we don't have a lot of users where
+percpu counters needs to be reliable during the suspend cycle.
+
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Reported-by: Laszlo Ersek <lersek@redhat.com>
+Tested-by: Laszlo Ersek <lersek@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+---
+ lib/percpu_counter.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
+index 8280a5dd1727..7dd33577b905 100644
+--- a/lib/percpu_counter.c
++++ b/lib/percpu_counter.c
+@@ -169,7 +169,7 @@ static int percpu_counter_hotcpu_callback(struct notifier_block *nb,
+ struct percpu_counter *fbc;
+
+ compute_batch_value();
+- if (action != CPU_DEAD)
++ if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
+ return NOTIFY_OK;
+
+ cpu = (unsigned long)hcpu;
+--
+1.8.5.3
+
diff --git a/makefile-after_link.patch b/makefile-after_link.patch
index 8332afb79..23406fc95 100644
--- a/makefile-after_link.patch
+++ b/makefile-after_link.patch
@@ -1,3 +1,6 @@
+Bugzilla: N/A
+Upstream-status: ??
+
From b707aea6a4947c3806ced2c23e889943a0f36876 Mon Sep 17 00:00:00 2001
From: Roland McGrath <roland@redhat.com>
Date: Mon, 6 Oct 2008 23:03:03 -0700
@@ -8,17 +11,18 @@ after each final link. This includes vmlinux itself and vDSO images.
Signed-off-by: Roland McGrath <roland@redhat.com>
+
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
-index d8064af..04dcfe1 100644
+index 6d20b7d..863a01b 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -48,7 +48,8 @@ $(obj-vdso): %.o: %.S
# Actual build commands
quiet_cmd_vdsold = VDSOL $@
-- cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@
-+ cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@ \
-+ $(if $(AFTER_LINK),; $(AFTER_LINK))
+- cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
++ cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@ \
++ $(if $(AFTER_LINK),;$(AFTER_LINK))
quiet_cmd_vdsoas = VDSOA $@
cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
@@ -95,7 +99,7 @@ index fd14be1..1f3eb19 100644
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
GCOV_PROFILE := n
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
-index 0149949..e307cda 100644
+index 2dcb377..25e170e 100644
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -65,6 +65,10 @@ vmlinux_link()
diff --git a/modsign-uefi.patch b/modsign-uefi.patch
index 17009c196..d8e762cb7 100644
--- a/modsign-uefi.patch
+++ b/modsign-uefi.patch
@@ -1,4 +1,7 @@
-From 0a5e59dd7a921f20d77b13aa4e01392086ddbd12 Mon Sep 17 00:00:00 2001
+Bugzilla: N/A
+Upstream-status: Fedora mustard for now
+
+From 2b668e069365b608e855cf1f5edcf8caed0aaa4d Mon Sep 17 00:00:00 2001
From: Dave Howells <dhowells@redhat.com>
Date: Tue, 23 Oct 2012 09:30:54 -0400
Subject: [PATCH 1/5] Add EFI signature data types
@@ -12,10 +15,10 @@ Signed-off-by: David Howells <dhowells@redhat.com>
1 file changed, 20 insertions(+)
diff --git a/include/linux/efi.h b/include/linux/efi.h
-index eed2202..1da1b3c 100644
+index 0c1d367..de1faea 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
-@@ -389,6 +389,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
+@@ -394,6 +394,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
#define EFI_FILE_SYSTEM_GUID \
EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
@@ -28,7 +31,7 @@ index eed2202..1da1b3c 100644
typedef struct {
efi_guid_t guid;
u64 table;
-@@ -524,6 +530,20 @@ typedef struct {
+@@ -541,6 +547,20 @@ typedef struct _efi_file_io_interface {
#define EFI_INVALID_TABLE_ADDR (~0UL)
@@ -50,10 +53,10 @@ index eed2202..1da1b3c 100644
* All runtime access to EFI goes through this structure:
*/
--
-1.8.3.1
+1.8.4.2
-From 8b75428a7e1813cd3bc225a959e63d67898e4808 Mon Sep 17 00:00:00 2001
+From 42d75e3e3fe134cc274f765525031b764540a587 Mon Sep 17 00:00:00 2001
From: Dave Howells <dhowells@redhat.com>
Date: Tue, 23 Oct 2012 09:36:28 -0400
Subject: [PATCH 2/5] Add an EFI signature blob parser and key loader.
@@ -71,10 +74,10 @@ Signed-off-by: David Howells <dhowells@redhat.com>
create mode 100644 crypto/asymmetric_keys/efi_parser.c
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
-index 6d2c2ea..ace9c30 100644
+index 03a6eb9..6306ffc 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
-@@ -35,4 +35,12 @@ config X509_CERTIFICATE_PARSER
+@@ -37,4 +37,12 @@ config X509_CERTIFICATE_PARSER
data and provides the ability to instantiate a crypto key from a
public key packet found inside the certificate.
@@ -215,10 +218,10 @@ index 0000000..424896a
+ return 0;
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
-index 1da1b3c..42a1d25 100644
+index de1faea..13e1425 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
-@@ -619,6 +619,10 @@ extern int efi_set_rtc_mmss(const struct timespec *now);
+@@ -641,6 +641,10 @@ extern int efi_set_rtc_mmss(const struct timespec *now);
extern void efi_reserve_boot_services(void);
extern struct efi_memory_map memmap;
@@ -230,10 +233,10 @@ index 1da1b3c..42a1d25 100644
* efi_range_is_wc - check the WC bit on an address range
* @start: starting kvirt address
--
-1.8.3.1
+1.8.4.2
-From 920108c0f9cc5854dd329a5dfc904e91d40a4b26 Mon Sep 17 00:00:00 2001
+From d750dbcdcb3a712a2ea4ec57b9c9729c6a26b41d Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 26 Oct 2012 12:36:24 -0400
Subject: [PATCH 3/5] KEYS: Add a system blacklist keyring
@@ -267,10 +270,10 @@ index 8dabc39..e466de1 100644
#endif /* _KEYS_SYSTEM_KEYRING_H */
diff --git a/init/Kconfig b/init/Kconfig
-index 0ff5407..ba76e57 100644
+index 5236dc5..f59e6fe 100644
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -1680,6 +1680,15 @@ config SYSTEM_TRUSTED_KEYRING
+@@ -1673,6 +1673,15 @@ config SYSTEM_TRUSTED_KEYRING
Keys in this keyring are used by module signature checking.
@@ -287,7 +290,7 @@ index 0ff5407..ba76e57 100644
bool "Enable loadable module support"
option modules
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
-index 0b6b870..0a29b40 100644
+index be5b8fa..fed815f 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -158,6 +158,18 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
@@ -310,7 +313,7 @@ index 0b6b870..0a29b40 100644
&key_type_asymmetric, id);
if (IS_ERR(key))
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
-index 564dd93..389b50d 100644
+index 52ebc70..478c4f8 100644
--- a/kernel/system_keyring.c
+++ b/kernel/system_keyring.c
@@ -20,6 +20,9 @@
@@ -322,7 +325,7 @@ index 564dd93..389b50d 100644
+#endif
extern __initconst const u8 system_certificate_list[];
- extern __initconst const u8 system_certificate_list_end[];
+ extern __initconst const unsigned long system_certificate_list_size;
@@ -41,6 +44,20 @@ static __init int system_trusted_keyring_init(void)
panic("Can't allocate system trusted keyring\n");
@@ -345,10 +348,10 @@ index 564dd93..389b50d 100644
}
--
-1.8.3.1
+1.8.4.2
-From 69dca9998380c1931227a01205cdf23c34509753 Mon Sep 17 00:00:00 2001
+From c32beadd0d75fddcd75b700e4a75884d7a82e9bb Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 26 Oct 2012 12:42:16 -0400
Subject: [PATCH 4/5] MODSIGN: Import certificates from UEFI Secure Boot
@@ -376,10 +379,10 @@ Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
create mode 100644 kernel/modsign_uefi.c
diff --git a/include/linux/efi.h b/include/linux/efi.h
-index 42a1d25..d3e6036 100644
+index 13e1425..a7175eb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
-@@ -395,6 +395,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
+@@ -400,6 +400,12 @@ typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long si
#define EFI_CERT_X509_GUID \
EFI_GUID( 0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 )
@@ -393,10 +396,10 @@ index 42a1d25..d3e6036 100644
efi_guid_t guid;
u64 table;
diff --git a/init/Kconfig b/init/Kconfig
-index ba76e57..b09cd98 100644
+index f59e6fe..90fa75f 100644
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -1799,6 +1799,15 @@ config MODULE_SIG_ALL
+@@ -1792,6 +1792,15 @@ config MODULE_SIG_ALL
comment "Do not forget to sign required modules with scripts/sign-file"
depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL
@@ -413,10 +416,10 @@ index ba76e57..b09cd98 100644
prompt "Which hash algorithm should modules be signed with?"
depends on MODULE_SIG
diff --git a/kernel/Makefile b/kernel/Makefile
-index 6313698..cb35a89 100644
+index bc010ee..bee938f 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
-@@ -57,6 +57,7 @@ obj-$(CONFIG_UID16) += uid16.o
+@@ -44,6 +44,7 @@ obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_MODULE_SIG) += module_signing.o
@@ -424,7 +427,7 @@ index 6313698..cb35a89 100644
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
-@@ -115,6 +116,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
+@@ -96,6 +97,8 @@ obj-$(CONFIG_CONTEXT_TRACKING) += context_tracking.o
$(obj)/configs.o: $(obj)/config_data.h
@@ -532,10 +535,10 @@ index 0000000..94b0eb3
+}
+late_initcall(load_uefi_certs);
--
-1.8.3.1
+1.8.4.2
-From c8e6d256ddfa2182d5b011a4ab70f8c5c9b2b590 Mon Sep 17 00:00:00 2001
+From 5c86fc6c7e4d51286d75ee6d8ceedf983ae434fb Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Thu, 3 Oct 2013 10:14:23 -0400
Subject: [PATCH 5/5] MODSIGN: Support not importing certs from db
@@ -617,5 +620,5 @@ index 94b0eb3..ae28b97 100644
mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
--
-1.8.3.1
+1.8.4.2
diff --git a/nfs-check-gssd-running-before-krb5i-auth.patch b/nfs-check-gssd-running-before-krb5i-auth.patch
deleted file mode 100644
index 988fe6922..000000000
--- a/nfs-check-gssd-running-before-krb5i-auth.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-Bugzilla: N/A
-Upstream-status: queued in NFS git tree (for 3.13/3.14?)
-
-Currently, the client will attempt to use krb5i in the SETCLIENTID call
-even if rpc.gssd isn't running. When that fails, it'll then fall back to
-RPC_AUTH_UNIX. This introduced a delay when mounting if rpc.gssd isn't
-running, and causes warning messages to pop up in the ring buffer.
-
-Check to see if rpc.gssd is running before even attempting to use krb5i
-auth, and just silently skip trying to do so if it isn't. In the event
-that the admin is actually trying to mount with krb5*, it will still
-fail at a later stage of the mount attempt.
-
-Signed-off-by: Jeff Layton <jlayton@redhat.com>
-Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
----
- fs/nfs/nfs4client.c | 7 ++++++-
- 1 files changed, 6 insertions(+), 1 deletions(-)
-
-diff -up linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c.orig linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c
---- linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c.orig 2013-09-02 16:46:10.000000000 -0400
-+++ linux-3.11.9-200.fc19.x86_64/fs/nfs/nfs4client.c 2013-11-21 10:20:27.288286000 -0500
-@@ -10,6 +10,7 @@
- #include <linux/sunrpc/auth.h>
- #include <linux/sunrpc/xprt.h>
- #include <linux/sunrpc/bc_xprt.h>
-+#include <linux/sunrpc/rpc_pipe_fs.h>
- #include "internal.h"
- #include "callback.h"
- #include "delegation.h"
-@@ -206,7 +207,11 @@ struct nfs_client *nfs4_init_client(stru
- if (clp->cl_minorversion != 0)
- __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
- __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
-- error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
-+
-+ error = -EINVAL;
-+ if (gssd_running(clp->cl_net))
-+ error = nfs_create_rpc_client(clp, timeparms,
-+ RPC_AUTH_GSS_KRB5I);
- if (error == -EINVAL)
- error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX);
- if (error < 0)
-
diff --git a/sb-hibernate.patch b/sb-hibernate.patch
index 447237c60..da7bb7428 100644
--- a/sb-hibernate.patch
+++ b/sb-hibernate.patch
@@ -1,3 +1,6 @@
+Bugzilla: N/A
+Upstream-status: Fedora mustard
+
From ffe1ee94d526900ce1e5191cdd38934477dd209a Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Fri, 26 Oct 2012 14:02:09 -0400
diff --git a/secure-modules.patch b/secure-modules.patch
index 9d01b9356..86bf9dc6f 100644
--- a/secure-modules.patch
+++ b/secure-modules.patch
@@ -1,4 +1,7 @@
-From 8dea807503a1ba88d9e27595daae7f86ec968711 Mon Sep 17 00:00:00 2001
+Bugzilla: N/A
+Upstream-status: Fedora mustard. Replaced by securelevels, but that was nak'd
+
+From f212a4d8b8638a3e15e4cd76874d4fab60726752 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Aug 2013 17:58:15 -0400
Subject: [PATCH 01/14] Add secure_modules() call
@@ -14,10 +17,10 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
2 files changed, 17 insertions(+)
diff --git a/include/linux/module.h b/include/linux/module.h
-index 46f1ea0..0c266b2 100644
+index 15cd6b1..30702eb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
-@@ -509,6 +509,8 @@ int unregister_module_notifier(struct notifier_block * nb);
+@@ -512,6 +512,8 @@ int unregister_module_notifier(struct notifier_block * nb);
extern void print_modules(void);
@@ -26,7 +29,7 @@ index 46f1ea0..0c266b2 100644
#else /* !CONFIG_MODULES... */
/* Given an address, look for it in the exception tables. */
-@@ -619,6 +621,11 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
+@@ -622,6 +624,11 @@ static inline int unregister_module_notifier(struct notifier_block * nb)
static inline void print_modules(void)
{
}
@@ -39,10 +42,10 @@ index 46f1ea0..0c266b2 100644
#ifdef CONFIG_SYSFS
diff --git a/kernel/module.c b/kernel/module.c
-index 2069158..0e94acf 100644
+index f5a3b1e..644c33e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
-@@ -3852,3 +3852,13 @@ void module_layout(struct module *mod,
+@@ -3831,3 +3831,13 @@ void module_layout(struct module *mod,
}
EXPORT_SYMBOL(module_layout);
#endif
@@ -57,10 +60,10 @@ index 2069158..0e94acf 100644
+}
+EXPORT_SYMBOL(secure_modules);
--
-1.8.3.1
+1.8.4.2
-From 9b7b3f6283bf784e4ea1c34e52646b12971b2823 Mon Sep 17 00:00:00 2001
+From 394a8259d0b457495dddda8704821ec9e56ea44a Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Thu, 8 Mar 2012 10:10:38 -0500
Subject: [PATCH 02/14] PCI: Lock down BAR access when module security is
@@ -80,7 +83,7 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
-index c0dbe1f..cd4e35f 100644
+index c91e6c1..447742e 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -29,6 +29,7 @@
@@ -91,7 +94,7 @@ index c0dbe1f..cd4e35f 100644
#include "pci.h"
static int sysfs_initialized; /* = 0 */
-@@ -624,6 +625,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,
+@@ -668,6 +669,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,
loff_t init_off = off;
u8 *data = (u8*) buf;
@@ -101,7 +104,7 @@ index c0dbe1f..cd4e35f 100644
if (off > dev->cfg_size)
return 0;
if (off + count > dev->cfg_size) {
-@@ -930,6 +934,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+@@ -974,6 +978,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
resource_size_t start, end;
int i;
@@ -111,7 +114,7 @@ index c0dbe1f..cd4e35f 100644
for (i = 0; i < PCI_ROM_RESOURCE; i++)
if (res == &pdev->resource[i])
break;
-@@ -1037,6 +1044,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,
+@@ -1081,6 +1088,9 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
@@ -122,7 +125,7 @@ index c0dbe1f..cd4e35f 100644
}
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
-index cdc7836..e3d498b 100644
+index 46d1378..294fe7b 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -117,6 +117,9 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
@@ -155,7 +158,7 @@ index cdc7836..e3d498b 100644
/* Make sure the caller is mapping a real resource for this device */
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
-index e1c1ec5..bffbf71 100644
+index 24750a1..fa57896 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -10,6 +10,7 @@
@@ -176,10 +179,10 @@ index e1c1ec5..bffbf71 100644
dev = pci_get_bus_and_slot(bus, dfn);
--
-1.8.3.1
+1.8.4.2
-From aac2425a2664c09c2a369e1eec6e7a5bc2713cb1 Mon Sep 17 00:00:00 2001
+From 69532e626cece8a43c2528246e0421488b468102 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Thu, 8 Mar 2012 10:35:59 -0500
Subject: [PATCH 03/14] x86: Lock down IO port access when module security is
@@ -249,10 +252,10 @@ index f895a8c..1af8664 100644
return -EFAULT;
while (count-- > 0 && i < 65536) {
--
-1.8.3.1
+1.8.4.2
-From e7f9789c7eedf291972666befee726ff8e7126f6 Mon Sep 17 00:00:00 2001
+From 8771ff55273e964d707b174dd0dbe433783c0254 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Mar 2012 08:39:37 -0500
Subject: [PATCH 04/14] ACPI: Limit access to custom_method
@@ -281,10 +284,10 @@ index 12b62f2..50647b3 100644
/* parse the table header to get the table length */
if (count <= sizeof(struct acpi_table_header))
--
-1.8.3.1
+1.8.4.2
-From d81cd6628c821d47bd086354cbc57b1474f3c1a8 Mon Sep 17 00:00:00 2001
+From 7d3e3db90e1b4cf33ba4a46624ae4a68f787e5fc Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Mar 2012 08:46:50 -0500
Subject: [PATCH 05/14] asus-wmi: Restrict debugfs interface when module
@@ -336,10 +339,10 @@ index 19c313b..db18ef66 100644
1, asus->debug.method_id,
&input, &output);
--
-1.8.3.1
+1.8.4.2
-From df75e984729ef50bb691b4d15472529fcd81580b Mon Sep 17 00:00:00 2001
+From 98ebe083d75333e269730fe374cca42ac7f08a07 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Mar 2012 09:28:15 -0500
Subject: [PATCH 06/14] Restrict /dev/mem and /dev/kmem when module loading is
@@ -379,10 +382,10 @@ index 1af8664..61406c8 100644
unsigned long to_write = min_t(unsigned long, count,
(unsigned long)high_memory - p);
--
-1.8.3.1
+1.8.4.2
-From 78955913cc46cc5e5c7f2c71c1b07a5c18e06456 Mon Sep 17 00:00:00 2001
+From 71353d491c70b303a07b4e79c896e729a4f74978 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@redhat.com>
Date: Mon, 25 Jun 2012 19:57:30 -0400
Subject: [PATCH 07/14] acpi: Ignore acpi_rsdp kernel parameter when module
@@ -398,7 +401,7 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com>
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
-index 6ab2c35..e4c4410 100644
+index 54a20ff..d21d269 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -45,6 +45,7 @@
@@ -409,7 +412,7 @@ index 6ab2c35..e4c4410 100644
#include <asm/io.h>
#include <asm/uaccess.h>
-@@ -245,7 +246,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp);
+@@ -248,7 +249,7 @@ early_param("acpi_rsdp", setup_acpi_rsdp);
acpi_physical_address __init acpi_os_get_root_pointer(void)
{
#ifdef CONFIG_KEXEC
@@ -419,10 +422,10 @@ index 6ab2c35..e4c4410 100644
#endif
--
-1.8.3.1
+1.8.4.2
-From 23aae9143fbece326b3a26bf5ba48956c99cabe4 Mon Sep 17 00:00:00 2001
+From e0a6b0dd91460123d71784d531b9df26449940ae Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Aug 2013 03:33:56 -0400
Subject: [PATCH 08/14] kexec: Disable at runtime if the kernel enforces module
@@ -438,7 +441,7 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
1 file changed, 8 insertions(+)
diff --git a/kernel/kexec.c b/kernel/kexec.c
-index 59f7b55..3e2b63a 100644
+index 9c97016..8ad0d38 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -32,6 +32,7 @@
@@ -449,7 +452,7 @@ index 59f7b55..3e2b63a 100644
#include <asm/page.h>
#include <asm/uaccess.h>
-@@ -943,6 +944,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
+@@ -946,6 +947,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
return -EPERM;
/*
@@ -464,10 +467,10 @@ index 59f7b55..3e2b63a 100644
* This leaves us room for future extensions.
*/
--
-1.8.3.1
+1.8.4.2
-From 218cd49aa2d6a085c5c4edc0396200864f0b54ad Mon Sep 17 00:00:00 2001
+From c340630e68e5ed4d731d60d05ef9e2ae27080b66 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Tue, 3 Sep 2013 11:23:29 -0400
Subject: [PATCH 09/14] uswsusp: Disable when module loading is restricted
@@ -482,7 +485,7 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
1 file changed, 4 insertions(+)
diff --git a/kernel/power/user.c b/kernel/power/user.c
-index 4ed81e7..15cb72f 100644
+index 98d3575..efe99de 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -24,6 +24,7 @@
@@ -493,7 +496,7 @@ index 4ed81e7..15cb72f 100644
#include <asm/uaccess.h>
-@@ -48,6 +49,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
+@@ -49,6 +50,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
struct snapshot_data *data;
int error;
@@ -504,10 +507,10 @@ index 4ed81e7..15cb72f 100644
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
--
-1.8.3.1
+1.8.4.2
-From beeaac053d4ae57dc65be1da8b46e5d4bc6542b8 Mon Sep 17 00:00:00 2001
+From 273deda4ddec360ce67ac256b8cbdabdc5e8c51d Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 8 Feb 2013 11:12:13 -0800
Subject: [PATCH 10/14] x86: Restrict MSR access when module loading is
@@ -524,7 +527,7 @@ Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
1 file changed, 7 insertions(+)
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
-index 88458fa..d08f7e3 100644
+index 05266b5..e2bd647 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -103,6 +103,9 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
@@ -549,10 +552,10 @@ index 88458fa..d08f7e3 100644
err = -EFAULT;
break;
--
-1.8.3.1
+1.8.4.2
-From b4331711c52aff0a6a9cef0f4b52fe261874d6f2 Mon Sep 17 00:00:00 2001
+From 089166c0d42f1b82988aad4f23607deb6ee531e7 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <matthew.garrett@nebula.com>
Date: Fri, 9 Aug 2013 18:36:30 -0400
Subject: [PATCH 11/14] Add option to automatically enforce module signatures
@@ -588,12 +591,12 @@ index 199f453..ec38acf 100644
290/040 ALL edd_mbr_sig_buffer EDD MBR signatures
2D0/A00 ALL e820_map E820 memory map table
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index b32ebf9..6a6c19b 100644
+index 5216e28..2a147a3 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -1581,6 +1581,16 @@ config EFI_STUB
+@@ -1582,6 +1582,16 @@ config EFI_STUB
- See Documentation/x86/efi-stub.txt for more information.
+ See Documentation/efi-stub.txt for more information.
+config EFI_SECURE_BOOT_SIG_ENFORCE
+ def_bool n
@@ -609,7 +612,7 @@ index b32ebf9..6a6c19b 100644
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
-index b7388a4..53bfe4f 100644
+index a7677ba..4e172e9 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -12,6 +12,7 @@
@@ -620,10 +623,10 @@ index b7388a4..53bfe4f 100644
#undef memcpy /* Use memcpy from misc.c */
-@@ -861,6 +862,37 @@ fail:
- return status;
+@@ -741,6 +742,37 @@ free_mem_map:
}
+
+static int get_secure_boot(void)
+{
+ u8 sb, setup;
@@ -656,9 +659,9 @@ index b7388a4..53bfe4f 100644
+
+
/*
- * Because the x86 boot code expects to be passed a boot_params we
- * need to create one ourselves (usually the bootloader would create
-@@ -1169,6 +1201,10 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
+ * On success we return a pointer to a boot_params structure, and NULL
+ * on failure.
+@@ -760,6 +792,10 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
goto fail;
@@ -670,10 +673,10 @@ index b7388a4..53bfe4f 100644
setup_efi_pci(boot_params);
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
-index c15ddaf..85d7685 100644
+index 225b098..90dbfb7 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
-@@ -131,7 +131,8 @@ struct boot_params {
+@@ -133,7 +133,8 @@ struct boot_params {
__u8 eddbuf_entries; /* 0x1e9 */
__u8 edd_mbr_sig_buf_entries; /* 0x1ea */
__u8 kbd_status; /* 0x1eb */
@@ -684,7 +687,7 @@ index c15ddaf..85d7685 100644
* The sentinel is set to a nonzero value (0xff) in header.S.
*
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
-index f8ec578..deeb7bc 100644
+index 182b3f9..ab6cc9e 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1129,6 +1129,12 @@ void __init setup_arch(char **cmdline_p)
@@ -701,10 +704,10 @@ index f8ec578..deeb7bc 100644
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
diff --git a/include/linux/module.h b/include/linux/module.h
-index 0c266b2..5a6374a 100644
+index 30702eb..3eb0f52 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
-@@ -184,6 +184,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add);
+@@ -190,6 +190,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add);
struct notifier_block;
@@ -718,10 +721,10 @@ index 0c266b2..5a6374a 100644
extern int modules_disabled; /* for sysctl */
diff --git a/kernel/module.c b/kernel/module.c
-index 0e94acf..974139b 100644
+index 644c33e..92b73b1 100644
--- a/kernel/module.c
+++ b/kernel/module.c
-@@ -3853,6 +3853,13 @@ void module_layout(struct module *mod,
+@@ -3832,6 +3832,13 @@ void module_layout(struct module *mod,
EXPORT_SYMBOL(module_layout);
#endif
@@ -736,10 +739,10 @@ index 0e94acf..974139b 100644
{
#ifdef CONFIG_MODULE_SIG
--
-1.8.3.1
+1.8.4.2
-From bb28516d346e6511f1e012321c48eb142763e539 Mon Sep 17 00:00:00 2001
+From e9ad6bd405fa01b7dd52d8c75b9dc91ae52e131d Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@redhat.com>
Date: Tue, 5 Feb 2013 19:25:05 -0500
Subject: [PATCH 12/14] efi: Disable secure boot if shim is in insecure mode
@@ -756,10 +759,10 @@ Signed-off-by: Josh Boyer <jwboyer@redhat.com>
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
-index 53bfe4f..946028b 100644
+index 4e172e9..4905f4d 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
-@@ -864,8 +864,9 @@ fail:
+@@ -744,8 +744,9 @@ free_mem_map:
static int get_secure_boot(void)
{
@@ -770,7 +773,7 @@ index 53bfe4f..946028b 100644
efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
efi_status_t status;
-@@ -889,6 +890,23 @@ static int get_secure_boot(void)
+@@ -769,6 +770,23 @@ static int get_secure_boot(void)
if (setup == 1)
return 0;
@@ -795,10 +798,10 @@ index 53bfe4f..946028b 100644
}
--
-1.8.3.1
+1.8.4.2
-From 4c8824bac8d4284e66c39c365ba84151f2d78e87 Mon Sep 17 00:00:00 2001
+From f9f355d5e58c1503bb7c03d92c9e89267e0f46ad Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Tue, 27 Aug 2013 13:28:43 -0400
Subject: [PATCH 13/14] efi: Make EFI_SECURE_BOOT_SIG_ENFORCE depend on EFI
@@ -812,11 +815,11 @@ Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 6a6c19b..10498ec 100644
+index 2a147a3..9e644d5 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -1582,7 +1582,8 @@ config EFI_STUB
- See Documentation/x86/efi-stub.txt for more information.
+@@ -1583,7 +1583,8 @@ config EFI_STUB
+ See Documentation/efi-stub.txt for more information.
config EFI_SECURE_BOOT_SIG_ENFORCE
- def_bool n
@@ -826,10 +829,10 @@ index 6a6c19b..10498ec 100644
---help---
UEFI Secure Boot provides a mechanism for ensuring that the
--
-1.8.3.1
+1.8.4.2
-From 871b0ed1847c3c5413a4ca72ecf18735858f7708 Mon Sep 17 00:00:00 2001
+From a30576a9db583213474b74360c5869e8882e6ed7 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@fedoraproject.org>
Date: Tue, 27 Aug 2013 13:33:03 -0400
Subject: [PATCH 14/14] efi: Add EFI_SECURE_BOOT bit
@@ -844,7 +847,7 @@ Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
2 files changed, 3 insertions(+)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
-index deeb7bc..08dc16e 100644
+index ab6cc9e..99933cd 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1131,7 +1131,9 @@ void __init setup_arch(char **cmdline_p)
@@ -858,17 +861,17 @@ index deeb7bc..08dc16e 100644
#endif
diff --git a/include/linux/efi.h b/include/linux/efi.h
-index 5f8f176..eed2202 100644
+index 0a819e7..0c1d367 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
-@@ -634,6 +634,7 @@ extern int __init efi_setup_pcdp_console(char *);
- #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */
+@@ -657,6 +657,7 @@ extern int __init efi_setup_pcdp_console(char *);
#define EFI_MEMMAP 4 /* Can we use EFI memory map? */
#define EFI_64BIT 5 /* Is the firmware 64-bit? */
-+#define EFI_SECURE_BOOT 6 /* Are we in Secure Boot mode? */
+ #define EFI_ARCH_1 6 /* First arch-specific bit */
++#define EFI_SECURE_BOOT 7 /* Are we in Secure Boot mode? */
#ifdef CONFIG_EFI
# ifdef CONFIG_X86
--
-1.8.3.1
+1.8.4.2
diff --git a/silence-acpi-blacklist.patch b/silence-acpi-blacklist.patch
deleted file mode 100644
index c5997bb6e..000000000
--- a/silence-acpi-blacklist.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-diff -up linux-2.6.26.noarch/drivers/acpi/blacklist.c.jx linux-2.6.26.noarch/drivers/acpi/blacklist.c
---- linux-2.6.26.noarch/drivers/acpi/blacklist.c.jx 2008-07-13 17:51:29.000000000 -0400
-+++ linux-2.6.26.noarch/drivers/acpi/blacklist.c 2008-08-12 14:21:39.000000000 -0400
-@@ -81,18 +81,18 @@ static int __init blacklist_by_year(void
-
- /* Doesn't exist? Likely an old system */
- if (!dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL)) {
-- printk(KERN_ERR PREFIX "no DMI BIOS year, "
-+ printk(KERN_INFO PREFIX "no DMI BIOS year, "
- "acpi=force is required to enable ACPI\n" );
- return 1;
- }
- /* 0? Likely a buggy new BIOS */
- if (year == 0) {
-- printk(KERN_ERR PREFIX "DMI BIOS year==0, "
-+ printk(KERN_INFO PREFIX "DMI BIOS year==0, "
- "assuming ACPI-capable machine\n" );
- return 0;
- }
- if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
-- printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), "
-+ printk(KERN_INFO PREFIX "BIOS age (%d) fails cutoff (%d), "
- "acpi=force is required to enable ACPI\n",
- year, CONFIG_ACPI_BLACKLIST_YEAR);
- return 1;
diff --git a/sources b/sources
index df0f7b616..3d6940b42 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
-cc6ee608854e0da4b64f6c1ff8b6398c linux-3.12.tar.xz
-70e456d21f7e7c0dc2f9bd170f1ae4ee patch-3.12.5.xz
+b621207b3f6ecbb67db18b13258f8ea8 linux-3.14.tar.xz
+d36baf2d62de5aa61f10a976d00d2d2a perf-man-3.14.tar.gz
diff --git a/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch b/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch
deleted file mode 100644
index 805498a70..000000000
--- a/sunrpc-create-a-new-dummy-pipe-for-gssd-to-hold-open.patch
+++ /dev/null
@@ -1,233 +0,0 @@
-Bugzilla: N/A
-Upstream-status: queued in NFS git tree (for 3.13/3.14?)
-
-rpc.gssd will naturally hold open any pipe named */clnt*/gssd that shows
-up under rpc_pipefs. That behavior gives us a reliable mechanism to tell
-whether it's actually running or not.
-
-Create a new toplevel "gssd" directory in rpc_pipefs when it's mounted.
-Under that directory create another directory called "clntXX", and then
-within that a pipe called "gssd".
-
-We'll never send an upcall along that pipe, and any downcall written to
-it will just return -EINVAL.
-
-Signed-off-by: Jeff Layton <jlayton@redhat.com>
-Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
----
- include/linux/sunrpc/rpc_pipe_fs.h | 3 +-
- net/sunrpc/netns.h | 1 +
- net/sunrpc/rpc_pipe.c | 93 ++++++++++++++++++++++++++++++++++-
- net/sunrpc/sunrpc_syms.c | 8 +++-
- 4 files changed, 100 insertions(+), 5 deletions(-)
-
-diff -up linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h.orig linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h
---- linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h.orig 2013-09-02 16:46:10.000000000 -0400
-+++ linux-3.11.9-200.fc19.x86_64/include/linux/sunrpc/rpc_pipe_fs.h 2013-11-21 10:11:17.893026000 -0500
-@@ -64,7 +64,8 @@ enum {
-
- extern struct dentry *rpc_d_lookup_sb(const struct super_block *sb,
- const unsigned char *dir_name);
--extern void rpc_pipefs_init_net(struct net *net);
-+extern int rpc_pipefs_init_net(struct net *net);
-+extern void rpc_pipefs_exit_net(struct net *net);
- extern struct super_block *rpc_get_sb_net(const struct net *net);
- extern void rpc_put_sb_net(const struct net *net);
-
-diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h
---- linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h.orig 2013-09-02 16:46:10.000000000 -0400
-+++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/netns.h 2013-11-21 10:11:17.897029000 -0500
-@@ -14,6 +14,7 @@ struct sunrpc_net {
- struct cache_detail *rsi_cache;
-
- struct super_block *pipefs_sb;
-+ struct rpc_pipe *gssd_dummy;
- struct mutex pipefs_sb_lock;
-
- struct list_head all_clients;
-diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c
---- linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c.orig 2013-09-02 16:46:10.000000000 -0400
-+++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/rpc_pipe.c 2013-11-21 10:11:17.903026000 -0500
-@@ -38,7 +38,7 @@
- #define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "")
-
- static struct file_system_type rpc_pipe_fs_type;
--
-+static const struct rpc_pipe_ops gssd_dummy_pipe_ops;
-
- static struct kmem_cache *rpc_inode_cachep __read_mostly;
-
-@@ -1019,6 +1019,7 @@ enum {
- RPCAUTH_nfsd4_cb,
- RPCAUTH_cache,
- RPCAUTH_nfsd,
-+ RPCAUTH_gssd,
- RPCAUTH_RootEOF
- };
-
-@@ -1055,6 +1056,10 @@ static const struct rpc_filelist files[]
- .name = "nfsd",
- .mode = S_IFDIR | S_IRUGO | S_IXUGO,
- },
-+ [RPCAUTH_gssd] = {
-+ .name = "gssd",
-+ .mode = S_IFDIR | S_IRUGO | S_IXUGO,
-+ },
- };
-
- /*
-@@ -1068,13 +1073,25 @@ struct dentry *rpc_d_lookup_sb(const str
- }
- EXPORT_SYMBOL_GPL(rpc_d_lookup_sb);
-
--void rpc_pipefs_init_net(struct net *net)
-+int rpc_pipefs_init_net(struct net *net)
- {
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-
-+ sn->gssd_dummy = rpc_mkpipe_data(&gssd_dummy_pipe_ops, 0);
-+ if (IS_ERR(sn->gssd_dummy))
-+ return PTR_ERR(sn->gssd_dummy);
-+
- mutex_init(&sn->pipefs_sb_lock);
- sn->gssd_running = 1;
- sn->pipe_version = -1;
-+ return 0;
-+}
-+
-+void rpc_pipefs_exit_net(struct net *net)
-+{
-+ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-+
-+ rpc_destroy_pipe_data(sn->gssd_dummy);
- }
-
- /*
-@@ -1104,11 +1121,73 @@ void rpc_put_sb_net(const struct net *ne
- }
- EXPORT_SYMBOL_GPL(rpc_put_sb_net);
-
-+static const struct rpc_filelist gssd_dummy_clnt_dir[] = {
-+ [0] = {
-+ .name = "clntXX",
-+ .mode = S_IFDIR | S_IRUGO | S_IXUGO,
-+ },
-+};
-+
-+static ssize_t
-+dummy_downcall(struct file *filp, const char __user *src, size_t len)
-+{
-+ return -EINVAL;
-+}
-+
-+static const struct rpc_pipe_ops gssd_dummy_pipe_ops = {
-+ .upcall = rpc_pipe_generic_upcall,
-+ .downcall = dummy_downcall,
-+};
-+
-+/**
-+ * rpc_gssd_dummy_populate - create a dummy gssd pipe
-+ * @root: root of the rpc_pipefs filesystem
-+ * @pipe_data: pipe data created when netns is initialized
-+ *
-+ * Create a dummy set of directories and a pipe that gssd can hold open to
-+ * indicate that it is up and running.
-+ */
-+static struct dentry *
-+rpc_gssd_dummy_populate(struct dentry *root, struct rpc_pipe *pipe_data)
-+{
-+ int ret = 0;
-+ struct dentry *gssd_dentry;
-+ struct dentry *clnt_dentry = NULL;
-+ struct dentry *pipe_dentry = NULL;
-+ struct qstr q = QSTR_INIT(files[RPCAUTH_gssd].name,
-+ strlen(files[RPCAUTH_gssd].name));
-+
-+ /* We should never get this far if "gssd" doesn't exist */
-+ gssd_dentry = d_hash_and_lookup(root, &q);
-+ if (!gssd_dentry)
-+ return ERR_PTR(-ENOENT);
-+
-+ ret = rpc_populate(gssd_dentry, gssd_dummy_clnt_dir, 0, 1, NULL);
-+ if (ret) {
-+ pipe_dentry = ERR_PTR(ret);
-+ goto out;
-+ }
-+
-+ q.name = gssd_dummy_clnt_dir[0].name;
-+ q.len = strlen(gssd_dummy_clnt_dir[0].name);
-+ clnt_dentry = d_hash_and_lookup(gssd_dentry, &q);
-+ if (!clnt_dentry) {
-+ pipe_dentry = ERR_PTR(-ENOENT);
-+ goto out;
-+ }
-+
-+ pipe_dentry = rpc_mkpipe_dentry(clnt_dentry, "gssd", NULL, pipe_data);
-+out:
-+ dput(clnt_dentry);
-+ dput(gssd_dentry);
-+ return pipe_dentry;
-+}
-+
- static int
- rpc_fill_super(struct super_block *sb, void *data, int silent)
- {
- struct inode *inode;
-- struct dentry *root;
-+ struct dentry *root, *gssd_dentry;
- struct net *net = data;
- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- int err;
-@@ -1126,6 +1205,13 @@ rpc_fill_super(struct super_block *sb, v
- return -ENOMEM;
- if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
- return -ENOMEM;
-+
-+ gssd_dentry = rpc_gssd_dummy_populate(root, sn->gssd_dummy);
-+ if (IS_ERR(gssd_dentry)) {
-+ __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
-+ return PTR_ERR(gssd_dentry);
-+ }
-+
- dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n",
- net, NET_NAME(net));
- mutex_lock(&sn->pipefs_sb_lock);
-@@ -1140,6 +1226,7 @@ rpc_fill_super(struct super_block *sb, v
- return 0;
-
- err_depopulate:
-+ dput(gssd_dentry);
- blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
- RPC_PIPEFS_UMOUNT,
- sb);
-diff -up linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c.orig linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c
---- linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c.orig 2013-09-02 16:46:10.000000000 -0400
-+++ linux-3.11.9-200.fc19.x86_64/net/sunrpc/sunrpc_syms.c 2013-11-21 10:11:17.908026000 -0500
-@@ -44,12 +44,17 @@ static __net_init int sunrpc_init_net(st
- if (err)
- goto err_unixgid;
-
-- rpc_pipefs_init_net(net);
-+ err = rpc_pipefs_init_net(net);
-+ if (err)
-+ goto err_pipefs;
-+
- INIT_LIST_HEAD(&sn->all_clients);
- spin_lock_init(&sn->rpc_client_lock);
- spin_lock_init(&sn->rpcb_clnt_lock);
- return 0;
-
-+err_pipefs:
-+ unix_gid_cache_destroy(net);
- err_unixgid:
- ip_map_cache_destroy(net);
- err_ipmap:
-@@ -60,6 +65,7 @@ err_proc:
-
- static __net_exit void sunrpc_exit_net(struct net *net)
- {
-+ rpc_pipefs_exit_net(net);
- unix_gid_cache_destroy(net);
- ip_map_cache_destroy(net);
- rpc_proc_exit(net);
-
diff --git a/sunrpc-replace-gssd_running-with-more-reliable-check.patch b/sunrpc-replace-gssd_running-with-more-reliable-check.patch
deleted file mode 100644
index 8cd5c0090..000000000
--- a/sunrpc-replace-gssd_running-with-more-reliable-check.patch
+++ /dev/null
@@ -1,139 +0,0 @@
-Bugzilla: N/A
-Upstream-status: queued in NFS git tree (for 3.13/3.14?)
-
-Now that we have a more reliable method to tell if gssd is running, we
-can replace the sn->gssd_running flag with a function that will query to
-see if it's up and running.
-
-There's also no need to attempt an upcall that we know will fail, so
-just return -EACCES if gssd isn't running. Finally, fix the warn_gss()
-message not to claim that that the upcall timed out since we don't
-necesarily perform one now when gssd isn't running, and remove the
-extraneous newline from the message.
-
-Signed-off-by: Jeff Layton <jlayton@redhat.com>
-Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
----
- Fixed up to apply to 3.12.1 by Josh Boyer <jwboyer@fedoraproject.org>
-
- include/linux/sunrpc/rpc_pipe_fs.h | 2 ++
- net/sunrpc/auth_gss/auth_gss.c | 17 +++++++----------
- net/sunrpc/netns.h | 2 --
- net/sunrpc/rpc_pipe.c | 14 ++++++++++----
- 4 files changed, 19 insertions(+), 16 deletions(-)
-
-diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
-index 85f1342..7f490be 100644
---- a/include/linux/sunrpc/rpc_pipe_fs.h
-+++ b/include/linux/sunrpc/rpc_pipe_fs.h
-@@ -131,5 +131,7 @@ extern int rpc_unlink(struct dentry *);
- extern int register_rpc_pipefs(void);
- extern void unregister_rpc_pipefs(void);
-
-+extern bool gssd_running(struct net *net);
-+
- #endif
- #endif
-diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
-index 0846566..1ada878 100644
---- a/net/sunrpc/auth_gss/auth_gss.c
-+++ b/net/sunrpc/auth_gss/auth_gss.c
-@@ -517,8 +517,7 @@ static void warn_gssd(void)
- unsigned long now = jiffies;
-
- if (time_after(now, ratelimit)) {
-- printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
-- "Please check user daemon is running.\n");
-+ pr_warn("RPC: AUTH_GSS upcall failed. Please check user daemon is running.\n");
- ratelimit = now + 15*HZ;
- }
- }
-@@ -581,7 +580,6 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
- struct rpc_pipe *pipe;
- struct rpc_cred *cred = &gss_cred->gc_base;
- struct gss_upcall_msg *gss_msg;
-- unsigned long timeout;
- DEFINE_WAIT(wait);
- int err;
-
-@@ -589,17 +587,16 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
- __func__, from_kuid(&init_user_ns, cred->cr_uid));
- retry:
- err = 0;
-- /* Default timeout is 15s unless we know that gssd is not running */
-- timeout = 15 * HZ;
-- if (!sn->gssd_running)
-- timeout = HZ >> 2;
-+ /* if gssd is down, just skip upcalling altogether */
-+ if (!gssd_running(net)) {
-+ warn_gssd();
-+ return -EACCES;
-+ }
- gss_msg = gss_setup_upcall(gss_auth, cred);
- if (PTR_ERR(gss_msg) == -EAGAIN) {
- err = wait_event_interruptible_timeout(pipe_version_waitqueue,
-- sn->pipe_version >= 0, timeout);
-+ sn->pipe_version >= 0, 15 * HZ);
- if (sn->pipe_version < 0) {
-- if (err == 0)
-- sn->gssd_running = 0;
- warn_gssd();
- err = -EACCES;
- }
-diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
-index 8a8e841..94e506f 100644
---- a/net/sunrpc/netns.h
-+++ b/net/sunrpc/netns.h
-@@ -33,8 +33,6 @@ struct sunrpc_net {
- int pipe_version;
- atomic_t pipe_users;
- struct proc_dir_entry *use_gssp_proc;
--
-- unsigned int gssd_running;
- };
-
- extern int sunrpc_net_id;
-diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
-index 40aef18..ad444f3 100644
---- a/net/sunrpc/rpc_pipe.c
-+++ b/net/sunrpc/rpc_pipe.c
-@@ -216,14 +216,11 @@ rpc_destroy_inode(struct inode *inode)
- static int
- rpc_pipe_open(struct inode *inode, struct file *filp)
- {
-- struct net *net = inode->i_sb->s_fs_info;
-- struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
- struct rpc_pipe *pipe;
- int first_open;
- int res = -ENXIO;
-
- mutex_lock(&inode->i_mutex);
-- sn->gssd_running = 1;
- pipe = RPC_I(inode)->pipe;
- if (pipe == NULL)
- goto out;
-@@ -1231,7 +1228,6 @@ int rpc_pipefs_init_net(struct net *net)
- return PTR_ERR(sn->gssd_dummy);
-
- mutex_init(&sn->pipefs_sb_lock);
-- sn->gssd_running = 1;
- sn->pipe_version = -1;
- return 0;
- }
-@@ -1385,6 +1381,16 @@ err_depopulate:
- return err;
- }
-
-+bool
-+gssd_running(struct net *net)
-+{
-+ struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
-+ struct rpc_pipe *pipe = sn->gssd_dummy;
-+
-+ return pipe->nreaders || pipe->nwriters;
-+}
-+EXPORT_SYMBOL_GPL(gssd_running);
-+
- static struct dentry *
- rpc_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
diff --git a/sysrq-secure-boot.patch b/sysrq-secure-boot.patch
index b4bb80d00..c73e3d252 100644
--- a/sysrq-secure-boot.patch
+++ b/sysrq-secure-boot.patch
@@ -1,20 +1,23 @@
-From 71aac34ed679daa0bf772051eb40412b5bd95da3 Mon Sep 17 00:00:00 2001
+Bugzilla: N/A
+Upstream-status: Fedora mustard
+
+From 29c1f71a2d0845a71ea2ebd2fb33542373dc52dd Mon Sep 17 00:00:00 2001
From: Kyle McMartin <kyle@redhat.com>
Date: Fri, 30 Aug 2013 09:28:51 -0400
Subject: [PATCH] Add sysrq option to disable secure boot mode
---
- arch/x86/kernel/setup.c | 35 +++++++++++++++++++++++++++++++++++
+ arch/x86/kernel/setup.c | 36 ++++++++++++++++++++++++++++++++++++
drivers/input/misc/uinput.c | 1 +
drivers/tty/sysrq.c | 19 +++++++++++++------
include/linux/input.h | 5 +++++
include/linux/sysrq.h | 8 +++++++-
kernel/debug/kdb/kdb_main.c | 2 +-
kernel/module.c | 4 ++--
- 7 files changed, 64 insertions(+), 10 deletions(-)
+ 7 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
-index 08dc16e..6971f8e 100644
+index c773add..92c480c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -70,6 +70,11 @@
@@ -29,11 +32,10 @@ index 08dc16e..6971f8e 100644
#include <video/edid.h>
#include <asm/mtrr.h>
-@@ -1253,3 +1258,33 @@ void __init i386_reserve_resources(void)
- }
+@@ -1275,6 +1280,37 @@ void __init i386_reserve_resources(void)
#endif /* CONFIG_X86_32 */
-+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MODULE_SIG
+extern bool sig_enforce;
@@ -63,8 +65,13 @@ index 08dc16e..6971f8e 100644
+}
+late_initcall(secure_boot_sysrq);
+#endif /*CONFIG_MAGIC_SYSRQ*/
++
++
+ static struct notifier_block kernel_offset_notifier = {
+ .notifier_call = dump_kernel_offset
+ };
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
-index a0a4bba..3327cc3 100644
+index 7728359..a3e8ba8 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -351,6 +351,7 @@ static int uinput_allocate_device(struct uinput_device *udev)
@@ -76,10 +83,10 @@ index a0a4bba..3327cc3 100644
input_set_drvdata(udev->dev, udev);
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
-index d5cc3ac..05b33f5 100644
+index ce396ec..aee594a 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
-@@ -461,6 +461,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
+@@ -462,6 +462,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
&sysrq_showstate_blocked_op, /* w */
/* x: May be registered on ppc/powerpc for xmon */
/* x: May be registered on sparc64 for global PMU dump */
@@ -87,7 +94,7 @@ index d5cc3ac..05b33f5 100644
NULL, /* x */
/* y: May be registered on sparc64 for global register dump */
NULL, /* y */
-@@ -504,7 +505,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
+@@ -505,7 +506,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
sysrq_key_table[i] = op_p;
}
@@ -96,7 +103,7 @@ index d5cc3ac..05b33f5 100644
{
struct sysrq_key_op *op_p;
int orig_log_level;
-@@ -524,11 +525,15 @@ void __handle_sysrq(int key, bool check_mask)
+@@ -525,11 +526,15 @@ void __handle_sysrq(int key, bool check_mask)
op_p = __sysrq_get_key_op(key);
if (op_p) {
@@ -113,7 +120,7 @@ index d5cc3ac..05b33f5 100644
printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
op_p->handler(key);
-@@ -559,7 +564,7 @@ void __handle_sysrq(int key, bool check_mask)
+@@ -560,7 +565,7 @@ void __handle_sysrq(int key, bool check_mask)
void handle_sysrq(int key)
{
if (sysrq_on())
@@ -122,7 +129,7 @@ index d5cc3ac..05b33f5 100644
}
EXPORT_SYMBOL(handle_sysrq);
-@@ -639,7 +644,7 @@ static void sysrq_do_reset(unsigned long _state)
+@@ -640,7 +645,7 @@ static void sysrq_do_reset(unsigned long _state)
static void sysrq_handle_reset_request(struct sysrq_state *state)
{
if (state->reset_requested)
@@ -131,7 +138,7 @@ index d5cc3ac..05b33f5 100644
if (sysrq_reset_downtime_ms)
mod_timer(&state->keyreset_timer,
-@@ -756,8 +761,10 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
+@@ -791,8 +796,10 @@ static bool sysrq_handle_keypress(struct sysrq_state *sysrq,
default:
if (sysrq->active && value && value != 2) {
@@ -143,7 +150,7 @@ index d5cc3ac..05b33f5 100644
}
break;
}
-@@ -1038,7 +1045,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
+@@ -1080,7 +1087,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
if (get_user(c, buf))
return -EFAULT;
@@ -183,10 +190,10 @@ index 82ce323..9e534f2 100644
* Verify that we are in sync with input_device_id mod_devicetable.h #defines
*/
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
-index 7faf933..87ae634 100644
+index 387fa7d..4b07e30 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
-@@ -31,6 +31,8 @@
+@@ -28,6 +28,8 @@
#define SYSRQ_ENABLE_BOOT 0x0080
#define SYSRQ_ENABLE_RTNICE 0x0100
@@ -195,7 +202,7 @@ index 7faf933..87ae634 100644
struct sysrq_key_op {
void (*handler)(int);
char *help_msg;
-@@ -45,8 +47,12 @@ struct sysrq_key_op {
+@@ -42,8 +44,12 @@ struct sysrq_key_op {
* are available -- else NULL's).
*/
@@ -210,10 +217,10 @@ index 7faf933..87ae634 100644
int unregister_sysrq_key(int key, struct sysrq_key_op *op);
struct sysrq_key_op *__sysrq_get_key_op(int key);
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
-index 00eb8f7..54fbbcc 100644
+index 0b097c8..18b400d 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
-@@ -1921,7 +1921,7 @@ static int kdb_sr(int argc, const char **argv)
+@@ -1924,7 +1924,7 @@ static int kdb_sr(int argc, const char **argv)
if (argc != 1)
return KDB_ARGCOUNT;
kdb_trap_printk++;
@@ -223,7 +230,7 @@ index 00eb8f7..54fbbcc 100644
return 0;
diff --git a/kernel/module.c b/kernel/module.c
-index bc7c987..5e4e2c2 100644
+index 92b73b1..a44fb2a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -109,9 +109,9 @@ struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
@@ -239,5 +246,5 @@ index bc7c987..5e4e2c2 100644
static int param_set_bool_enable_only(const char *val,
const struct kernel_param *kp)
--
-1.8.3.1
+1.8.4.2
diff --git a/x86-allow-1024-cpus.patch b/x86-allow-1024-cpus.patch
deleted file mode 100644
index decafd6ef..000000000
--- a/x86-allow-1024-cpus.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index f67e839..d726b2d 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -825,7 +825,7 @@ config MAXSMP
- config NR_CPUS
- int "Maximum number of CPUs" if SMP && !MAXSMP
- range 2 8 if SMP && X86_32 && !X86_BIGSMP
-- range 2 512 if SMP && !MAXSMP
-+ range 2 1024 if SMP && !MAXSMP
- default "1" if !SMP
- default "4096" if MAXSMP
- default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000)
diff --git a/xfs-underflow-bug-in-xfs_attrlist_by_handle.patch b/xfs-underflow-bug-in-xfs_attrlist_by_handle.patch
deleted file mode 100644
index 6c7f60dd9..000000000
--- a/xfs-underflow-bug-in-xfs_attrlist_by_handle.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-Bugzilla: 1033603
-Upstream-status: Submitted but not queued http://thread.gmane.org/gmane.comp.file-systems.xfs.general/57654
-
-Path: news.gmane.org!not-for-mail
-From: Dan Carpenter <dan.carpenter@oracle.com>
-Newsgroups: gmane.comp.file-systems.xfs.general
-Subject: [patch] xfs: underflow bug in xfs_attrlist_by_handle()
-Date: Thu, 31 Oct 2013 21:00:10 +0300
-Lines: 43
-Approved: news@gmane.org
-Message-ID: <20131031180010.GA24839@longonot.mountain>
-References: <20131025144452.GA28451@ngolde.de>
-NNTP-Posting-Host: plane.gmane.org
-Mime-Version: 1.0
-Content-Type: text/plain; charset="us-ascii"
-Content-Transfer-Encoding: 7bit
-X-Trace: ger.gmane.org 1383242609 27303 80.91.229.3 (31 Oct 2013 18:03:29 GMT)
-X-Complaints-To: usenet@ger.gmane.org
-NNTP-Posting-Date: Thu, 31 Oct 2013 18:03:29 +0000 (UTC)
-Cc: Fabian Yamaguchi <fabs@goesec.de>, security@kernel.org,
- Alex Elder <elder@kernel.org>, Nico Golde <nico@ngolde.de>, xfs@oss.sgi.com
-To: Ben Myers <bpm@sgi.com>
-Original-X-From: xfs-bounces@oss.sgi.com Thu Oct 31 19:03:33 2013
-Return-path: <xfs-bounces@oss.sgi.com>
-Envelope-to: sgi-linux-xfs@gmane.org
-Original-Received: from oss.sgi.com ([192.48.182.195])
- by plane.gmane.org with esmtp (Exim 4.69)
- (envelope-from <xfs-bounces@oss.sgi.com>)
- id 1Vbwag-0001Ow-Sv
- for sgi-linux-xfs@gmane.org; Thu, 31 Oct 2013 19:03:31 +0100
-Original-Received: from oss.sgi.com (localhost [IPv6:::1])
- by oss.sgi.com (Postfix) with ESMTP id DB14A7F85;
- Thu, 31 Oct 2013 13:03:28 -0500 (CDT)
-X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com
-X-Spam-Level:
-X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY
- autolearn=ham version=3.3.1
-X-Original-To: xfs@oss.sgi.com
-Delivered-To: xfs@oss.sgi.com
-Original-Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111])
- by oss.sgi.com (Postfix) with ESMTP id A0ED87F83
- for <xfs@oss.sgi.com>; Thu, 31 Oct 2013 13:03:27 -0500 (CDT)
-Original-Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11])
- by relay1.corp.sgi.com (Postfix) with ESMTP id 71E0A8F804B
- for <xfs@oss.sgi.com>; Thu, 31 Oct 2013 11:03:24 -0700 (PDT)
-X-ASG-Debug-ID: 1383242599-04bdf0789a41ef30001-NocioJ
-Original-Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by
- cuda.sgi.com with ESMTP id CWKetu2Mc6MhJZij (version=TLSv1
- cipher=AES256-SHA bits=256 verify=NO);
- Thu, 31 Oct 2013 11:03:20 -0700 (PDT)
-X-Barracuda-Envelope-From: dan.carpenter@oracle.com
-X-Barracuda-Apparent-Source-IP: 156.151.31.81
-Original-Received: from acsinet22.oracle.com (acsinet22.oracle.com [141.146.126.238])
- by userp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with
- ESMTP id r9VI3AZn009606
- (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK);
- Thu, 31 Oct 2013 18:03:11 GMT
-Original-Received: from aserz7022.oracle.com (aserz7022.oracle.com [141.146.126.231])
- by acsinet22.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id
- r9VI39qG016923
- (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO);
- Thu, 31 Oct 2013 18:03:10 GMT
-Original-Received: from abhmt101.oracle.com (abhmt101.oracle.com [141.146.116.53])
- by aserz7022.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id
- r9VI395m016915; Thu, 31 Oct 2013 18:03:09 GMT
-Original-Received: from longonot.mountain (/105.160.144.228)
- by default (Oracle Beehive Gateway v4.0)
- with ESMTP ; Thu, 31 Oct 2013 11:03:08 -0700
-X-ASG-Orig-Subj: [patch] xfs: underflow bug in xfs_attrlist_by_handle()
-Content-Disposition: inline
-In-Reply-To: <20131025144452.GA28451@ngolde.de>
-User-Agent: Mutt/1.5.21 (2010-09-15)
-X-Source-IP: acsinet22.oracle.com [141.146.126.238]
-X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81]
-X-Barracuda-Start-Time: 1383242600
-X-Barracuda-Encrypted: AES256-SHA
-X-Barracuda-URL: http://192.48.157.11:80/cgi-mod/mark.cgi
-X-Virus-Scanned: by bsmtpd at sgi.com
-X-Barracuda-BRTS-Status: 1
-X-Barracuda-Spam-Score: 0.00
-X-Barracuda-Spam-Status: No,
- SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0
- QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=UNPARSEABLE_RELAY
-X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.141937
- Rule breakdown below
- pts rule name description
- ---- ----------------------
- --------------------------------------------------
- 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay
- lines
-X-BeenThere: xfs@oss.sgi.com
-X-Mailman-Version: 2.1.14
-Precedence: list
-List-Id: XFS Filesystem from SGI <xfs.oss.sgi.com>
-List-Unsubscribe: <http://oss.sgi.com/mailman/options/xfs>,
- <mailto:xfs-request@oss.sgi.com?subject=unsubscribe>
-List-Archive: <http://oss.sgi.com/pipermail/xfs>
-List-Post: <mailto:xfs@oss.sgi.com>
-List-Help: <mailto:xfs-request@oss.sgi.com?subject=help>
-List-Subscribe: <http://oss.sgi.com/mailman/listinfo/xfs>,
- <mailto:xfs-request@oss.sgi.com?subject=subscribe>
-Errors-To: xfs-bounces@oss.sgi.com
-Original-Sender: xfs-bounces@oss.sgi.com
-Xref: news.gmane.org gmane.comp.file-systems.xfs.general:57654
-Archived-At: <http://permalink.gmane.org/gmane.comp.file-systems.xfs.general/57654>
-
-If we allocate less than sizeof(struct attrlist) then we end up
-corrupting memory or doing a ZERO_PTR_SIZE dereference.
-
-This can only be triggered with CAP_SYS_ADMIN.
-
-Reported-by: Nico Golde <nico@ngolde.de>
-Reported-by: Fabian Yamaguchi <fabs@goesec.de>
-Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
-
-diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
-index 4d61340..33ad9a7 100644
---- a/fs/xfs/xfs_ioctl.c
-+++ b/fs/xfs/xfs_ioctl.c
-@@ -442,7 +442,8 @@ xfs_attrlist_by_handle(
- return -XFS_ERROR(EPERM);
- if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
- return -XFS_ERROR(EFAULT);
-- if (al_hreq.buflen > XATTR_LIST_MAX)
-+ if (al_hreq.buflen < sizeof(struct attrlist) ||
-+ al_hreq.buflen > XATTR_LIST_MAX)
- return -XFS_ERROR(EINVAL);
-
- /*
-diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
-index e8fb123..a7992f8 100644
---- a/fs/xfs/xfs_ioctl32.c
-+++ b/fs/xfs/xfs_ioctl32.c
-@@ -356,7 +356,8 @@ xfs_compat_attrlist_by_handle(
- if (copy_from_user(&al_hreq, arg,
- sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
- return -XFS_ERROR(EFAULT);
-- if (al_hreq.buflen > XATTR_LIST_MAX)
-+ if (al_hreq.buflen < sizeof(struct attrlist) ||
-+ al_hreq.buflen > XATTR_LIST_MAX)
- return -XFS_ERROR(EINVAL);
-
- /*
-
-_______________________________________________
-xfs mailing list
-xfs@oss.sgi.com
-http://oss.sgi.com/mailman/listinfo/xfs
-