Merge branch 'xgene-fixes'
Iyappan Subramanian says: ==================== drivers: net: xgene: Bug fixes This patch set addresses the following bug fixes that were found during testing. 1. IPv4 forward test crash - drivers: net: xgene: fix IPv4 forward crash 2. Sharing of irqs - drivers: net: xgene: fix sharing of irqs 3. Ununiform latency across queues - drivers: net: xgene: fix ununiform latency across queues 4. Fix statistics counters race condition - drivers: net: xgene: fix statistics counters race condition 5. Correcting register offset and field lengths - drivers: net: xgene: fix register offset v2: Address review comments from v1 - Defer TSO fix, and reposting all other patches from v1 v1: - Initial version ==================== Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b915065862
|
@ -43,6 +43,7 @@ static void xgene_cle_idt_to_hw(u32 dstqid, u32 fpsel,
|
||||||
static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
|
static void xgene_cle_dbptr_to_hw(struct xgene_enet_pdata *pdata,
|
||||||
struct xgene_cle_dbptr *dbptr, u32 *buf)
|
struct xgene_cle_dbptr *dbptr, u32 *buf)
|
||||||
{
|
{
|
||||||
|
buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
|
||||||
buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
|
buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
|
||||||
SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
|
SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
|
||||||
|
|
||||||
|
@ -412,7 +413,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
|
||||||
.branch = {
|
.branch = {
|
||||||
{
|
{
|
||||||
/* IPV4 */
|
/* IPV4 */
|
||||||
.valid = 0,
|
.valid = 1,
|
||||||
.next_packet_pointer = 22,
|
.next_packet_pointer = 22,
|
||||||
.jump_bw = JMP_FW,
|
.jump_bw = JMP_FW,
|
||||||
.jump_rel = JMP_ABS,
|
.jump_rel = JMP_ABS,
|
||||||
|
@ -420,7 +421,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
|
||||||
.next_node = PKT_PROT_NODE,
|
.next_node = PKT_PROT_NODE,
|
||||||
.next_branch = 0,
|
.next_branch = 0,
|
||||||
.data = 0x8,
|
.data = 0x8,
|
||||||
.mask = 0xffff
|
.mask = 0x0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.valid = 0,
|
.valid = 0,
|
||||||
|
@ -456,7 +457,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
|
||||||
.next_node = RSS_IPV4_TCP_NODE,
|
.next_node = RSS_IPV4_TCP_NODE,
|
||||||
.next_branch = 0,
|
.next_branch = 0,
|
||||||
.data = 0x0600,
|
.data = 0x0600,
|
||||||
.mask = 0xffff
|
.mask = 0x00ff
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
/* UDP */
|
/* UDP */
|
||||||
|
@ -468,7 +469,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
|
||||||
.next_node = RSS_IPV4_UDP_NODE,
|
.next_node = RSS_IPV4_UDP_NODE,
|
||||||
.next_branch = 0,
|
.next_branch = 0,
|
||||||
.data = 0x1100,
|
.data = 0x1100,
|
||||||
.mask = 0xffff
|
.mask = 0x00ff
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.valid = 0,
|
.valid = 0,
|
||||||
|
@ -642,7 +643,7 @@ static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
|
||||||
{
|
{
|
||||||
/* TCP DST Port */
|
/* TCP DST Port */
|
||||||
.valid = 0,
|
.valid = 0,
|
||||||
.next_packet_pointer = 256,
|
.next_packet_pointer = 258,
|
||||||
.jump_bw = JMP_FW,
|
.jump_bw = JMP_FW,
|
||||||
.jump_rel = JMP_ABS,
|
.jump_rel = JMP_ABS,
|
||||||
.operation = EQT,
|
.operation = EQT,
|
||||||
|
|
|
@ -83,6 +83,8 @@
|
||||||
#define CLE_TYPE_POS 0
|
#define CLE_TYPE_POS 0
|
||||||
#define CLE_TYPE_LEN 2
|
#define CLE_TYPE_LEN 2
|
||||||
|
|
||||||
|
#define CLE_DROP_POS 28
|
||||||
|
#define CLE_DROP_LEN 1
|
||||||
#define CLE_DSTQIDL_POS 25
|
#define CLE_DSTQIDL_POS 25
|
||||||
#define CLE_DSTQIDL_LEN 7
|
#define CLE_DSTQIDL_LEN 7
|
||||||
#define CLE_DSTQIDH_POS 0
|
#define CLE_DSTQIDH_POS 0
|
||||||
|
|
|
@ -219,27 +219,30 @@ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
|
||||||
struct xgene_enet_pdata *pdata,
|
struct xgene_enet_pdata *pdata,
|
||||||
enum xgene_enet_err_code status)
|
enum xgene_enet_err_code status)
|
||||||
{
|
{
|
||||||
struct rtnl_link_stats64 *stats = &pdata->stats;
|
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case INGRESS_CRC:
|
case INGRESS_CRC:
|
||||||
stats->rx_crc_errors++;
|
ring->rx_crc_errors++;
|
||||||
|
ring->rx_dropped++;
|
||||||
break;
|
break;
|
||||||
case INGRESS_CHECKSUM:
|
case INGRESS_CHECKSUM:
|
||||||
case INGRESS_CHECKSUM_COMPUTE:
|
case INGRESS_CHECKSUM_COMPUTE:
|
||||||
stats->rx_errors++;
|
ring->rx_errors++;
|
||||||
|
ring->rx_dropped++;
|
||||||
break;
|
break;
|
||||||
case INGRESS_TRUNC_FRAME:
|
case INGRESS_TRUNC_FRAME:
|
||||||
stats->rx_frame_errors++;
|
ring->rx_frame_errors++;
|
||||||
|
ring->rx_dropped++;
|
||||||
break;
|
break;
|
||||||
case INGRESS_PKT_LEN:
|
case INGRESS_PKT_LEN:
|
||||||
stats->rx_length_errors++;
|
ring->rx_length_errors++;
|
||||||
|
ring->rx_dropped++;
|
||||||
break;
|
break;
|
||||||
case INGRESS_PKT_UNDER:
|
case INGRESS_PKT_UNDER:
|
||||||
stats->rx_frame_errors++;
|
ring->rx_frame_errors++;
|
||||||
|
ring->rx_dropped++;
|
||||||
break;
|
break;
|
||||||
case INGRESS_FIFO_OVERRUN:
|
case INGRESS_FIFO_OVERRUN:
|
||||||
stats->rx_fifo_errors++;
|
ring->rx_fifo_errors++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -86,7 +86,7 @@ enum xgene_enet_rm {
|
||||||
#define RINGADDRL_POS 5
|
#define RINGADDRL_POS 5
|
||||||
#define RINGADDRL_LEN 27
|
#define RINGADDRL_LEN 27
|
||||||
#define RINGADDRH_POS 0
|
#define RINGADDRH_POS 0
|
||||||
#define RINGADDRH_LEN 6
|
#define RINGADDRH_LEN 7
|
||||||
#define RINGSIZE_POS 23
|
#define RINGSIZE_POS 23
|
||||||
#define RINGSIZE_LEN 3
|
#define RINGSIZE_LEN 3
|
||||||
#define RINGTYPE_POS 19
|
#define RINGTYPE_POS 19
|
||||||
|
@ -94,9 +94,9 @@ enum xgene_enet_rm {
|
||||||
#define RINGMODE_POS 20
|
#define RINGMODE_POS 20
|
||||||
#define RINGMODE_LEN 3
|
#define RINGMODE_LEN 3
|
||||||
#define RECOMTIMEOUTL_POS 28
|
#define RECOMTIMEOUTL_POS 28
|
||||||
#define RECOMTIMEOUTL_LEN 3
|
#define RECOMTIMEOUTL_LEN 4
|
||||||
#define RECOMTIMEOUTH_POS 0
|
#define RECOMTIMEOUTH_POS 0
|
||||||
#define RECOMTIMEOUTH_LEN 2
|
#define RECOMTIMEOUTH_LEN 3
|
||||||
#define NUMMSGSINQ_POS 1
|
#define NUMMSGSINQ_POS 1
|
||||||
#define NUMMSGSINQ_LEN 16
|
#define NUMMSGSINQ_LEN 16
|
||||||
#define ACCEPTLERR BIT(19)
|
#define ACCEPTLERR BIT(19)
|
||||||
|
@ -201,6 +201,8 @@ enum xgene_enet_rm {
|
||||||
#define USERINFO_LEN 32
|
#define USERINFO_LEN 32
|
||||||
#define FPQNUM_POS 32
|
#define FPQNUM_POS 32
|
||||||
#define FPQNUM_LEN 12
|
#define FPQNUM_LEN 12
|
||||||
|
#define ELERR_POS 46
|
||||||
|
#define ELERR_LEN 2
|
||||||
#define NV_POS 50
|
#define NV_POS 50
|
||||||
#define NV_LEN 1
|
#define NV_LEN 1
|
||||||
#define LL_POS 51
|
#define LL_POS 51
|
||||||
|
|
|
@ -443,8 +443,8 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
|
||||||
|
|
||||||
skb_tx_timestamp(skb);
|
skb_tx_timestamp(skb);
|
||||||
|
|
||||||
pdata->stats.tx_packets++;
|
tx_ring->tx_packets++;
|
||||||
pdata->stats.tx_bytes += skb->len;
|
tx_ring->tx_bytes += skb->len;
|
||||||
|
|
||||||
pdata->ring_ops->wr_cmd(tx_ring, count);
|
pdata->ring_ops->wr_cmd(tx_ring, count);
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
@ -483,12 +483,12 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
|
||||||
skb = buf_pool->rx_skb[skb_index];
|
skb = buf_pool->rx_skb[skb_index];
|
||||||
|
|
||||||
/* checking for error */
|
/* checking for error */
|
||||||
status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
|
status = (GET_VAL(ELERR, le64_to_cpu(raw_desc->m0)) << LERR_LEN) ||
|
||||||
|
GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
|
||||||
if (unlikely(status > 2)) {
|
if (unlikely(status > 2)) {
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
|
xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
|
||||||
status);
|
status);
|
||||||
pdata->stats.rx_dropped++;
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -506,8 +506,8 @@ static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
|
||||||
xgene_enet_skip_csum(skb);
|
xgene_enet_skip_csum(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
pdata->stats.rx_packets++;
|
rx_ring->rx_packets++;
|
||||||
pdata->stats.rx_bytes += datalen;
|
rx_ring->rx_bytes += datalen;
|
||||||
napi_gro_receive(&rx_ring->napi, skb);
|
napi_gro_receive(&rx_ring->napi, skb);
|
||||||
out:
|
out:
|
||||||
if (--rx_ring->nbufpool == 0) {
|
if (--rx_ring->nbufpool == 0) {
|
||||||
|
@ -630,7 +630,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
|
||||||
ring = pdata->rx_ring[i];
|
ring = pdata->rx_ring[i];
|
||||||
irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
|
irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
|
||||||
ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
|
ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
|
||||||
IRQF_SHARED, ring->irq_name, ring);
|
0, ring->irq_name, ring);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
netdev_err(ndev, "Failed to request irq %s\n",
|
netdev_err(ndev, "Failed to request irq %s\n",
|
||||||
ring->irq_name);
|
ring->irq_name);
|
||||||
|
@ -641,7 +641,7 @@ static int xgene_enet_register_irq(struct net_device *ndev)
|
||||||
ring = pdata->tx_ring[i]->cp_ring;
|
ring = pdata->tx_ring[i]->cp_ring;
|
||||||
irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
|
irq_set_status_flags(ring->irq, IRQ_DISABLE_UNLAZY);
|
||||||
ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
|
ret = devm_request_irq(dev, ring->irq, xgene_enet_rx_irq,
|
||||||
IRQF_SHARED, ring->irq_name, ring);
|
0, ring->irq_name, ring);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
netdev_err(ndev, "Failed to request irq %s\n",
|
netdev_err(ndev, "Failed to request irq %s\n",
|
||||||
ring->irq_name);
|
ring->irq_name);
|
||||||
|
@ -1114,12 +1114,31 @@ static struct rtnl_link_stats64 *xgene_enet_get_stats64(
|
||||||
{
|
{
|
||||||
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
struct xgene_enet_pdata *pdata = netdev_priv(ndev);
|
||||||
struct rtnl_link_stats64 *stats = &pdata->stats;
|
struct rtnl_link_stats64 *stats = &pdata->stats;
|
||||||
|
struct xgene_enet_desc_ring *ring;
|
||||||
|
int i;
|
||||||
|
|
||||||
stats->rx_errors += stats->rx_length_errors +
|
memset(stats, 0, sizeof(struct rtnl_link_stats64));
|
||||||
stats->rx_crc_errors +
|
for (i = 0; i < pdata->txq_cnt; i++) {
|
||||||
stats->rx_frame_errors +
|
ring = pdata->tx_ring[i];
|
||||||
stats->rx_fifo_errors;
|
if (ring) {
|
||||||
memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64));
|
stats->tx_packets += ring->tx_packets;
|
||||||
|
stats->tx_bytes += ring->tx_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pdata->rxq_cnt; i++) {
|
||||||
|
ring = pdata->rx_ring[i];
|
||||||
|
if (ring) {
|
||||||
|
stats->rx_packets += ring->rx_packets;
|
||||||
|
stats->rx_bytes += ring->rx_bytes;
|
||||||
|
stats->rx_errors += ring->rx_length_errors +
|
||||||
|
ring->rx_crc_errors +
|
||||||
|
ring->rx_frame_errors +
|
||||||
|
ring->rx_fifo_errors;
|
||||||
|
stats->rx_dropped += ring->rx_dropped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(storage, stats, sizeof(struct rtnl_link_stats64));
|
||||||
|
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
@ -1234,6 +1253,13 @@ static int xgene_enet_get_irqs(struct xgene_enet_pdata *pdata)
|
||||||
for (i = 0; i < max_irqs; i++) {
|
for (i = 0; i < max_irqs; i++) {
|
||||||
ret = platform_get_irq(pdev, i);
|
ret = platform_get_irq(pdev, i);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||||
|
max_irqs = i;
|
||||||
|
pdata->rxq_cnt = max_irqs / 2;
|
||||||
|
pdata->txq_cnt = max_irqs / 2;
|
||||||
|
pdata->cq_cnt = max_irqs / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
dev_err(dev, "Unable to get ENET IRQ\n");
|
dev_err(dev, "Unable to get ENET IRQ\n");
|
||||||
ret = ret ? : -ENXIO;
|
ret = ret ? : -ENXIO;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1437,19 +1463,28 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
|
||||||
pdata->port_ops = &xgene_xgport_ops;
|
pdata->port_ops = &xgene_xgport_ops;
|
||||||
pdata->cle_ops = &xgene_cle3in_ops;
|
pdata->cle_ops = &xgene_cle3in_ops;
|
||||||
pdata->rm = RM0;
|
pdata->rm = RM0;
|
||||||
pdata->rxq_cnt = XGENE_NUM_RX_RING;
|
if (!pdata->rxq_cnt) {
|
||||||
pdata->txq_cnt = XGENE_NUM_TX_RING;
|
pdata->rxq_cnt = XGENE_NUM_RX_RING;
|
||||||
pdata->cq_cnt = XGENE_NUM_TXC_RING;
|
pdata->txq_cnt = XGENE_NUM_TX_RING;
|
||||||
|
pdata->cq_cnt = XGENE_NUM_TXC_RING;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdata->enet_id == XGENE_ENET1) {
|
if (pdata->enet_id == XGENE_ENET1) {
|
||||||
switch (pdata->port_id) {
|
switch (pdata->port_id) {
|
||||||
case 0:
|
case 0:
|
||||||
pdata->cpu_bufnum = START_CPU_BUFNUM_0;
|
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||||
pdata->eth_bufnum = START_ETH_BUFNUM_0;
|
pdata->cpu_bufnum = X2_START_CPU_BUFNUM_0;
|
||||||
pdata->bp_bufnum = START_BP_BUFNUM_0;
|
pdata->eth_bufnum = X2_START_ETH_BUFNUM_0;
|
||||||
pdata->ring_num = START_RING_NUM_0;
|
pdata->bp_bufnum = X2_START_BP_BUFNUM_0;
|
||||||
|
pdata->ring_num = START_RING_NUM_0;
|
||||||
|
} else {
|
||||||
|
pdata->cpu_bufnum = START_CPU_BUFNUM_0;
|
||||||
|
pdata->eth_bufnum = START_ETH_BUFNUM_0;
|
||||||
|
pdata->bp_bufnum = START_BP_BUFNUM_0;
|
||||||
|
pdata->ring_num = START_RING_NUM_0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
|
||||||
|
|
|
@ -49,10 +49,10 @@
|
||||||
#define XGENE_ENET_MSS 1448
|
#define XGENE_ENET_MSS 1448
|
||||||
#define XGENE_MIN_ENET_FRAME_SIZE 60
|
#define XGENE_MIN_ENET_FRAME_SIZE 60
|
||||||
|
|
||||||
#define XGENE_MAX_ENET_IRQ 8
|
#define XGENE_MAX_ENET_IRQ 16
|
||||||
#define XGENE_NUM_RX_RING 4
|
#define XGENE_NUM_RX_RING 8
|
||||||
#define XGENE_NUM_TX_RING 4
|
#define XGENE_NUM_TX_RING 8
|
||||||
#define XGENE_NUM_TXC_RING 4
|
#define XGENE_NUM_TXC_RING 8
|
||||||
|
|
||||||
#define START_CPU_BUFNUM_0 0
|
#define START_CPU_BUFNUM_0 0
|
||||||
#define START_ETH_BUFNUM_0 2
|
#define START_ETH_BUFNUM_0 2
|
||||||
|
@ -121,6 +121,16 @@ struct xgene_enet_desc_ring {
|
||||||
struct xgene_enet_raw_desc16 *raw_desc16;
|
struct xgene_enet_raw_desc16 *raw_desc16;
|
||||||
};
|
};
|
||||||
__le64 *exp_bufs;
|
__le64 *exp_bufs;
|
||||||
|
u64 tx_packets;
|
||||||
|
u64 tx_bytes;
|
||||||
|
u64 rx_packets;
|
||||||
|
u64 rx_bytes;
|
||||||
|
u64 rx_dropped;
|
||||||
|
u64 rx_errors;
|
||||||
|
u64 rx_length_errors;
|
||||||
|
u64 rx_crc_errors;
|
||||||
|
u64 rx_frame_errors;
|
||||||
|
u64 rx_fifo_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xgene_mac_ops {
|
struct xgene_mac_ops {
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#define LINK_STATUS BIT(2)
|
#define LINK_STATUS BIT(2)
|
||||||
#define LINK_UP BIT(15)
|
#define LINK_UP BIT(15)
|
||||||
#define MPA_IDLE_WITH_QMI_EMPTY BIT(12)
|
#define MPA_IDLE_WITH_QMI_EMPTY BIT(12)
|
||||||
#define SG_RX_DV_GATE_REG_0_ADDR 0x0dfc
|
#define SG_RX_DV_GATE_REG_0_ADDR 0x05fc
|
||||||
|
|
||||||
extern const struct xgene_mac_ops xgene_sgmac_ops;
|
extern const struct xgene_mac_ops xgene_sgmac_ops;
|
||||||
extern const struct xgene_port_ops xgene_sgport_ops;
|
extern const struct xgene_port_ops xgene_sgport_ops;
|
||||||
|
|
Loading…
Reference in New Issue