Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On 03/21/18 16:03, Andy Shevchenko wrote: > On Thu, Mar 15, 2018 at 7:57 AM, Kirill Marinushkin >wrote: >> On 03/13/18 22:23, Andy Shevchenko wrote: >>> On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin >>> wrote: In the current implementation, `rmmod snd_bcm2835` does not release resources properly. It causes an oops when trying to list sound devices. This commit fixes it. >>> Nice catch! >>> >>> See my comments below. >>> static void snd_devm_unregister_child(struct device *dev, void *res) { struct device *childdev = *(struct device **)res; + struct bcm2835_chip *chip = dev_get_drvdata(childdev); + struct snd_card *card = chip->card; + + snd_card_free(card); + dev_set_drvdata(childdev, NULL); >>> AFAIU this is done by device core. >> Maybe you are right. But I don't know, which function in the device core >> does it. >> It is safe to have this line. So, I suggest to keep it. > Please, remove. > If you don't know, perhaps you need to spend more time on doing homework? You are right, I actually should pay more attention to this detail. I will remove this line and send as a patch v3 > % git grep -n -w dev_set_drvdata -- drivers/base/dd.c > drivers/base/dd.c:469: dev_set_drvdata(dev, NULL); > drivers/base/dd.c:499: dev_set_drvdata(dev, NULL); > drivers/base/dd.c:902: dev_set_drvdata(dev, NULL); > > Last one is the point of your interest. >
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On 03/21/18 16:03, Andy Shevchenko wrote: > On Thu, Mar 15, 2018 at 7:57 AM, Kirill Marinushkin > wrote: >> On 03/13/18 22:23, Andy Shevchenko wrote: >>> On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin >>> wrote: In the current implementation, `rmmod snd_bcm2835` does not release resources properly. It causes an oops when trying to list sound devices. This commit fixes it. >>> Nice catch! >>> >>> See my comments below. >>> static void snd_devm_unregister_child(struct device *dev, void *res) { struct device *childdev = *(struct device **)res; + struct bcm2835_chip *chip = dev_get_drvdata(childdev); + struct snd_card *card = chip->card; + + snd_card_free(card); + dev_set_drvdata(childdev, NULL); >>> AFAIU this is done by device core. >> Maybe you are right. But I don't know, which function in the device core >> does it. >> It is safe to have this line. So, I suggest to keep it. > Please, remove. > If you don't know, perhaps you need to spend more time on doing homework? You are right, I actually should pay more attention to this detail. I will remove this line and send as a patch v3 > % git grep -n -w dev_set_drvdata -- drivers/base/dd.c > drivers/base/dd.c:469: dev_set_drvdata(dev, NULL); > drivers/base/dd.c:499: dev_set_drvdata(dev, NULL); > drivers/base/dd.c:902: dev_set_drvdata(dev, NULL); > > Last one is the point of your interest. >
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On Thu, Mar 15, 2018 at 7:57 AM, Kirill Marinushkinwrote: > On 03/13/18 22:23, Andy Shevchenko wrote: >> On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin >> wrote: >>> In the current implementation, `rmmod snd_bcm2835` does not release >>> resources properly. It causes an oops when trying to list sound devices. >>> >>> This commit fixes it. >> Nice catch! >> >> See my comments below. >> >>> static void snd_devm_unregister_child(struct device *dev, void *res) >>> { >>> struct device *childdev = *(struct device **)res; >>> + struct bcm2835_chip *chip = dev_get_drvdata(childdev); >>> + struct snd_card *card = chip->card; >>> + >>> + snd_card_free(card); >>> + dev_set_drvdata(childdev, NULL); >> AFAIU this is done by device core. > > Maybe you are right. But I don't know, which function in the device core does > it. > It is safe to have this line. So, I suggest to keep it. Please, remove. If you don't know, perhaps you need to spend more time on doing homework? % git grep -n -w dev_set_drvdata -- drivers/base/dd.c drivers/base/dd.c:469: dev_set_drvdata(dev, NULL); drivers/base/dd.c:499: dev_set_drvdata(dev, NULL); drivers/base/dd.c:902: dev_set_drvdata(dev, NULL); Last one is the point of your interest. -- With Best Regards, Andy Shevchenko
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On Thu, Mar 15, 2018 at 7:57 AM, Kirill Marinushkin wrote: > On 03/13/18 22:23, Andy Shevchenko wrote: >> On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin >> wrote: >>> In the current implementation, `rmmod snd_bcm2835` does not release >>> resources properly. It causes an oops when trying to list sound devices. >>> >>> This commit fixes it. >> Nice catch! >> >> See my comments below. >> >>> static void snd_devm_unregister_child(struct device *dev, void *res) >>> { >>> struct device *childdev = *(struct device **)res; >>> + struct bcm2835_chip *chip = dev_get_drvdata(childdev); >>> + struct snd_card *card = chip->card; >>> + >>> + snd_card_free(card); >>> + dev_set_drvdata(childdev, NULL); >> AFAIU this is done by device core. > > Maybe you are right. But I don't know, which function in the device core does > it. > It is safe to have this line. So, I suggest to keep it. Please, remove. If you don't know, perhaps you need to spend more time on doing homework? % git grep -n -w dev_set_drvdata -- drivers/base/dd.c drivers/base/dd.c:469: dev_set_drvdata(dev, NULL); drivers/base/dd.c:499: dev_set_drvdata(dev, NULL); drivers/base/dd.c:902: dev_set_drvdata(dev, NULL); Last one is the point of your interest. -- With Best Regards, Andy Shevchenko
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On 03/13/18 22:23, Andy Shevchenko wrote: > On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin >wrote: >> In the current implementation, `rmmod snd_bcm2835` does not release >> resources properly. It causes an oops when trying to list sound devices. >> >> This commit fixes it. > Nice catch! > > See my comments below. > >> static void snd_devm_unregister_child(struct device *dev, void *res) >> { >> struct device *childdev = *(struct device **)res; >> + struct bcm2835_chip *chip = dev_get_drvdata(childdev); >> + struct snd_card *card = chip->card; >> + >> + snd_card_free(card); >> + dev_set_drvdata(childdev, NULL); > AFAIU this is done by device core. Maybe you are right. But I don't know, which function in the device core does it. It is safe to have this line. So, I suggest to keep it. > >> device_unregister(childdev); >> } >> +static void snd_devm_release(struct device *dev) >> +{ >> + struct bcm2835_chip *chip = dev_get_drvdata(dev); >> + >> + kfree(chip); >> +} > >> /* chip-specific constructor >> @@ -122,7 +136,7 @@ static int snd_bcm2835_create(struct snd_card *card, >> >> err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, ); >> if (err) { >> - snd_bcm2835_free(chip); >> + kfree(chip); > Do you call device_register() inside snd_device_new()? > In this case you might need put_device() here instead of simple kfree(). No, from what I see, device_register() does not happen inside snd_device_new(). >> return err; >> }
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On 03/13/18 22:23, Andy Shevchenko wrote: > On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin > wrote: >> In the current implementation, `rmmod snd_bcm2835` does not release >> resources properly. It causes an oops when trying to list sound devices. >> >> This commit fixes it. > Nice catch! > > See my comments below. > >> static void snd_devm_unregister_child(struct device *dev, void *res) >> { >> struct device *childdev = *(struct device **)res; >> + struct bcm2835_chip *chip = dev_get_drvdata(childdev); >> + struct snd_card *card = chip->card; >> + >> + snd_card_free(card); >> + dev_set_drvdata(childdev, NULL); > AFAIU this is done by device core. Maybe you are right. But I don't know, which function in the device core does it. It is safe to have this line. So, I suggest to keep it. > >> device_unregister(childdev); >> } >> +static void snd_devm_release(struct device *dev) >> +{ >> + struct bcm2835_chip *chip = dev_get_drvdata(dev); >> + >> + kfree(chip); >> +} > >> /* chip-specific constructor >> @@ -122,7 +136,7 @@ static int snd_bcm2835_create(struct snd_card *card, >> >> err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, ); >> if (err) { >> - snd_bcm2835_free(chip); >> + kfree(chip); > Do you call device_register() inside snd_device_new()? > In this case you might need put_device() here instead of simple kfree(). No, from what I see, device_register() does not happen inside snd_device_new(). >> return err; >> }
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkinwrote: > In the current implementation, `rmmod snd_bcm2835` does not release > resources properly. It causes an oops when trying to list sound devices. > > This commit fixes it. Nice catch! See my comments below. > static void snd_devm_unregister_child(struct device *dev, void *res) > { > struct device *childdev = *(struct device **)res; > + struct bcm2835_chip *chip = dev_get_drvdata(childdev); > + struct snd_card *card = chip->card; > + > + snd_card_free(card); > + dev_set_drvdata(childdev, NULL); AFAIU this is done by device core. > device_unregister(childdev); > } > +static void snd_devm_release(struct device *dev) > +{ > + struct bcm2835_chip *chip = dev_get_drvdata(dev); > + > + kfree(chip); > +} > /* chip-specific constructor > @@ -122,7 +136,7 @@ static int snd_bcm2835_create(struct snd_card *card, > > err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, ); > if (err) { > - snd_bcm2835_free(chip); > + kfree(chip); Do you call device_register() inside snd_device_new()? In this case you might need put_device() here instead of simple kfree(). > return err; > } -- With Best Regards, Andy Shevchenko
Re: [PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
On Tue, Mar 13, 2018 at 9:34 PM, Kirill Marinushkin wrote: > In the current implementation, `rmmod snd_bcm2835` does not release > resources properly. It causes an oops when trying to list sound devices. > > This commit fixes it. Nice catch! See my comments below. > static void snd_devm_unregister_child(struct device *dev, void *res) > { > struct device *childdev = *(struct device **)res; > + struct bcm2835_chip *chip = dev_get_drvdata(childdev); > + struct snd_card *card = chip->card; > + > + snd_card_free(card); > + dev_set_drvdata(childdev, NULL); AFAIU this is done by device core. > device_unregister(childdev); > } > +static void snd_devm_release(struct device *dev) > +{ > + struct bcm2835_chip *chip = dev_get_drvdata(dev); > + > + kfree(chip); > +} > /* chip-specific constructor > @@ -122,7 +136,7 @@ static int snd_bcm2835_create(struct snd_card *card, > > err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, ); > if (err) { > - snd_bcm2835_free(chip); > + kfree(chip); Do you call device_register() inside snd_device_new()? In this case you might need put_device() here instead of simple kfree(). > return err; > } -- With Best Regards, Andy Shevchenko
[PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
In the current implementation, `rmmod snd_bcm2835` does not release resources properly. It causes an oops when trying to list sound devices. This commit fixes it. The details WRT allocation / free are described below. Device structure WRT allocation: pdev \childdev[] \card \chip \pcm \ctl Allocation / register sequence: * childdev: devm_kzalloc - freed during driver detach * childdev: device_initialize - freed during device_unregister * pdev: devres_alloc - freed during driver detach * childdev: device_add- removed during device_unregister * pdev, childdev: devres_add - freed during driver detach * card: snd_card_new - freed during snd_card_free * chip: kzalloc - freed during kfree * card, chip: snd_device_new - freed during snd_device_free * chip: new_pcm - TODO: free pcm * chip: new_ctl - TODO: free ctl * card: snd_card_register - unregistered during snd_card_free Free / unregister sequence: * card: snd_card_free * card, chip: snd_device_free * childdev: device_unregister * chip: kfree Steps to reproduce the issue before this commit: $ rmmod snd_bcm2835 $ aplay -L [ 138.648130] Unable to handle kernel paging request at virtual address 7f1343c0 [ 138.660415] pgd = ad8f [ 138.665567] [7f1343c0] *pgd=3864c811, *pte=, *ppte= [ 138.674887] Internal error: Oops: 7 [#1] SMP ARM [ 138.683571] Modules linked in: sha256_generic cfg80211 rfkill snd_pcm snd_timer snd fixed uio_pdrv_genirq uio ip_tables x_tables ipv6 [last unloaded: snd_bcm2835 ] [ 138.706594] CPU: 3 PID: 463 Comm: aplay Tainted: GWC 4.15.0-rc1-v 7+ #6 [ 138.719833] Hardware name: BCM2835 [ 138.726016] task: b877ac00 task.stack: aebec000 [ 138.733408] PC is at try_module_get+0x38/0x24c [ 138.740813] LR is at snd_ctl_open+0x58/0x194 [snd] [ 138.748485] pc : [<801c4d5c>]lr : [<7f0e6b2c>]psr: 2013 [ 138.757709] sp : aebedd60 ip : aebedd88 fp : aebedd84 [ 138.765884] r10: r9 : 0004 r8 : 7f0ed440 [ 138.774040] r7 : b7e469b0 r6 : 7f0e6b2c r5 : afd91900 r4 : 7f1343c0 [ 138.783571] r3 : aebec000 r2 : 0001 r1 : b877ac00 r0 : 7f1343c0 [ 138.793084] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 138.803300] Control: 10c5387d Table: 2d8f006a DAC: 0055 [ 138.812064] Process aplay (pid: 463, stack limit = 0xaebec210) [ 138.820868] Stack: (0xaebedd60 to 0xaebee000) [ 138.828207] dd60: b848d000 afd91900 b7e469b0 7f0ed440 aebedda4 aebedd88 [ 138.842371] dd80: 7f0e6b2c 801c4d30 afd91900 7f0ea4dc b7e469b0 aebeddcc aebedda8 [ 138.856611] dda0: 7f0e250c 7f0e6ae0 7f0e2464 b8478ec0 b7e469b0 afd91900 7f0ea388 [ 138.870864] ddc0: aebeddf4 aebeddd0 802ce590 7f0e2470 8090ab64 afd91900 afd91900 b7e469b0 [ 138.885301] dde0: afd91908 802ce4e4 aebede1c aebeddf8 802c57b4 802ce4f0 afd91900 aebedea8 [ 138.900110] de00: b7fa4c00 0004 aebede3c aebede20 802c6ba8 802c56b4 [ 138.915260] de20: aebedea8 aebedf5c aebedea4 aebede40 802d9a68 802c6b58 [ 138.930661] de40: b874ddd0 0001 0041 afd91900 aebede70 [ 138.946402] de60: 0002 b7e469b0 b8a87610 b8d6ab80 801852f8 0008 [ 138.962314] de80: aebedf5c aebedea8 0001 80108464 aebec000 aebedf4c aebedea8 [ 138.978414] dea0: 802dacd4 802d970c b8a87610 b8d6ab80 a7982bc6 0009 af363019 b9231480 [ 138.994617] dec0: b8c038a0 b7e469b0 0101 0002 0238 [ 139.010823] dee0: aebedee8 0008 000f aebedf3c aebedf00 802ed7e4 80843f94 [ 139.027025] df00: 0003 0008 b9231490 b9231480 0008 af363000 [ 139.043229] df20: 0005 0002 ff9c 0008 ff9c af363000 0003 [ 139.059430] df40: aebedf94 aebedf50 802c6f70 802dac70 aebec000 0001 [ 139.075629] df60: 0002 0004 0100 0001 7ebe577c 0002e038 0005 [ 139.091828] df80: 80108464 aebec000 aebedfa4 aebedf98 802c7060 802c6e6c aebedfa8 [ 139.108025] dfa0: 801082c0 802c7040 7ebe577c 0002e038 7ebe577c 0008 0b98 e81c8400 [ 139.124222] dfc0: 7ebe577c 0002e038 0005 7ebe57e4 00a20af8 7ebe57f0 76f87394 [ 139.140419] dfe0: 7ebe55c4 76ec88e8 76df1d9c 6010 7ebe577c [ 139.156715] [<801c4d5c>] (try_module_get) from [<7f0e6b2c>] (snd_ctl_open+0x58/0x194 [snd]) [ 139.173222] [<7f0e6b2c>] (snd_ctl_open [snd]) from [<7f0e250c>] (snd_open+0xa8/0x14c [snd]) [ 139.189683] [<7f0e250c>] (snd_open [snd]) from [<802ce590>] (chrdev_open+0xac/0x188) [ 139.205465] [<802ce590>] (chrdev_open) from [<802c57b4>] (do_dentry_open+0x10c/0x314) [ 139.221347] [<802c57b4>] (do_dentry_open) from [<802c6ba8>] (vfs_open+0x5c/0x88) [ 139.236788] [<802c6ba8>] (vfs_open) from [<802d9a68>]
[PATCH v2] staging: bcm2835-audio: Release resources on module_exit()
In the current implementation, `rmmod snd_bcm2835` does not release resources properly. It causes an oops when trying to list sound devices. This commit fixes it. The details WRT allocation / free are described below. Device structure WRT allocation: pdev \childdev[] \card \chip \pcm \ctl Allocation / register sequence: * childdev: devm_kzalloc - freed during driver detach * childdev: device_initialize - freed during device_unregister * pdev: devres_alloc - freed during driver detach * childdev: device_add- removed during device_unregister * pdev, childdev: devres_add - freed during driver detach * card: snd_card_new - freed during snd_card_free * chip: kzalloc - freed during kfree * card, chip: snd_device_new - freed during snd_device_free * chip: new_pcm - TODO: free pcm * chip: new_ctl - TODO: free ctl * card: snd_card_register - unregistered during snd_card_free Free / unregister sequence: * card: snd_card_free * card, chip: snd_device_free * childdev: device_unregister * chip: kfree Steps to reproduce the issue before this commit: $ rmmod snd_bcm2835 $ aplay -L [ 138.648130] Unable to handle kernel paging request at virtual address 7f1343c0 [ 138.660415] pgd = ad8f [ 138.665567] [7f1343c0] *pgd=3864c811, *pte=, *ppte= [ 138.674887] Internal error: Oops: 7 [#1] SMP ARM [ 138.683571] Modules linked in: sha256_generic cfg80211 rfkill snd_pcm snd_timer snd fixed uio_pdrv_genirq uio ip_tables x_tables ipv6 [last unloaded: snd_bcm2835 ] [ 138.706594] CPU: 3 PID: 463 Comm: aplay Tainted: GWC 4.15.0-rc1-v 7+ #6 [ 138.719833] Hardware name: BCM2835 [ 138.726016] task: b877ac00 task.stack: aebec000 [ 138.733408] PC is at try_module_get+0x38/0x24c [ 138.740813] LR is at snd_ctl_open+0x58/0x194 [snd] [ 138.748485] pc : [<801c4d5c>]lr : [<7f0e6b2c>]psr: 2013 [ 138.757709] sp : aebedd60 ip : aebedd88 fp : aebedd84 [ 138.765884] r10: r9 : 0004 r8 : 7f0ed440 [ 138.774040] r7 : b7e469b0 r6 : 7f0e6b2c r5 : afd91900 r4 : 7f1343c0 [ 138.783571] r3 : aebec000 r2 : 0001 r1 : b877ac00 r0 : 7f1343c0 [ 138.793084] Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 138.803300] Control: 10c5387d Table: 2d8f006a DAC: 0055 [ 138.812064] Process aplay (pid: 463, stack limit = 0xaebec210) [ 138.820868] Stack: (0xaebedd60 to 0xaebee000) [ 138.828207] dd60: b848d000 afd91900 b7e469b0 7f0ed440 aebedda4 aebedd88 [ 138.842371] dd80: 7f0e6b2c 801c4d30 afd91900 7f0ea4dc b7e469b0 aebeddcc aebedda8 [ 138.856611] dda0: 7f0e250c 7f0e6ae0 7f0e2464 b8478ec0 b7e469b0 afd91900 7f0ea388 [ 138.870864] ddc0: aebeddf4 aebeddd0 802ce590 7f0e2470 8090ab64 afd91900 afd91900 b7e469b0 [ 138.885301] dde0: afd91908 802ce4e4 aebede1c aebeddf8 802c57b4 802ce4f0 afd91900 aebedea8 [ 138.900110] de00: b7fa4c00 0004 aebede3c aebede20 802c6ba8 802c56b4 [ 138.915260] de20: aebedea8 aebedf5c aebedea4 aebede40 802d9a68 802c6b58 [ 138.930661] de40: b874ddd0 0001 0041 afd91900 aebede70 [ 138.946402] de60: 0002 b7e469b0 b8a87610 b8d6ab80 801852f8 0008 [ 138.962314] de80: aebedf5c aebedea8 0001 80108464 aebec000 aebedf4c aebedea8 [ 138.978414] dea0: 802dacd4 802d970c b8a87610 b8d6ab80 a7982bc6 0009 af363019 b9231480 [ 138.994617] dec0: b8c038a0 b7e469b0 0101 0002 0238 [ 139.010823] dee0: aebedee8 0008 000f aebedf3c aebedf00 802ed7e4 80843f94 [ 139.027025] df00: 0003 0008 b9231490 b9231480 0008 af363000 [ 139.043229] df20: 0005 0002 ff9c 0008 ff9c af363000 0003 [ 139.059430] df40: aebedf94 aebedf50 802c6f70 802dac70 aebec000 0001 [ 139.075629] df60: 0002 0004 0100 0001 7ebe577c 0002e038 0005 [ 139.091828] df80: 80108464 aebec000 aebedfa4 aebedf98 802c7060 802c6e6c aebedfa8 [ 139.108025] dfa0: 801082c0 802c7040 7ebe577c 0002e038 7ebe577c 0008 0b98 e81c8400 [ 139.124222] dfc0: 7ebe577c 0002e038 0005 7ebe57e4 00a20af8 7ebe57f0 76f87394 [ 139.140419] dfe0: 7ebe55c4 76ec88e8 76df1d9c 6010 7ebe577c [ 139.156715] [<801c4d5c>] (try_module_get) from [<7f0e6b2c>] (snd_ctl_open+0x58/0x194 [snd]) [ 139.173222] [<7f0e6b2c>] (snd_ctl_open [snd]) from [<7f0e250c>] (snd_open+0xa8/0x14c [snd]) [ 139.189683] [<7f0e250c>] (snd_open [snd]) from [<802ce590>] (chrdev_open+0xac/0x188) [ 139.205465] [<802ce590>] (chrdev_open) from [<802c57b4>] (do_dentry_open+0x10c/0x314) [ 139.221347] [<802c57b4>] (do_dentry_open) from [<802c6ba8>] (vfs_open+0x5c/0x88) [ 139.236788] [<802c6ba8>] (vfs_open) from [<802d9a68>]