Commit f583a884afecb16fcb8200ebb9956ea369aff57f
Committed by
Andy Shevchenko
1 parent
4967020685
watchdog: iTCO_wdt: cleanup set/unset no_reboot_bit functions
iTCO_wdt no_reboot_bit set/unset functions has lot of common code between them. So merging these two functions into a single update function would remove these unnecessary code duplications. This patch fixes this issue by creating a no_reboot_bit update function to handle both set/unset functions. Also checking for iTCO version every time you make no_reboot_bit set/unset call is inefficient and makes the code look complex. This can be improved by performing this check once during device probe and selecting the appropriate no_reboot_bit update function. This patch fixes this issue by splitting the update function into multiple helper functions. Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Showing 1 changed file with 50 additions and 33 deletions Side-by-side Diff
drivers/watchdog/iTCO_wdt.c
... | ... | @@ -106,6 +106,8 @@ |
106 | 106 | struct pci_dev *pci_dev; |
107 | 107 | /* whether or not the watchdog has been suspended */ |
108 | 108 | bool suspended; |
109 | + /* no reboot update function pointer */ | |
110 | + int (*update_no_reboot_bit)(void *p, bool set); | |
109 | 111 | }; |
110 | 112 | |
111 | 113 | /* module parameters */ |
112 | 114 | |
113 | 115 | |
114 | 116 | |
115 | 117 | |
116 | 118 | |
117 | 119 | |
118 | 120 | |
119 | 121 | |
... | ... | @@ -170,48 +172,61 @@ |
170 | 172 | return enable_bit; |
171 | 173 | } |
172 | 174 | |
173 | -static void iTCO_wdt_set_NO_REBOOT_bit(struct iTCO_wdt_private *p) | |
175 | +static int update_no_reboot_bit_def(void *priv, bool set) | |
174 | 176 | { |
175 | - u32 val32; | |
176 | - | |
177 | - /* Set the NO_REBOOT bit: this disables reboots */ | |
178 | - if (p->iTCO_version >= 2) { | |
179 | - val32 = readl(p->gcs_pmc); | |
180 | - val32 |= no_reboot_bit(p); | |
181 | - writel(val32, p->gcs_pmc); | |
182 | - } else if (p->iTCO_version == 1) { | |
183 | - pci_read_config_dword(p->pci_dev, 0xd4, &val32); | |
184 | - val32 |= no_reboot_bit(p); | |
185 | - pci_write_config_dword(p->pci_dev, 0xd4, val32); | |
186 | - } | |
177 | + return 0; | |
187 | 178 | } |
188 | 179 | |
189 | -static int iTCO_wdt_unset_NO_REBOOT_bit(struct iTCO_wdt_private *p) | |
180 | +static int update_no_reboot_bit_pci(void *priv, bool set) | |
190 | 181 | { |
191 | - u32 enable_bit = no_reboot_bit(p); | |
192 | - u32 val32 = 0; | |
182 | + struct iTCO_wdt_private *p = priv; | |
183 | + u32 val32 = 0, newval32 = 0; | |
193 | 184 | |
194 | - /* Unset the NO_REBOOT bit: this enables reboots */ | |
195 | - if (p->iTCO_version >= 2) { | |
196 | - val32 = readl(p->gcs_pmc); | |
197 | - val32 &= ~enable_bit; | |
198 | - writel(val32, p->gcs_pmc); | |
185 | + pci_read_config_dword(p->pci_dev, 0xd4, &val32); | |
186 | + if (set) | |
187 | + val32 |= no_reboot_bit(p); | |
188 | + else | |
189 | + val32 &= ~no_reboot_bit(p); | |
190 | + pci_write_config_dword(p->pci_dev, 0xd4, val32); | |
191 | + pci_read_config_dword(p->pci_dev, 0xd4, &newval32); | |
199 | 192 | |
200 | - val32 = readl(p->gcs_pmc); | |
201 | - } else if (p->iTCO_version == 1) { | |
202 | - pci_read_config_dword(p->pci_dev, 0xd4, &val32); | |
203 | - val32 &= ~enable_bit; | |
204 | - pci_write_config_dword(p->pci_dev, 0xd4, val32); | |
193 | + /* make sure the update is successful */ | |
194 | + if (val32 != newval32) | |
195 | + return -EIO; | |
205 | 196 | |
206 | - pci_read_config_dword(p->pci_dev, 0xd4, &val32); | |
207 | - } | |
197 | + return 0; | |
198 | +} | |
208 | 199 | |
209 | - if (val32 & enable_bit) | |
200 | +static int update_no_reboot_bit_mem(void *priv, bool set) | |
201 | +{ | |
202 | + struct iTCO_wdt_private *p = priv; | |
203 | + u32 val32 = 0, newval32 = 0; | |
204 | + | |
205 | + val32 = readl(p->gcs_pmc); | |
206 | + if (set) | |
207 | + val32 |= no_reboot_bit(p); | |
208 | + else | |
209 | + val32 &= ~no_reboot_bit(p); | |
210 | + writel(val32, p->gcs_pmc); | |
211 | + newval32 = readl(p->gcs_pmc); | |
212 | + | |
213 | + /* make sure the update is successful */ | |
214 | + if (val32 != newval32) | |
210 | 215 | return -EIO; |
211 | 216 | |
212 | 217 | return 0; |
213 | 218 | } |
214 | 219 | |
220 | +static void iTCO_wdt_no_reboot_bit_setup(struct iTCO_wdt_private *p) | |
221 | +{ | |
222 | + if (p->iTCO_version >= 2) | |
223 | + p->update_no_reboot_bit = update_no_reboot_bit_mem; | |
224 | + else if (p->iTCO_version == 1) | |
225 | + p->update_no_reboot_bit = update_no_reboot_bit_pci; | |
226 | + else | |
227 | + p->update_no_reboot_bit = update_no_reboot_bit_def; | |
228 | +} | |
229 | + | |
215 | 230 | static int iTCO_wdt_start(struct watchdog_device *wd_dev) |
216 | 231 | { |
217 | 232 | struct iTCO_wdt_private *p = watchdog_get_drvdata(wd_dev); |
... | ... | @@ -222,7 +237,7 @@ |
222 | 237 | iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout); |
223 | 238 | |
224 | 239 | /* disable chipset's NO_REBOOT bit */ |
225 | - if (iTCO_wdt_unset_NO_REBOOT_bit(p)) { | |
240 | + if (p->update_no_reboot_bit(p, false)) { | |
226 | 241 | spin_unlock(&p->io_lock); |
227 | 242 | pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); |
228 | 243 | return -EIO; |
... | ... | @@ -263,7 +278,7 @@ |
263 | 278 | val = inw(TCO1_CNT(p)); |
264 | 279 | |
265 | 280 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ |
266 | - iTCO_wdt_set_NO_REBOOT_bit(p); | |
281 | + p->update_no_reboot_bit(p, true); | |
267 | 282 | |
268 | 283 | spin_unlock(&p->io_lock); |
269 | 284 | |
... | ... | @@ -428,6 +443,8 @@ |
428 | 443 | p->iTCO_version = pdata->version; |
429 | 444 | p->pci_dev = to_pci_dev(dev->parent); |
430 | 445 | |
446 | + iTCO_wdt_no_reboot_bit_setup(p); | |
447 | + | |
431 | 448 | /* |
432 | 449 | * Get the Memory-Mapped GCS or PMC register, we need it for the |
433 | 450 | * NO_REBOOT flag (TCO v2 and v3). |
434 | 451 | |
... | ... | @@ -442,14 +459,14 @@ |
442 | 459 | } |
443 | 460 | |
444 | 461 | /* Check chipset's NO_REBOOT bit */ |
445 | - if (iTCO_wdt_unset_NO_REBOOT_bit(p) && | |
462 | + if (p->update_no_reboot_bit(p, false) && | |
446 | 463 | iTCO_vendor_check_noreboot_on()) { |
447 | 464 | pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); |
448 | 465 | return -ENODEV; /* Cannot reset NO_REBOOT bit */ |
449 | 466 | } |
450 | 467 | |
451 | 468 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ |
452 | - iTCO_wdt_set_NO_REBOOT_bit(p); | |
469 | + p->update_no_reboot_bit(p, true); | |
453 | 470 | |
454 | 471 | /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ |
455 | 472 | if (!devm_request_region(dev, p->smi_res->start, |