This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DSP eth offload driver



Hi Tis,

I am using DVRRDK4.1 and our custom board.

There are two ethernet ports: eth0, eth1 in my board, eth0 always used as stream out  and eth1 used as local lan use.

eth0 port is connected with hardware ips EMAC2, eth1 port is connected with EMAC1 and two ethernet interface is configured  as different subnet.(ex. eth0: 192.168.1.x, eth1: 192.168.2.x)

I have the following questions, please help check:

(1) Does DSP offload driver have limitation that only support hardware ips EMAC1 only? It means that offload driver is only supported in eth1 interface(EMAC1 in my board)?

(2) As I know, In DM816x, when eth_offload driver is enabled, c6x DSP cannot be used for any other purpose other than ethernet offload. But I found the following discussion in other thread:

"Actually the offload driver is a low priority task on DSP while SCD (AlgLink) will be a higher priority one so it can pre-empt the offload driver task. Currently (in RDK 4.1) the offload driver is a busy loop looking for packets, semPendTimeout is 0. If you want to run SCD along with offload driver, it is recommended to change pin->semPendTimeout  to a non-zero value (1 / 2) ETH_OFFLOAD_emacOpen()."

Does it means that it is possible to use SCD function with offload driver enable in RDK4.1??

Thank in advance!

  • 1. Offload driver can be enabled only on 1 interface. Limitation is documented.

    2. More details on sharing other tasks with offload driver.

    Offload task running on the offload processor handles all of EMAC HW programming, L3/L4 checksum computation and communication with the main Host processor(running Linux). To maximize throughput and minimize latency, the offload task is run as a minimum priority task that continuosly polls for packets to be sent and received. For some applications depending on more relaxed throughput and latency requirements it might be possible to use the offload processor for additional tasks. In this case, following changes need to be carried out

    • Modify the ethernet offload task priority relative to other tasks in the system. For instance, if an audio codec needs to be run on the offload processor and remaining CPU cycles be used for offload process - set the priority of the audio codec task higher than that of offload task.
      • The offload task priority is set at the time of task creation in the ETH_OFFLOAD_Emac_TaskInit() function in "mcfw/src_bios6/eth_offload/bios6/src/eth_offload_emac.c" file. By default it is set to run as the lowest priority task in the system
    • Modify the offload task to poll with a timeout instead of continuos polling.
      • In the driver open function "ETH_OFFLOAD_emacOpen()" in "mcfw/src_bios6/eth_offload/bios6/src/eth_offload_emac.c", the polling timeout is set to "0", thereby enabling continuos polling. For accomodating other tasks in the system, modify the timeout interval("pin->semPendTimeout=10") to a meaningful number in the open call. You can choose a larger or smaller interval depending on the throughput vs cpu cycle needed for the application
  • Hi Sivagamy,

    Very thanks for quick and  the detailed reply.

    Q1: 1. Offload driver can be enabled only on 1 interface. Limitation is documented.

    Sorry! I know that only one EMAC can be offloaded currently.  My question:  only HW EMAC1 is supported? Because there are a large number of packets in HW EMAC2(eth0 in my system) in my usecase. Does offload driver can be enabled for HW EMAC2(eth0)? Is it hardware related?

    Thanks!

  • I think it can be interchanged. You will have to rebuild kernel by changing "eth_offload" string in kernel code - arch/arm/mach-omap2/devices.c

  • Hi Sivagamy,

    Thanks for your reply.

    I have tried to modify kernel_code/arch/arm/mach-omap/devices.c

    static struct platform_device ti816x_emac1_device = {
        .name    =    "davinci_emac",
        .id    =    0,
        .num_resources    =    ARRAY_SIZE(ti816x_emac1_resources),
        .resource    =    ti816x_emac1_resources,
    };

    static struct platform_device ti816x_emac2_device = {
        .name    =    "eth_offload",
        .id    =    1,
        .num_resources    =    ARRAY_SIZE(ti816x_emac2_resources),
        .resource    =    ti816x_emac2_resources,
    };

    eth0 : driver: TI DaVinci EMAC Linux v6.1

    eth1 : driver: TI DSP Accelarated EMAC Linux v0

    When I exchange the modifes to the following:

    static struct platform_device ti816x_emac1_device = {
        .name    =    "eth_offload",
        .id    =    0,
        .num_resources    =    ARRAY_SIZE(ti816x_emac1_resources),
        .resource    =    ti816x_emac1_resources,
    };

    static struct platform_device ti816x_emac2_device = {
        .name    =    "davinci_emac",
        .id    =    1,
        .num_resources    =    ARRAY_SIZE(ti816x_emac2_resources),
        .resource    =    ti816x_emac2_resources,
    };

    why linux system eth0 and eth1 port in my board have be changed...and driver information is the same as below...

    eth0 : driver: TI DaVinci EMAC Linux v6.1

    eth1 : driver: TI DSP Accelarated EMAC Linux v0

    Am I missing something?

    Thanks again!

  • Hi

    Your observations are correct and i will summarize once more

    1) only one of the ethernet MAC instances can be managed by the offload driver. You can interchange the instance to be managed by modifying the platform device definitions as above

    2) The device numbering "eth0" vs "eth1" is dependent on order in which the driver/device binding happens during linux initialization. This should not be confused with the id field in platform device structure. The id field is used internally when the same driver has to manage multiple instances of the same peripheral

    It is most likely that in your case, the native ethernet driver completes its initialization first - and hence always gets recognized as eth0. You can cross-check your init console log(or paste it here for review)

    The important part is , though the offload driver reports its instance as eth1 - on the board physically the interface being managed by the offload driver must have changed and you should verify that

    Hope this helps.

  • Hi Srirama,

    Very thanks for you help.

    "The important part is , though the offload driver reports its instance as eth1 - on the board physically the interface being managed by the offload driver must have changed and you should verify that"

    Yes, you are right.

    Sorry! I am new for ethernet driver. Please help me check:

    I dont know why the native ethernet driver always be initialized first and recognized as eth0.

    In my board, there are two emac phys: phy address 0x03, 0x07,

    phy address 0x03 <-> EMAC2 in DM8168

    phy address 0x07 <-> EMAC1 in DM8168

    I want phy:0x03 bind with interface eth0 and phy:0x07 with eth1. The following is some modifies in devices.c:

    static struct emac_platform_data ti816x_emac1_pdata = {
        .rmii_en    =    0,
        .phy_id        =    "0:03",
        .gigabit_en    =    1,
    };
    static struct emac_platform_data ti816x_emac2_pdata = {
        .rmii_en    =    0,
        .phy_id        =    "0:07",
        .gigabit_en    =    1,
    };

    static struct resource ti816x_emac1_resources[] = {
        {
            .start    =    TI816X_EMAC2_BASE,
            .end    =    TI816X_EMAC2_BASE + 0x3FFF,
            .flags    =    IORESOURCE_MEM,
        },
        {
            .start    =    TI816X_IRQ_MACRXTHR1,
            .end    =    TI816X_IRQ_MACRXTHR1,
            .flags    =    IORESOURCE_IRQ,
        },
        {
            .start    =    TI816X_IRQ_MACRXINT1,
            .end    =    TI816X_IRQ_MACRXINT1,
            .flags    =    IORESOURCE_IRQ,
        },
        {
            .start    =    TI816X_IRQ_MACTXINT1,
            .end    =    TI816X_IRQ_MACTXINT1,
            .flags    =    IORESOURCE_IRQ,
        },
        {
            .start    =    TI816X_IRQ_MACMISC1,
            .end    =    TI816X_IRQ_MACMISC1,
            .flags    =    IORESOURCE_IRQ,
        },
    };

    static struct resource ti816x_emac2_resources[] = {
        {
            .start    =    TI816X_EMAC1_BASE,
            .end    =    TI816X_EMAC1_BASE + 0x3FFF,
            .flags    =    IORESOURCE_MEM,
        },
        {
            .start    =    TI816X_IRQ_MACRXTHR0,
            .end    =    TI816X_IRQ_MACRXTHR0,
            .flags    =    IORESOURCE_IRQ,
        },
        {
            .start    =    TI816X_IRQ_MACRXINT0,
            .end    =    TI816X_IRQ_MACRXINT0,
            .flags    =    IORESOURCE_IRQ,
        },
        {
            .start    =    TI816X_IRQ_MACTXINT0,
            .end    =    TI816X_IRQ_MACTXINT0,
            .flags    =    IORESOURCE_IRQ,
        },
        {
            .start    =    TI816X_IRQ_MACMISC0,
            .end    =    TI816X_IRQ_MACMISC0,
            .flags    =    IORESOURCE_IRQ,
        },
    };

    static struct platform_device ti816x_emac1_device = {
        .name    =    "eth_offload",
        .id    =    0,
        .num_resources    =    ARRAY_SIZE(ti816x_emac1_resources),
        .resource    =    ti816x_emac1_resources,
    };

    static struct platform_device ti816x_emac2_device = {
        .name    =    "davinci_emac",
        .id    =    1,
        .num_resources    =    ARRAY_SIZE(ti816x_emac2_resources),
        .resource    =    ti816x_emac2_resources,
    };


    In ti816x_ethernet_init function,

    ti816x_emac1_pdata.hw_ram_addr = TI816X_EMAC2_HW_RAM_ADDR;
    ti816x_emac1_device.dev.platform_data = &ti816x_emac1_pdata;
    platform_device_register(&ti816x_emac1_device);

    ...

    ti816x_emac2_pdata.hw_ram_addr = TI816X_EMAC1_HW_RAM_ADDR;
    ti816x_emac2_device.dev.platform_data = &ti816x_emac2_pdata;
    platform_device_register(&ti816x_emac2_device);

    ...


    init console log:

    ...

    davinci_mdio davinci_mdio.0: davinci mdio revision 1.6
    davinci_mdio davinci_mdio.0: detected phy mask ffffff76
    davinci_mdio.0: probed
    davinci_mdio davinci_mdio.0: phy[0]: device 0:00, driver unknown
    davinci_mdio davinci_mdio.0: phy[3]: device 0:03, driver unknown
    davinci_mdio davinci_mdio.0: phy[7]: device 0:07, driver unknown

    ...

    Thanks in advance.