diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/omap_wdt.c | 132 |
1 files changed, 78 insertions, 54 deletions
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 9c389b16497f..7bcbb7f4745f 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -70,11 +70,14 @@ struct omap_wdt_dev { | |||
70 | static void omap_wdt_ping(struct omap_wdt_dev *wdev) | 70 | static void omap_wdt_ping(struct omap_wdt_dev *wdev) |
71 | { | 71 | { |
72 | void __iomem *base = wdev->base; | 72 | void __iomem *base = wdev->base; |
73 | |||
73 | /* wait for posted write to complete */ | 74 | /* wait for posted write to complete */ |
74 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) | 75 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
75 | cpu_relax(); | 76 | cpu_relax(); |
77 | |||
76 | wdt_trgr_pattern = ~wdt_trgr_pattern; | 78 | wdt_trgr_pattern = ~wdt_trgr_pattern; |
77 | __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); | 79 | __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); |
80 | |||
78 | /* wait for posted write to complete */ | 81 | /* wait for posted write to complete */ |
79 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) | 82 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
80 | cpu_relax(); | 83 | cpu_relax(); |
@@ -83,12 +86,13 @@ static void omap_wdt_ping(struct omap_wdt_dev *wdev) | |||
83 | 86 | ||
84 | static void omap_wdt_enable(struct omap_wdt_dev *wdev) | 87 | static void omap_wdt_enable(struct omap_wdt_dev *wdev) |
85 | { | 88 | { |
86 | void __iomem *base; | 89 | void __iomem *base = wdev->base; |
87 | base = wdev->base; | 90 | |
88 | /* Sequence to enable the watchdog */ | 91 | /* Sequence to enable the watchdog */ |
89 | __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); | 92 | __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); |
90 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) | 93 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) |
91 | cpu_relax(); | 94 | cpu_relax(); |
95 | |||
92 | __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR); | 96 | __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR); |
93 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) | 97 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) |
94 | cpu_relax(); | 98 | cpu_relax(); |
@@ -96,12 +100,13 @@ static void omap_wdt_enable(struct omap_wdt_dev *wdev) | |||
96 | 100 | ||
97 | static void omap_wdt_disable(struct omap_wdt_dev *wdev) | 101 | static void omap_wdt_disable(struct omap_wdt_dev *wdev) |
98 | { | 102 | { |
99 | void __iomem *base; | 103 | void __iomem *base = wdev->base; |
100 | base = wdev->base; | 104 | |
101 | /* sequence required to disable watchdog */ | 105 | /* sequence required to disable watchdog */ |
102 | __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ | 106 | __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ |
103 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) | 107 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) |
104 | cpu_relax(); | 108 | cpu_relax(); |
109 | |||
105 | __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ | 110 | __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ |
106 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) | 111 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) |
107 | cpu_relax(); | 112 | cpu_relax(); |
@@ -119,12 +124,12 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout) | |||
119 | static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | 124 | static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) |
120 | { | 125 | { |
121 | u32 pre_margin = GET_WLDR_VAL(timer_margin); | 126 | u32 pre_margin = GET_WLDR_VAL(timer_margin); |
122 | void __iomem *base; | 127 | void __iomem *base = wdev->base; |
123 | base = wdev->base; | ||
124 | 128 | ||
125 | /* just count up at 32 KHz */ | 129 | /* just count up at 32 KHz */ |
126 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | 130 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
127 | cpu_relax(); | 131 | cpu_relax(); |
132 | |||
128 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); | 133 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); |
129 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | 134 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
130 | cpu_relax(); | 135 | cpu_relax(); |
@@ -133,13 +138,11 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) | |||
133 | /* | 138 | /* |
134 | * Allow only one task to hold it open | 139 | * Allow only one task to hold it open |
135 | */ | 140 | */ |
136 | |||
137 | static int omap_wdt_open(struct inode *inode, struct file *file) | 141 | static int omap_wdt_open(struct inode *inode, struct file *file) |
138 | { | 142 | { |
139 | struct omap_wdt_dev *wdev; | 143 | struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev); |
140 | void __iomem *base; | 144 | void __iomem *base = wdev->base; |
141 | wdev = platform_get_drvdata(omap_wdt_dev); | 145 | |
142 | base = wdev->base; | ||
143 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) | 146 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) |
144 | return -EBUSY; | 147 | return -EBUSY; |
145 | 148 | ||
@@ -154,6 +157,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
154 | /* initialize prescaler */ | 157 | /* initialize prescaler */ |
155 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) | 158 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
156 | cpu_relax(); | 159 | cpu_relax(); |
160 | |||
157 | __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); | 161 | __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); |
158 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) | 162 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
159 | cpu_relax(); | 163 | cpu_relax(); |
@@ -162,13 +166,14 @@ static int omap_wdt_open(struct inode *inode, struct file *file) | |||
162 | 166 | ||
163 | omap_wdt_set_timeout(wdev); | 167 | omap_wdt_set_timeout(wdev); |
164 | omap_wdt_enable(wdev); | 168 | omap_wdt_enable(wdev); |
169 | |||
165 | return nonseekable_open(inode, file); | 170 | return nonseekable_open(inode, file); |
166 | } | 171 | } |
167 | 172 | ||
168 | static int omap_wdt_release(struct inode *inode, struct file *file) | 173 | static int omap_wdt_release(struct inode *inode, struct file *file) |
169 | { | 174 | { |
170 | struct omap_wdt_dev *wdev; | 175 | struct omap_wdt_dev *wdev = file->private_data; |
171 | wdev = file->private_data; | 176 | |
172 | /* | 177 | /* |
173 | * Shut off the timer unless NOWAYOUT is defined. | 178 | * Shut off the timer unless NOWAYOUT is defined. |
174 | */ | 179 | */ |
@@ -187,14 +192,15 @@ static int omap_wdt_release(struct inode *inode, struct file *file) | |||
187 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); | 192 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); |
188 | #endif | 193 | #endif |
189 | wdev->omap_wdt_users = 0; | 194 | wdev->omap_wdt_users = 0; |
195 | |||
190 | return 0; | 196 | return 0; |
191 | } | 197 | } |
192 | 198 | ||
193 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, | 199 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, |
194 | size_t len, loff_t *ppos) | 200 | size_t len, loff_t *ppos) |
195 | { | 201 | { |
196 | struct omap_wdt_dev *wdev; | 202 | struct omap_wdt_dev *wdev = file->private_data; |
197 | wdev = file->private_data; | 203 | |
198 | /* Refresh LOAD_TIME. */ | 204 | /* Refresh LOAD_TIME. */ |
199 | if (len) { | 205 | if (len) { |
200 | spin_lock(&wdt_lock); | 206 | spin_lock(&wdt_lock); |
@@ -214,6 +220,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
214 | .options = WDIOF_SETTIMEOUT, | 220 | .options = WDIOF_SETTIMEOUT, |
215 | .firmware_version = 0, | 221 | .firmware_version = 0, |
216 | }; | 222 | }; |
223 | |||
217 | wdev = file->private_data; | 224 | wdev = file->private_data; |
218 | 225 | ||
219 | switch (cmd) { | 226 | switch (cmd) { |
@@ -262,31 +269,37 @@ static const struct file_operations omap_wdt_fops = { | |||
262 | .release = omap_wdt_release, | 269 | .release = omap_wdt_release, |
263 | }; | 270 | }; |
264 | 271 | ||
265 | |||
266 | static int __init omap_wdt_probe(struct platform_device *pdev) | 272 | static int __init omap_wdt_probe(struct platform_device *pdev) |
267 | { | 273 | { |
268 | struct resource *res, *mem; | 274 | struct resource *res, *mem; |
269 | int ret; | ||
270 | struct omap_wdt_dev *wdev; | 275 | struct omap_wdt_dev *wdev; |
276 | int ret; | ||
271 | 277 | ||
272 | /* reserve static register mappings */ | 278 | /* reserve static register mappings */ |
273 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 279 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
274 | if (!res) | 280 | if (!res) { |
275 | return -ENOENT; | 281 | ret = -ENOENT; |
282 | goto err_get_resource; | ||
283 | } | ||
276 | 284 | ||
277 | if (omap_wdt_dev) | 285 | if (omap_wdt_dev) { |
278 | return -EBUSY; | 286 | ret = -EBUSY; |
287 | goto err_busy; | ||
288 | } | ||
279 | 289 | ||
280 | mem = request_mem_region(res->start, res->end - res->start + 1, | 290 | mem = request_mem_region(res->start, res->end - res->start + 1, |
281 | pdev->name); | 291 | pdev->name); |
282 | if (mem == NULL) | 292 | if (!mem) { |
283 | return -EBUSY; | 293 | ret = -EBUSY; |
294 | goto err_busy; | ||
295 | } | ||
284 | 296 | ||
285 | wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); | 297 | wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); |
286 | if (!wdev) { | 298 | if (!wdev) { |
287 | ret = -ENOMEM; | 299 | ret = -ENOMEM; |
288 | goto fail; | 300 | goto err_kzalloc; |
289 | } | 301 | } |
302 | |||
290 | wdev->omap_wdt_users = 0; | 303 | wdev->omap_wdt_users = 0; |
291 | wdev->mem = mem; | 304 | wdev->mem = mem; |
292 | 305 | ||
@@ -295,7 +308,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev) | |||
295 | if (IS_ERR(wdev->armwdt_ck)) { | 308 | if (IS_ERR(wdev->armwdt_ck)) { |
296 | ret = PTR_ERR(wdev->armwdt_ck); | 309 | ret = PTR_ERR(wdev->armwdt_ck); |
297 | wdev->armwdt_ck = NULL; | 310 | wdev->armwdt_ck = NULL; |
298 | goto fail; | 311 | goto err_clk; |
299 | } | 312 | } |
300 | } | 313 | } |
301 | 314 | ||
@@ -304,13 +317,13 @@ static int __init omap_wdt_probe(struct platform_device *pdev) | |||
304 | if (IS_ERR(wdev->mpu_wdt_ick)) { | 317 | if (IS_ERR(wdev->mpu_wdt_ick)) { |
305 | ret = PTR_ERR(wdev->mpu_wdt_ick); | 318 | ret = PTR_ERR(wdev->mpu_wdt_ick); |
306 | wdev->mpu_wdt_ick = NULL; | 319 | wdev->mpu_wdt_ick = NULL; |
307 | goto fail; | 320 | goto err_clk; |
308 | } | 321 | } |
309 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); | 322 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); |
310 | if (IS_ERR(wdev->mpu_wdt_fck)) { | 323 | if (IS_ERR(wdev->mpu_wdt_fck)) { |
311 | ret = PTR_ERR(wdev->mpu_wdt_fck); | 324 | ret = PTR_ERR(wdev->mpu_wdt_fck); |
312 | wdev->mpu_wdt_fck = NULL; | 325 | wdev->mpu_wdt_fck = NULL; |
313 | goto fail; | 326 | goto err_clk; |
314 | } | 327 | } |
315 | } | 328 | } |
316 | 329 | ||
@@ -319,19 +332,19 @@ static int __init omap_wdt_probe(struct platform_device *pdev) | |||
319 | if (IS_ERR(wdev->mpu_wdt_ick)) { | 332 | if (IS_ERR(wdev->mpu_wdt_ick)) { |
320 | ret = PTR_ERR(wdev->mpu_wdt_ick); | 333 | ret = PTR_ERR(wdev->mpu_wdt_ick); |
321 | wdev->mpu_wdt_ick = NULL; | 334 | wdev->mpu_wdt_ick = NULL; |
322 | goto fail; | 335 | goto err_clk; |
323 | } | 336 | } |
324 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); | 337 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); |
325 | if (IS_ERR(wdev->mpu_wdt_fck)) { | 338 | if (IS_ERR(wdev->mpu_wdt_fck)) { |
326 | ret = PTR_ERR(wdev->mpu_wdt_fck); | 339 | ret = PTR_ERR(wdev->mpu_wdt_fck); |
327 | wdev->mpu_wdt_fck = NULL; | 340 | wdev->mpu_wdt_fck = NULL; |
328 | goto fail; | 341 | goto err_clk; |
329 | } | 342 | } |
330 | } | 343 | } |
331 | wdev->base = ioremap(res->start, res->end - res->start + 1); | 344 | wdev->base = ioremap(res->start, res->end - res->start + 1); |
332 | if (!wdev->base) { | 345 | if (!wdev->base) { |
333 | ret = -ENOMEM; | 346 | ret = -ENOMEM; |
334 | goto fail; | 347 | goto err_ioremap; |
335 | } | 348 | } |
336 | 349 | ||
337 | platform_set_drvdata(pdev, wdev); | 350 | platform_set_drvdata(pdev, wdev); |
@@ -346,7 +359,7 @@ static int __init omap_wdt_probe(struct platform_device *pdev) | |||
346 | 359 | ||
347 | ret = misc_register(&(wdev->omap_wdt_miscdev)); | 360 | ret = misc_register(&(wdev->omap_wdt_miscdev)); |
348 | if (ret) | 361 | if (ret) |
349 | goto fail; | 362 | goto err_misc; |
350 | 363 | ||
351 | pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", | 364 | pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", |
352 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, | 365 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, |
@@ -359,28 +372,34 @@ static int __init omap_wdt_probe(struct platform_device *pdev) | |||
359 | 372 | ||
360 | return 0; | 373 | return 0; |
361 | 374 | ||
362 | fail: | 375 | err_misc: |
363 | if (wdev) { | 376 | platform_set_drvdata(pdev, NULL); |
364 | platform_set_drvdata(pdev, NULL); | 377 | iounmap(wdev->base); |
365 | if (wdev->armwdt_ck) | 378 | |
366 | clk_put(wdev->armwdt_ck); | 379 | err_ioremap: |
367 | if (wdev->mpu_wdt_ick) | 380 | wdev->base = NULL; |
368 | clk_put(wdev->mpu_wdt_ick); | 381 | |
369 | if (wdev->mpu_wdt_fck) | 382 | err_clk: |
370 | clk_put(wdev->mpu_wdt_fck); | 383 | if (wdev->armwdt_ck) |
371 | iounmap(wdev->base); | 384 | clk_put(wdev->armwdt_ck); |
372 | kfree(wdev); | 385 | if (wdev->mpu_wdt_ick) |
373 | } | 386 | clk_put(wdev->mpu_wdt_ick); |
374 | if (mem) { | 387 | if (wdev->mpu_wdt_fck) |
375 | release_mem_region(res->start, res->end - res->start + 1); | 388 | clk_put(wdev->mpu_wdt_fck); |
376 | } | 389 | kfree(wdev); |
390 | |||
391 | err_kzalloc: | ||
392 | release_mem_region(res->start, res->end - res->start + 1); | ||
393 | |||
394 | err_busy: | ||
395 | err_get_resource: | ||
396 | |||
377 | return ret; | 397 | return ret; |
378 | } | 398 | } |
379 | 399 | ||
380 | static void omap_wdt_shutdown(struct platform_device *pdev) | 400 | static void omap_wdt_shutdown(struct platform_device *pdev) |
381 | { | 401 | { |
382 | struct omap_wdt_dev *wdev; | 402 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
383 | wdev = platform_get_drvdata(pdev); | ||
384 | 403 | ||
385 | if (wdev->omap_wdt_users) | 404 | if (wdev->omap_wdt_users) |
386 | omap_wdt_disable(wdev); | 405 | omap_wdt_disable(wdev); |
@@ -388,8 +407,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev) | |||
388 | 407 | ||
389 | static int omap_wdt_remove(struct platform_device *pdev) | 408 | static int omap_wdt_remove(struct platform_device *pdev) |
390 | { | 409 | { |
391 | struct omap_wdt_dev *wdev; | 410 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
392 | wdev = platform_get_drvdata(pdev); | ||
393 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 411 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
394 | 412 | ||
395 | if (!res) | 413 | if (!res) |
@@ -398,14 +416,17 @@ static int omap_wdt_remove(struct platform_device *pdev) | |||
398 | misc_deregister(&(wdev->omap_wdt_miscdev)); | 416 | misc_deregister(&(wdev->omap_wdt_miscdev)); |
399 | release_mem_region(res->start, res->end - res->start + 1); | 417 | release_mem_region(res->start, res->end - res->start + 1); |
400 | platform_set_drvdata(pdev, NULL); | 418 | platform_set_drvdata(pdev, NULL); |
419 | |||
401 | if (wdev->armwdt_ck) { | 420 | if (wdev->armwdt_ck) { |
402 | clk_put(wdev->armwdt_ck); | 421 | clk_put(wdev->armwdt_ck); |
403 | wdev->armwdt_ck = NULL; | 422 | wdev->armwdt_ck = NULL; |
404 | } | 423 | } |
424 | |||
405 | if (wdev->mpu_wdt_ick) { | 425 | if (wdev->mpu_wdt_ick) { |
406 | clk_put(wdev->mpu_wdt_ick); | 426 | clk_put(wdev->mpu_wdt_ick); |
407 | wdev->mpu_wdt_ick = NULL; | 427 | wdev->mpu_wdt_ick = NULL; |
408 | } | 428 | } |
429 | |||
409 | if (wdev->mpu_wdt_fck) { | 430 | if (wdev->mpu_wdt_fck) { |
410 | clk_put(wdev->mpu_wdt_fck); | 431 | clk_put(wdev->mpu_wdt_fck); |
411 | wdev->mpu_wdt_fck = NULL; | 432 | wdev->mpu_wdt_fck = NULL; |
@@ -414,6 +435,7 @@ static int omap_wdt_remove(struct platform_device *pdev) | |||
414 | 435 | ||
415 | kfree(wdev); | 436 | kfree(wdev); |
416 | omap_wdt_dev = NULL; | 437 | omap_wdt_dev = NULL; |
438 | |||
417 | return 0; | 439 | return 0; |
418 | } | 440 | } |
419 | 441 | ||
@@ -427,21 +449,23 @@ static int omap_wdt_remove(struct platform_device *pdev) | |||
427 | 449 | ||
428 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) | 450 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) |
429 | { | 451 | { |
430 | struct omap_wdt_dev *wdev; | 452 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
431 | wdev = platform_get_drvdata(pdev); | 453 | |
432 | if (wdev->omap_wdt_users) | 454 | if (wdev->omap_wdt_users) |
433 | omap_wdt_disable(wdev); | 455 | omap_wdt_disable(wdev); |
456 | |||
434 | return 0; | 457 | return 0; |
435 | } | 458 | } |
436 | 459 | ||
437 | static int omap_wdt_resume(struct platform_device *pdev) | 460 | static int omap_wdt_resume(struct platform_device *pdev) |
438 | { | 461 | { |
439 | struct omap_wdt_dev *wdev; | 462 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
440 | wdev = platform_get_drvdata(pdev); | 463 | |
441 | if (wdev->omap_wdt_users) { | 464 | if (wdev->omap_wdt_users) { |
442 | omap_wdt_enable(wdev); | 465 | omap_wdt_enable(wdev); |
443 | omap_wdt_ping(wdev); | 466 | omap_wdt_ping(wdev); |
444 | } | 467 | } |
468 | |||
445 | return 0; | 469 | return 0; |
446 | } | 470 | } |
447 | 471 | ||