The struct ps3_notification_device in the ps3_probe_thread routine
is too large to be on the stack, causing a warning for an
allmodconfig build with clang.

Change the struct ps3_notification_device from a variable on the stack
to a dynamically allocated variable.

Reported-by: Arnd Bergmann <a...@kernel.org>
Signed-off-by: Geoff Levand <ge...@infradead.org>

diff --git a/arch/powerpc/platforms/ps3/device-init.c 
b/arch/powerpc/platforms/ps3/device-init.c
index 878bc160246e..03292869e6a1 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -770,49 +770,51 @@ static struct task_struct *probe_task;
 
 static int ps3_probe_thread(void *data)
 {
-       struct ps3_notification_device dev;
+       struct {
+               struct ps3_notification_device dev;
+               u8 buf[512];
+       } *local;
+       struct ps3_notify_cmd *notify_cmd;
+       struct ps3_notify_event *notify_event;
        int res;
        unsigned int irq;
        u64 lpar;
-       void *buf;
-       struct ps3_notify_cmd *notify_cmd;
-       struct ps3_notify_event *notify_event;
 
        pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__);
 
-       buf = kzalloc(512, GFP_KERNEL);
-       if (!buf)
+       local = kzalloc(sizeof(local), GFP_KERNEL);
+       if (!local)
                return -ENOMEM;
 
-       lpar = ps3_mm_phys_to_lpar(__pa(buf));
-       notify_cmd = buf;
-       notify_event = buf;
+       lpar = ps3_mm_phys_to_lpar(__pa(&local->buf));
+       notify_cmd = (struct ps3_notify_cmd *)&local->buf;
+       notify_event = (struct ps3_notify_event *)&local->buf;
 
        /* dummy system bus device */
-       dev.sbd.bus_id = (u64)data;
-       dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID;
-       dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID;
+       local->dev.sbd.bus_id = (u64)data;
+       local->dev.sbd.dev_id = PS3_NOTIFICATION_DEV_ID;
+       local->dev.sbd.interrupt_id = PS3_NOTIFICATION_INTERRUPT_ID;
 
-       res = lv1_open_device(dev.sbd.bus_id, dev.sbd.dev_id, 0);
+       res = lv1_open_device(local->dev.sbd.bus_id, local->dev.sbd.dev_id, 0);
        if (res) {
                pr_err("%s:%u: lv1_open_device failed %s\n", __func__,
                       __LINE__, ps3_result(res));
                goto fail_free;
        }
 
-       res = ps3_sb_event_receive_port_setup(&dev.sbd, PS3_BINDING_CPU_ANY,
-                                             &irq);
+       res = ps3_sb_event_receive_port_setup(&local->dev.sbd,
+               PS3_BINDING_CPU_ANY, &irq);
        if (res) {
                pr_err("%s:%u: ps3_sb_event_receive_port_setup failed %d\n",
                       __func__, __LINE__, res);
               goto fail_close_device;
        }
 
-       spin_lock_init(&dev.lock);
-       rcuwait_init(&dev.wait);
+       spin_lock_init(&local->dev.lock);
+       rcuwait_init(&local->dev.wait);
 
        res = request_irq(irq, ps3_notification_interrupt, 0,
-                         "ps3_notification", &dev);
+                         "ps3_notification", &local->dev);
        if (res) {
                pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
                       res);
@@ -823,7 +825,7 @@ static int ps3_probe_thread(void *data)
        notify_cmd->operation_code = 0; /* must be zero */
        notify_cmd->event_mask = 1UL << notify_region_probe;
 
-       res = ps3_notification_read_write(&dev, lpar, 1);
+       res = ps3_notification_read_write(&local->dev, lpar, 1);
        if (res)
                goto fail_free_irq;
 
@@ -834,36 +836,37 @@ static int ps3_probe_thread(void *data)
 
                memset(notify_event, 0, sizeof(*notify_event));
 
-               res = ps3_notification_read_write(&dev, lpar, 0);
+               res = ps3_notification_read_write(&local->dev, lpar, 0);
                if (res)
                        break;
 
                pr_debug("%s:%u: notify event type 0x%llx bus id %llu dev id 
%llu"
                         " type %llu port %llu\n", __func__, __LINE__,
-                        notify_event->event_type, notify_event->bus_id,
-                        notify_event->dev_id, notify_event->dev_type,
-                        notify_event->dev_port);
+                       notify_event->event_type, notify_event->bus_id,
+                       notify_event->dev_id, notify_event->dev_type,
+                       notify_event->dev_port);
 
                if (notify_event->event_type != notify_region_probe ||
-                   notify_event->bus_id != dev.sbd.bus_id) {
+                       notify_event->bus_id != local->dev.sbd.bus_id) {
                        pr_warn("%s:%u: bad notify_event: event %llu, dev_id 
%llu, dev_type %llu\n",
                                __func__, __LINE__, notify_event->event_type,
                                notify_event->dev_id, notify_event->dev_type);
                        continue;
                }
 
-               ps3_find_and_add_device(dev.sbd.bus_id, notify_event->dev_id);
+               ps3_find_and_add_device(local->dev.sbd.bus_id,
+                       notify_event->dev_id);
 
        } while (!kthread_should_stop());
 
 fail_free_irq:
-       free_irq(irq, &dev);
+       free_irq(irq, &local->dev);
 fail_sb_event_receive_port_destroy:
-       ps3_sb_event_receive_port_destroy(&dev.sbd, irq);
+       ps3_sb_event_receive_port_destroy(&local->dev.sbd, irq);
 fail_close_device:
-       lv1_close_device(dev.sbd.bus_id, dev.sbd.dev_id);
+       lv1_close_device(local->dev.sbd.bus_id, local->dev.sbd.dev_id);
 fail_free:
-       kfree(buf);
+       kfree(local);
 
        probe_task = NULL;
 

Reply via email to