Commit ebe9d9eb authored by David S. Miller's avatar David S. Miller

Merge branch 'fec-tx'

Joakim Zhang says:

====================
net: fec: fix TX bandwidth fluctuations

This patch set intends to fix TX bandwidth fluctuations, any feedback would be appreciated.

---
ChangeLogs:
	V1: remove RFC tag, RFC discussions please turn to below:
	    https://lore.kernel.org/lkml/YK0Ce5YxR2WYbrAo@lunn.ch/T/
	V2: change functions to be static in this patch set. And add the
	t-b tag.
	V3: fix sparse warining: ntohs()->htons()
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6ff5f813 52c4a1a8
...@@ -467,6 +467,11 @@ struct bufdesc_ex { ...@@ -467,6 +467,11 @@ struct bufdesc_ex {
*/ */
#define FEC_QUIRK_NO_HARD_RESET (1 << 18) #define FEC_QUIRK_NO_HARD_RESET (1 << 18)
/* i.MX6SX ENET IP supports multiple queues (3 queues), use this quirk to
* represents this ENET IP.
*/
#define FEC_QUIRK_HAS_MULTI_QUEUES (1 << 19)
struct bufdesc_prop { struct bufdesc_prop {
int qid; int qid;
/* Address of Rx and Tx buffers */ /* Address of Rx and Tx buffers */
......
...@@ -76,6 +76,8 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); ...@@ -76,6 +76,8 @@ static void fec_enet_itr_coal_init(struct net_device *ndev);
#define DRIVER_NAME "fec" #define DRIVER_NAME "fec"
static const u16 fec_enet_vlan_pri_to_queue[8] = {0, 0, 1, 1, 1, 2, 2, 2};
/* Pause frame feild and FIFO threshold */ /* Pause frame feild and FIFO threshold */
#define FEC_ENET_FCE (1 << 5) #define FEC_ENET_FCE (1 << 5)
#define FEC_ENET_RSEM_V 0x84 #define FEC_ENET_RSEM_V 0x84
...@@ -122,7 +124,7 @@ static const struct fec_devinfo fec_imx6x_info = { ...@@ -122,7 +124,7 @@ static const struct fec_devinfo fec_imx6x_info = {
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
FEC_QUIRK_CLEAR_SETUP_MII, FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES,
}; };
static const struct fec_devinfo fec_imx6ul_info = { static const struct fec_devinfo fec_imx6ul_info = {
...@@ -421,6 +423,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, ...@@ -421,6 +423,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
if (skb->ip_summed == CHECKSUM_PARTIAL) if (skb->ip_summed == CHECKSUM_PARTIAL)
estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
ebdp->cbd_bdu = 0; ebdp->cbd_bdu = 0;
ebdp->cbd_esc = cpu_to_fec32(estatus); ebdp->cbd_esc = cpu_to_fec32(estatus);
} }
...@@ -954,7 +957,7 @@ fec_restart(struct net_device *ndev) ...@@ -954,7 +957,7 @@ fec_restart(struct net_device *ndev)
* For i.MX6SX SOC, enet use AXI bus, we use disable MAC * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
* instead of reset MAC itself. * instead of reset MAC itself.
*/ */
if (fep->quirks & FEC_QUIRK_HAS_AVB || if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES ||
((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) {
writel(0, fep->hwp + FEC_ECNTRL); writel(0, fep->hwp + FEC_ECNTRL);
} else { } else {
...@@ -1165,7 +1168,7 @@ fec_stop(struct net_device *ndev) ...@@ -1165,7 +1168,7 @@ fec_stop(struct net_device *ndev)
* instead of reset MAC itself. * instead of reset MAC itself.
*/ */
if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
if (fep->quirks & FEC_QUIRK_HAS_AVB) { if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) {
writel(0, fep->hwp + FEC_ECNTRL); writel(0, fep->hwp + FEC_ECNTRL);
} else { } else {
writel(1, fep->hwp + FEC_ECNTRL); writel(1, fep->hwp + FEC_ECNTRL);
...@@ -2570,7 +2573,7 @@ static void fec_enet_itr_coal_set(struct net_device *ndev) ...@@ -2570,7 +2573,7 @@ static void fec_enet_itr_coal_set(struct net_device *ndev)
writel(tx_itr, fep->hwp + FEC_TXIC0); writel(tx_itr, fep->hwp + FEC_TXIC0);
writel(rx_itr, fep->hwp + FEC_RXIC0); writel(rx_itr, fep->hwp + FEC_RXIC0);
if (fep->quirks & FEC_QUIRK_HAS_AVB) { if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) {
writel(tx_itr, fep->hwp + FEC_TXIC1); writel(tx_itr, fep->hwp + FEC_TXIC1);
writel(rx_itr, fep->hwp + FEC_RXIC1); writel(rx_itr, fep->hwp + FEC_RXIC1);
writel(tx_itr, fep->hwp + FEC_TXIC2); writel(tx_itr, fep->hwp + FEC_TXIC2);
...@@ -3239,10 +3242,40 @@ static int fec_set_features(struct net_device *netdev, ...@@ -3239,10 +3242,40 @@ static int fec_set_features(struct net_device *netdev,
return 0; return 0;
} }
static u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb)
{
struct vlan_ethhdr *vhdr;
unsigned short vlan_TCI = 0;
if (skb->protocol == htons(ETH_P_ALL)) {
vhdr = (struct vlan_ethhdr *)(skb->data);
vlan_TCI = ntohs(vhdr->h_vlan_TCI);
}
return vlan_TCI;
}
static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb,
struct net_device *sb_dev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
u16 vlan_tag;
if (!(fep->quirks & FEC_QUIRK_HAS_AVB))
return netdev_pick_tx(ndev, skb, NULL);
vlan_tag = fec_enet_get_raw_vlan_tci(skb);
if (!vlan_tag)
return vlan_tag;
return fec_enet_vlan_pri_to_queue[vlan_tag >> 13];
}
static const struct net_device_ops fec_netdev_ops = { static const struct net_device_ops fec_netdev_ops = {
.ndo_open = fec_enet_open, .ndo_open = fec_enet_open,
.ndo_stop = fec_enet_close, .ndo_stop = fec_enet_close,
.ndo_start_xmit = fec_enet_start_xmit, .ndo_start_xmit = fec_enet_start_xmit,
.ndo_select_queue = fec_enet_select_queue,
.ndo_set_rx_mode = set_multicast_list, .ndo_set_rx_mode = set_multicast_list,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = fec_timeout, .ndo_tx_timeout = fec_timeout,
...@@ -3371,7 +3404,7 @@ static int fec_enet_init(struct net_device *ndev) ...@@ -3371,7 +3404,7 @@ static int fec_enet_init(struct net_device *ndev)
fep->csum_flags |= FLAG_RX_CSUM_ENABLED; fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
} }
if (fep->quirks & FEC_QUIRK_HAS_AVB) { if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) {
fep->tx_align = 0; fep->tx_align = 0;
fep->rx_align = 0x3f; fep->rx_align = 0x3f;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment