On Fri, Apr 15, 2016 at 10:47:52AM +1000, Alistair Popple wrote:
>Hi Gavin,
>
>I was reading through this to understand how it all works and noticed a couple
>of things, comments below.
>
Alistair, thanks for your time on review.

>
>On Wed, 17 Feb 2016 14:44:28 Gavin Shan wrote:
>
><snip>
>
>> +
>> +static void pnv_php_handle_poweron(struct pnv_php_slot *php_slot)
>> +{
>> +    void *fdt, *fdt1, *dt;
>> +    int confirm = PNV_PHP_POWER_CONFIRMED_SUCCESS;
>> +    int ret;
>> +
>> +    /* We don't know the FDT blob size. We try to get it through
>> +     * maximal memory chunk and then copy it to another chunk that
>> +     * fits the real size.
>> +     */
>> +    fdt1 = kzalloc(0x10000, GFP_KERNEL);
>> +    if (!fdt1)
>> +            goto error;
>> +
>> +    ret = pnv_pci_get_device_tree(php_slot->dn->phandle, fdt1, 0x10000);
>> +    if (ret)
>> +            goto free_fdt1;
>> +
>> +    fdt = kzalloc(fdt_totalsize(fdt1), GFP_KERNEL);
>> +    if (!fdt)
>> +            goto free_fdt1;
>> +
>> +    /* Unflatten device tree blob */
>> +    memcpy(fdt, fdt1, fdt_totalsize(fdt1));
>> +    dt = of_fdt_unflatten_tree(fdt, php_slot->dn, NULL);
>> +    if (!dt) {
>> +            dev_warn(&php_slot->pdev->dev, "Cannot unflatten FDT\n");
>> +            goto free_fdt;
>> +    }
>> +
>> +    /* Initialize and apply the changeset */
>> +    of_changeset_init(&php_slot->ocs);
>> +    ret = pnv_php_populate_changeset(&php_slot->ocs, php_slot->dn);
>> +    if (ret) {
>> +            dev_warn(&php_slot->pdev->dev, "Error %d populating 
>> changeset\n",
>> +                     ret);
>> +            goto free_dt;
>> +    }
>> +
>> +    php_slot->dn->child = NULL;
>> +    ret = of_changeset_apply(&php_slot->ocs);
>> +    if (ret) {
>> +            dev_warn(&php_slot->pdev->dev, "Error %d applying changeset\n",
>> +                     ret);
>> +            goto destroy_changeset;
>> +    }
>> +
>> +    /* Add device node firmware data */
>> +    pnv_php_add_pdns(php_slot);
>> +    php_slot->fdt = fdt;
>> +    php_slot->dt  = dt;
>> +    goto out;
>
>Doesn't this leak memory from fdt1? I can't see where it gets freed in this
>case.
>

You're right that @fdt1 should be released here. I'll fix it in
next revision.

>> +destroy_changeset:
>> +    of_changeset_destroy(&php_slot->ocs);
>> +free_dt:
>> +    kfree(dt);
>> +    php_slot->dn->child = NULL;
>> +free_fdt:
>> +    kfree(fdt);
>> +free_fdt1:
>> +    kfree(fdt1);
>> +error:
>> +    confirm = PNV_PHP_POWER_CONFIRMED_FAIL;
>> +out:
>> +    /* Confirm status change */
>> +    php_slot->power_state_confirmed = confirm;
>> +    wake_up_interruptible(&php_slot->queue);
>> +}
>> +
>
><snip>
>
>> +
>> +static void __exit pnv_php_exit(void)
>> +{
>> +    struct device_node *dn;
>> +
>> +    for_each_compatible_node(dn, NULL, "ibm,ioda-phb")
>> +            pnv_php_unregister(dn);
>> +    for_each_compatible_node(dn, NULL, "ibm,ioda2-phb")
>> +            pnv_php_unregister(dn);
>> +
>> +    pnv_pci_hotplug_notifier_unregister(&php_msg_nb);
>
>Do you flush the workqueues anywhere? Usually you would stop work being queued 
>and call something like flush_workqueue() to ensure no work is still
>running/queued before unloading the module.
>

Good question. Yeah, I'll flush the workqueue before the module is going
to be unloaded.

Thanks,
Gavin

>- Alistair
>
>> +}
>> +
>> +module_init(pnv_php_init);
>> +module_exit(pnv_php_exit);
>> +
>> +MODULE_VERSION(DRIVER_VERSION);
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_AUTHOR(DRIVER_AUTHOR);
>> +MODULE_DESCRIPTION(DRIVER_DESC);
>> 
>

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to