Skip to content

Commit

Permalink
Merge branch 'Add-support-for-SFPs-behind-PHYs'
Browse files Browse the repository at this point in the history
Russell King says:

====================
Add support for SFPs behind PHYs

This series adds partial support for SFP cages connected to PHYs,
specifically optical SFPs.

We add core infrastructure to phylib for this, and arrange for
minimal code in the PHY driver - currently, this is code to verify
that the module is one that we can support for Marvell 10G PHYs.

v2: add yaml binding patch
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 19, 2019
2 parents 99638e9 + 36023da commit e64dbb1
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ properties:
and is useful for determining certain configuration settings
such as flow control thresholds.

sfp:
$ref: /schemas/types.yaml#definitions/phandle
description:
Specifies a reference to a node representing a SFP cage.

tx-fifo-depth:
$ref: /schemas/types.yaml#definitions/uint32
description:
Expand Down
5 changes: 5 additions & 0 deletions Documentation/devicetree/bindings/net/ethernet-phy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ properties:
Delay after the reset was deasserted in microseconds. If
this property is missing the delay will be skipped.

sfp:
$ref: /schemas/types.yaml#definitions/phandle
description:
Specifies a reference to a node representing a SFP cage.

required:
- reg

Expand Down
25 changes: 24 additions & 1 deletion drivers/net/phy/marvell10g.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/hwmon.h>
#include <linux/marvell_phy.h>
#include <linux/phy.h>
#include <linux/sfp.h>

#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
Expand Down Expand Up @@ -206,6 +207,28 @@ static int mv3310_hwmon_probe(struct phy_device *phydev)
}
#endif

static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
struct phy_device *phydev = upstream;
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
phy_interface_t iface;

sfp_parse_support(phydev->sfp_bus, id, support);
iface = sfp_select_interface(phydev->sfp_bus, id, support);

if (iface != PHY_INTERFACE_MODE_10GKR) {
dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
return -EINVAL;
}
return 0;
}

static const struct sfp_upstream_ops mv3310_sfp_ops = {
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
.module_insert = mv3310_sfp_insert,
};

static int mv3310_probe(struct phy_device *phydev)
{
struct mv3310_priv *priv;
Expand Down Expand Up @@ -236,7 +259,7 @@ static int mv3310_probe(struct phy_device *phydev)
if (ret)
return ret;

return 0;
return phy_sfp_probe(phydev, &mv3310_sfp_ops);
}

static int mv3310_suspend(struct phy_device *phydev)
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/phy/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/phy_led_triggers.h>
#include <linux/sfp.h>
#include <linux/workqueue.h>
#include <linux/mdio.h>
#include <linux/io.h>
Expand Down Expand Up @@ -841,6 +842,9 @@ void phy_stop(struct phy_device *phydev)

mutex_lock(&phydev->lock);

if (phydev->sfp_bus)
sfp_upstream_stop(phydev->sfp_bus);

phydev->state = PHY_HALTED;

mutex_unlock(&phydev->lock);
Expand Down Expand Up @@ -875,6 +879,9 @@ void phy_start(struct phy_device *phydev)
goto out;
}

if (phydev->sfp_bus)
sfp_upstream_start(phydev->sfp_bus);

/* if phy was suspended, bring the physical link up again */
__phy_resume(phydev);

Expand Down
66 changes: 66 additions & 0 deletions drivers/net/phy/phy_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/bitmap.h>
#include <linux/phy.h>
#include <linux/phy_led_triggers.h>
#include <linux/sfp.h>
#include <linux/mdio.h>
#include <linux/io.h>
#include <linux/uaccess.h>
Expand Down Expand Up @@ -1174,6 +1175,65 @@ phy_standalone_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(phy_standalone);

/**
* phy_sfp_attach - attach the SFP bus to the PHY upstream network device
* @upstream: pointer to the phy device
* @bus: sfp bus representing cage being attached
*
* This is used to fill in the sfp_upstream_ops .attach member.
*/
void phy_sfp_attach(void *upstream, struct sfp_bus *bus)
{
struct phy_device *phydev = upstream;

if (phydev->attached_dev)
phydev->attached_dev->sfp_bus = bus;
phydev->sfp_bus_attached = true;
}
EXPORT_SYMBOL(phy_sfp_attach);

/**
* phy_sfp_detach - detach the SFP bus from the PHY upstream network device
* @upstream: pointer to the phy device
* @bus: sfp bus representing cage being attached
*
* This is used to fill in the sfp_upstream_ops .detach member.
*/
void phy_sfp_detach(void *upstream, struct sfp_bus *bus)
{
struct phy_device *phydev = upstream;

if (phydev->attached_dev)
phydev->attached_dev->sfp_bus = NULL;
phydev->sfp_bus_attached = false;
}
EXPORT_SYMBOL(phy_sfp_detach);

/**
* phy_sfp_probe - probe for a SFP cage attached to this PHY device
* @phydev: Pointer to phy_device
* @ops: SFP's upstream operations
*/
int phy_sfp_probe(struct phy_device *phydev,
const struct sfp_upstream_ops *ops)
{
struct sfp_bus *bus;
int ret;

if (phydev->mdio.dev.fwnode) {
bus = sfp_bus_find_fwnode(phydev->mdio.dev.fwnode);
if (IS_ERR(bus))
return PTR_ERR(bus);

phydev->sfp_bus = bus;

ret = sfp_bus_add_upstream(bus, phydev, ops);
sfp_bus_put(bus);
}
return 0;
}
EXPORT_SYMBOL(phy_sfp_probe);

/**
* phy_attach_direct - attach a network device to a given PHY device pointer
* @dev: network device to attach
Expand Down Expand Up @@ -1249,6 +1309,9 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
if (dev) {
phydev->attached_dev = dev;
dev->phydev = phydev;

if (phydev->sfp_bus_attached)
dev->sfp_bus = phydev->sfp_bus;
}

/* Some Ethernet drivers try to connect to a PHY device before
Expand Down Expand Up @@ -2418,6 +2481,9 @@ static int phy_remove(struct device *dev)
phydev->state = PHY_DOWN;
mutex_unlock(&phydev->lock);

sfp_bus_del_upstream(phydev->sfp_bus);
phydev->sfp_bus = NULL;

if (phydev->drv && phydev->drv->remove) {
phydev->drv->remove(phydev);

Expand Down
11 changes: 11 additions & 0 deletions include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ static inline const char *phy_modes(phy_interface_t interface)

struct device;
struct phylink;
struct sfp_bus;
struct sfp_upstream_ops;
struct sk_buff;

/*
Expand Down Expand Up @@ -342,6 +344,8 @@ struct phy_c45_device_ids {
* dev_flags: Device-specific flags used by the PHY driver.
* irq: IRQ number of the PHY's interrupt (-1 if none)
* phy_timer: The timer for handling the state machine
* sfp_bus_attached: flag indicating whether the SFP bus has been attached
* sfp_bus: SFP bus attached to this PHY's fiber port
* attached_dev: The attached enet driver's device instance ptr
* adjust_link: Callback for the enet controller to respond to
* changes in the link state.
Expand Down Expand Up @@ -432,6 +436,9 @@ struct phy_device {

struct mutex lock;

/* This may be modified under the rtnl lock */
bool sfp_bus_attached;
struct sfp_bus *sfp_bus;
struct phylink *phylink;
struct net_device *attached_dev;

Expand Down Expand Up @@ -1020,6 +1027,10 @@ int phy_suspend(struct phy_device *phydev);
int phy_resume(struct phy_device *phydev);
int __phy_resume(struct phy_device *phydev);
int phy_loopback(struct phy_device *phydev, bool enable);
void phy_sfp_attach(void *upstream, struct sfp_bus *bus);
void phy_sfp_detach(void *upstream, struct sfp_bus *bus);
int phy_sfp_probe(struct phy_device *phydev,
const struct sfp_upstream_ops *ops);
struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
phy_interface_t interface);
struct phy_device *phy_find_first(struct mii_bus *bus);
Expand Down

0 comments on commit e64dbb1

Please sign in to comment.