]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jul 2017 00:06:28 +0000 (17:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 8 Jul 2017 00:06:28 +0000 (17:06 -0700)
Pull security layer fixes from James Morris:
 "Bugfixes for TPM and SELinux"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  IB/core: Fix static analysis warning in ib_policy_change_task
  IB/core: Fix uninitialized variable use in check_qp_port_pkey_settings
  tpm: do not suspend/resume if power stays on
  tpm: use tpm2_pcr_read() in tpm2_do_selftest()
  tpm: use tpm_buf functions in tpm2_pcr_read()
  tpm_tis: make ilb_base_addr static
  tpm: consolidate the TPM startup code
  tpm: Enable CLKRUN protocol for Braswell systems
  tpm/tpm_crb: fix priv->cmd_size initialisation
  tpm: fix a kernel memory leak in tpm-sysfs.c
  tpm: Issue a TPM2_Shutdown for TPM2 devices.
  Add "shutdown" to "struct class".

12 files changed:
drivers/base/core.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm-sysfs.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_of.c
drivers/char/tpm/tpm_tis.c
drivers/infiniband/core/device.c
drivers/infiniband/core/security.c
include/linux/device.h

index 8dde934f8d15a2906a99a0835a76e5fb0c2c92bc..755451f684bcac6c2e94e3dcccfa279ce90cb80a 100644 (file)
@@ -2664,7 +2664,11 @@ void device_shutdown(void)
                pm_runtime_get_noresume(dev);
                pm_runtime_barrier(dev);
 
-               if (dev->bus && dev->bus->shutdown) {
+               if (dev->class && dev->class->shutdown) {
+                       if (initcall_debug)
+                               dev_info(dev, "shutdown\n");
+                       dev->class->shutdown(dev);
+               } else if (dev->bus && dev->bus->shutdown) {
                        if (initcall_debug)
                                dev_info(dev, "shutdown\n");
                        dev->bus->shutdown(dev);
index 322b8a51ffc67d5d9df216c55503b04ebfc08072..67ec9d3d04f529ba07fa1feb926bd1809a78a405 100644 (file)
@@ -142,6 +142,39 @@ static void tpm_devs_release(struct device *dev)
        put_device(&chip->dev);
 }
 
+/**
+ * tpm_class_shutdown() - prepare the TPM device for loss of power.
+ * @dev: device to which the chip is associated.
+ *
+ * Issues a TPM2_Shutdown command prior to loss of power, as required by the
+ * TPM 2.0 spec.
+ * Then, calls bus- and device- specific shutdown code.
+ *
+ * XXX: This codepath relies on the fact that sysfs is not enabled for
+ * TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2
+ * has sysfs support enabled before TPM sysfs's implicit locking is fixed.
+ */
+static int tpm_class_shutdown(struct device *dev)
+{
+       struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
+
+       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+               down_write(&chip->ops_sem);
+               tpm2_shutdown(chip, TPM2_SU_CLEAR);
+               chip->ops = NULL;
+               up_write(&chip->ops_sem);
+       }
+       /* Allow bus- and device-specific code to run. Note: since chip->ops
+        * is NULL, more-specific shutdown code will not be able to issue TPM
+        * commands.
+        */
+       if (dev->bus && dev->bus->shutdown)
+               dev->bus->shutdown(dev);
+       else if (dev->driver && dev->driver->shutdown)
+               dev->driver->shutdown(dev);
+       return 0;
+}
+
 /**
  * tpm_chip_alloc() - allocate a new struct tpm_chip instance
  * @pdev: device to which the chip is associated
@@ -181,6 +214,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
        device_initialize(&chip->devs);
 
        chip->dev.class = tpm_class;
+       chip->dev.class->shutdown = tpm_class_shutdown;
        chip->dev.release = tpm_dev_release;
        chip->dev.parent = pdev;
        chip->dev.groups = chip->groups;
index d2b4df6d98946682b84d56190202f83bbf80f921..fe597e6c55c40ca34f070f83a2af53e9b42a66de 100644 (file)
@@ -540,6 +540,47 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
 }
 EXPORT_SYMBOL_GPL(tpm_transmit_cmd);
 
+#define TPM_ORD_STARTUP 153
+#define TPM_ST_CLEAR 1
+
+/**
+ * tpm_startup - turn on the TPM
+ * @chip: TPM chip to use
+ *
+ * Normally the firmware should start the TPM. This function is provided as a
+ * workaround if this does not happen. A legal case for this could be for
+ * example when a TPM emulator is used.
+ *
+ * Return: same as tpm_transmit_cmd()
+ */
+int tpm_startup(struct tpm_chip *chip)
+{
+       struct tpm_buf buf;
+       int rc;
+
+       dev_info(&chip->dev, "starting up the TPM manually\n");
+
+       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+               rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
+               if (rc < 0)
+                       return rc;
+
+               tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
+       } else {
+               rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
+               if (rc < 0)
+                       return rc;
+
+               tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
+       }
+
+       rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+                             "attempting to start the TPM");
+
+       tpm_buf_destroy(&buf);
+       return rc;
+}
+
 #define TPM_DIGEST_SIZE 20
 #define TPM_RET_CODE_IDX 6
 #define TPM_INTERNAL_RESULT_SIZE 200
@@ -586,27 +627,6 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
 }
 EXPORT_SYMBOL_GPL(tpm_getcap);
 
-#define TPM_ORD_STARTUP 153
-#define TPM_ST_CLEAR cpu_to_be16(1)
-#define TPM_ST_STATE cpu_to_be16(2)
-#define TPM_ST_DEACTIVATED cpu_to_be16(3)
-static const struct tpm_input_header tpm_startup_header = {
-       .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
-       .length = cpu_to_be32(12),
-       .ordinal = cpu_to_be32(TPM_ORD_STARTUP)
-};
-
-static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
-{
-       struct tpm_cmd_t start_cmd;
-       start_cmd.header.in = tpm_startup_header;
-
-       start_cmd.params.startup_in.startup_type = startup_type;
-       return tpm_transmit_cmd(chip, NULL, &start_cmd,
-                               TPM_INTERNAL_RESULT_SIZE, 0,
-                               0, "attempting to start the TPM");
-}
-
 int tpm_get_timeouts(struct tpm_chip *chip)
 {
        cap_t cap;
@@ -636,10 +656,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
        rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
                        sizeof(cap.timeout));
        if (rc == TPM_ERR_INVALID_POSTINIT) {
-               /* The TPM is not started, we are the first to talk to it.
-                  Execute a startup command. */
-               dev_info(&chip->dev, "Issuing TPM_STARTUP\n");
-               if (tpm_startup(chip, TPM_ST_CLEAR))
+               if (tpm_startup(chip))
                        return rc;
 
                rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
@@ -1102,6 +1119,9 @@ int tpm_pm_suspend(struct device *dev)
        if (chip == NULL)
                return -ENODEV;
 
+       if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
+               return 0;
+
        if (chip->flags & TPM_CHIP_FLAG_TPM2) {
                tpm2_shutdown(chip, TPM2_SU_STATE);
                return 0;
index 4bd0997cfa2d3e0dbf850ad1798eeefa8a27aaa4..86f38d239476ab00a70db97640e0ff843c7dd3de 100644 (file)
@@ -36,9 +36,10 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
        ssize_t err;
        int i, rc;
        char *str = buf;
-
        struct tpm_chip *chip = to_tpm_chip(dev);
 
+       memset(&tpm_cmd, 0, sizeof(tpm_cmd));
+
        tpm_cmd.header.in = tpm_readpubek_header;
        err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
                               READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
@@ -294,6 +295,9 @@ static const struct attribute_group tpm_dev_group = {
 
 void tpm_sysfs_add_device(struct tpm_chip *chip)
 {
+       /* XXX: If you wish to remove this restriction, you must first update
+        * tpm_sysfs to explicitly lock chip->ops.
+        */
        if (chip->flags & TPM_CHIP_FLAG_TPM2)
                return;
 
index 1df0521138d316816f89fceb9db143c917155ded..04fbff2edbf38ce19845e5c1fdd1cd619293419d 100644 (file)
 #include <linux/highmem.h>
 #include <crypto/hash_info.h>
 
+#ifdef CONFIG_X86
+#include <asm/intel-family.h>
+#endif
+
 enum tpm_const {
        TPM_MINOR = 224,        /* officially assigned */
        TPM_BUFSIZE = 4096,
@@ -170,6 +174,7 @@ enum tpm_chip_flags {
        TPM_CHIP_FLAG_IRQ               = BIT(2),
        TPM_CHIP_FLAG_VIRTUAL           = BIT(3),
        TPM_CHIP_FLAG_HAVE_TIMEOUTS     = BIT(4),
+       TPM_CHIP_FLAG_ALWAYS_POWERED    = BIT(5),
 };
 
 struct tpm_bios_log {
@@ -378,10 +383,6 @@ struct tpm_getrandom_in {
        __be32 num_bytes;
 } __packed;
 
-struct tpm_startup_in {
-       __be16  startup_type;
-} __packed;
-
 typedef union {
        struct  tpm_readpubek_params_out readpubek_out;
        u8      readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)];
@@ -389,7 +390,6 @@ typedef union {
        struct  tpm_pcrread_out pcrread_out;
        struct  tpm_getrandom_in getrandom_in;
        struct  tpm_getrandom_out getrandom_out;
-       struct tpm_startup_in startup_in;
 } tpm_cmd_params;
 
 struct tpm_cmd_t {
@@ -515,6 +515,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
                         const void *buf, size_t bufsiz,
                         size_t min_rsp_body_length, unsigned int flags,
                         const char *desc);
+int tpm_startup(struct tpm_chip *chip);
 ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
                   const char *desc, size_t min_cap_length);
 int tpm_get_timeouts(struct tpm_chip *);
index 3a9964326279302d7898774431d332f73d2487b8..f7f34b2aa98190c7474b3dd6c0f02b2abc032ec9 100644 (file)
@@ -35,24 +35,6 @@ struct tpm2_self_test_in {
        u8      full_test;
 } __packed;
 
-struct tpm2_pcr_read_in {
-       __be32  pcr_selects_cnt;
-       __be16  hash_alg;
-       u8      pcr_select_size;
-       u8      pcr_select[TPM2_PCR_SELECT_MIN];
-} __packed;
-
-struct tpm2_pcr_read_out {
-       __be32  update_cnt;
-       __be32  pcr_selects_cnt;
-       __be16  hash_alg;
-       u8      pcr_select_size;
-       u8      pcr_select[TPM2_PCR_SELECT_MIN];
-       __be32  digests_cnt;
-       __be16  digest_size;
-       u8      digest[TPM_DIGEST_SIZE];
-} __packed;
-
 struct tpm2_get_tpm_pt_in {
        __be32  cap_id;
        __be32  property_id;
@@ -79,8 +61,6 @@ struct tpm2_get_random_out {
 union tpm2_cmd_params {
        struct  tpm2_startup_in         startup_in;
        struct  tpm2_self_test_in       selftest_in;
-       struct  tpm2_pcr_read_in        pcrread_in;
-       struct  tpm2_pcr_read_out       pcrread_out;
        struct  tpm2_get_tpm_pt_in      get_tpm_pt_in;
        struct  tpm2_get_tpm_pt_out     get_tpm_pt_out;
        struct  tpm2_get_random_in      getrandom_in;
@@ -227,18 +207,16 @@ static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
        TPM_UNDEFINED           /* 18f */
 };
 
-#define TPM2_PCR_READ_IN_SIZE \
-       (sizeof(struct tpm_input_header) + \
-        sizeof(struct tpm2_pcr_read_in))
-
-#define TPM2_PCR_READ_RESP_BODY_SIZE \
-        sizeof(struct tpm2_pcr_read_out)
-
-static const struct tpm_input_header tpm2_pcrread_header = {
-       .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-       .length = cpu_to_be32(TPM2_PCR_READ_IN_SIZE),
-       .ordinal = cpu_to_be32(TPM2_CC_PCR_READ)
-};
+struct tpm2_pcr_read_out {
+       __be32  update_cnt;
+       __be32  pcr_selects_cnt;
+       __be16  hash_alg;
+       u8      pcr_select_size;
+       u8      pcr_select[TPM2_PCR_SELECT_MIN];
+       __be32  digests_cnt;
+       __be16  digest_size;
+       u8      digest[];
+} __packed;
 
 /**
  * tpm2_pcr_read() - read a PCR value
@@ -251,29 +229,33 @@ static const struct tpm_input_header tpm2_pcrread_header = {
 int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
 {
        int rc;
-       struct tpm2_cmd cmd;
-       u8 *buf;
+       struct tpm_buf buf;
+       struct tpm2_pcr_read_out *out;
+       u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
 
        if (pcr_idx >= TPM2_PLATFORM_PCR)
                return -EINVAL;
 
-       cmd.header.in = tpm2_pcrread_header;
-       cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
-       cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
-       cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
+       rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ);
+       if (rc)
+               return rc;
+
+       pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
 
-       memset(cmd.params.pcrread_in.pcr_select, 0,
-              sizeof(cmd.params.pcrread_in.pcr_select));
-       cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
+       tpm_buf_append_u32(&buf, 1);
+       tpm_buf_append_u16(&buf, TPM2_ALG_SHA1);
+       tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
+       tpm_buf_append(&buf, (const unsigned char *)pcr_select,
+                      sizeof(pcr_select));
 
-       rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
-                             TPM2_PCR_READ_RESP_BODY_SIZE,
-                             0, "attempting to read a pcr value");
-       if (rc == 0) {
-               buf = cmd.params.pcrread_out.digest;
-               memcpy(res_buf, buf, TPM_DIGEST_SIZE);
+       rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+                       res_buf ? "attempting to read a pcr value" : NULL);
+       if (rc == 0 && res_buf) {
+               out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
+               memcpy(res_buf, out->digest, SHA1_DIGEST_SIZE);
        }
 
+       tpm_buf_destroy(&buf);
        return rc;
 }
 
@@ -779,36 +761,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,  u32 *value,
 }
 EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt);
 
-#define TPM2_STARTUP_IN_SIZE \
-       (sizeof(struct tpm_input_header) + \
-        sizeof(struct tpm2_startup_in))
-
-static const struct tpm_input_header tpm2_startup_header = {
-       .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS),
-       .length = cpu_to_be32(TPM2_STARTUP_IN_SIZE),
-       .ordinal = cpu_to_be32(TPM2_CC_STARTUP)
-};
-
-/**
- * tpm2_startup() - send startup command to the TPM chip
- *
- * @chip:              TPM chip to use.
- * @startup_type:      startup type. The value is either
- *                     TPM_SU_CLEAR or TPM_SU_STATE.
- *
- * Return: Same as with tpm_transmit_cmd.
- */
-static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
-{
-       struct tpm2_cmd cmd;
-
-       cmd.header.in = tpm2_startup_header;
-
-       cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
-       return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
-                               "attempting to start the TPM");
-}
-
 #define TPM2_SHUTDOWN_IN_SIZE \
        (sizeof(struct tpm_input_header) + \
         sizeof(struct tpm2_startup_in))
@@ -928,7 +880,6 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
        unsigned int loops;
        unsigned int delay_msec = 100;
        unsigned long duration;
-       struct tpm2_cmd cmd;
        int i;
 
        duration = tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST);
@@ -941,20 +892,10 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
 
        for (i = 0; i < loops; i++) {
                /* Attempt to read a PCR value */
-               cmd.header.in = tpm2_pcrread_header;
-               cmd.params.pcrread_in.pcr_selects_cnt = cpu_to_be32(1);
-               cmd.params.pcrread_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1);
-               cmd.params.pcrread_in.pcr_select_size = TPM2_PCR_SELECT_MIN;
-               cmd.params.pcrread_in.pcr_select[0] = 0x01;
-               cmd.params.pcrread_in.pcr_select[1] = 0x00;
-               cmd.params.pcrread_in.pcr_select[2] = 0x00;
-
-               rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
-                                     NULL);
+               rc = tpm2_pcr_read(chip, 0, NULL);
                if (rc < 0)
                        break;
 
-               rc = be32_to_cpu(cmd.header.out.return_code);
                if (rc != TPM2_RC_TESTING)
                        break;
 
@@ -1150,7 +1091,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
        }
 
        if (rc == TPM2_RC_INITIALIZE) {
-               rc = tpm2_startup(chip, TPM2_SU_CLEAR);
+               rc = tpm_startup(chip);
                if (rc)
                        goto out;
 
index fe42c4a0d8d1a6d283fadf611159d1968066f47c..a4ac63a21d8a051da3c336f5343b9dc72574b719 100644 (file)
@@ -514,11 +514,12 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
                goto out;
        }
 
-       priv->cmd_size = cmd_size;
-
        priv->rsp = priv->cmd;
 
 out:
+       if (!ret)
+               priv->cmd_size = cmd_size;
+
        crb_go_idle(dev, priv);
 
        return ret;
index de57d4ac8901df9b2c2f5585db825efc0ae3587c..aadb7f464076ba8f83fb7775f2ca88cb1386af5a 100644 (file)
@@ -36,6 +36,9 @@ int tpm_read_log_of(struct tpm_chip *chip)
        else
                return -ENODEV;
 
+       if (of_property_read_bool(np, "powered-while-suspended"))
+               chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
+
        sizep = of_get_property(np, "linux,sml-size", NULL);
        basep = of_get_property(np, "linux,sml-base", NULL);
        if (sizep == NULL && basep == NULL)
index b14d4aa97af87afebcf9f84ed9941f8b993fa77c..7e55aa9ce680cbc6cd2802710625e41775c9b2e9 100644 (file)
@@ -132,13 +132,93 @@ static int check_acpi_tpm2(struct device *dev)
 }
 #endif
 
+#ifdef CONFIG_X86
+#define INTEL_LEGACY_BLK_BASE_ADDR      0xFED08000
+#define ILB_REMAP_SIZE                 0x100
+#define LPC_CNTRL_REG_OFFSET            0x84
+#define LPC_CLKRUN_EN                   (1 << 2)
+
+static void __iomem *ilb_base_addr;
+
+static inline bool is_bsw(void)
+{
+       return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0);
+}
+
+/**
+ * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
+ */
+static void tpm_platform_begin_xfer(void)
+{
+       u32 clkrun_val;
+
+       if (!is_bsw())
+               return;
+
+       clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET);
+
+       /* Disable LPC CLKRUN# */
+       clkrun_val &= ~LPC_CLKRUN_EN;
+       iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET);
+
+       /*
+        * Write any random value on port 0x80 which is on LPC, to make
+        * sure LPC clock is running before sending any TPM command.
+        */
+       outb(0xCC, 0x80);
+
+}
+
+/**
+ * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
+ */
+static void tpm_platform_end_xfer(void)
+{
+       u32 clkrun_val;
+
+       if (!is_bsw())
+               return;
+
+       clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET);
+
+       /* Enable LPC CLKRUN# */
+       clkrun_val |= LPC_CLKRUN_EN;
+       iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET);
+
+       /*
+        * Write any random value on port 0x80 which is on LPC, to make
+        * sure LPC clock is running before sending any TPM command.
+        */
+       outb(0xCC, 0x80);
+
+}
+#else
+static inline bool is_bsw(void)
+{
+       return false;
+}
+
+static void tpm_platform_begin_xfer(void)
+{
+}
+
+static void tpm_platform_end_xfer(void)
+{
+}
+#endif
+
 static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
                              u8 *result)
 {
        struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
+       tpm_platform_begin_xfer();
+
        while (len--)
                *result++ = ioread8(phy->iobase + addr);
+
+       tpm_platform_end_xfer();
+
        return 0;
 }
 
@@ -147,8 +227,13 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
 {
        struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
+       tpm_platform_begin_xfer();
+
        while (len--)
                iowrite8(*value++, phy->iobase + addr);
+
+       tpm_platform_end_xfer();
+
        return 0;
 }
 
@@ -156,7 +241,12 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
 {
        struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
+       tpm_platform_begin_xfer();
+
        *result = ioread16(phy->iobase + addr);
+
+       tpm_platform_end_xfer();
+
        return 0;
 }
 
@@ -164,7 +254,12 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
 {
        struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
+       tpm_platform_begin_xfer();
+
        *result = ioread32(phy->iobase + addr);
+
+       tpm_platform_end_xfer();
+
        return 0;
 }
 
@@ -172,7 +267,12 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
 {
        struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
 
+       tpm_platform_begin_xfer();
+
        iowrite32(value, phy->iobase + addr);
+
+       tpm_platform_end_xfer();
+
        return 0;
 }
 
@@ -360,6 +460,11 @@ static int __init init_tis(void)
        if (rc)
                goto err_force;
 
+#ifdef CONFIG_X86
+       if (is_bsw())
+               ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
+                                       ILB_REMAP_SIZE);
+#endif
        rc = platform_driver_register(&tis_drv);
        if (rc)
                goto err_platform;
@@ -378,6 +483,10 @@ err_pnp:
 err_platform:
        if (force_pdev)
                platform_device_unregister(force_pdev);
+#ifdef CONFIG_X86
+       if (is_bsw())
+               iounmap(ilb_base_addr);
+#endif
 err_force:
        return rc;
 }
@@ -387,6 +496,10 @@ static void __exit cleanup_tis(void)
        pnp_unregister_driver(&tis_pnp_driver);
        platform_driver_unregister(&tis_drv);
 
+#ifdef CONFIG_X86
+       if (is_bsw())
+               iounmap(ilb_base_addr);
+#endif
        if (force_pdev)
                platform_device_unregister(force_pdev);
 }
index 631eaa9daf65d30156eafd29635315455c912dfa..a5dfab6adf495b88e846ee03b815536a7917bf48 100644 (file)
@@ -376,7 +376,8 @@ static void ib_policy_change_task(struct work_struct *work)
                        WARN_ONCE(ret,
                                  "ib_get_cached_subnet_prefix err: %d, this should never happen here\n",
                                  ret);
-                       ib_security_cache_change(dev, i, sp);
+                       if (!ret)
+                               ib_security_cache_change(dev, i, sp);
                }
        }
        up_read(&lists_rwsem);
index 3e8c389539127b7c52daaa4d0ab361498502ed04..70ad19c4c73e77da961ffccd9958887dcead8027 100644 (file)
@@ -120,21 +120,25 @@ static int check_qp_port_pkey_settings(struct ib_ports_pkeys *pps,
                return 0;
 
        if (pps->main.state != IB_PORT_PKEY_NOT_VALID) {
-               get_pkey_and_subnet_prefix(&pps->main,
-                                          &pkey,
-                                          &subnet_prefix);
+               ret = get_pkey_and_subnet_prefix(&pps->main,
+                                                &pkey,
+                                                &subnet_prefix);
+               if (ret)
+                       return ret;
 
                ret = enforce_qp_pkey_security(pkey,
                                               subnet_prefix,
                                               sec);
+               if (ret)
+                       return ret;
        }
-       if (ret)
-               return ret;
 
        if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) {
-               get_pkey_and_subnet_prefix(&pps->alt,
-                                          &pkey,
-                                          &subnet_prefix);
+               ret = get_pkey_and_subnet_prefix(&pps->alt,
+                                                &pkey,
+                                                &subnet_prefix);
+               if (ret)
+                       return ret;
 
                ret = enforce_qp_pkey_security(pkey,
                                               subnet_prefix,
index 6baa1238f1580aae38e50eded4ef354f8e0faada..723cd54b94da84f95cd18934d14198b6d21040dd 100644 (file)
@@ -375,6 +375,7 @@ int subsys_virtual_register(struct bus_type *subsys,
  * @suspend:   Used to put the device to sleep mode, usually to a low power
  *             state.
  * @resume:    Used to bring the device from the sleep mode.
+ * @shutdown:  Called at shut-down time to quiesce the device.
  * @ns_type:   Callbacks so sysfs can detemine namespaces.
  * @namespace: Namespace of the device belongs to this class.
  * @pm:                The default device power management operations of this class.
@@ -403,6 +404,7 @@ struct class {
 
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
+       int (*shutdown)(struct device *dev);
 
        const struct kobj_ns_type_operations *ns_type;
        const void *(*namespace)(struct device *dev);