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

Merge branch 'thunderx-pass2'

Sunil Goutham says:

====================
net: thunderx: Support for pass-2 hw features

This patch set adds support for new features added in pass-2 revision
of hardware like TSO and count based interrupt coalescing.

Changes from v1:
- Addressed comments received regarding boolean bit field changes
  by excluding them from this patch. Will submit a seperate
  patch along with cleanup of unsed field.
- Got rid of new macro 'VNIC_NAPI_WEIGHT' introduced in
  count threshold interrupt patch.
====================
Reviewed-by: default avatarPavel Fedin <p.fedin@samsung.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2ad7b756 b9687b48
...@@ -265,6 +265,7 @@ struct nicvf { ...@@ -265,6 +265,7 @@ struct nicvf {
u8 tns_mode:1; u8 tns_mode:1;
u8 sqs_mode:1; u8 sqs_mode:1;
u8 loopback_supported:1; u8 loopback_supported:1;
bool hw_tso;
u16 mtu; u16 mtu;
struct queue_set *qs; struct queue_set *qs;
#define MAX_SQS_PER_VF_SINGLE_NODE 5 #define MAX_SQS_PER_VF_SINGLE_NODE 5
...@@ -489,6 +490,11 @@ static inline int nic_get_node_id(struct pci_dev *pdev) ...@@ -489,6 +490,11 @@ static inline int nic_get_node_id(struct pci_dev *pdev)
return ((addr >> NIC_NODE_ID_SHIFT) & NIC_NODE_ID_MASK); return ((addr >> NIC_NODE_ID_SHIFT) & NIC_NODE_ID_MASK);
} }
static inline bool pass1_silicon(struct pci_dev *pdev)
{
return pdev->revision < 8;
}
int nicvf_set_real_num_queues(struct net_device *netdev, int nicvf_set_real_num_queues(struct net_device *netdev,
int tx_queues, int rx_queues); int tx_queues, int rx_queues);
int nicvf_open(struct net_device *netdev); int nicvf_open(struct net_device *netdev);
......
...@@ -55,11 +55,6 @@ struct nicpf { ...@@ -55,11 +55,6 @@ struct nicpf {
bool irq_allocated[NIC_PF_MSIX_VECTORS]; bool irq_allocated[NIC_PF_MSIX_VECTORS];
}; };
static inline bool pass1_silicon(struct nicpf *nic)
{
return nic->pdev->revision < 8;
}
/* Supported devices */ /* Supported devices */
static const struct pci_device_id nic_id_table[] = { static const struct pci_device_id nic_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) }, { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) },
...@@ -123,7 +118,7 @@ static void nic_send_msg_to_vf(struct nicpf *nic, int vf, union nic_mbx *mbx) ...@@ -123,7 +118,7 @@ static void nic_send_msg_to_vf(struct nicpf *nic, int vf, union nic_mbx *mbx)
* when PF writes to MBOX(1), in next revisions when * when PF writes to MBOX(1), in next revisions when
* PF writes to MBOX(0) * PF writes to MBOX(0)
*/ */
if (pass1_silicon(nic)) { if (pass1_silicon(nic->pdev)) {
/* see the comment for nic_reg_write()/nic_reg_read() /* see the comment for nic_reg_write()/nic_reg_read()
* functions above * functions above
*/ */
...@@ -400,7 +395,7 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg) ...@@ -400,7 +395,7 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */ padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */
/* Leave RSS_SIZE as '0' to disable RSS */ /* Leave RSS_SIZE as '0' to disable RSS */
if (pass1_silicon(nic)) { if (pass1_silicon(nic->pdev)) {
nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3), nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
(vnic << 24) | (padd << 16) | (vnic << 24) | (padd << 16) |
(rssi_base + rssi)); (rssi_base + rssi));
...@@ -470,7 +465,7 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg) ...@@ -470,7 +465,7 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
} }
cpi_base = nic->cpi_base[cfg->vf_id]; cpi_base = nic->cpi_base[cfg->vf_id];
if (pass1_silicon(nic)) if (pass1_silicon(nic->pdev))
idx_addr = NIC_PF_CPI_0_2047_CFG; idx_addr = NIC_PF_CPI_0_2047_CFG;
else else
idx_addr = NIC_PF_MPI_0_2047_CFG; idx_addr = NIC_PF_MPI_0_2047_CFG;
......
...@@ -525,14 +525,22 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev, ...@@ -525,14 +525,22 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev,
__func__, cqe_tx->sq_qs, cqe_tx->sq_idx, __func__, cqe_tx->sq_qs, cqe_tx->sq_idx,
cqe_tx->sqe_ptr, hdr->subdesc_cnt); cqe_tx->sqe_ptr, hdr->subdesc_cnt);
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1);
nicvf_check_cqe_tx_errs(nic, cq, cqe_tx); nicvf_check_cqe_tx_errs(nic, cq, cqe_tx);
skb = (struct sk_buff *)sq->skbuff[cqe_tx->sqe_ptr]; skb = (struct sk_buff *)sq->skbuff[cqe_tx->sqe_ptr];
/* For TSO offloaded packets only one head SKB needs to be freed */ /* For TSO offloaded packets only one SQE will have a valid SKB */
if (skb) { if (skb) {
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1);
prefetch(skb); prefetch(skb);
dev_consume_skb_any(skb); dev_consume_skb_any(skb);
sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL; sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
} else {
/* In case of HW TSO, HW sends a CQE for each segment of a TSO
* packet instead of a single CQE for the whole TSO packet
* transmitted. Each of this CQE points to the same SQE, so
* avoid freeing same SQE multiple times.
*/
if (!nic->hw_tso)
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1);
} }
} }
...@@ -1549,6 +1557,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1549,6 +1557,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; netdev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
if (!pass1_silicon(nic->pdev))
nic->hw_tso = true;
netdev->netdev_ops = &nicvf_netdev_ops; netdev->netdev_ops = &nicvf_netdev_ops;
netdev->watchdog_timeo = NICVF_TX_TIMEOUT; netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
......
...@@ -299,7 +299,7 @@ static int nicvf_init_cmp_queue(struct nicvf *nic, ...@@ -299,7 +299,7 @@ static int nicvf_init_cmp_queue(struct nicvf *nic,
return err; return err;
cq->desc = cq->dmem.base; cq->desc = cq->dmem.base;
cq->thresh = CMP_QUEUE_CQE_THRESH; cq->thresh = pass1_silicon(nic->pdev) ? 0 : CMP_QUEUE_CQE_THRESH;
nic->cq_coalesce_usecs = (CMP_QUEUE_TIMER_THRESH * 0.05) - 1; nic->cq_coalesce_usecs = (CMP_QUEUE_TIMER_THRESH * 0.05) - 1;
return 0; return 0;
...@@ -925,7 +925,7 @@ static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb) ...@@ -925,7 +925,7 @@ static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb)
{ {
int subdesc_cnt = MIN_SQ_DESC_PER_PKT_XMIT; int subdesc_cnt = MIN_SQ_DESC_PER_PKT_XMIT;
if (skb_shinfo(skb)->gso_size) { if (skb_shinfo(skb)->gso_size && !nic->hw_tso) {
subdesc_cnt = nicvf_tso_count_subdescs(skb); subdesc_cnt = nicvf_tso_count_subdescs(skb);
return subdesc_cnt; return subdesc_cnt;
} }
...@@ -940,7 +940,7 @@ static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb) ...@@ -940,7 +940,7 @@ static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb)
* First subdescriptor for every send descriptor. * First subdescriptor for every send descriptor.
*/ */
static inline void static inline void
nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry, nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
int subdesc_cnt, struct sk_buff *skb, int len) int subdesc_cnt, struct sk_buff *skb, int len)
{ {
int proto; int proto;
...@@ -976,6 +976,15 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry, ...@@ -976,6 +976,15 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry,
break; break;
} }
} }
if (nic->hw_tso && skb_shinfo(skb)->gso_size) {
hdr->tso = 1;
hdr->tso_start = skb_transport_offset(skb) + tcp_hdrlen(skb);
hdr->tso_max_paysize = skb_shinfo(skb)->gso_size;
/* For non-tunneled pkts, point this to L2 ethertype */
hdr->inner_l3_offset = skb_network_offset(skb) - 2;
nic->drv_stats.tx_tso++;
}
} }
/* SQ GATHER subdescriptor /* SQ GATHER subdescriptor
...@@ -1045,7 +1054,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq, ...@@ -1045,7 +1054,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq,
data_left -= size; data_left -= size;
tso_build_data(skb, &tso, size); tso_build_data(skb, &tso, size);
} }
nicvf_sq_add_hdr_subdesc(sq, hdr_qentry, nicvf_sq_add_hdr_subdesc(nic, sq, hdr_qentry,
seg_subdescs - 1, skb, seg_len); seg_subdescs - 1, skb, seg_len);
sq->skbuff[hdr_qentry] = (u64)NULL; sq->skbuff[hdr_qentry] = (u64)NULL;
qentry = nicvf_get_nxt_sqentry(sq, qentry); qentry = nicvf_get_nxt_sqentry(sq, qentry);
...@@ -1098,11 +1107,12 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb) ...@@ -1098,11 +1107,12 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb)
qentry = nicvf_get_sq_desc(sq, subdesc_cnt); qentry = nicvf_get_sq_desc(sq, subdesc_cnt);
/* Check if its a TSO packet */ /* Check if its a TSO packet */
if (skb_shinfo(skb)->gso_size) if (skb_shinfo(skb)->gso_size && !nic->hw_tso)
return nicvf_sq_append_tso(nic, sq, sq_num, qentry, skb); return nicvf_sq_append_tso(nic, sq, sq_num, qentry, skb);
/* Add SQ header subdesc */ /* Add SQ header subdesc */
nicvf_sq_add_hdr_subdesc(sq, qentry, subdesc_cnt - 1, skb, skb->len); nicvf_sq_add_hdr_subdesc(nic, sq, qentry, subdesc_cnt - 1,
skb, skb->len);
/* Add SQ gather subdescs */ /* Add SQ gather subdescs */
qentry = nicvf_get_nxt_sqentry(sq, qentry); qentry = nicvf_get_nxt_sqentry(sq, qentry);
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
*/ */
#define CMP_QSIZE CMP_QUEUE_SIZE2 #define CMP_QSIZE CMP_QUEUE_SIZE2
#define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10)) #define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10))
#define CMP_QUEUE_CQE_THRESH 0 #define CMP_QUEUE_CQE_THRESH (NAPI_POLL_WEIGHT / 2)
#define CMP_QUEUE_TIMER_THRESH 80 /* ~2usec */ #define CMP_QUEUE_TIMER_THRESH 80 /* ~2usec */
#define RBDR_SIZE RBDR_SIZE0 #define RBDR_SIZE RBDR_SIZE0
......
...@@ -545,25 +545,28 @@ struct sq_hdr_subdesc { ...@@ -545,25 +545,28 @@ struct sq_hdr_subdesc {
u64 subdesc_cnt:8; u64 subdesc_cnt:8;
u64 csum_l4:2; u64 csum_l4:2;
u64 csum_l3:1; u64 csum_l3:1;
u64 rsvd0:5; u64 csum_inner_l4:2;
u64 csum_inner_l3:1;
u64 rsvd0:2;
u64 l4_offset:8; u64 l4_offset:8;
u64 l3_offset:8; u64 l3_offset:8;
u64 rsvd1:4; u64 rsvd1:4;
u64 tot_len:20; /* W0 */ u64 tot_len:20; /* W0 */
u64 tso_sdc_cont:8; u64 rsvd2:24;
u64 tso_sdc_first:8; u64 inner_l4_offset:8;
u64 tso_l4_offset:8; u64 inner_l3_offset:8;
u64 tso_flags_last:12; u64 tso_start:8;
u64 tso_flags_first:12; u64 rsvd3:2;
u64 rsvd2:2;
u64 tso_max_paysize:14; /* W1 */ u64 tso_max_paysize:14; /* W1 */
#elif defined(__LITTLE_ENDIAN_BITFIELD) #elif defined(__LITTLE_ENDIAN_BITFIELD)
u64 tot_len:20; u64 tot_len:20;
u64 rsvd1:4; u64 rsvd1:4;
u64 l3_offset:8; u64 l3_offset:8;
u64 l4_offset:8; u64 l4_offset:8;
u64 rsvd0:5; u64 rsvd0:2;
u64 csum_inner_l3:1;
u64 csum_inner_l4:2;
u64 csum_l3:1; u64 csum_l3:1;
u64 csum_l4:2; u64 csum_l4:2;
u64 subdesc_cnt:8; u64 subdesc_cnt:8;
...@@ -574,12 +577,11 @@ struct sq_hdr_subdesc { ...@@ -574,12 +577,11 @@ struct sq_hdr_subdesc {
u64 subdesc_type:4; /* W0 */ u64 subdesc_type:4; /* W0 */
u64 tso_max_paysize:14; u64 tso_max_paysize:14;
u64 rsvd2:2; u64 rsvd3:2;
u64 tso_flags_first:12; u64 tso_start:8;
u64 tso_flags_last:12; u64 inner_l3_offset:8;
u64 tso_l4_offset:8; u64 inner_l4_offset:8;
u64 tso_sdc_first:8; u64 rsvd2:24; /* W1 */
u64 tso_sdc_cont:8; /* W1 */
#endif #endif
}; };
......
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