diff options
Diffstat (limited to 'target/linux/generic/backport-5.4/744-v5.5-net-sfp-soft-status-and-control-support.patch')
-rw-r--r-- | target/linux/generic/backport-5.4/744-v5.5-net-sfp-soft-status-and-control-support.patch | 225 |
1 files changed, 0 insertions, 225 deletions
diff --git a/target/linux/generic/backport-5.4/744-v5.5-net-sfp-soft-status-and-control-support.patch b/target/linux/generic/backport-5.4/744-v5.5-net-sfp-soft-status-and-control-support.patch deleted file mode 100644 index abc9f65f09..0000000000 --- a/target/linux/generic/backport-5.4/744-v5.5-net-sfp-soft-status-and-control-support.patch +++ /dev/null @@ -1,225 +0,0 @@ -From 40e0b3b15f7da92e6b065292b14af7b9bfb1c6e0 Mon Sep 17 00:00:00 2001 -From: Russell King <rmk+kernel@armlinux.org.uk> -Date: Fri, 13 Sep 2019 23:00:35 +0100 -Subject: [PATCH 642/660] net: sfp: soft status and control support - -Add support for the soft status and control register, which allows -TX_FAULT and RX_LOS to be monitored and TX_DISABLE to be set. We -make use of this when the board does not support GPIOs for these -signals. - -Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> ---- - drivers/net/phy/sfp.c | 110 ++++++++++++++++++++++++++++++++++-------- - include/linux/sfp.h | 4 ++ - 2 files changed, 94 insertions(+), 20 deletions(-) - ---- a/drivers/net/phy/sfp.c -+++ b/drivers/net/phy/sfp.c -@@ -201,7 +201,10 @@ struct sfp { - struct gpio_desc *gpio[GPIO_MAX]; - int gpio_irq[GPIO_MAX]; - -+ bool need_poll; -+ - struct mutex st_mutex; /* Protects state */ -+ unsigned int state_soft_mask; - unsigned int state; - struct delayed_work poll; - struct delayed_work timeout; -@@ -395,24 +398,90 @@ static int sfp_i2c_configure(struct sfp - } - - /* Interface */ --static unsigned int sfp_get_state(struct sfp *sfp) -+static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) - { -- return sfp->get_state(sfp); -+ return sfp->read(sfp, a2, addr, buf, len); - } - --static void sfp_set_state(struct sfp *sfp, unsigned int state) -+static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) - { -- sfp->set_state(sfp, state); -+ return sfp->write(sfp, a2, addr, buf, len); - } - --static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) -+static unsigned int sfp_soft_get_state(struct sfp *sfp) - { -- return sfp->read(sfp, a2, addr, buf, len); -+ unsigned int state = 0; -+ u8 status; -+ -+ if (sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)) == -+ sizeof(status)) { -+ if (status & SFP_STATUS_RX_LOS) -+ state |= SFP_F_LOS; -+ if (status & SFP_STATUS_TX_FAULT) -+ state |= SFP_F_TX_FAULT; -+ } -+ -+ return state & sfp->state_soft_mask; - } - --static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len) -+static void sfp_soft_set_state(struct sfp *sfp, unsigned int state) - { -- return sfp->write(sfp, a2, addr, buf, len); -+ u8 status; -+ -+ if (sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)) == -+ sizeof(status)) { -+ if (state & SFP_F_TX_DISABLE) -+ status |= SFP_STATUS_TX_DISABLE_FORCE; -+ else -+ status &= ~SFP_STATUS_TX_DISABLE_FORCE; -+ -+ sfp_write(sfp, true, SFP_STATUS, &status, sizeof(status)); -+ } -+} -+ -+static void sfp_soft_start_poll(struct sfp *sfp) -+{ -+ const struct sfp_eeprom_id *id = &sfp->id; -+ -+ sfp->state_soft_mask = 0; -+ if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE && -+ !sfp->gpio[GPIO_TX_DISABLE]) -+ sfp->state_soft_mask |= SFP_F_TX_DISABLE; -+ if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT && -+ !sfp->gpio[GPIO_TX_FAULT]) -+ sfp->state_soft_mask |= SFP_F_TX_FAULT; -+ if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS && -+ !sfp->gpio[GPIO_LOS]) -+ sfp->state_soft_mask |= SFP_F_LOS; -+ -+ if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) && -+ !sfp->need_poll) -+ mod_delayed_work(system_wq, &sfp->poll, poll_jiffies); -+} -+ -+static void sfp_soft_stop_poll(struct sfp *sfp) -+{ -+ sfp->state_soft_mask = 0; -+} -+ -+static unsigned int sfp_get_state(struct sfp *sfp) -+{ -+ unsigned int state = sfp->get_state(sfp); -+ -+ if (state & SFP_F_PRESENT && -+ sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT)) -+ state |= sfp_soft_get_state(sfp); -+ -+ return state; -+} -+ -+static void sfp_set_state(struct sfp *sfp, unsigned int state) -+{ -+ sfp->set_state(sfp, state); -+ -+ if (state & SFP_F_PRESENT && -+ sfp->state_soft_mask & SFP_F_TX_DISABLE) -+ sfp_soft_set_state(sfp, state); - } - - static unsigned int sfp_check(void *buf, size_t len) -@@ -1407,11 +1476,6 @@ static void sfp_sm_fault(struct sfp *sfp - } - } - --static void sfp_sm_mod_init(struct sfp *sfp) --{ -- sfp_module_tx_enable(sfp); --} -- - static void sfp_sm_probe_for_phy(struct sfp *sfp) - { - /* Setting the serdes link mode is guesswork: there's no -@@ -1574,7 +1638,7 @@ static int sfp_sm_mod_probe(struct sfp * - (int)sizeof(id.ext.datecode), id.ext.datecode); - - /* Check whether we support this module */ -- if (!sfp->type->module_supported(&sfp->id)) { -+ if (!sfp->type->module_supported(&id)) { - dev_err(sfp->dev, - "module is not supported - phys id 0x%02x 0x%02x\n", - sfp->id.base.phys_id, sfp->id.base.phys_ext_id); -@@ -1764,6 +1828,7 @@ static void sfp_sm_main(struct sfp *sfp, - if (sfp->mod_phy) - sfp_sm_phy_detach(sfp); - sfp_module_tx_disable(sfp); -+ sfp_soft_stop_poll(sfp); - sfp_sm_next(sfp, SFP_S_DOWN, 0); - return; - } -@@ -1775,7 +1840,10 @@ static void sfp_sm_main(struct sfp *sfp, - sfp->sm_dev_state != SFP_DEV_UP) - break; - -- sfp_sm_mod_init(sfp); -+ if (!(sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)) -+ sfp_soft_start_poll(sfp); -+ -+ sfp_module_tx_enable(sfp); - - /* Initialise the fault clearance retries */ - sfp->sm_retries = 5; -@@ -2031,7 +2099,10 @@ static void sfp_poll(struct work_struct - struct sfp *sfp = container_of(work, struct sfp, poll.work); - - sfp_check_state(sfp); -- mod_delayed_work(system_wq, &sfp->poll, poll_jiffies); -+ -+ if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) || -+ sfp->need_poll) -+ mod_delayed_work(system_wq, &sfp->poll, poll_jiffies); - } - - static struct sfp *sfp_alloc(struct device *dev) -@@ -2076,7 +2147,6 @@ static int sfp_probe(struct platform_dev - const struct sff_data *sff; - struct i2c_adapter *i2c; - struct sfp *sfp; -- bool poll = false; - int err, i; - - sfp = sfp_alloc(&pdev->dev); -@@ -2184,7 +2254,7 @@ static int sfp_probe(struct platform_dev - sfp->gpio_irq[i] = gpiod_to_irq(sfp->gpio[i]); - if (sfp->gpio_irq[i] < 0) { - sfp->gpio_irq[i] = 0; -- poll = true; -+ sfp->need_poll = true; - continue; - } - -@@ -2196,11 +2266,11 @@ static int sfp_probe(struct platform_dev - dev_name(sfp->dev), sfp); - if (err) { - sfp->gpio_irq[i] = 0; -- poll = true; -+ sfp->need_poll = true; - } - } - -- if (poll) -+ if (sfp->need_poll) - mod_delayed_work(system_wq, &sfp->poll, poll_jiffies); - - /* We could have an issue in cases no Tx disable pin is available or ---- a/include/linux/sfp.h -+++ b/include/linux/sfp.h -@@ -428,6 +428,10 @@ enum { - SFP_TEC_CUR = 0x6c, - - SFP_STATUS = 0x6e, -+ SFP_STATUS_TX_DISABLE = BIT(7), -+ SFP_STATUS_TX_DISABLE_FORCE = BIT(6), -+ SFP_STATUS_TX_FAULT = BIT(2), -+ SFP_STATUS_RX_LOS = BIT(1), - SFP_ALARM0 = 0x70, - SFP_ALARM0_TEMP_HIGH = BIT(7), - SFP_ALARM0_TEMP_LOW = BIT(6), |