diff options
Diffstat (limited to 'drivers/net/ethernet/cavium/thunder/nicvf_queues.c')
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 64 |
1 files changed, 57 insertions, 7 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 0ff8e60deccb..dda3ea3f3bb6 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c | |||
@@ -938,6 +938,8 @@ static int nicvf_tso_count_subdescs(struct sk_buff *skb) | |||
938 | return num_edescs + sh->gso_segs; | 938 | return num_edescs + sh->gso_segs; |
939 | } | 939 | } |
940 | 940 | ||
941 | #define POST_CQE_DESC_COUNT 2 | ||
942 | |||
941 | /* Get the number of SQ descriptors needed to xmit this skb */ | 943 | /* Get the number of SQ descriptors needed to xmit this skb */ |
942 | static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb) | 944 | static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb) |
943 | { | 945 | { |
@@ -948,6 +950,10 @@ static int nicvf_sq_subdesc_required(struct nicvf *nic, struct sk_buff *skb) | |||
948 | return subdesc_cnt; | 950 | return subdesc_cnt; |
949 | } | 951 | } |
950 | 952 | ||
953 | /* Dummy descriptors to get TSO pkt completion notification */ | ||
954 | if (nic->t88 && nic->hw_tso && skb_shinfo(skb)->gso_size) | ||
955 | subdesc_cnt += POST_CQE_DESC_COUNT; | ||
956 | |||
951 | if (skb_shinfo(skb)->nr_frags) | 957 | if (skb_shinfo(skb)->nr_frags) |
952 | subdesc_cnt += skb_shinfo(skb)->nr_frags; | 958 | subdesc_cnt += skb_shinfo(skb)->nr_frags; |
953 | 959 | ||
@@ -965,14 +971,21 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry, | |||
965 | struct sq_hdr_subdesc *hdr; | 971 | struct sq_hdr_subdesc *hdr; |
966 | 972 | ||
967 | hdr = (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, qentry); | 973 | hdr = (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, qentry); |
968 | sq->skbuff[qentry] = (u64)skb; | ||
969 | |||
970 | memset(hdr, 0, SND_QUEUE_DESC_SIZE); | 974 | memset(hdr, 0, SND_QUEUE_DESC_SIZE); |
971 | hdr->subdesc_type = SQ_DESC_TYPE_HEADER; | 975 | hdr->subdesc_type = SQ_DESC_TYPE_HEADER; |
972 | /* Enable notification via CQE after processing SQE */ | 976 | |
973 | hdr->post_cqe = 1; | 977 | if (nic->t88 && nic->hw_tso && skb_shinfo(skb)->gso_size) { |
974 | /* No of subdescriptors following this */ | 978 | /* post_cqe = 0, to avoid HW posting a CQE for every TSO |
975 | hdr->subdesc_cnt = subdesc_cnt; | 979 | * segment transmitted on 88xx. |
980 | */ | ||
981 | hdr->subdesc_cnt = subdesc_cnt - POST_CQE_DESC_COUNT; | ||
982 | } else { | ||
983 | sq->skbuff[qentry] = (u64)skb; | ||
984 | /* Enable notification via CQE after processing SQE */ | ||
985 | hdr->post_cqe = 1; | ||
986 | /* No of subdescriptors following this */ | ||
987 | hdr->subdesc_cnt = subdesc_cnt; | ||
988 | } | ||
976 | hdr->tot_len = len; | 989 | hdr->tot_len = len; |
977 | 990 | ||
978 | /* Offload checksum calculation to HW */ | 991 | /* Offload checksum calculation to HW */ |
@@ -1023,6 +1036,37 @@ static inline void nicvf_sq_add_gather_subdesc(struct snd_queue *sq, int qentry, | |||
1023 | gather->addr = data; | 1036 | gather->addr = data; |
1024 | } | 1037 | } |
1025 | 1038 | ||
1039 | /* Add HDR + IMMEDIATE subdescriptors right after descriptors of a TSO | ||
1040 | * packet so that a CQE is posted as a notifation for transmission of | ||
1041 | * TSO packet. | ||
1042 | */ | ||
1043 | static inline void nicvf_sq_add_cqe_subdesc(struct snd_queue *sq, int qentry, | ||
1044 | int tso_sqe, struct sk_buff *skb) | ||
1045 | { | ||
1046 | struct sq_imm_subdesc *imm; | ||
1047 | struct sq_hdr_subdesc *hdr; | ||
1048 | |||
1049 | sq->skbuff[qentry] = (u64)skb; | ||
1050 | |||
1051 | hdr = (struct sq_hdr_subdesc *)GET_SQ_DESC(sq, qentry); | ||
1052 | memset(hdr, 0, SND_QUEUE_DESC_SIZE); | ||
1053 | hdr->subdesc_type = SQ_DESC_TYPE_HEADER; | ||
1054 | /* Enable notification via CQE after processing SQE */ | ||
1055 | hdr->post_cqe = 1; | ||
1056 | /* There is no packet to transmit here */ | ||
1057 | hdr->dont_send = 1; | ||
1058 | hdr->subdesc_cnt = POST_CQE_DESC_COUNT - 1; | ||
1059 | hdr->tot_len = 1; | ||
1060 | /* Actual TSO header SQE index, needed for cleanup */ | ||
1061 | hdr->rsvd2 = tso_sqe; | ||
1062 | |||
1063 | qentry = nicvf_get_nxt_sqentry(sq, qentry); | ||
1064 | imm = (struct sq_imm_subdesc *)GET_SQ_DESC(sq, qentry); | ||
1065 | memset(imm, 0, SND_QUEUE_DESC_SIZE); | ||
1066 | imm->subdesc_type = SQ_DESC_TYPE_IMMEDIATE; | ||
1067 | imm->len = 1; | ||
1068 | } | ||
1069 | |||
1026 | /* Segment a TSO packet into 'gso_size' segments and append | 1070 | /* Segment a TSO packet into 'gso_size' segments and append |
1027 | * them to SQ for transfer | 1071 | * them to SQ for transfer |
1028 | */ | 1072 | */ |
@@ -1096,7 +1140,7 @@ static int nicvf_sq_append_tso(struct nicvf *nic, struct snd_queue *sq, | |||
1096 | int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb) | 1140 | int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb) |
1097 | { | 1141 | { |
1098 | int i, size; | 1142 | int i, size; |
1099 | int subdesc_cnt; | 1143 | int subdesc_cnt, tso_sqe = 0; |
1100 | int sq_num, qentry; | 1144 | int sq_num, qentry; |
1101 | struct queue_set *qs; | 1145 | struct queue_set *qs; |
1102 | struct snd_queue *sq; | 1146 | struct snd_queue *sq; |
@@ -1131,6 +1175,7 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb) | |||
1131 | /* Add SQ header subdesc */ | 1175 | /* Add SQ header subdesc */ |
1132 | nicvf_sq_add_hdr_subdesc(nic, sq, qentry, subdesc_cnt - 1, | 1176 | nicvf_sq_add_hdr_subdesc(nic, sq, qentry, subdesc_cnt - 1, |
1133 | skb, skb->len); | 1177 | skb, skb->len); |
1178 | tso_sqe = qentry; | ||
1134 | 1179 | ||
1135 | /* Add SQ gather subdescs */ | 1180 | /* Add SQ gather subdescs */ |
1136 | qentry = nicvf_get_nxt_sqentry(sq, qentry); | 1181 | qentry = nicvf_get_nxt_sqentry(sq, qentry); |
@@ -1154,6 +1199,11 @@ int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb) | |||
1154 | } | 1199 | } |
1155 | 1200 | ||
1156 | doorbell: | 1201 | doorbell: |
1202 | if (nic->t88 && skb_shinfo(skb)->gso_size) { | ||
1203 | qentry = nicvf_get_nxt_sqentry(sq, qentry); | ||
1204 | nicvf_sq_add_cqe_subdesc(sq, qentry, tso_sqe, skb); | ||
1205 | } | ||
1206 | |||
1157 | /* make sure all memory stores are done before ringing doorbell */ | 1207 | /* make sure all memory stores are done before ringing doorbell */ |
1158 | smp_wmb(); | 1208 | smp_wmb(); |
1159 | 1209 | ||