Skip to content

Commit c89c675

Browse files
committed
Merge branch 'ibmvnic-ibmvnic-rr-patchset'
Nick Child says: ==================== ibmvnic: ibmvnic rr patchset v1 - https://lore.kernel.org/netdev/[email protected]/ v2 - https://lore.kernel.org/netdev/[email protected]/ ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents c146f3d + e633e32 commit c89c675

File tree

1 file changed

+108
-75
lines changed

1 file changed

+108
-75
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 108 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
117117
struct ibmvnic_long_term_buff *ltb);
118118
static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter);
119119
static void flush_reset_queue(struct ibmvnic_adapter *adapter);
120+
static void print_subcrq_error(struct device *dev, int rc, const char *func);
120121

121122
struct ibmvnic_stat {
122123
char name[ETH_GSTRING_LEN];
@@ -2140,63 +2141,49 @@ static int ibmvnic_close(struct net_device *netdev)
21402141
}
21412142

21422143
/**
2143-
* build_hdr_data - creates L2/L3/L4 header data buffer
2144+
* get_hdr_lens - fills list of L2/L3/L4 hdr lens
21442145
* @hdr_field: bitfield determining needed headers
21452146
* @skb: socket buffer
2146-
* @hdr_len: array of header lengths
2147-
* @hdr_data: buffer to write the header to
2147+
* @hdr_len: array of header lengths to be filled
21482148
*
21492149
* Reads hdr_field to determine which headers are needed by firmware.
21502150
* Builds a buffer containing these headers. Saves individual header
21512151
* lengths and total buffer length to be used to build descriptors.
2152+
*
2153+
* Return: total len of all headers
21522154
*/
2153-
static int build_hdr_data(u8 hdr_field, struct sk_buff *skb,
2154-
int *hdr_len, u8 *hdr_data)
2155+
static int get_hdr_lens(u8 hdr_field, struct sk_buff *skb,
2156+
int *hdr_len)
21552157
{
21562158
int len = 0;
2157-
u8 *hdr;
21582159

2159-
if (skb_vlan_tagged(skb) && !skb_vlan_tag_present(skb))
2160-
hdr_len[0] = sizeof(struct vlan_ethhdr);
2161-
else
2162-
hdr_len[0] = sizeof(struct ethhdr);
2160+
2161+
if ((hdr_field >> 6) & 1) {
2162+
hdr_len[0] = skb_mac_header_len(skb);
2163+
len += hdr_len[0];
2164+
}
2165+
2166+
if ((hdr_field >> 5) & 1) {
2167+
hdr_len[1] = skb_network_header_len(skb);
2168+
len += hdr_len[1];
2169+
}
2170+
2171+
if (!((hdr_field >> 4) & 1))
2172+
return len;
21632173

21642174
if (skb->protocol == htons(ETH_P_IP)) {
2165-
hdr_len[1] = ip_hdr(skb)->ihl * 4;
21662175
if (ip_hdr(skb)->protocol == IPPROTO_TCP)
21672176
hdr_len[2] = tcp_hdrlen(skb);
21682177
else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
21692178
hdr_len[2] = sizeof(struct udphdr);
21702179
} else if (skb->protocol == htons(ETH_P_IPV6)) {
2171-
hdr_len[1] = sizeof(struct ipv6hdr);
21722180
if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
21732181
hdr_len[2] = tcp_hdrlen(skb);
21742182
else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)
21752183
hdr_len[2] = sizeof(struct udphdr);
2176-
} else if (skb->protocol == htons(ETH_P_ARP)) {
2177-
hdr_len[1] = arp_hdr_len(skb->dev);
2178-
hdr_len[2] = 0;
21792184
}
21802185

2181-
memset(hdr_data, 0, 120);
2182-
if ((hdr_field >> 6) & 1) {
2183-
hdr = skb_mac_header(skb);
2184-
memcpy(hdr_data, hdr, hdr_len[0]);
2185-
len += hdr_len[0];
2186-
}
2187-
2188-
if ((hdr_field >> 5) & 1) {
2189-
hdr = skb_network_header(skb);
2190-
memcpy(hdr_data + len, hdr, hdr_len[1]);
2191-
len += hdr_len[1];
2192-
}
2193-
2194-
if ((hdr_field >> 4) & 1) {
2195-
hdr = skb_transport_header(skb);
2196-
memcpy(hdr_data + len, hdr, hdr_len[2]);
2197-
len += hdr_len[2];
2198-
}
2199-
return len;
2186+
return len + hdr_len[2];
22002187
}
22012188

22022189
/**
@@ -2209,12 +2196,14 @@ static int build_hdr_data(u8 hdr_field, struct sk_buff *skb,
22092196
*
22102197
* Creates header and, if needed, header extension descriptors and
22112198
* places them in a descriptor array, scrq_arr
2199+
*
2200+
* Return: Number of header descs
22122201
*/
22132202

22142203
static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len,
22152204
union sub_crq *scrq_arr)
22162205
{
2217-
union sub_crq hdr_desc;
2206+
union sub_crq *hdr_desc;
22182207
int tmp_len = len;
22192208
int num_descs = 0;
22202209
u8 *data, *cur;
@@ -2223,28 +2212,26 @@ static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len,
22232212
while (tmp_len > 0) {
22242213
cur = hdr_data + len - tmp_len;
22252214

2226-
memset(&hdr_desc, 0, sizeof(hdr_desc));
2227-
if (cur != hdr_data) {
2228-
data = hdr_desc.hdr_ext.data;
2215+
hdr_desc = &scrq_arr[num_descs];
2216+
if (num_descs) {
2217+
data = hdr_desc->hdr_ext.data;
22292218
tmp = tmp_len > 29 ? 29 : tmp_len;
2230-
hdr_desc.hdr_ext.first = IBMVNIC_CRQ_CMD;
2231-
hdr_desc.hdr_ext.type = IBMVNIC_HDR_EXT_DESC;
2232-
hdr_desc.hdr_ext.len = tmp;
2219+
hdr_desc->hdr_ext.first = IBMVNIC_CRQ_CMD;
2220+
hdr_desc->hdr_ext.type = IBMVNIC_HDR_EXT_DESC;
2221+
hdr_desc->hdr_ext.len = tmp;
22332222
} else {
2234-
data = hdr_desc.hdr.data;
2223+
data = hdr_desc->hdr.data;
22352224
tmp = tmp_len > 24 ? 24 : tmp_len;
2236-
hdr_desc.hdr.first = IBMVNIC_CRQ_CMD;
2237-
hdr_desc.hdr.type = IBMVNIC_HDR_DESC;
2238-
hdr_desc.hdr.len = tmp;
2239-
hdr_desc.hdr.l2_len = (u8)hdr_len[0];
2240-
hdr_desc.hdr.l3_len = cpu_to_be16((u16)hdr_len[1]);
2241-
hdr_desc.hdr.l4_len = (u8)hdr_len[2];
2242-
hdr_desc.hdr.flag = hdr_field << 1;
2225+
hdr_desc->hdr.first = IBMVNIC_CRQ_CMD;
2226+
hdr_desc->hdr.type = IBMVNIC_HDR_DESC;
2227+
hdr_desc->hdr.len = tmp;
2228+
hdr_desc->hdr.l2_len = (u8)hdr_len[0];
2229+
hdr_desc->hdr.l3_len = cpu_to_be16((u16)hdr_len[1]);
2230+
hdr_desc->hdr.l4_len = (u8)hdr_len[2];
2231+
hdr_desc->hdr.flag = hdr_field << 1;
22432232
}
22442233
memcpy(data, cur, tmp);
22452234
tmp_len -= tmp;
2246-
*scrq_arr = hdr_desc;
2247-
scrq_arr++;
22482235
num_descs++;
22492236
}
22502237

@@ -2267,13 +2254,11 @@ static void build_hdr_descs_arr(struct sk_buff *skb,
22672254
int *num_entries, u8 hdr_field)
22682255
{
22692256
int hdr_len[3] = {0, 0, 0};
2270-
u8 hdr_data[140] = {0};
22712257
int tot_len;
22722258

2273-
tot_len = build_hdr_data(hdr_field, skb, hdr_len,
2274-
hdr_data);
2275-
*num_entries += create_hdr_descs(hdr_field, hdr_data, tot_len, hdr_len,
2276-
indir_arr + 1);
2259+
tot_len = get_hdr_lens(hdr_field, skb, hdr_len);
2260+
*num_entries += create_hdr_descs(hdr_field, skb_mac_header(skb),
2261+
tot_len, hdr_len, indir_arr + 1);
22772262
}
22782263

22792264
static int ibmvnic_xmit_workarounds(struct sk_buff *skb,
@@ -2350,8 +2335,29 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
23502335
}
23512336
}
23522337

2338+
static int send_subcrq_direct(struct ibmvnic_adapter *adapter,
2339+
u64 remote_handle, u64 *entry)
2340+
{
2341+
unsigned int ua = adapter->vdev->unit_address;
2342+
struct device *dev = &adapter->vdev->dev;
2343+
int rc;
2344+
2345+
/* Make sure the hypervisor sees the complete request */
2346+
dma_wmb();
2347+
rc = plpar_hcall_norets(H_SEND_SUB_CRQ, ua,
2348+
cpu_to_be64(remote_handle),
2349+
cpu_to_be64(entry[0]), cpu_to_be64(entry[1]),
2350+
cpu_to_be64(entry[2]), cpu_to_be64(entry[3]));
2351+
2352+
if (rc)
2353+
print_subcrq_error(dev, rc, __func__);
2354+
2355+
return rc;
2356+
}
2357+
23532358
static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
2354-
struct ibmvnic_sub_crq_queue *tx_scrq)
2359+
struct ibmvnic_sub_crq_queue *tx_scrq,
2360+
bool indirect)
23552361
{
23562362
struct ibmvnic_ind_xmit_queue *ind_bufp;
23572363
u64 dma_addr;
@@ -2366,7 +2372,13 @@ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
23662372

23672373
if (!entries)
23682374
return 0;
2369-
rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
2375+
2376+
if (indirect)
2377+
rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
2378+
else
2379+
rc = send_subcrq_direct(adapter, handle,
2380+
(u64 *)ind_bufp->indir_arr);
2381+
23702382
if (rc)
23712383
ibmvnic_tx_scrq_clean_buffer(adapter, tx_scrq);
23722384
else
@@ -2397,6 +2409,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
23972409
unsigned long lpar_rc;
23982410
union sub_crq tx_crq;
23992411
unsigned int offset;
2412+
bool use_scrq_send_direct = false;
24002413
int num_entries = 1;
24012414
unsigned char *dst;
24022415
int bufidx = 0;
@@ -2424,7 +2437,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
24242437
tx_dropped++;
24252438
tx_send_failed++;
24262439
ret = NETDEV_TX_OK;
2427-
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2440+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
24282441
if (lpar_rc != H_SUCCESS)
24292442
goto tx_err;
24302443
goto out;
@@ -2442,7 +2455,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
24422455
tx_send_failed++;
24432456
tx_dropped++;
24442457
ret = NETDEV_TX_OK;
2445-
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2458+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
24462459
if (lpar_rc != H_SUCCESS)
24472460
goto tx_err;
24482461
goto out;
@@ -2456,6 +2469,18 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
24562469
memset(dst, 0, tx_pool->buf_size);
24572470
data_dma_addr = ltb->addr + offset;
24582471

2472+
/* if we are going to send_subcrq_direct this then we need to
2473+
* update the checksum before copying the data into ltb. Essentially
2474+
* these packets force disable CSO so that we can guarantee that
2475+
* FW does not need header info and we can send direct.
2476+
*/
2477+
if (!skb_is_gso(skb) && !ind_bufp->index && !netdev_xmit_more()) {
2478+
use_scrq_send_direct = true;
2479+
if (skb->ip_summed == CHECKSUM_PARTIAL &&
2480+
skb_checksum_help(skb))
2481+
use_scrq_send_direct = false;
2482+
}
2483+
24592484
if (skb_shinfo(skb)->nr_frags) {
24602485
int cur, i;
24612486

@@ -2475,9 +2500,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
24752500
skb_copy_from_linear_data(skb, dst, skb->len);
24762501
}
24772502

2478-
/* post changes to long_term_buff *dst before VIOS accessing it */
2479-
dma_wmb();
2480-
24812503
tx_pool->consumer_index =
24822504
(tx_pool->consumer_index + 1) % tx_pool->num_buffers;
24832505

@@ -2540,6 +2562,18 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
25402562
tx_crq.v1.flags1 |= IBMVNIC_TX_LSO;
25412563
tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
25422564
hdrs += 2;
2565+
} else if (use_scrq_send_direct) {
2566+
/* See above comment, CSO disabled with direct xmit */
2567+
tx_crq.v1.flags1 &= ~(IBMVNIC_TX_CHKSUM_OFFLOAD);
2568+
ind_bufp->index = 1;
2569+
tx_buff->num_entries = 1;
2570+
netdev_tx_sent_queue(txq, skb->len);
2571+
ind_bufp->indir_arr[0] = tx_crq;
2572+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, false);
2573+
if (lpar_rc != H_SUCCESS)
2574+
goto tx_err;
2575+
2576+
goto early_exit;
25432577
}
25442578

25452579
if ((*hdrs >> 7) & 1)
@@ -2549,23 +2583,25 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
25492583
tx_buff->num_entries = num_entries;
25502584
/* flush buffer if current entry can not fit */
25512585
if (num_entries + ind_bufp->index > IBMVNIC_MAX_IND_DESCS) {
2552-
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2586+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
25532587
if (lpar_rc != H_SUCCESS)
25542588
goto tx_flush_err;
25552589
}
25562590

25572591
indir_arr[0] = tx_crq;
25582592
memcpy(&ind_bufp->indir_arr[ind_bufp->index], &indir_arr[0],
25592593
num_entries * sizeof(struct ibmvnic_generic_scrq));
2594+
25602595
ind_bufp->index += num_entries;
25612596
if (__netdev_tx_sent_queue(txq, skb->len,
25622597
netdev_xmit_more() &&
25632598
ind_bufp->index < IBMVNIC_MAX_IND_DESCS)) {
2564-
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
2599+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq, true);
25652600
if (lpar_rc != H_SUCCESS)
25662601
goto tx_err;
25672602
}
25682603

2604+
early_exit:
25692605
if (atomic_add_return(num_entries, &tx_scrq->used)
25702606
>= adapter->req_tx_entries_per_subcrq) {
25712607
netdev_dbg(netdev, "Stopping queue %d\n", queue_num);
@@ -3527,9 +3563,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget)
35273563
}
35283564

35293565
if (adapter->state != VNIC_CLOSING &&
3530-
((atomic_read(&adapter->rx_pool[scrq_num].available) <
3531-
adapter->req_rx_add_entries_per_subcrq / 2) ||
3532-
frames_processed < budget))
3566+
(atomic_read(&adapter->rx_pool[scrq_num].available) <
3567+
adapter->req_rx_add_entries_per_subcrq / 2))
35333568
replenish_rx_pool(adapter, &adapter->rx_pool[scrq_num]);
35343569
if (frames_processed < budget) {
35353570
if (napi_complete_done(napi, frames_processed)) {
@@ -4169,20 +4204,17 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
41694204
struct ibmvnic_sub_crq_queue *scrq)
41704205
{
41714206
struct device *dev = &adapter->vdev->dev;
4207+
int num_packets = 0, total_bytes = 0;
41724208
struct ibmvnic_tx_pool *tx_pool;
41734209
struct ibmvnic_tx_buff *txbuff;
41744210
struct netdev_queue *txq;
41754211
union sub_crq *next;
4176-
int index;
4177-
int i;
4212+
int index, i;
41784213

41794214
restart_loop:
41804215
while (pending_scrq(adapter, scrq)) {
41814216
unsigned int pool = scrq->pool_index;
41824217
int num_entries = 0;
4183-
int total_bytes = 0;
4184-
int num_packets = 0;
4185-
41864218
next = ibmvnic_next_scrq(adapter, scrq);
41874219
for (i = 0; i < next->tx_comp.num_comps; i++) {
41884220
index = be32_to_cpu(next->tx_comp.correlators[i]);
@@ -4218,8 +4250,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
42184250
/* remove tx_comp scrq*/
42194251
next->tx_comp.first = 0;
42204252

4221-
txq = netdev_get_tx_queue(adapter->netdev, scrq->pool_index);
4222-
netdev_tx_completed_queue(txq, num_packets, total_bytes);
42234253

42244254
if (atomic_sub_return(num_entries, &scrq->used) <=
42254255
(adapter->req_tx_entries_per_subcrq / 2) &&
@@ -4244,6 +4274,9 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
42444274
goto restart_loop;
42454275
}
42464276

4277+
txq = netdev_get_tx_queue(adapter->netdev, scrq->pool_index);
4278+
netdev_tx_completed_queue(txq, num_packets, total_bytes);
4279+
42474280
return 0;
42484281
}
42494282

0 commit comments

Comments
 (0)