diff options
author | Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> | 2017-04-09 18:00:18 -0400 |
---|---|---|
committer | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2017-04-28 14:51:27 -0400 |
commit | f583a884afecb16fcb8200ebb9956ea369aff57f (patch) | |
tree | 54e733c3e4e4c653b769f3963b37e64d0d95c777 /drivers/watchdog | |
parent | 496702068597ff29092e724301f77b91864454b3 (diff) |
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>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/iTCO_wdt.c | 83 |
1 files changed, 50 insertions, 33 deletions
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 3d0abc0d59b4..a62993381c52 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -106,6 +106,8 @@ struct iTCO_wdt_private { | |||
106 | struct pci_dev *pci_dev; | 106 | struct pci_dev *pci_dev; |
107 | /* whether or not the watchdog has been suspended */ | 107 | /* whether or not the watchdog has been suspended */ |
108 | bool suspended; | 108 | bool suspended; |
109 | /* no reboot update function pointer */ | ||
110 | int (*update_no_reboot_bit)(void *p, bool set); | ||
109 | }; | 111 | }; |
110 | 112 | ||
111 | /* module parameters */ | 113 | /* module parameters */ |
@@ -170,48 +172,61 @@ static inline u32 no_reboot_bit(struct iTCO_wdt_private *p) | |||
170 | return enable_bit; | 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; | 177 | return 0; |
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 | } | ||
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); | 182 | struct iTCO_wdt_private *p = priv; |
192 | u32 val32 = 0; | 183 | u32 val32 = 0, newval32 = 0; |
193 | 184 | ||
194 | /* Unset the NO_REBOOT bit: this enables reboots */ | 185 | pci_read_config_dword(p->pci_dev, 0xd4, &val32); |
195 | if (p->iTCO_version >= 2) { | 186 | if (set) |
196 | val32 = readl(p->gcs_pmc); | 187 | val32 |= no_reboot_bit(p); |
197 | val32 &= ~enable_bit; | 188 | else |
198 | writel(val32, p->gcs_pmc); | 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); | 193 | /* make sure the update is successful */ |
201 | } else if (p->iTCO_version == 1) { | 194 | if (val32 != newval32) |
202 | pci_read_config_dword(p->pci_dev, 0xd4, &val32); | 195 | return -EIO; |
203 | val32 &= ~enable_bit; | ||
204 | pci_write_config_dword(p->pci_dev, 0xd4, val32); | ||
205 | 196 | ||
206 | pci_read_config_dword(p->pci_dev, 0xd4, &val32); | 197 | return 0; |
207 | } | 198 | } |
199 | |||
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); | ||
208 | 212 | ||
209 | if (val32 & enable_bit) | 213 | /* make sure the update is successful */ |
214 | if (val32 != newval32) | ||
210 | return -EIO; | 215 | return -EIO; |
211 | 216 | ||
212 | return 0; | 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 | static int iTCO_wdt_start(struct watchdog_device *wd_dev) | 230 | static int iTCO_wdt_start(struct watchdog_device *wd_dev) |
216 | { | 231 | { |
217 | struct iTCO_wdt_private *p = watchdog_get_drvdata(wd_dev); | 232 | struct iTCO_wdt_private *p = watchdog_get_drvdata(wd_dev); |
@@ -222,7 +237,7 @@ static int iTCO_wdt_start(struct watchdog_device *wd_dev) | |||
222 | iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout); | 237 | iTCO_vendor_pre_start(p->smi_res, wd_dev->timeout); |
223 | 238 | ||
224 | /* disable chipset's NO_REBOOT bit */ | 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 | spin_unlock(&p->io_lock); | 241 | spin_unlock(&p->io_lock); |
227 | pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); | 242 | pr_err("failed to reset NO_REBOOT flag, reboot disabled by hardware/BIOS\n"); |
228 | return -EIO; | 243 | return -EIO; |
@@ -263,7 +278,7 @@ static int iTCO_wdt_stop(struct watchdog_device *wd_dev) | |||
263 | val = inw(TCO1_CNT(p)); | 278 | val = inw(TCO1_CNT(p)); |
264 | 279 | ||
265 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | 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 | spin_unlock(&p->io_lock); | 283 | spin_unlock(&p->io_lock); |
269 | 284 | ||
@@ -428,6 +443,8 @@ static int iTCO_wdt_probe(struct platform_device *pdev) | |||
428 | p->iTCO_version = pdata->version; | 443 | p->iTCO_version = pdata->version; |
429 | p->pci_dev = to_pci_dev(dev->parent); | 444 | p->pci_dev = to_pci_dev(dev->parent); |
430 | 445 | ||
446 | iTCO_wdt_no_reboot_bit_setup(p); | ||
447 | |||
431 | /* | 448 | /* |
432 | * Get the Memory-Mapped GCS or PMC register, we need it for the | 449 | * Get the Memory-Mapped GCS or PMC register, we need it for the |
433 | * NO_REBOOT flag (TCO v2 and v3). | 450 | * NO_REBOOT flag (TCO v2 and v3). |
@@ -442,14 +459,14 @@ static int iTCO_wdt_probe(struct platform_device *pdev) | |||
442 | } | 459 | } |
443 | 460 | ||
444 | /* Check chipset's NO_REBOOT bit */ | 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 | iTCO_vendor_check_noreboot_on()) { | 463 | iTCO_vendor_check_noreboot_on()) { |
447 | pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); | 464 | pr_info("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); |
448 | return -ENODEV; /* Cannot reset NO_REBOOT bit */ | 465 | return -ENODEV; /* Cannot reset NO_REBOOT bit */ |
449 | } | 466 | } |
450 | 467 | ||
451 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | 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 | /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ | 471 | /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ |
455 | if (!devm_request_region(dev, p->smi_res->start, | 472 | if (!devm_request_region(dev, p->smi_res->start, |