Skip to content

Commit 727b366

Browse files
Russell Kingdavem330
authored andcommitted
net: sfp: rework upstream interface
The current upstream interface is an all-or-nothing, which is sub-optimal for future changes, as it doesn't allow the upstream driver to prepare for the SFP module becoming available, as it is at boot. Switch to a find-sfp-bus, add-upstream, del-upstream, put-sfp-bus interface structure instead, which allows the upstream driver to prepare for a module being available as soon as add-upstream is called. Signed-off-by: Russell King <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 14684b9 commit 727b366

File tree

3 files changed

+88
-39
lines changed

3 files changed

+88
-39
lines changed

drivers/net/phy/phylink.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ static int phylink_register_sfp(struct phylink *pl,
567567
struct sfp_bus *bus;
568568
int ret;
569569

570-
bus = sfp_register_upstream_node(fwnode, pl, &sfp_phylink_ops);
570+
bus = sfp_bus_find_fwnode(fwnode);
571571
if (IS_ERR(bus)) {
572572
ret = PTR_ERR(bus);
573573
phylink_err(pl, "unable to attach SFP bus: %d\n", ret);
@@ -576,7 +576,10 @@ static int phylink_register_sfp(struct phylink *pl,
576576

577577
pl->sfp_bus = bus;
578578

579-
return 0;
579+
ret = sfp_bus_add_upstream(bus, pl, &sfp_phylink_ops);
580+
sfp_bus_put(bus);
581+
582+
return ret;
580583
}
581584

582585
/**
@@ -670,8 +673,7 @@ EXPORT_SYMBOL_GPL(phylink_create);
670673
*/
671674
void phylink_destroy(struct phylink *pl)
672675
{
673-
if (pl->sfp_bus)
674-
sfp_unregister_upstream(pl->sfp_bus);
676+
sfp_bus_del_upstream(pl->sfp_bus);
675677
if (pl->link_gpio)
676678
gpiod_put(pl->link_gpio);
677679

drivers/net/phy/sfp-bus.c

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,19 @@ static void sfp_bus_release(struct kref *kref)
329329
kfree(bus);
330330
}
331331

332-
static void sfp_bus_put(struct sfp_bus *bus)
332+
/**
333+
* sfp_bus_put() - put a reference on the &struct sfp_bus
334+
* bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
335+
*
336+
* Put a reference on the &struct sfp_bus and free the underlying structure
337+
* if this was the last reference.
338+
*/
339+
void sfp_bus_put(struct sfp_bus *bus)
333340
{
334-
kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
341+
if (bus)
342+
kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
335343
}
344+
EXPORT_SYMBOL_GPL(sfp_bus_put);
336345

337346
static int sfp_register_bus(struct sfp_bus *bus)
338347
{
@@ -348,11 +357,11 @@ static int sfp_register_bus(struct sfp_bus *bus)
348357
return ret;
349358
}
350359
}
360+
bus->registered = true;
351361
bus->socket_ops->attach(bus->sfp);
352362
if (bus->started)
353363
bus->socket_ops->start(bus->sfp);
354364
bus->upstream_ops->attach(bus->upstream, bus);
355-
bus->registered = true;
356365
return 0;
357366
}
358367

@@ -446,13 +455,12 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
446455
}
447456

448457
/**
449-
* sfp_register_upstream_node() - parse and register the neighbouring device
458+
* sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
450459
* @fwnode: firmware node for the parent device (MAC or PHY)
451-
* @upstream: the upstream private data
452-
* @ops: the upstream's &struct sfp_upstream_ops
453460
*
454-
* Parse the parent device's firmware node for a SFP bus, and register the
455-
* SFP bus using sfp_register_upstream().
461+
* Parse the parent device's firmware node for a SFP bus, and locate
462+
* the sfp_bus structure, incrementing its reference count. This must
463+
* be put via sfp_bus_put() when done.
456464
*
457465
* Returns: on success, a pointer to the sfp_bus structure,
458466
* %NULL if no SFP is specified,
@@ -462,9 +470,7 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
462470
* %-ENOMEM if we failed to allocate the bus.
463471
* an error from the upstream's connect_phy() method.
464472
*/
465-
struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
466-
void *upstream,
467-
const struct sfp_upstream_ops *ops)
473+
struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
468474
{
469475
struct fwnode_reference_args ref;
470476
struct sfp_bus *bus;
@@ -482,7 +488,39 @@ struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
482488
if (!bus)
483489
return ERR_PTR(-ENOMEM);
484490

491+
return bus;
492+
}
493+
EXPORT_SYMBOL_GPL(sfp_bus_find_fwnode);
494+
495+
/**
496+
* sfp_bus_add_upstream() - parse and register the neighbouring device
497+
* @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
498+
* @upstream: the upstream private data
499+
* @ops: the upstream's &struct sfp_upstream_ops
500+
*
501+
* Add upstream driver for the SFP bus, and if the bus is complete, register
502+
* the SFP bus using sfp_register_upstream(). This takes a reference on the
503+
* bus, so it is safe to put the bus after this call.
504+
*
505+
* Returns: on success, a pointer to the sfp_bus structure,
506+
* %NULL if no SFP is specified,
507+
* on failure, an error pointer value:
508+
* corresponding to the errors detailed for
509+
* fwnode_property_get_reference_args().
510+
* %-ENOMEM if we failed to allocate the bus.
511+
* an error from the upstream's connect_phy() method.
512+
*/
513+
int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
514+
const struct sfp_upstream_ops *ops)
515+
{
516+
int ret;
517+
518+
/* If no bus, return success */
519+
if (!bus)
520+
return 0;
521+
485522
rtnl_lock();
523+
kref_get(&bus->kref);
486524
bus->upstream_ops = ops;
487525
bus->upstream = upstream;
488526

@@ -495,33 +533,33 @@ struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
495533
}
496534
rtnl_unlock();
497535

498-
if (ret) {
536+
if (ret)
499537
sfp_bus_put(bus);
500-
bus = ERR_PTR(ret);
501-
}
502538

503-
return bus;
539+
return ret;
504540
}
505-
EXPORT_SYMBOL_GPL(sfp_register_upstream_node);
541+
EXPORT_SYMBOL_GPL(sfp_bus_add_upstream);
506542

507543
/**
508-
* sfp_unregister_upstream() - Unregister sfp bus
544+
* sfp_bus_del_upstream() - Delete a sfp bus
509545
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
510546
*
511-
* Unregister a previously registered upstream connection for the SFP
512-
* module. @bus is returned from sfp_register_upstream().
547+
* Delete a previously registered upstream connection for the SFP
548+
* module. @bus should have been added by sfp_bus_add_upstream().
513549
*/
514-
void sfp_unregister_upstream(struct sfp_bus *bus)
550+
void sfp_bus_del_upstream(struct sfp_bus *bus)
515551
{
516-
rtnl_lock();
517-
if (bus->sfp)
518-
sfp_unregister_bus(bus);
519-
sfp_upstream_clear(bus);
520-
rtnl_unlock();
552+
if (bus) {
553+
rtnl_lock();
554+
if (bus->sfp)
555+
sfp_unregister_bus(bus);
556+
sfp_upstream_clear(bus);
557+
rtnl_unlock();
521558

522-
sfp_bus_put(bus);
559+
sfp_bus_put(bus);
560+
}
523561
}
524-
EXPORT_SYMBOL_GPL(sfp_unregister_upstream);
562+
EXPORT_SYMBOL_GPL(sfp_bus_del_upstream);
525563

526564
/* Socket driver entry points */
527565
int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev)

include/linux/sfp.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -508,10 +508,11 @@ int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
508508
u8 *data);
509509
void sfp_upstream_start(struct sfp_bus *bus);
510510
void sfp_upstream_stop(struct sfp_bus *bus);
511-
struct sfp_bus *sfp_register_upstream_node(struct fwnode_handle *fwnode,
512-
void *upstream,
513-
const struct sfp_upstream_ops *ops);
514-
void sfp_unregister_upstream(struct sfp_bus *bus);
511+
void sfp_bus_put(struct sfp_bus *bus);
512+
struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode);
513+
int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
514+
const struct sfp_upstream_ops *ops);
515+
void sfp_bus_del_upstream(struct sfp_bus *bus);
515516
#else
516517
static inline int sfp_parse_port(struct sfp_bus *bus,
517518
const struct sfp_eeprom_id *id,
@@ -553,14 +554,22 @@ static inline void sfp_upstream_stop(struct sfp_bus *bus)
553554
{
554555
}
555556

556-
static inline struct sfp_bus *sfp_register_upstream_node(
557-
struct fwnode_handle *fwnode, void *upstream,
558-
const struct sfp_upstream_ops *ops)
557+
static inline void sfp_bus_put(struct sfp_bus *bus)
558+
{
559+
}
560+
561+
static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
559562
{
560563
return NULL;
561564
}
562565

563-
static inline void sfp_unregister_upstream(struct sfp_bus *bus)
566+
static int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
567+
const struct sfp_upstream_ops *ops)
568+
{
569+
return 0;
570+
}
571+
572+
static inline void sfp_bus_del_upstream(struct sfp_bus *bus)
564573
{
565574
}
566575
#endif

0 commit comments

Comments
 (0)