Re: [PATCH net-next 5/6] net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/12/21 4:03 PM, Vladimir Oltean wrote:
> On Tue, Oct 12, 2021 at 01:50:44PM +0000, Alvin Šipraga wrote:
>>>>> +static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int
>>>>> port,
>>>>> +                      phy_interface_t interface)
>>>>> +{
>>>>> +    int tx_delay = 0;
>>>>> +    int rx_delay = 0;
>>>>> +    int ext_port;
>>>>> +    int ret;
>>>>> +
>>>>> +    if (port == smi->cpu_port) {
>>>>> +        ext_port = PORT_NUM_L2E(port);
>>>>> +    } else {
>>>>> +        dev_err(smi->dev, "only one EXT port is currently
>>>>> supported\n");
>>>>> +        return -EINVAL;
>>>>> +    }
>>>>> +
>>>>> +    /* Set the RGMII TX/RX delay
>>>>> +     *
>>>>> +     * The Realtek vendor driver indicates the following possible
>>>>> +     * configuration settings:
>>>>> +     *
>>>>> +     *   TX delay:
>>>>> +     *     0 = no delay, 1 = 2 ns delay
>>>>> +     *   RX delay:
>>>>> +     *     0 = no delay, 7 = maximum delay
>>>>> +     *     No units are specified, but there are a total of 8 steps.
>>>>> +     *
>>>>> +     * The vendor driver also states that this must be configured
>>>>> *before*
>>>>> +     * forcing the external interface into a particular mode, which
>>>>> is done
>>>>> +     * in the rtl8365mb_phylink_mac_link_{up,down} functions.
>>>>> +     *
>>>>> +     * NOTE: For now this is hardcoded to tx_delay = 1, rx_delay = 4.
>>>>> +     */
>>>>> +    if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
>>>>> +        interface == PHY_INTERFACE_MODE_RGMII_TXID)
>>>>> +        tx_delay = 1; /* 2 ns */
>>>>> +
>>>>> +    if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
>>>>> +        interface == PHY_INTERFACE_MODE_RGMII_RXID)
>>>>> +        rx_delay = 4;
>>>>
>>>> There is this ongoing discussion that we have been interpreting the
>>>> meaning of "phy-mode" incorrectly for RGMII all along. The conclusion
>>>> seems to be that for a PHY driver, it is okay to configure its internal
>>>> delay lines based on the value of the phy-mode string, but for a MAC
>>>> driver it is not. The only viable option for a MAC driver to configure
>>>> its internal delays is based on parsing some new device tree properties
>>>> called rx-internal-delay-ps and tx-internal-delay-ps.
>>>> Since you do not seem to have any baggage to support here (new driver),
>>>> could you please just accept any PHY_INTERFACE_MODE_RGMII* value and
>>>> apply delays (or not) based on those other OF properties?
>>>> https://patchwork.kernel.org/project/netdevbpf/patch/20210723173108.459770-6-prasanna.vengateshan@xxxxxxxxxxxxx/>>>>
>>>
>>> Ugh, I remember my head spinning when I first looked into this. But OK,
>>> I can do as you suggest.
>>>
>>> Just to clarify: if the *-internal-delay-ps property is missing, you are
>>> saying that I should set the delay to 0 rather than my defaults (tx=1,
>>> rx=4), right?
> 
> Yes, I think so.
> 
>> Another problem is that for the RX delay, I have no idea what the actual
>> unit of measurement is. See the comment I left in
>> rtl8365mb_ext_config_rgmii().
>>
>> So I guess I could "reinterpret" rx-internal-delay-ps to mean these
>> magic step values, or otherwise I don't know what might be the best
>> practice.
> 
> I think what could work is you could accept only the 0 or 2000 ps values.
> For the TX delay you say it is clear that you should program "1" to hardware.
> For the RX delay I guess that the value of "4" is simply your best guess
> of what would correspond to 2 ns. So you could just transform the 2000 ps
> value into a "4" for the RX delay and make no other guesses otherwise.

OK, this is also the most obvious way to deal with it. Will address in v2.

> 
>>>>> +    ret = regmap_update_bits(
>>>>> +        smi->map, RTL8365MB_EXT_RGMXF_REG(ext_port),
>>>>> +        RTL8365MB_EXT_RGMXF_TXDELAY_MASK |
>>>>> +            RTL8365MB_EXT_RGMXF_RXDELAY_MASK,
>>>>> +        FIELD_PREP(RTL8365MB_EXT_RGMXF_TXDELAY_MASK, tx_delay) |
>>>>> +            FIELD_PREP(RTL8365MB_EXT_RGMXF_RXDELAY_MASK, rx_delay));
>>>>> +    if (ret)
>>>>> +        return ret;
>>>>> +
>>>>> +    ret = regmap_update_bits(
>>>>> +        smi->map, RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(ext_port),
>>>>> +        RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(ext_port),
>>>>> +        RTL8365MB_EXT_PORT_MODE_RGMII
>>>>> +            << RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(
>>>>> +                   ext_port));
>>>>> +    if (ret)
>>>>> +        return ret;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>
>>>>> +static void rtl8365mb_phylink_mac_config(struct dsa_switch *ds, int
>>>>> port,
>>>>> +                     unsigned int mode,
>>>>> +                     const struct phylink_link_state *state)
>>>>> +{
>>>>> +    struct realtek_smi *smi = ds->priv;
>>>>> +    int ret;
>>>>> +
>>>>> +    if (!rtl8365mb_phy_mode_supported(ds, port, state->interface)) {
>>>>> +        dev_err(smi->dev, "phy mode %s is unsupported on port %d\n",
>>>>> +            phy_modes(state->interface), port);
>>>>> +        return;
>>>>> +    }
>>>>> +
>>>>> +    /* If port MAC is connected to an internal PHY, we have nothing
>>>>> to do */
>>>>> +    if (dsa_is_user_port(ds, port))
>>>>> +        return;
>>>>> +
>>>>> +    if (mode != MLO_AN_PHY && mode != MLO_AN_FIXED) {
>>>>> +        dev_err(smi->dev,
>>>>> +            "port %d supports only conventional PHY or fixed-link\n",
>>>>> +            port);
>>>>> +        return;
>>>>> +    }
>>>>> +
>>>>> +    if (phy_interface_mode_is_rgmii(state->interface)) {
>>>>> +        ret = rtl8365mb_ext_config_rgmii(smi, port, state->interface);
>>>>> +        if (ret)
>>>>> +            dev_err(smi->dev,
>>>>> +                "failed to configure RGMII mode on port %d: %d\n",
>>>>> +                port, ret);
>>>>> +        return;
>>>>> +    }
>>>>> +
>>>>> +    /* TODO: Implement MII and RMII modes, which the RTL8365MB-VC also
>>>>> +     * supports
>>>>> +     */
>>>>> +}
>>>>> +
>>>>> +static void rtl8365mb_phylink_mac_link_down(struct dsa_switch *ds,
>>>>> int port,
>>>>> +                        unsigned int mode,
>>>>> +                        phy_interface_t interface)
>>>>> +{
>>>>> +    struct realtek_smi *smi = ds->priv;
>>>>> +    int ret;
>>>>> +
>>>>> +    if (dsa_is_cpu_port(ds, port)) {
>>>>
>>>> I assume the "dsa_is_cpu_port()" check here can also be replaced with
>>>> "phy_interface_mode_is_rgmii(interface)"? Can you please do that for
>>>> consistency?
>>>
>>> Consistency with what exactly?
> 
> I was going to say with rtl8365mb_phylink_mac_config() where you do have
> a specific check for phy_interface_mode_is_rgmii(), but now I notice
> that it is further guarded by a "dsa_is_user_port()" check. So, with nothing.
> 
>>> All I'm saying with this code is that for CPU ports, we have to
>>> force some mode on it in response to mac_link_up. This doesn't
>>> apply to user ports because the PHY is always internal to the switch
>>> (this appears to be the case for all switches in the rtl8365mb-like
>>> family). Or are you wondering about a scenario where the port is
>>> treated as a DSA port?
> 
> Understood that the code is functionally correct, but you're not forcing
> the link because it's a CPU port, you're forcing the link because it's
> an RGMII port. Semantically, a CPU port means something entirely
> different: pass DSA-tagged frames to a host. Nothing at the physical link level.
> On your switch it is basically a coincidence that all user ports have
> internal PHYs, and the CPU port is RGMII. All I'm saying is to remove
> the assumptions based on port roles from your MAC configuration logic.

I see your point. However I would still like to keep the 
dsa_is_{user,cpu}_port() checks in rtl8365mb_phy_mode_supported(), just 
so that somebody doesn't unwittingly misconfigure the chip via device 
tree. But I'll remove the port type checks in 
.phylink_mac_{config,link_down,link_up}.

> 
> For somebody searching the git tree for .phylink_mac_link_up implementations
> and sleepwalking into your code, it will be deeply confusing to see such
> logic, even if there is a drawing at the top of the file.
> 
> Why do you need these checks anyway and cannot simply distinguish based
> on PHY_INTERFACE_MODE_INTERNAL vs PHY_INTERFACE_MODE_RGMII*?


Even this might not be necessary, but I'll check it out for v2.




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux