diff options
author | Cristian Bercaru <cristian.bercaru@freescale.com> | 2014-03-28 18:46:02 (GMT) |
---|---|---|
committer | Jose Rivera <German.Rivera@freescale.com> | 2014-03-31 19:55:28 (GMT) |
commit | 1877f35001b018bc7ad0f7b8ef41bdea04311b54 (patch) | |
tree | 37df0c76fe330453da6e8fbc8345261d190ed8a2 /drivers | |
parent | 642ff687a348d96f1d6ed0ffc8fed321fb9b95d5 (diff) | |
download | linux-fsl-qoriq-1877f35001b018bc7ad0f7b8ef41bdea04311b54.tar.xz |
FMD: add PFC support for FMan v3 platforms
Configure up to 4 PFC priorities each with its PAUSE quanta.
Each PFC priority controls a Work Queue on a FMan port.
When the private interfaces' buffer pool depletes, there are issued
PFC frames for the number of all configured priorities.
Signed-off-by: Cristian Bercaru <cristian.bercaru@freescale.com>
Change-Id: I8a6102f4a77b44d07973a38b98493226e9b69bbd
Reviewed-on: http://git.am.freescale.net:8181/9767
Reviewed-by: Madalin-Cristian Bucur <madalin.bucur@freescale.com>
Tested-by: Madalin-Cristian Bucur <madalin.bucur@freescale.com>
Reviewed-by: Cristian-Constantin Sovaiala <Cristian.Sovaiala@freescale.com>
Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers')
5 files changed, 190 insertions, 25 deletions
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig index 0b9b813..9bc40f8 100644 --- a/drivers/net/ethernet/freescale/fman/Kconfig +++ b/drivers/net/ethernet/freescale/fman/Kconfig @@ -108,6 +108,49 @@ config FSL_FM_RX_EXTRA_HEADROOM * in non-Hypervisor-based scenarios, via u-boot's env, by modifying the "bootargs" env variable. +config FMAN_PFC + bool "FMan PFC support" + depends on FMAN_T4240 && FSL_FMAN + default n + ---help--- + This option enables PFC support on FMan v3 ports. + Data Center Bridging defines Classes of Service that are + flow-controlled using PFC pause frames. + +if FMAN_PFC +config FMAN_PFC_COS_COUNT + int "Number of PFC Classes of Service" + depends on FMAN_PFC && FSL_FMAN + range 1 4 + default "1" + ---help --- + The number of Classes of Service controlled by PFC. + +config FMAN_PFC_QUANTA_0 + int "The pause quanta for PFC CoS 0" + depends on FMAN_PFC && FSL_FMAN + range 0 65535 + default "65535" + +config FMAN_PFC_QUANTA_1 + int "The pause quanta for PFC CoS 1" + depends on FMAN_PFC && FSL_FMAN + range 0 65535 + default "65535" + +config FMAN_PFC_QUANTA_2 + int "The pause quanta for PFC CoS 2" + depends on FMAN_PFC && FSL_FMAN + range 0 65535 + default "65535" + +config FMAN_PFC_QUANTA_3 + int "The pause quanta for PFC CoS 3" + depends on FMAN_PFC && FSL_FMAN + range 0 65535 + default "65535" +endif + endif # FSL_FMAN endmenu diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h index a45682f..5bba643 100644 --- a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h +++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h @@ -411,17 +411,6 @@ typedef struct t_FmExtPoolParams { } t_FmExtPoolParams; /**************************************************************************//** - @Description A structure for informing the driver about the external - buffer pools allocated in the BM and used by a port or a - storage-profile. -*//***************************************************************************/ -typedef struct t_FmExtPools { - uint8_t numOfPoolsUsed; /**< Number of pools use by this port */ - t_FmExtPoolParams extBufPool[FM_PORT_MAX_NUM_OF_EXT_POOLS]; - /**< Parameters for each port */ -} t_FmExtPools; - -/**************************************************************************//** @Description A structure for defining backup BM Pools. *//***************************************************************************/ typedef struct t_FmBackupBmPools { @@ -458,6 +447,21 @@ typedef struct t_FmBufPoolDepletion { } t_FmBufPoolDepletion; /**************************************************************************//** + @Description A structure for informing the driver about the external + buffer pools allocated in the BM and used by a port or a + storage-profile. +*//***************************************************************************/ +typedef struct t_FmExtPools { + uint8_t numOfPoolsUsed; /**< Number of pools use by this port */ + t_FmExtPoolParams extBufPool[FM_PORT_MAX_NUM_OF_EXT_POOLS]; + /**< Parameters for each port */ + /**< External buffer pool depletion parameters */ +#ifdef CONFIG_FMAN_PFC + t_FmBufPoolDepletion poolDepletion; +#endif +} t_FmExtPools; + +/**************************************************************************//** @Description A Structure for defining Ucode patch for loading. *//***************************************************************************/ typedef struct t_FmFirmwareParams { diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h index 4c551ff..b30ec50 100644 --- a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h +++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h @@ -101,6 +101,12 @@ struct fm_port_pcd_param { struct fm_port_pool_param { uint8_t id; /**< External buffer pool id */ uint16_t size; /**< External buffer pool buffer size */ +#ifdef CONFIG_FMAN_PFC + /**<The Priority Enable Vector in the PFC frame which is transmitted + * when the buffer pool depletes; + */ + uint8_t pfcv; +#endif }; /**************************************************************************//** @@ -548,6 +554,25 @@ int fm_port_resume(struct fm_port *port); int fm_port_suspend(struct fm_port *port); +#ifdef CONFIG_FMAN_PFC +/**************************************************************************//** +@Function fm_port_set_pfc_priorities_mapping_to_qman_wq + +@Description Associate a QMan Work Queue with a PFC priority on this + FM-port device (Tx port). + +@Param[in] port - A handle of the FM port device. + +@Param[in] prio - The PFC priority. + +@Param[in] wq - The Work Queue associated with the PFC priority. + +@Cautions Allowed only after the port is initialized. +*//***************************************************************************/ +int fm_port_set_pfc_priorities_mapping_to_qman_wq(struct fm_port *port, + uint8_t prio, uint8_t wq); +#endif + /**************************************************************************//** @Function fm_mac_set_exception diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c index d30f2ed..4ea2885 100755 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c @@ -110,10 +110,9 @@ extern struct device_node *GetFmPortAdvArgsDevTreeNode (struct device_node *fm_n #define FSL_FM_RX_EXTRA_HEADROOM_MIN 16 #define FSL_FM_RX_EXTRA_HEADROOM_MAX 384 -#define TX_PAUSE_PRIO_DEFAULT 0xff -#define TX_PAUSE_TIME_ENABLE 0xf000 -#define TX_PAUSE_TIME_DISABLE 0 -#define TX_PAUSE_THRESH_DEFAULT 0 +#define FSL_FM_PAUSE_TIME_ENABLE 0xf000 +#define FSL_FM_PAUSE_TIME_DISABLE 0 +#define FSL_FM_PAUSE_THRESH_DEFAULT 0 /* * Max frame size, across all interfaces. @@ -140,6 +139,15 @@ int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; */ int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; +#ifdef CONFIG_FMAN_PFC +static int fsl_fm_pfc_quanta[] = { + CONFIG_FMAN_PFC_QUANTA_0, + CONFIG_FMAN_PFC_QUANTA_1, + CONFIG_FMAN_PFC_QUANTA_2, + CONFIG_FMAN_PFC_QUANTA_3 +}; +#endif + static t_LnxWrpFm lnxWrpFm; int fm_get_max_frm() @@ -1410,6 +1418,25 @@ bool fm_port_is_in_auto_res_mode(struct fm_port *port) } EXPORT_SYMBOL(fm_port_is_in_auto_res_mode); +#ifdef CONFIG_FMAN_PFC +int fm_port_set_pfc_priorities_mapping_to_qman_wq(struct fm_port *port, + uint8_t prio, uint8_t wq) +{ + t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + int err; + int _errno; + + err = FM_PORT_SetPfcPrioritiesMappingToQmanWQ(p_LnxWrpFmPortDev->h_Dev, + prio, wq); + _errno = -GET_ERROR_TYPE(err); + if (unlikely(_errno < 0)) + pr_err("FM_PORT_SetPfcPrioritiesMappingToQmanWQ() = 0x%08x\n", err); + + return _errno; +} +EXPORT_SYMBOL(fm_port_set_pfc_priorities_mapping_to_qman_wq); +#endif + int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev, e_FmMacExceptions exception, bool enable) { @@ -1695,6 +1722,39 @@ int fm_mac_set_rx_pause_frames( } EXPORT_SYMBOL(fm_mac_set_rx_pause_frames); +#ifdef CONFIG_FMAN_PFC +int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev, + bool en) +{ + int _errno, i; + t_Error err; + + if (en) + for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) { + err = FM_MAC_SetTxPauseFrames(fm_mac_dev, + i, fsl_fm_pfc_quanta[i], + FSL_FM_PAUSE_THRESH_DEFAULT); + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) { + pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err); + return _errno; + } + } + else + for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) { + err = FM_MAC_SetTxPauseFrames(fm_mac_dev, + i, FSL_FM_PAUSE_TIME_DISABLE, + FSL_FM_PAUSE_THRESH_DEFAULT); + _errno = -GET_ERROR_TYPE(err); + if (_errno < 0) { + pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err); + return _errno; + } + } + + return _errno; +} +#else int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en) { @@ -1702,22 +1762,19 @@ int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev, t_Error err; if (en) - err = FM_MAC_SetTxPauseFrames(fm_mac_dev, - TX_PAUSE_PRIO_DEFAULT, - TX_PAUSE_TIME_ENABLE, - TX_PAUSE_THRESH_DEFAULT); + err = FM_MAC_SetTxAutoPauseFrames(fm_mac_dev, + FSL_FM_PAUSE_TIME_ENABLE); else - err = FM_MAC_SetTxPauseFrames(fm_mac_dev, - TX_PAUSE_PRIO_DEFAULT, - TX_PAUSE_TIME_DISABLE, - TX_PAUSE_THRESH_DEFAULT); + err = FM_MAC_SetTxAutoPauseFrames(fm_mac_dev, + FSL_FM_PAUSE_TIME_DISABLE); _errno = -GET_ERROR_TYPE(err); if (_errno < 0) - pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err); + pr_err("FM_MAC_SetTxAutoPauseFrames() = 0x%08x\n", err); return _errno; } +#endif EXPORT_SYMBOL(fm_mac_set_tx_pause_frames); int fm_rtc_enable(struct fm *fm_dev) diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c index 6e135a2..198691c 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c @@ -502,7 +502,17 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) /*const char *str_prop;*/ int lenp; - +#ifdef CONFIG_FMAN_PFC + if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX || + p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G) { + t_Error errCode = FM_PORT_ConfigPoolDepletion(p_LnxWrpFmPortDev->h_Dev, + &p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. + extBufPools.poolDepletion); + if (errCode != E_OK) + RETURN_ERROR(MAJOR, errCode, ("FM_PORT_ConfigPoolDepletion() failed")); + } +#endif + fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id); if (!fm_node) /* no advance parameters for FMan */ return E_OK; @@ -925,6 +935,10 @@ void fm_set_rx_port_params(struct fm_port *port, { t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port; int i; +#ifdef CONFIG_FMAN_PFC + uint8_t pfcv = 0; + uint8_t id; +#endif p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.errFqid = params->errq; @@ -932,6 +946,14 @@ void fm_set_rx_port_params(struct fm_port *port, params->defq; p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools. numOfPoolsUsed = params->num_pools; + +#ifdef CONFIG_FMAN_PFC + memset(&(p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. + extBufPools.poolDepletion), 0, sizeof(t_FmBufPoolDepletion)); + p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools. + poolDepletion.singlePoolModeEnable = true; +#endif + for (i = 0; i < params->num_pools; i++) { p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. extBufPools.extBufPool[i].id = @@ -939,8 +961,22 @@ void fm_set_rx_port_params(struct fm_port *port, p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. extBufPools.extBufPool[i].size = params->pool_param[i].size; + +#ifdef CONFIG_FMAN_PFC + id = params->pool_param[i].id; + p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. + extBufPools.poolDepletion.poolsToConsiderForSingleMode[id] = true; + pfcv |= params->pool_param[i].pfcv; +#endif } +#ifdef CONFIG_FMAN_PFC + for (i = 0; i < FM_MAX_NUM_OF_PFC_PRIORITIES; i++) + if (pfcv & (1 << i)) + p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. + extBufPools.poolDepletion.pfcPrioritiesEn[i] = true; +#endif + p_LnxWrpFmPortDev->buffPrefixContent.privDataSize = params->priv_data_size; p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult = |