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 +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 +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina + +- 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 +--- + 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 ++ * 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 ++ ++#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 ++ * Copyright (c) 2013 Synaptics Incorporated ++ * Copyright (c) 2014 Benjamin Tissoires ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 "); ++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 +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 +--- + 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 -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 -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 ---- - 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 +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 , Christian Güdel +Message-ID: <1396975740-22160-1-git-send-email-tiwai@suse.de> + +From: Takashi Iwai + +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 +Reported-by: Anssi Hannula +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + +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 +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 + +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 +Signed-off-by: Paul Moore +Acked-by: Eric Paris +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 18 Jan 2014 12:48:16 +0100 +Subject: x86, pageattr: Export page unmapping interface + +From: Borislav Petkov + +commit 42a5477251f0e0f33ad5f6a95c48d685ec03191e upstream. + +We will use it in efi so expose it. + +Signed-off-by: Borislav Petkov +Tested-by: Toshi Kani +Signed-off-by: Matt Fleming +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 18 Jan 2014 12:48:17 +0100 +Subject: x86/efi: Make efi virtual runtime map passing more robust + +From: Borislav Petkov + +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 +Signed-off-by: Borislav Petkov +Tested-by: Toshi Kani +Signed-off-by: Matt Fleming +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Tue, 8 Apr 2014 15:30:07 -0700 +Subject: futex: avoid race between requeue and wake + +From: Linus Torvalds + +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 +Acked-by: Davidlohr Bueso +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Fri, 28 Mar 2014 11:39:05 +0000 +Subject: xen-netback: remove pointless clause from if statement + +From: Paul Durrant + +[ 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 +Cc: Ian Campbell +Cc: Wei Liu +Cc: Sander Eikelenboom +Reported-By: Sander Eikelenboom +Tested-By: Sander Eikelenboom +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Fri, 28 Mar 2014 11:39:06 +0000 +Subject: xen-netback: worse-case estimate in xenvif_rx_action is underestimating + +From: Paul Durrant + +[ 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 +Cc: Ian Campbell +Cc: Wei Liu +Cc: Sander Eikelenboom +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Fri, 28 Mar 2014 11:39:07 +0000 +Subject: xen-netback: BUG_ON in xenvif_rx_action() not catching overflow + +From: Paul Durrant + +[ 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 +Cc: Ian Campbell +Cc: Wei Liu +Cc: Sander Eikelenboom +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Mon, 31 Mar 2014 20:14:10 +0200 +Subject: ipv6: some ipv6 statistic counters failed to disable bh + +From: Hannes Frederic Sowa + +[ 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 +Tested-by: Fabio Estevam +Cc: Eric Dumazet +Signed-off-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Tue, 1 Apr 2014 19:38:44 +0200 +Subject: netlink: don't compare the nul-termination in nla_strcmp + +From: Pablo Neira + +[ 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 +Cc: Thomas Graf +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +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 + +[ 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 +Signed-off-by: Wei Liu +Cc: Ian Campbell +Reviewed-by: David Vrabel +Acked-by: Ian Campbell +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Tue, 1 Apr 2014 13:10:34 +0100 +Subject: Call efx_set_channels() before efx->type->dimension_resources() + +From: Daniel Pieczko + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Tue, 1 Apr 2014 09:23:01 +0300 +Subject: net: vxlan: fix crash when interface is created with no group + +From: Mike Rapoport + +[ 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 +$ 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: [] 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:[] [] 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: + + [] ip6_dst_lookup_tail+0x2d/0xa4 + [] ip6_dst_lookup+0x10/0x12 + [] vxlan_xmit_one+0x32a/0x68c + [] ? _raw_spin_unlock_irqrestore+0x12/0x14 + [] ? lock_timer_base.isra.23+0x26/0x4b + [] vxlan_xmit+0x66a/0x6a8 + [] ? ipt_do_table+0x35f/0x37e + [] ? selinux_ip_postroute+0x41/0x26e + [] dev_hard_start_xmit+0x2ce/0x3ce + [] __dev_queue_xmit+0x2d0/0x392 + [] ? eth_header+0x28/0xb5 + [] dev_queue_xmit+0xb/0xd + [] neigh_resolve_output+0x134/0x152 + [] ip_finish_output2+0x236/0x299 + [] ip_finish_output+0x98/0x9d + [] ip_output+0x62/0x67 + [] dst_output+0xf/0x11 + [] ip_local_out+0x1b/0x1f + [] ip_send_skb+0x11/0x37 + [] ip_push_pending_frames+0x2f/0x33 + [] icmp_push_reply+0x106/0x115 + [] icmp_reply+0x142/0x164 + [] icmp_echo.part.16+0x46/0x48 + [] ? nf_iterate+0x43/0x80 + [] ? xfrm4_policy_check.constprop.11+0x52/0x52 + [] icmp_echo+0x25/0x27 + [] icmp_rcv+0x1d2/0x20a + [] ? xfrm4_policy_check.constprop.11+0x52/0x52 + [] ip_local_deliver_finish+0xd6/0x14f + [] ? xfrm4_policy_check.constprop.11+0x52/0x52 + [] NF_HOOK.constprop.10+0x4c/0x53 + [] ip_local_deliver+0x4a/0x4f + [] ip_rcv_finish+0x253/0x26a + [] ? inet_add_protocol+0x3e/0x3e + [] NF_HOOK.constprop.10+0x4c/0x53 + [] ip_rcv+0x2a6/0x2ec + [] __netif_receive_skb_core+0x43e/0x478 + [] ? virtqueue_poll+0x16/0x27 + [] __netif_receive_skb+0x55/0x5a + [] process_backlog+0x76/0x12f + [] net_rx_action+0xa2/0x1ab + [] __do_softirq+0xca/0x1d1 + [] irq_exit+0x3e/0x85 + [] do_IRQ+0xa9/0xc4 + [] common_interrupt+0x6d/0x6d + + [] ? native_safe_halt+0x6/0x8 + [] default_idle+0x9/0xd + [] arch_cpu_idle+0x13/0x1c + [] cpu_startup_entry+0xbc/0x137 + [] 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 [] ip6_route_output+0x58/0x82 + RSP + 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Wed, 2 Apr 2014 12:48:42 +0900 +Subject: isdnloop: Validate NUL-terminated strings from user. + +From: YOSHIFUJI Hideaki + +[ Upstream commit 77bc6bed7121936bb2e019a8c336075f4c8eef62 ] + +Return -EINVAL unless all of user-given strings are correctly +NUL-terminated. + +Signed-off-by: YOSHIFUJI Hideaki +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Tue, 8 Apr 2014 12:23:09 +0300 +Subject: isdnloop: several buffer overflows + +From: Dan Carpenter + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +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 + +[ Upstream commit bf39b4247b8799935ea91d90db250ab608a58e50 ] + +Binding might result in a NULL device which is later dereferenced +without checking. + +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Sun, 6 Apr 2014 20:37:44 +0200 +Subject: net/at91_ether: avoid NULL pointer dereference + +From: Gilles Chanteperdrix + +[ 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 +Acked-by: Nicolas Ferre +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 +Date: Sun, 16 Mar 2014 05:23:21 +0200 +Subject: iwlwifi: mvm: rs: fix search cycle rules + +From: Eyal Shapira + +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 +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 16 May 2013 19:36:08 +0200 +Subject: ARC: [nsimosci] Change .dts to use generic 8250 UART + +From: Mischa Jonker + +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 +Signed-off-by: Vineet Gupta +Cc: Francois Bedard +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sat, 5 Apr 2014 15:30:22 +0530 +Subject: ARC: [nsimosci] Unbork console + +From: Vineet Gupta + +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 +Cc: Francois Bedard +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Sun, 2 Mar 2014 13:09:47 +0100 +Subject: futex: Allow architectures to skip futex_atomic_cmpxchg_inatomic() test + +From: Heiko Carstens + +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 +Cc: Finn Thain +Cc: Geert Uytterhoeven +Link: http://lkml.kernel.org/r/20140302120947.GA3641@osiris +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 6 Mar 2014 10:29:27 +1100 +Subject: m68k: Skip futex_atomic_cmpxchg_inatomic() test + +From: Finn Thain + +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 +Acked-by: Geert Uytterhoeven +Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1403061006440.5525@nippy.intranet +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +Date: Thu, 27 Mar 2014 18:14:40 +0100 +Subject: crypto: ghash-clmulni-intel - use C implementation for setkey() + +From: Ard Biesheuvel + +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 +Acked-by: H. Peter Anvin +Fixes: 0e1227d356e9b (crypto: ghash - Add PCLMULQDQ accelerated implementation) +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +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 +Acked-by: Greg Kroah-Hartman +Signed-off-by: Marcel Holtmann +--- +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 -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 -Signed-off-by: Dmitry Torokhov ---- - 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: -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 ; - 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 + 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 - ); Thu, 12 Dec 2013 15:37:13 -0500 -Received: by mail-ea0-f179.google.com with SMTP id r15so485140ead.24 - for ; 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 - (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); - Thu, 12 Dec 2013 12:37:01 -0800 (PST) -From: Paolo Bonzini -To: linux-kernel@vger.kernel.org -Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, - Andy Honig , 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: -X-Mailing-List: stable@vger.kernel.org - -From: Andy Honig - -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 -Cc: stable@vger.kernel.org -Signed-off-by: Andrew Honig -Signed-off-by: Paolo Bonzini ---- - 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 +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 + +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: -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 ; - 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 + 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 - ); Thu, 12 Dec 2013 15:37:17 -0500 -Received: by mail-ea0-f169.google.com with SMTP id l9so411843eaj.0 - for ; 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 - (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); - Thu, 12 Dec 2013 12:37:14 -0800 (PST) -From: Paolo Bonzini -To: linux-kernel@vger.kernel.org -Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, - Andy Honig , 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: -X-Mailing-List: stable@vger.kernel.org - -From: Andy Honig - -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 -Cc: stable@vger.kernel.org -Signed-off-by: Andrew Honig -Signed-off-by: Paolo Bonzini ---- - 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: -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 ; - 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 - + 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 - ); - Thu, 12 Dec 2013 15:37:15 -0500 -Received: by mail-ee0-f45.google.com with SMTP id d49so478739eek.32 - for ; 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 - (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); - Thu, 12 Dec 2013 12:37:12 -0800 (PST) -From: Paolo Bonzini -To: linux-kernel@vger.kernel.org -Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, - Andy Honig , 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: -X-Mailing-List: linux-kernel@vger.kernel.org - -From: Andy Honig - -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 -Cc: stable@vger.kernel.org -Signed-off-by: Andrew Honig -Signed-off-by: Paolo Bonzini ---- - 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: -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 ; - 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 + 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 - ); Thu, 12 Dec 2013 15:37:18 -0500 -Received: by mail-ee0-f54.google.com with SMTP id e51so406857eek.13 - for ; 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 - (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); - Thu, 12 Dec 2013 12:37:16 -0800 (PST) -From: Paolo Bonzini -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: -X-Mailing-List: stable@vger.kernel.org - -From: Gleb Natapov - -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 -Cc: stable@vger.kernel.org -Signed-off-by: Gleb Natapov -Signed-off-by: Paolo Bonzini ---- - 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 +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 -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 -Signed-off-by: David S. Miller ---- -(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 -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 -Signed-off-by: Benoit Cousson ---- - 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 -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 -Reviewed-by: Javier Martinez Canillas -Acked-by: Mark Rutland -Signed-off-by: Benoit Cousson ---- - 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 -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 ] -Drop DT entries that are non-hardware-description as discussed in [1] - -[1] https://patchwork.kernel.org/patch/2226761/ - -Signed-off-by: Matt Porter -Signed-off-by: Joel A Fernandes -Signed-off-by: Benoit Cousson ---- - 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 -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 -Signed-off-by: Joel A Fernandes -Signed-off-by: Benoit Cousson ---- - 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 -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 -Acked-by: Tony Lindgren -Signed-off-by: Joel Fernandes -Signed-off-by: Benoit Cousson ---- - .../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 -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 -Signed-off-by: Koen Kooi -Tested-by: Kevin Hilman -Reviewed-by: Nishanth Menon -Signed-off-by: Benoit Cousson ---- - 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 -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 -Tested-by: Kevin Hilman -Reviewed-by: Nishanth Menon -[bcousson@baylibre.com: Fix traling spaces and useless comments] -Signed-off-by: Benoit Cousson ---- - 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 -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 -Tested-by: Kevin Hilman -Reviewed-by: Nishanth Menon -Signed-off-by: Benoit Cousson ---- - 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 -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 -Tested-by: Kevin Hilman -Reviewed-by: Nishanth Menon -Signed-off-by: Benoit Cousson ---- - 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 -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 -Signed-off-by: Benoit Cousson ---- - 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 -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 -Signed-off-by: Benoit Cousson ---- - 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 -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 -Tested-by: Mugunthan V N -Signed-off-by: Benoit Cousson ---- - 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 -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 -Cc: Sekhar Nori -Cc: Koen Kooi -Signed-off-by: Nishanth Menon -Tested-by: Felipe Balbi -Tested-by: Balaji T K -Signed-off-by: Benoit Cousson ---- - 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 -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 -Tested-by: Felipe Balbi -Signed-off-by: Benoit Cousson ---- - 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 -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 - Signed-off-by: Joel Fernandes - Signed-off-by: Benoit Cousson - -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 -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 - Signed-off-by: Joel Fernandes - Signed-off-by: Benoit Cousson - -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 -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 - Signed-off-by: Tony Lindgren - -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 -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 -Reviewed-by: Stephen Warren ---- - .../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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 "); -+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 -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 ---- - 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 -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 -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 ---- - 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 - #include - #include -+#include -+#include - - /* 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 -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 "); - 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 -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 ---- - 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 +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 -Acked-by: Igor Grinberg ---- - 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 + Signed-off-by: Igor Grinberg + Signed-off-by: Shawn Guo +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 ++ * + * 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 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand_1>; -+ status = "okay"; -+}; -+ +&fec { + pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet_1>; ++ pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + status = "okay"; +}; + -+&uart4 { ++&gpmi { + pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart4_1>; ++ pinctrl-0 = <&pinctrl_gpmi_nand>; + 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 - ++ ++&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>; ++ status = "okay"; ++}; ++ ++&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 +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 +--- + 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_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_OMAP3_PANDORA=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y -# CONFIG_MACH_OMAP3EVM is not set -# CONFIG_MACH_OMAP3517EVM is not set -CONFIG_MACH_CRANEBOARD=y -CONFIG_MACH_OMAP3_PANDORA=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 -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 ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 - #include - #include -+#include - #include - #include - #include -@@ -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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 -Signed-off-by: Matthew Garrett ---- - 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 -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 ---- -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 -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 ---- - 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 + +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: +Reviewed-by: Johannes Berg +Signed-off-by: Emmanuel Grumbach +--- + 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 1051748 +Patch25035: Bluetooth-allocate-static-minor-for-vhci.patch -#rhbz 993744 -Patch25128: dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch +#rhbz 1046495 +Patch25044: iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch -#rhbz 1000439 -Patch25129: cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch +#CVE-2014-0155 rhbz 1081589 1085016 +Patch25036: KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch -Patch25140: drm-qxl-backport-fixes-for-Fedora.patch +#rhbz 1048314 +Patch25062: 0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.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 958826 -Patch25164: dell-laptop.patch - -#rhbz 1030802 -Patch25170: Input-elantech-add-support-for-newer-August-2013-dev.patch -Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch - -#CVE-2013-6367 rhbz 1032207 1042081 -Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.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 1051748 +ApplyPatch Bluetooth-allocate-static-minor-for-vhci.patch -#rhbz 993744 -ApplyPatch dm-cache-policy-mq_fix-large-scale-table-allocation-bug.patch +#rhbz 1046495 +ApplyPatch iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch -#rhbz 1000439 -ApplyPatch cpupower-Fix-segfault-due-to-incorrect-getopt_long-a.patch +#CVE-2014-0155 rhbz 1081589 1085016 +ApplyPatch KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch -ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch +#rhbz 1048314 +ApplyPatch 0001-HID-rmi-introduce-RMI-driver-for-Synaptics-touchpads.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 - -#CVE-2013-6367 rhbz 1032207 1042081 -ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch - -#CVE-2013-6368 rhbz 1032210 1042090 -ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch - -#CVE-2013-6376 rhbz 1033106 1042099 -ApplyPatch KVM-x86-fix-guest-initiated-crash-with-x2apic.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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 - #include - #include "internal.h" -+#include - - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 . 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 -+ -+#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 -+ -+#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 -+#include -+ -+/* -+ * 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 -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 ---- - 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 --#include -- --/* -- * 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 - - #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 - #include - #include -+#include - - #ifdef __KERNEL__ - #include -@@ -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 -+#include - #include - - /* -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 - #include - #include -+#include -+#include - #include - #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 -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 and Scott Mayhew - for tracking this down. - -This may be the cause of: - -BUG: unable to handle kernel NULL pointer dereference at 0000000000000070 -IP: [] 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:[] 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 - 0000000000000000 ffff880a000000d0 ffff880c6ab337a8 000000000000000f - ffffffffa03afb93 000000000000000f ffff88186c7882c0 0000000000000014 -Call Trace: - [] request_key+0x65/0xa0 - [] nfs_idmap_request_key+0xc5/0x170 [nfs] - [] nfs_idmap_lookup_id+0x34/0x80 [nfs] - [] nfs_map_group_to_gid+0x75/0xa0 [nfs] - [] decode_getfattr_attrs+0xbdd/0xfb0 [nfs] - [] ? __dequeue_entity+0x30/0x50 - [] ? __switch_to+0x26e/0x320 - [] decode_getfattr+0x83/0xe0 [nfs] - [] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs] - [] nfs4_xdr_dec_getattr+0x8f/0xa0 [nfs] - [] rpcauth_unwrap_resp+0x84/0xb0 [sunrpc] - [] ? nfs4_xdr_dec_getattr+0x0/0xa0 [nfs] - [] call_decode+0x1b3/0x800 [sunrpc] - [] ? wake_bit_function+0x0/0x50 - [] ? call_decode+0x0/0x800 [sunrpc] - [] __rpc_execute+0x77/0x350 [sunrpc] - [] ? bit_waitqueue+0x17/0xd0 - [] rpc_execute+0x61/0xa0 [sunrpc] - [] rpc_run_task+0x75/0x90 [sunrpc] - [] rpc_call_sync+0x42/0x70 [sunrpc] - [] _nfs4_call_sync+0x30/0x40 [nfs] - [] _nfs4_proc_getattr+0xac/0xc0 [nfs] - [] ? futex_wait+0x227/0x380 - [] nfs4_proc_getattr+0x56/0x80 [nfs] - [] __nfs_revalidate_inode+0xe3/0x220 [nfs] - [] nfs_revalidate_mapping+0x4e/0x170 [nfs] - [] nfs_file_read+0x77/0x130 [nfs] - [] do_sync_read+0xfa/0x140 - [] ? autoremove_wake_function+0x0/0x40 - [] ? apic_timer_interrupt+0xe/0x20 - [] ? common_interrupt+0xe/0x13 - [] ? selinux_file_permission+0xfb/0x150 - [] ? security_file_permission+0x16/0x20 - [] vfs_read+0xb5/0x1a0 - [] sys_read+0x51/0x90 - [] ? __audit_syscall_exit+0x265/0x290 - [] system_call_fastpath+0x16/0x1b - -Signed-off-by: David Howells -cc: Dave Wysochanski -cc: Scott Mayhew ---- - 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 -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 -Signed-off-by: David Howells ---- - 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 -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 -Acked-by: Simo Sorce ---- - 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 -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 -Signed-off-by: David Howells ---- - 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 -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:[] dentry_open+0xd1/0xe0 - ... - Call Trace: - [] big_key_read+0x55/0x100 - [] keyctl_read_key+0xb4/0xe0 - [] SyS_keyctl+0xf8/0x1d0 - [] system_call_fastpath+0x16/0x1b - -Signed-off-by: David Howells -Reviewed-by: Stephen Gallagher ---- - 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 -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:[] dput+0x21/0x2d0 - ... - Call Trace: - [] path_put+0x16/0x30 - [] big_key_destroy+0x44/0x60 - [] key_gc_unused_keys.constprop.2+0x5b/0xe0 - [] key_garbage_collector+0x1df/0x3c0 - [] process_one_work+0x17b/0x460 - [] worker_thread+0x11b/0x400 - [] ? rescuer_thread+0x3e0/0x3e0 - [] kthread+0xc0/0xd0 - [] ? kthread_create_on_node+0x110/0x110 - [] ret_from_fork+0x7c/0xb0 - [] ? kthread_create_on_node+0x110/0x110 - -Reported-by: Patrik Kis -Signed-off-by: David Howells -Reviewed-by: Stephen Gallagher ---- - 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 -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 -Signed-off-by: David Howells -Tested-by: Stephen Gallagher ---- - 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 -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: [] hash_key_type_and_desc+0x18/0xb0 -... -RIP: 0010:[] hash_key_type_and_desc+0x18/0xb0 -... -Call Trace: - [] keyring_diff_objects+0x21/0xd2 - [] assoc_array_insert+0x3b6/0x908 - [] __key_link_begin+0x78/0xe5 - [] key_create_or_update+0x17d/0x36a - [] SyS_add_key+0x123/0x183 - [] tracesys+0xdd/0xe2 - -Signed-off-by: David Howells -Tested-by: Stephen Gallagher ---- - 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 -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 -Tested-by: Stephen Gallagher ---- - 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 -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 -Signed-off-by: David Howells -cc: Hugh Dickins -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//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//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//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 -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 -Tested-by: Simo Sorce ---- - 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 -+ -+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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 -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." 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 -Tested-by: Simo Sorce -cc: Serge E. Hallyn -cc: Eric W. Biederman ---- - 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 -+#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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 - #include - - struct x509_certificate { --- -1.8.3.1 - - -From a326ca89468c73dacb00fa247e92873d09e1387b Mon Sep 17 00:00:00 2001 -From: David Howells -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 -Signed-off-by: David Howells ---- - 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 -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 -Reviewed-by: Kees Cook -Reviewed-by: Josh Boyer ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -+ -+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 -- --#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 --#include --#include --#include --#include --#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 - #include - #include -+#include - #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 -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#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 -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 -Reviewed-by: Kees Cook ---- - 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 -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 asymmetric id:d24b1226 - -should find the key, despite that not being its exact description. - -Signed-off-by: David Howells ---- - 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 -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 -Signed-off-by: David Howells ---- - 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 -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 -Signed-off-by: David Howells ---- - 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 - #include - #include -+#include - #include - #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 -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 -Signed-off-by: David Howells ---- - 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 +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 +Reported-by: Laszlo Ersek +Tested-by: Laszlo Ersek +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + 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 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 + 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 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 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 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 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 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 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 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 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 -Signed-off-by: Trond Myklebust ---- - 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 - #include - #include -+#include - #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 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 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 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 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 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 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 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 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 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 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 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 #include -@@ -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 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 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 #include -@@ -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 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 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 -@@ -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 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 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 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 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 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 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 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 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 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 -Signed-off-by: Trond Myklebust ---- - 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 -Signed-off-by: Trond Myklebust ---- - Fixed up to apply to 3.12.1 by Josh Boyer - - 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 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