drivers/net/phy/phy_caps.c

Source file repositories/reference/linux-study-clean/drivers/net/phy/phy_caps.c

File Facts

System
Linux kernel
Corpus path
drivers/net/phy/phy_caps.c
Extension
.c
Size
13671 bytes
Lines
448
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (linkmode->pairs < linkmode->min_pairs) {
			pr_err("Pairs count must not be under min_pairs for linkmode %d\n",
			       i);
			return -EINVAL;
		}

		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);

		if (capa < 0) {
			if (linkmode->speed != SPEED_UNKNOWN) {
				pr_err("Unknown speed %d, please update LINK_CAPS\n",
				       linkmode->speed);
				return -EINVAL;
			}
			continue;
		}

		__set_bit(i, link_caps[capa].linkmodes);
	}

	return 0;
}

/**
 * phy_caps_speeds() - Fill an array of supported SPEED_* values for given modes
 * @speeds: Output array to store the speeds list into
 * @size: Size of the output array
 * @linkmodes: Linkmodes to get the speeds from
 *
 * Fills the speeds array with all possible speeds that can be achieved with
 * the specified linkmodes.
 *
 * Returns: The number of speeds filled into the array. If the input array isn't
 *	    big enough to store all speeds, fill it as much as possible.
 */
size_t phy_caps_speeds(unsigned int *speeds, size_t size,
		       unsigned long *linkmodes)
{
	struct link_capabilities *lcap;
	size_t count = 0;

	for_each_link_caps_asc_speed(lcap) {
		if (linkmode_intersects(lcap->linkmodes, linkmodes) &&
		    (count == 0 || speeds[count - 1] != lcap->speed)) {
			speeds[count++] = lcap->speed;
			if (count >= size)
				break;
		}
	}

	return count;
}

/**
 * phy_caps_lookup_by_linkmode() - Lookup the fastest matching link_capabilities
 * @linkmodes: Linkmodes to match against
 *
 * Returns: The highest-speed link_capabilities that intersects the given
 *	    linkmodes. In case several DUPLEX_ options exist at that speed,
 *	    DUPLEX_FULL is matched first. NULL is returned if no match.
 */
const struct link_capabilities *
phy_caps_lookup_by_linkmode(const unsigned long *linkmodes)
{
	struct link_capabilities *lcap;

	for_each_link_caps_desc_speed(lcap)
		if (linkmode_intersects(lcap->linkmodes, linkmodes))
			return lcap;

	return NULL;
}

/**
 * phy_caps_lookup_by_linkmode_rev() - Lookup the slowest matching link_capabilities
 * @linkmodes: Linkmodes to match against
 * @fdx_only: Full duplex match only when set
 *
 * Returns: The lowest-speed link_capabilities that intersects the given
 *	    linkmodes. When set, fdx_only will ignore half-duplex matches.
 *	    NULL is returned if no match.
 */
const struct link_capabilities *
phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
{
	struct link_capabilities *lcap;

	for_each_link_caps_asc_speed(lcap) {
		if (fdx_only && lcap->duplex != DUPLEX_FULL)
			continue;

Annotation

Implementation Notes