Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: microchip: Add suspend/resume support to KSZ DSA driver

The KSZ DSA driver starts a timer to read MIB counters periodically to
avoid count overrun. During system suspend this will give an error for
not able to write to register as the SPI system returns an error when
it is in suspend state. This implementation stops the timer when the
system goes into suspend and restarts it when resumed.

Signed-off-by: Tristram Ha <tristram.ha@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20241218020311.70628-1-Tristram.Ha@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Tristram Ha and committed by
Jakub Kicinski
3fc87cb9 d5872aa2

+47
+4
drivers/net/dsa/microchip/ksz9477_i2c.c
··· 127 127 }; 128 128 MODULE_DEVICE_TABLE(of, ksz9477_dt_ids); 129 129 130 + static DEFINE_SIMPLE_DEV_PM_OPS(ksz_i2c_pm_ops, 131 + ksz_switch_suspend, ksz_switch_resume); 132 + 130 133 static struct i2c_driver ksz9477_i2c_driver = { 131 134 .driver = { 132 135 .name = "ksz9477-switch", 133 136 .of_match_table = ksz9477_dt_ids, 137 + .pm = &ksz_i2c_pm_ops, 134 138 }, 135 139 .probe = ksz9477_i2c_probe, 136 140 .remove = ksz9477_i2c_remove,
+37
drivers/net/dsa/microchip/ksz_common.c
··· 4586 4586 return 0; 4587 4587 } 4588 4588 4589 + static int ksz_suspend(struct dsa_switch *ds) 4590 + { 4591 + struct ksz_device *dev = ds->priv; 4592 + 4593 + cancel_delayed_work_sync(&dev->mib_read); 4594 + return 0; 4595 + } 4596 + 4597 + static int ksz_resume(struct dsa_switch *ds) 4598 + { 4599 + struct ksz_device *dev = ds->priv; 4600 + 4601 + if (dev->mib_read_interval) 4602 + schedule_delayed_work(&dev->mib_read, dev->mib_read_interval); 4603 + return 0; 4604 + } 4605 + 4589 4606 static const struct dsa_switch_ops ksz_switch_ops = { 4590 4607 .get_tag_protocol = ksz_get_tag_protocol, 4591 4608 .connect_tag_protocol = ksz_connect_tag_protocol, ··· 4643 4626 .port_max_mtu = ksz_max_mtu, 4644 4627 .get_wol = ksz_get_wol, 4645 4628 .set_wol = ksz_set_wol, 4629 + .suspend = ksz_suspend, 4630 + .resume = ksz_resume, 4646 4631 .get_ts_info = ksz_get_ts_info, 4647 4632 .port_hwtstamp_get = ksz_hwtstamp_get, 4648 4633 .port_hwtstamp_set = ksz_hwtstamp_set, ··· 5144 5125 5145 5126 } 5146 5127 EXPORT_SYMBOL(ksz_switch_remove); 5128 + 5129 + #ifdef CONFIG_PM_SLEEP 5130 + int ksz_switch_suspend(struct device *dev) 5131 + { 5132 + struct ksz_device *priv = dev_get_drvdata(dev); 5133 + 5134 + return dsa_switch_suspend(priv->ds); 5135 + } 5136 + EXPORT_SYMBOL(ksz_switch_suspend); 5137 + 5138 + int ksz_switch_resume(struct device *dev) 5139 + { 5140 + struct ksz_device *priv = dev_get_drvdata(dev); 5141 + 5142 + return dsa_switch_resume(priv->ds); 5143 + } 5144 + EXPORT_SYMBOL(ksz_switch_resume); 5145 + #endif 5147 5146 5148 5147 MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); 5149 5148 MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver");
+2
drivers/net/dsa/microchip/ksz_common.h
··· 444 444 struct ksz_device *ksz_switch_alloc(struct device *base, void *priv); 445 445 int ksz_switch_register(struct ksz_device *dev); 446 446 void ksz_switch_remove(struct ksz_device *dev); 447 + int ksz_switch_suspend(struct device *dev); 448 + int ksz_switch_resume(struct device *dev); 447 449 448 450 void ksz_init_mib_timer(struct ksz_device *dev); 449 451 bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
+4
drivers/net/dsa/microchip/ksz_spi.c
··· 239 239 }; 240 240 MODULE_DEVICE_TABLE(spi, ksz_spi_ids); 241 241 242 + static DEFINE_SIMPLE_DEV_PM_OPS(ksz_spi_pm_ops, 243 + ksz_switch_suspend, ksz_switch_resume); 244 + 242 245 static struct spi_driver ksz_spi_driver = { 243 246 .driver = { 244 247 .name = "ksz-switch", 245 248 .of_match_table = ksz_dt_ids, 249 + .pm = &ksz_spi_pm_ops, 246 250 }, 247 251 .id_table = ksz_spi_ids, 248 252 .probe = ksz_spi_probe,