Skip to content

Commit f3c7bbc

Browse files
committed
Merge: ibmvnic small packet improvements
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5253 Description: ibmvnic small packet improvements JIRA: https://issues.redhat.com/browse/RHEL-53368 Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=64377256 Tested: Verified Brew build test kernel RPMs Signed-off-by: Mamatha Inamdar <minamdar@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Approved-by: José Ignacio Tornos Martínez <jtornosm@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 40945cb + 61ff9a4 commit f3c7bbc

File tree

1 file changed

+115
-76
lines changed

1 file changed

+115
-76
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 115 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
116116
struct ibmvnic_long_term_buff *ltb);
117117
static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
118118
static void flush_reset_queue(struct ibmvnic_adapter *adapter);
119+
static void print_subcrq_error(struct device *dev, int rc, const char *func);
119120

120121
struct ibmvnic_stat {
121122
char name[ETH_GSTRING_LEN];
@@ -1935,63 +1936,49 @@ static int ibmvnic_close(struct net_device *netdev)
19351936
}
19361937

19371938
/**
1938-
* build_hdr_data - creates L2/L3/L4 header data buffer
1939+
* get_hdr_lens - fills list of L2/L3/L4 hdr lens
19391940
* @hdr_field: bitfield determining needed headers
19401941
* @skb: socket buffer
1941-
* @hdr_len: array of header lengths
1942-
* @hdr_data: buffer to write the header to
1942+
* @hdr_len: array of header lengths to be filled
19431943
*
19441944
* Reads hdr_field to determine which headers are needed by firmware.
19451945
* Builds a buffer containing these headers. Saves individual header
19461946
* lengths and total buffer length to be used to build descriptors.
1947+
*
1948+
* Return: total len of all headers
19471949
*/
1948-
static int build_hdr_data(u8 hdr_field, struct sk_buff *skb,
1949-
int *hdr_len, u8 *hdr_data)
1950+
static int get_hdr_lens(u8 hdr_field, struct sk_buff *skb,
1951+
int *hdr_len)
19501952
{
19511953
int len = 0;
1952-
u8 *hdr;
19531954

1954-
if (skb_vlan_tagged(skb) && !skb_vlan_tag_present(skb))
1955-
hdr_len[0] = sizeof(struct vlan_ethhdr);
1956-
else
1957-
hdr_len[0] = sizeof(struct ethhdr);
1955+
1956+
if ((hdr_field >> 6) & 1) {
1957+
hdr_len[0] = skb_mac_header_len(skb);
1958+
len += hdr_len[0];
1959+
}
1960+
1961+
if ((hdr_field >> 5) & 1) {
1962+
hdr_len[1] = skb_network_header_len(skb);
1963+
len += hdr_len[1];
1964+
}
1965+
1966+
if (!((hdr_field >> 4) & 1))
1967+
return len;
19581968

19591969
if (skb->protocol == htons(ETH_P_IP)) {
1960-
hdr_len[1] = ip_hdr(skb)->ihl * 4;
19611970
if (ip_hdr(skb)->protocol == IPPROTO_TCP)
19621971
hdr_len[2] = tcp_hdrlen(skb);
19631972
else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
19641973
hdr_len[2] = sizeof(struct udphdr);
19651974
} else if (skb->protocol == htons(ETH_P_IPV6)) {
1966-
hdr_len[1] = sizeof(struct ipv6hdr);
19671975
if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
19681976
hdr_len[2] = tcp_hdrlen(skb);
19691977
else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)
19701978
hdr_len[2] = sizeof(struct udphdr);
1971-
} else if (skb->protocol == htons(ETH_P_ARP)) {
1972-
hdr_len[1] = arp_hdr_len(skb->dev);
1973-
hdr_len[2] = 0;
1974-
}
1975-
1976-
memset(hdr_data, 0, 120);
1977-
if ((hdr_field >> 6) & 1) {
1978-
hdr = skb_mac_header(skb);
1979-
memcpy(hdr_data, hdr, hdr_len[0]);
1980-
len += hdr_len[0];
19811979
}
19821980

1983-
if ((hdr_field >> 5) & 1) {
1984-
hdr = skb_network_header(skb);
1985-
memcpy(hdr_data + len, hdr, hdr_len[1]);
1986-
len += hdr_len[1];
1987-
}
1988-
1989-
if ((hdr_field >> 4) & 1) {
1990-
hdr = skb_transport_header(skb);
1991-
memcpy(hdr_data + len, hdr, hdr_len[2]);
1992-
len += hdr_len[2];
1993-
}
1994-
return len;
1981+
return len + hdr_len[2];
19951982
}
19961983

19971984
/**
@@ -2004,12 +1991,14 @@ static int build_hdr_data(u8 hdr_field, struct sk_buff *skb,
20041991
*
20051992
* Creates header and, if needed, header extension descriptors and
20061993
* places them in a descriptor array, scrq_arr
1994+
*
1995+
* Return: Number of header descs
20071996
*/
20081997

20091998
static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len,
20101999
union sub_crq *scrq_arr)
20112000
{
2012-
union sub_crq hdr_desc;
2001+
union sub_crq *hdr_desc;
20132002
int tmp_len = len;
20142003
int num_descs = 0;
20152004
u8 *data, *cur;
@@ -2018,28 +2007,26 @@ static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len,
20182007
while (tmp_len > 0) {
20192008
cur = hdr_data + len - tmp_len;
20202009

2021-
memset(&hdr_desc, 0, sizeof(hdr_desc));
2022-
if (cur != hdr_data) {
2023-
data = hdr_desc.hdr_ext.data;
2010+
hdr_desc = &scrq_arr[num_descs];
2011+
if (num_descs) {
2012+
data = hdr_desc->hdr_ext.data;
20242013
tmp = tmp_len > 29 ? 29 : tmp_len;
2025-
hdr_desc.hdr_ext.first = IBMVNIC_CRQ_CMD;
2026-
hdr_desc.hdr_ext.type = IBMVNIC_HDR_EXT_DESC;
2027-
hdr_desc.hdr_ext.len = tmp;
2014+
hdr_desc->hdr_ext.first = IBMVNIC_CRQ_CMD;
2015+
hdr_desc->hdr_ext.type = IBMVNIC_HDR_EXT_DESC;
2016+
hdr_desc->hdr_ext.len = tmp;
20282017
} else {
2029-
data = hdr_desc.hdr.data;
2018+
data = hdr_desc->hdr.data;
20302019
tmp = tmp_len > 24 ? 24 : tmp_len;
2031-
hdr_desc.hdr.first = IBMVNIC_CRQ_CMD;
2032-
hdr_desc.hdr.type = IBMVNIC_HDR_DESC;
2033-
hdr_desc.hdr.len = tmp;
2034-
hdr_desc.hdr.l2_len = (u8)hdr_len[0];
2035-
hdr_desc.hdr.l3_len = cpu_to_be16((u16)hdr_len[1]);
2036-
hdr_desc.hdr.l4_len = (u8)hdr_len[2];
2037-
hdr_desc.hdr.flag = hdr_field << 1;
2020+
hdr_desc->hdr.first = IBMVNIC_CRQ_CMD;
2021+
hdr_desc->hdr.type = IBMVNIC_HDR_DESC;
2022+
hdr_desc->hdr.len = tmp;
2023+
hdr_desc->hdr.l2_len = (u8)hdr_len[0];
2024+
hdr_desc->hdr.l3_len = cpu_to_be16((u16)hdr_len[1]);
2025+
hdr_desc->hdr.l4_len = (u8)hdr_len[2];
2026+
hdr_desc->hdr.flag = hdr_field << 1;
20382027
}
20392028
memcpy(data, cur, tmp);
20402029
tmp_len -= tmp;
2041-
*scrq_arr = hdr_desc;
2042-
scrq_arr++;
20432030
num_descs++;
20442031
}
20452032

@@ -2062,13 +2049,11 @@ static void build_hdr_descs_arr(struct sk_buff *skb,
20622049
int *num_entries, u8 hdr_field)
20632050
{
20642051
int hdr_len[3] = {0, 0, 0};
2065-
u8 hdr_data[140] = {0};
20662052
int tot_len;
20672053

2068-
tot_len = build_hdr_data(hdr_field, skb, hdr_len,
2069-
hdr_data);
2070-
*num_entries += create_hdr_descs(hdr_field, hdr_data, tot_len, hdr_len,
2071-
indir_arr + 1);
2054+
tot_len = get_hdr_lens(hdr_field, skb, hdr_len);
2055+
*num_entries += create_hdr_descs(hdr_field, skb_mac_header(skb),
2056+
tot_len, hdr_len, indir_arr + 1);
20722057
}
20732058

20742059
static int ibmvnic_xmit_workarounds(struct sk_buff *skb,
@@ -2145,8 +2130,29 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
21452130
}
21462131
}
21472132

2133+
static int send_subcrq_direct(struct ibmvnic_adapter *adapter,
2134+
u64 remote_handle, u64 *entry)
2135+
{
2136+
unsigned int ua = adapter->vdev->unit_address;
2137+
struct device *dev = &adapter->vdev->dev;
2138+
int rc;
2139+
2140+
/* Make sure the hypervisor sees the complete request */
2141+
dma_wmb();
2142+
rc = plpar_hcall_norets(H_SEND_SUB_CRQ, ua,
2143+
cpu_to_be64(remote_handle),
2144+
cpu_to_be64(entry[0]), cpu_to_be64(entry[1]),
2145+
cpu_to_be64(entry[2]), cpu_to_be64(entry[3]));
2146+
2147+
if (rc)
2148+
print_subcrq_error(dev, rc, __func__);
2149+
2150+
return rc;
2151+
}
2152+
21482153
static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
2149-
struct ibmvnic_sub_crq_queue *tx_scrq)
2154+
struct ibmvnic_sub_crq_queue *tx_scrq,
2155+
bool indirect)
21502156
{
21512157
struct ibmvnic_ind_xmit_queue *ind_bufp;
21522158
u64 dma_addr;
@@ -2161,12 +2167,18 @@ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
21612167

21622168
if (!entries)
21632169
return 0;
2164-
rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
2170+
2171+
if (indirect)
2172+
rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
2173+
else
2174+
rc = send_subcrq_direct(adapter, handle,
2175+
(u64 *)ind_bufp->indir_arr);
2176+
21652177
if (rc)
21662178
ibmvnic_tx_scrq_clean_buffer(adapter, tx_scrq);
21672179
else
21682180
ind_bufp->index = 0;
2169-
return 0;
2181+
return rc;
21702182
}
21712183

21722184
static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
@@ -2191,6 +2203,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
21912203
unsigned long lpar_rc;
21922204
union sub_crq tx_crq;
21932205
unsigned int offset;
2206+
bool use_scrq_send_direct = false;
21942207
int num_entries = 1;
21952208
unsigned char *dst;
21962209
int bufidx = 0;
@@ -2218,7 +2231,9 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
22182231
tx_dropped++;
22192232
tx_send_failed++;
22202233
ret = NETDEV_TX_OK;
2221-
ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2234+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
2235+
if (lpar_rc != H_SUCCESS)
2236+
goto tx_err;
22222237
goto out;
22232238
}
22242239

@@ -2233,8 +2248,10 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
22332248
dev_kfree_skb_any(skb);
22342249
tx_send_failed++;
22352250
tx_dropped++;
2236-
ibmvnic_tx_scrq_flush(adapter, tx_scrq);
22372251
ret = NETDEV_TX_OK;
2252+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
2253+
if (lpar_rc != H_SUCCESS)
2254+
goto tx_err;
22382255
goto out;
22392256
}
22402257

@@ -2245,6 +2262,20 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
22452262
memset(dst, 0, tx_pool->buf_size);
22462263
data_dma_addr = tx_pool->long_term_buff.addr + offset;
22472264

2265+
/* if we are going to send_subcrq_direct this then we need to
2266+
* update the checksum before copying the data into ltb. Essentially
2267+
* these packets force disable CSO so that we can guarantee that
2268+
* FW does not need header info and we can send direct. Also, vnic
2269+
* server must be able to xmit standard packets without header data
2270+
*/
2271+
if (*hdrs == 0 && !skb_is_gso(skb) &&
2272+
!ind_bufp->index && !netdev_xmit_more()) {
2273+
use_scrq_send_direct = true;
2274+
if (skb->ip_summed == CHECKSUM_PARTIAL &&
2275+
skb_checksum_help(skb))
2276+
use_scrq_send_direct = false;
2277+
}
2278+
22482279
if (skb_shinfo(skb)->nr_frags) {
22492280
int cur, i;
22502281

@@ -2264,9 +2295,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
22642295
skb_copy_from_linear_data(skb, dst, skb->len);
22652296
}
22662297

2267-
/* post changes to long_term_buff *dst before VIOS accessing it */
2268-
dma_wmb();
2269-
22702298
tx_pool->consumer_index =
22712299
(tx_pool->consumer_index + 1) % tx_pool->num_buffers;
22722300

@@ -2329,6 +2357,18 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
23292357
tx_crq.v1.flags1 |= IBMVNIC_TX_LSO;
23302358
tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
23312359
hdrs += 2;
2360+
} else if (use_scrq_send_direct) {
2361+
/* See above comment, CSO disabled with direct xmit */
2362+
tx_crq.v1.flags1 &= ~(IBMVNIC_TX_CHKSUM_OFFLOAD);
2363+
ind_bufp->index = 1;
2364+
tx_buff->num_entries = 1;
2365+
netdev_tx_sent_queue(txq, skb->len);
2366+
ind_bufp->indir_arr[0] = tx_crq;
2367+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, false);
2368+
if (lpar_rc != H_SUCCESS)
2369+
goto tx_err;
2370+
2371+
goto early_exit;
23322372
}
23332373

23342374
if ((*hdrs >> 7) & 1)
@@ -2338,23 +2378,25 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
23382378
tx_buff->num_entries = num_entries;
23392379
/* flush buffer if current entry can not fit */
23402380
if (num_entries + ind_bufp->index > IBMVNIC_MAX_IND_DESCS) {
2341-
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2381+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
23422382
if (lpar_rc != H_SUCCESS)
23432383
goto tx_flush_err;
23442384
}
23452385

23462386
indir_arr[0] = tx_crq;
23472387
memcpy(&ind_bufp->indir_arr[ind_bufp->index], &indir_arr[0],
23482388
num_entries * sizeof(struct ibmvnic_generic_scrq));
2389+
23492390
ind_bufp->index += num_entries;
23502391
if (__netdev_tx_sent_queue(txq, skb->len,
23512392
netdev_xmit_more() &&
23522393
ind_bufp->index < IBMVNIC_MAX_IND_DESCS)) {
2353-
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2394+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
23542395
if (lpar_rc != H_SUCCESS)
23552396
goto tx_err;
23562397
}
23572398

2399+
early_exit:
23582400
if (atomic_add_return(num_entries, &tx_scrq->used)
23592401
>= adapter->req_tx_entries_per_subcrq) {
23602402
netdev_dbg(netdev, "Stopping queue %d\n", queue_num);
@@ -3316,9 +3358,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget)
33163358
}
33173359

33183360
if (adapter->state != VNIC_CLOSING &&
3319-
((atomic_read(&adapter->rx_pool[scrq_num].available) <
3320-
adapter->req_rx_add_entries_per_subcrq / 2) ||
3321-
frames_processed < budget))
3361+
(atomic_read(&adapter->rx_pool[scrq_num].available) <
3362+
adapter->req_rx_add_entries_per_subcrq / 2))
33223363
replenish_rx_pool(adapter, &adapter->rx_pool[scrq_num]);
33233364
if (frames_processed < budget) {
33243365
if (napi_complete_done(napi, frames_processed)) {
@@ -4017,20 +4058,17 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
40174058
struct ibmvnic_sub_crq_queue *scrq)
40184059
{
40194060
struct device *dev = &adapter->vdev->dev;
4061+
int num_packets = 0, total_bytes = 0;
40204062
struct ibmvnic_tx_pool *tx_pool;
40214063
struct ibmvnic_tx_buff *txbuff;
40224064
struct netdev_queue *txq;
40234065
union sub_crq *next;
4024-
int index;
4025-
int i;
4066+
int index, i;
40264067

40274068
restart_loop:
40284069
while (pending_scrq(adapter, scrq)) {
40294070
unsigned int pool = scrq->pool_index;
40304071
int num_entries = 0;
4031-
int total_bytes = 0;
4032-
int num_packets = 0;
4033-
40344072
next = ibmvnic_next_scrq(adapter, scrq);
40354073
for (i = 0; i < next->tx_comp.num_comps; i++) {
40364074
index = be32_to_cpu(next->tx_comp.correlators[i]);
@@ -4066,8 +4104,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
40664104
/* remove tx_comp scrq*/
40674105
next->tx_comp.first = 0;
40684106

4069-
txq = netdev_get_tx_queue(adapter->netdev, scrq->pool_index);
4070-
netdev_tx_completed_queue(txq, num_packets, total_bytes);
40714107

40724108
if (atomic_sub_return(num_entries, &scrq->used) <=
40734109
(adapter->req_tx_entries_per_subcrq / 2) &&
@@ -4092,6 +4128,9 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
40924128
goto restart_loop;
40934129
}
40944130

4131+
txq = netdev_get_tx_queue(adapter->netdev, scrq->pool_index);
4132+
netdev_tx_completed_queue(txq, num_packets, total_bytes);
4133+
40954134
return 0;
40964135
}
40974136

0 commit comments

Comments
 (0)