Merge branch 'stable-4.6' of git://git.infradead.org/users/pcmoore/audit
[cascardo/linux.git] / drivers / staging / nvec / nvec.c
index 4ae44a5..9fda136 100644 (file)
@@ -14,8 +14,6 @@
  *
  */
 
-/* #define DEBUG */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/atomic.h>
 #include "nvec.h"
 
 #define I2C_CNFG                       0x00
-#define I2C_CNFG_PACKET_MODE_EN                (1 << 10)
-#define I2C_CNFG_NEW_MASTER_SFM                (1 << 11)
+#define I2C_CNFG_PACKET_MODE_EN                BIT(10)
+#define I2C_CNFG_NEW_MASTER_SFM                BIT(11)
 #define I2C_CNFG_DEBOUNCE_CNT_SHIFT    12
 
 #define I2C_SL_CNFG            0x20
-#define I2C_SL_NEWSL           (1 << 2)
-#define I2C_SL_NACK            (1 << 1)
-#define I2C_SL_RESP            (1 << 0)
-#define I2C_SL_IRQ             (1 << 3)
-#define END_TRANS              (1 << 4)
-#define RCVD                   (1 << 2)
-#define RNW                    (1 << 1)
+#define I2C_SL_NEWSL           BIT(2)
+#define I2C_SL_NACK            BIT(1)
+#define I2C_SL_RESP            BIT(0)
+#define I2C_SL_IRQ             BIT(3)
+#define END_TRANS              BIT(4)
+#define RCVD                   BIT(2)
+#define RNW                    BIT(1)
 
 #define I2C_SL_RCVD            0x24
 #define I2C_SL_STATUS          0x28
@@ -143,14 +141,14 @@ static int nvec_status_notifier(struct notifier_block *nb,
 {
        struct nvec_chip *nvec = container_of(nb, struct nvec_chip,
                                                nvec_status_notifier);
-       unsigned char *msg = (unsigned char *)data;
+       unsigned char *msg = data;
 
        if (event_type != NVEC_CNTL)
                return NOTIFY_DONE;
 
        dev_warn(nvec->dev, "unhandled msg type %ld\n", event_type);
        print_hex_dump(KERN_WARNING, "payload: ", DUMP_PREFIX_NONE, 16, 1,
-               msg, msg[1] + 2, true);
+                      msg, msg[1] + 2, true);
 
        return NOTIFY_OK;
 }
@@ -259,7 +257,7 @@ static void nvec_gpio_set_value(struct nvec_chip *nvec, int value)
  * occurred, the nvec driver may print an error.
  */
 int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
-                       short size)
+                    short size)
 {
        struct nvec_msg *msg;
        unsigned long flags;
@@ -288,46 +286,49 @@ EXPORT_SYMBOL(nvec_write_async);
  * @nvec: An &struct nvec_chip
  * @data: The data to write
  * @size: The size of @data
+ * @msg:  The response message received
  *
  * This is similar to nvec_write_async(), but waits for the
  * request to be answered before returning. This function
  * uses a mutex and can thus not be called from e.g.
  * interrupt handlers.
  *
- * Returns: A pointer to the response message on success,
- * %NULL on failure. Free with nvec_msg_free() once no longer
- * used.
+ * Returns: 0 on success, a negative error code on failure.
+ * The response message is returned in @msg. Shall be freed with
+ * with nvec_msg_free() once no longer used.
+ *
  */
-struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
-               const unsigned char *data, short size)
+int nvec_write_sync(struct nvec_chip *nvec,
+                   const unsigned char *data, short size,
+                   struct nvec_msg **msg)
 {
-       struct nvec_msg *msg;
-
        mutex_lock(&nvec->sync_write_mutex);
 
+       *msg = NULL;
        nvec->sync_write_pending = (data[1] << 8) + data[0];
 
        if (nvec_write_async(nvec, data, size) < 0) {
                mutex_unlock(&nvec->sync_write_mutex);
-               return NULL;
+               return -ENOMEM;
        }
 
        dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n",
-                                       nvec->sync_write_pending);
+               nvec->sync_write_pending);
        if (!(wait_for_completion_timeout(&nvec->sync_write,
-                               msecs_to_jiffies(2000)))) {
-               dev_warn(nvec->dev, "timeout waiting for sync write to complete\n");
+                                         msecs_to_jiffies(2000)))) {
+               dev_warn(nvec->dev,
+                        "timeout waiting for sync write to complete\n");
                mutex_unlock(&nvec->sync_write_mutex);
-               return NULL;
+               return -ETIMEDOUT;
        }
 
        dev_dbg(nvec->dev, "nvec_sync_write: pong!\n");
 
-       msg = nvec->last_sync_msg;
+       *msg = nvec->last_sync_msg;
 
        mutex_unlock(&nvec->sync_write_mutex);
 
-       return msg;
+       return 0;
 }
 EXPORT_SYMBOL(nvec_write_sync);
 
@@ -422,8 +423,8 @@ static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg)
 
        if ((msg->data[0] >> 7) == 1 && (msg->data[0] & 0x0f) == 5)
                print_hex_dump(KERN_WARNING, "ec system event ",
-                               DUMP_PREFIX_NONE, 16, 1, msg->data,
-                               msg->data[1] + 2, true);
+                              DUMP_PREFIX_NONE, 16, 1, msg->data,
+                              msg->data[1] + 2, true);
 
        atomic_notifier_call_chain(&nvec->notifier_list, msg->data[0] & 0x8f,
                                   msg->data);
@@ -493,8 +494,8 @@ static void nvec_rx_completed(struct nvec_chip *nvec)
 {
        if (nvec->rx->pos != nvec_msg_size(nvec->rx)) {
                dev_err(nvec->dev, "RX incomplete: Expected %u bytes, got %u\n",
-                          (uint) nvec_msg_size(nvec->rx),
-                          (uint) nvec->rx->pos);
+                       (uint)nvec_msg_size(nvec->rx),
+                       (uint)nvec->rx->pos);
 
                nvec_msg_free(nvec, nvec->rx);
                nvec->state = 0;
@@ -508,8 +509,10 @@ static void nvec_rx_completed(struct nvec_chip *nvec)
 
        spin_lock(&nvec->rx_lock);
 
-       /* add the received data to the work list
-          and move the ring buffer pointer to the next entry */
+       /*
+        * Add the received data to the work list and move the ring buffer
+        * pointer to the next entry.
+        */
        list_add_tail(&nvec->rx->node, &nvec->rx_data);
 
        spin_unlock(&nvec->rx_lock);
@@ -638,11 +641,9 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
                        nvec_msg_free(nvec, nvec->rx);
                        nvec->state = 3;
                        nvec_tx_set(nvec);
-                       BUG_ON(nvec->tx->size < 1);
                        to_send = nvec->tx->data[0];
                        nvec->tx->pos = 1;
                } else if (status == (I2C_SL_IRQ)) {
-                       BUG_ON(nvec->rx == NULL);
                        nvec->rx->data[1] = received;
                        nvec->rx->pos = 2;
                        nvec->state = 4;
@@ -686,8 +687,8 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
        if ((status & (RCVD | RNW)) == RCVD) {
                if (received != nvec->i2c_addr)
                        dev_err(nvec->dev,
-                       "received address 0x%02x, expected 0x%02x\n",
-                       received, nvec->i2c_addr);
+                               "received address 0x%02x, expected 0x%02x\n",
+                               received, nvec->i2c_addr);
                nvec->state = 1;
        }
 
@@ -776,7 +777,7 @@ static int nvec_i2c_parse_dt_pdata(struct nvec_chip *nvec)
        }
 
        if (of_property_read_u32(nvec->dev->of_node, "slave-addr",
-                               &nvec->i2c_addr)) {
+                                &nvec->i2c_addr)) {
                dev_err(nvec->dev, "no i2c address specified");
                return -ENODEV;
        }
@@ -852,14 +853,14 @@ static int tegra_nvec_probe(struct platform_device *pdev)
        INIT_WORK(&nvec->tx_work, nvec_request_master);
 
        err = devm_gpio_request_one(&pdev->dev, nvec->gpio, GPIOF_OUT_INIT_HIGH,
-                                       "nvec gpio");
+                                   "nvec gpio");
        if (err < 0) {
                dev_err(nvec->dev, "couldn't request gpio\n");
                return -ENODEV;
        }
 
        err = devm_request_irq(&pdev->dev, nvec->irq, nvec_interrupt, 0,
-                               "nvec", nvec);
+                              "nvec", nvec);
        if (err) {
                dev_err(nvec->dev, "couldn't request irq\n");
                return -ENODEV;
@@ -878,11 +879,13 @@ static int tegra_nvec_probe(struct platform_device *pdev)
        pm_power_off = nvec_power_off;
 
        /* Get Firmware Version */
-       msg = nvec_write_sync(nvec, get_firmware_version, 2);
+       err = nvec_write_sync(nvec, get_firmware_version, 2, &msg);
 
-       if (msg) {
-               dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n",
-                       msg->data[4], msg->data[5], msg->data[6], msg->data[7]);
+       if (!err) {
+               dev_warn(nvec->dev,
+                        "ec firmware version %02x.%02x.%02x / %02x\n",
+                        msg->data[4], msg->data[5],
+                        msg->data[6], msg->data[7]);
 
                nvec_msg_free(nvec, msg);
        }
@@ -924,6 +927,7 @@ static int tegra_nvec_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int nvec_suspend(struct device *dev)
 {
+       int err;
        struct platform_device *pdev = to_platform_device(dev);
        struct nvec_chip *nvec = platform_get_drvdata(pdev);
        struct nvec_msg *msg;
@@ -934,8 +938,9 @@ static int nvec_suspend(struct device *dev)
        /* keep these sync or you'll break suspend */
        nvec_toggle_global_events(nvec, false);
 
-       msg = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend));
-       nvec_msg_free(nvec, msg);
+       err = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend), &msg);
+       if (!err)
+               nvec_msg_free(nvec, msg);
 
        nvec_disable_i2c_slave(nvec);