powerpc/powernv: fix construction of opal PRD messages
[cascardo/linux.git] / arch / powerpc / platforms / powernv / opal-prd.c
index d9e72bd..46cb3fe 100644 (file)
 #include <asm/uaccess.h>
 
 
+/**
+ * The msg member must be at the end of the struct, as it's followed by the
+ * message data.
+ */
 struct opal_prd_msg_queue_item {
-       struct opal_prd_msg_header      msg;
        struct list_head                list;
+       struct opal_prd_msg_header      msg;
 };
 
 static struct device_node *prd_node;
@@ -351,22 +355,23 @@ static int opal_prd_msg_notifier(struct notifier_block *nb,
        struct opal_prd_msg_queue_item *item;
        struct opal_prd_msg_header *hdr;
        struct opal_msg *msg = _msg;
+       int msg_size, item_size;
        unsigned long flags;
-       int size;
 
        if (msg_type != OPAL_MSG_PRD)
                return 0;
 
-       /* Calculate total size of the item we need to store. The 'size' field
-        * in the header includes the header itself. */
+       /* Calculate total size of the message and item we need to store. The
+        * 'size' field in the header includes the header itself. */
        hdr = (void *)msg->params;
-       size = (sizeof(*item) - sizeof(item->msg)) + be16_to_cpu(hdr->size);
+       msg_size = be16_to_cpu(hdr->size);
+       item_size = msg_size + sizeof(*item) - sizeof(item->msg);
 
-       item = kzalloc(size, GFP_ATOMIC);
+       item = kzalloc(item_size, GFP_ATOMIC);
        if (!item)
                return -ENOMEM;
 
-       memcpy(&item->msg, msg->params, size);
+       memcpy(&item->msg, msg->params, msg_size);
 
        spin_lock_irqsave(&opal_prd_msg_queue_lock, flags);
        list_add_tail(&item->list, &opal_prd_msg_queue);