diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2011-11-15 23:49:41 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-24 15:16:40 -0500 |
commit | 9105b8b200410383d0854bbe237ee385d7d33ba6 (patch) | |
tree | f03d48ed0f0f84204e319bdd13c3707238485601 /drivers/staging | |
parent | 37e22142891773fb883bbef435f2ebbb5670c0b0 (diff) |
[media] staging: lirc_serial: Fix init/exit order
Currently the module init function registers a platform_device and
only then allocates its IRQ and I/O region. This allows allocation to
race with the device's suspend() function. Instead, allocate
resources in the platform driver's probe() function and free them in
the remove() function.
The module exit function removes the platform device before the
character device that provides access to it. Change it to reverse the
order of initialisation.
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/media/lirc/lirc_serial.c | 56 |
1 files changed, 21 insertions, 35 deletions
diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c index 8a060a8a7224..86376311506b 100644 --- a/drivers/staging/media/lirc/lirc_serial.c +++ b/drivers/staging/media/lirc/lirc_serial.c | |||
@@ -836,7 +836,7 @@ static int hardware_init_port(void) | |||
836 | return 0; | 836 | return 0; |
837 | } | 837 | } |
838 | 838 | ||
839 | static int init_port(void) | 839 | static int __devinit lirc_serial_probe(struct platform_device *dev) |
840 | { | 840 | { |
841 | int i, nlow, nhigh, result; | 841 | int i, nlow, nhigh, result; |
842 | 842 | ||
@@ -913,6 +913,18 @@ static int init_port(void) | |||
913 | return 0; | 913 | return 0; |
914 | } | 914 | } |
915 | 915 | ||
916 | static int __devexit lirc_serial_remove(struct platform_device *dev) | ||
917 | { | ||
918 | free_irq(irq, (void *)&hardware); | ||
919 | |||
920 | if (iommap != 0) | ||
921 | release_mem_region(iommap, 8 << ioshift); | ||
922 | else | ||
923 | release_region(io, 8); | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
916 | static int set_use_inc(void *data) | 928 | static int set_use_inc(void *data) |
917 | { | 929 | { |
918 | unsigned long flags; | 930 | unsigned long flags; |
@@ -1076,16 +1088,6 @@ static struct lirc_driver driver = { | |||
1076 | 1088 | ||
1077 | static struct platform_device *lirc_serial_dev; | 1089 | static struct platform_device *lirc_serial_dev; |
1078 | 1090 | ||
1079 | static int __devinit lirc_serial_probe(struct platform_device *dev) | ||
1080 | { | ||
1081 | return 0; | ||
1082 | } | ||
1083 | |||
1084 | static int __devexit lirc_serial_remove(struct platform_device *dev) | ||
1085 | { | ||
1086 | return 0; | ||
1087 | } | ||
1088 | |||
1089 | static int lirc_serial_suspend(struct platform_device *dev, | 1091 | static int lirc_serial_suspend(struct platform_device *dev, |
1090 | pm_message_t state) | 1092 | pm_message_t state) |
1091 | { | 1093 | { |
@@ -1188,10 +1190,6 @@ static int __init lirc_serial_init_module(void) | |||
1188 | { | 1190 | { |
1189 | int result; | 1191 | int result; |
1190 | 1192 | ||
1191 | result = lirc_serial_init(); | ||
1192 | if (result) | ||
1193 | return result; | ||
1194 | |||
1195 | switch (type) { | 1193 | switch (type) { |
1196 | case LIRC_HOMEBREW: | 1194 | case LIRC_HOMEBREW: |
1197 | case LIRC_IRDEO: | 1195 | case LIRC_IRDEO: |
@@ -1211,8 +1209,7 @@ static int __init lirc_serial_init_module(void) | |||
1211 | break; | 1209 | break; |
1212 | #endif | 1210 | #endif |
1213 | default: | 1211 | default: |
1214 | result = -EINVAL; | 1212 | return -EINVAL; |
1215 | goto exit_serial_exit; | ||
1216 | } | 1213 | } |
1217 | if (!softcarrier) { | 1214 | if (!softcarrier) { |
1218 | switch (type) { | 1215 | switch (type) { |
@@ -1228,37 +1225,26 @@ static int __init lirc_serial_init_module(void) | |||
1228 | } | 1225 | } |
1229 | } | 1226 | } |
1230 | 1227 | ||
1231 | result = init_port(); | 1228 | result = lirc_serial_init(); |
1232 | if (result < 0) | 1229 | if (result) |
1233 | goto exit_serial_exit; | 1230 | return result; |
1231 | |||
1234 | driver.features = hardware[type].features; | 1232 | driver.features = hardware[type].features; |
1235 | driver.dev = &lirc_serial_dev->dev; | 1233 | driver.dev = &lirc_serial_dev->dev; |
1236 | driver.minor = lirc_register_driver(&driver); | 1234 | driver.minor = lirc_register_driver(&driver); |
1237 | if (driver.minor < 0) { | 1235 | if (driver.minor < 0) { |
1238 | printk(KERN_ERR LIRC_DRIVER_NAME | 1236 | printk(KERN_ERR LIRC_DRIVER_NAME |
1239 | ": register_chrdev failed!\n"); | 1237 | ": register_chrdev failed!\n"); |
1240 | result = -EIO; | 1238 | lirc_serial_exit(); |
1241 | goto exit_release; | 1239 | return -EIO; |
1242 | } | 1240 | } |
1243 | return 0; | 1241 | return 0; |
1244 | exit_release: | ||
1245 | release_region(io, 8); | ||
1246 | exit_serial_exit: | ||
1247 | lirc_serial_exit(); | ||
1248 | return result; | ||
1249 | } | 1242 | } |
1250 | 1243 | ||
1251 | static void __exit lirc_serial_exit_module(void) | 1244 | static void __exit lirc_serial_exit_module(void) |
1252 | { | 1245 | { |
1253 | lirc_serial_exit(); | ||
1254 | |||
1255 | free_irq(irq, (void *)&hardware); | ||
1256 | |||
1257 | if (iommap != 0) | ||
1258 | release_mem_region(iommap, 8 << ioshift); | ||
1259 | else | ||
1260 | release_region(io, 8); | ||
1261 | lirc_unregister_driver(driver.minor); | 1246 | lirc_unregister_driver(driver.minor); |
1247 | lirc_serial_exit(); | ||
1262 | dprintk("cleaned up module\n"); | 1248 | dprintk("cleaned up module\n"); |
1263 | } | 1249 | } |
1264 | 1250 | ||