@@ -117,6 +117,7 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
117
117
struct ibmvnic_long_term_buff * ltb );
118
118
static void ibmvnic_disable_irqs (struct ibmvnic_adapter * adapter );
119
119
static void flush_reset_queue (struct ibmvnic_adapter * adapter );
120
+ static void print_subcrq_error (struct device * dev , int rc , const char * func );
120
121
121
122
struct ibmvnic_stat {
122
123
char name [ETH_GSTRING_LEN ];
@@ -2140,63 +2141,49 @@ static int ibmvnic_close(struct net_device *netdev)
2140
2141
}
2141
2142
2142
2143
/**
2143
- * build_hdr_data - creates L2/L3/L4 header data buffer
2144
+ * get_hdr_lens - fills list of L2/L3/L4 hdr lens
2144
2145
* @hdr_field: bitfield determining needed headers
2145
2146
* @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
2148
2148
*
2149
2149
* Reads hdr_field to determine which headers are needed by firmware.
2150
2150
* Builds a buffer containing these headers. Saves individual header
2151
2151
* lengths and total buffer length to be used to build descriptors.
2152
+ *
2153
+ * Return: total len of all headers
2152
2154
*/
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 )
2155
2157
{
2156
2158
int len = 0 ;
2157
- u8 * hdr ;
2158
2159
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 ;
2163
2173
2164
2174
if (skb -> protocol == htons (ETH_P_IP )) {
2165
- hdr_len [1 ] = ip_hdr (skb )-> ihl * 4 ;
2166
2175
if (ip_hdr (skb )-> protocol == IPPROTO_TCP )
2167
2176
hdr_len [2 ] = tcp_hdrlen (skb );
2168
2177
else if (ip_hdr (skb )-> protocol == IPPROTO_UDP )
2169
2178
hdr_len [2 ] = sizeof (struct udphdr );
2170
2179
} else if (skb -> protocol == htons (ETH_P_IPV6 )) {
2171
- hdr_len [1 ] = sizeof (struct ipv6hdr );
2172
2180
if (ipv6_hdr (skb )-> nexthdr == IPPROTO_TCP )
2173
2181
hdr_len [2 ] = tcp_hdrlen (skb );
2174
2182
else if (ipv6_hdr (skb )-> nexthdr == IPPROTO_UDP )
2175
2183
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 ;
2179
2184
}
2180
2185
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 ];
2200
2187
}
2201
2188
2202
2189
/**
@@ -2209,12 +2196,14 @@ static int build_hdr_data(u8 hdr_field, struct sk_buff *skb,
2209
2196
*
2210
2197
* Creates header and, if needed, header extension descriptors and
2211
2198
* places them in a descriptor array, scrq_arr
2199
+ *
2200
+ * Return: Number of header descs
2212
2201
*/
2213
2202
2214
2203
static int create_hdr_descs (u8 hdr_field , u8 * hdr_data , int len , int * hdr_len ,
2215
2204
union sub_crq * scrq_arr )
2216
2205
{
2217
- union sub_crq hdr_desc ;
2206
+ union sub_crq * hdr_desc ;
2218
2207
int tmp_len = len ;
2219
2208
int num_descs = 0 ;
2220
2209
u8 * data , * cur ;
@@ -2223,28 +2212,26 @@ static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len,
2223
2212
while (tmp_len > 0 ) {
2224
2213
cur = hdr_data + len - tmp_len ;
2225
2214
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 ;
2229
2218
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 ;
2233
2222
} else {
2234
- data = hdr_desc . hdr .data ;
2223
+ data = hdr_desc -> hdr .data ;
2235
2224
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 ;
2243
2232
}
2244
2233
memcpy (data , cur , tmp );
2245
2234
tmp_len -= tmp ;
2246
- * scrq_arr = hdr_desc ;
2247
- scrq_arr ++ ;
2248
2235
num_descs ++ ;
2249
2236
}
2250
2237
@@ -2267,13 +2254,11 @@ static void build_hdr_descs_arr(struct sk_buff *skb,
2267
2254
int * num_entries , u8 hdr_field )
2268
2255
{
2269
2256
int hdr_len [3 ] = {0 , 0 , 0 };
2270
- u8 hdr_data [140 ] = {0 };
2271
2257
int tot_len ;
2272
2258
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 );
2277
2262
}
2278
2263
2279
2264
static int ibmvnic_xmit_workarounds (struct sk_buff * skb ,
@@ -2350,8 +2335,29 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
2350
2335
}
2351
2336
}
2352
2337
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
+
2353
2358
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 )
2355
2361
{
2356
2362
struct ibmvnic_ind_xmit_queue * ind_bufp ;
2357
2363
u64 dma_addr ;
@@ -2366,7 +2372,13 @@ static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
2366
2372
2367
2373
if (!entries )
2368
2374
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
+
2370
2382
if (rc )
2371
2383
ibmvnic_tx_scrq_clean_buffer (adapter , tx_scrq );
2372
2384
else
@@ -2397,6 +2409,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2397
2409
unsigned long lpar_rc ;
2398
2410
union sub_crq tx_crq ;
2399
2411
unsigned int offset ;
2412
+ bool use_scrq_send_direct = false;
2400
2413
int num_entries = 1 ;
2401
2414
unsigned char * dst ;
2402
2415
int bufidx = 0 ;
@@ -2424,7 +2437,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2424
2437
tx_dropped ++ ;
2425
2438
tx_send_failed ++ ;
2426
2439
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 );
2428
2441
if (lpar_rc != H_SUCCESS )
2429
2442
goto tx_err ;
2430
2443
goto out ;
@@ -2442,7 +2455,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2442
2455
tx_send_failed ++ ;
2443
2456
tx_dropped ++ ;
2444
2457
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 );
2446
2459
if (lpar_rc != H_SUCCESS )
2447
2460
goto tx_err ;
2448
2461
goto out ;
@@ -2456,6 +2469,18 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2456
2469
memset (dst , 0 , tx_pool -> buf_size );
2457
2470
data_dma_addr = ltb -> addr + offset ;
2458
2471
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
+
2459
2484
if (skb_shinfo (skb )-> nr_frags ) {
2460
2485
int cur , i ;
2461
2486
@@ -2475,9 +2500,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2475
2500
skb_copy_from_linear_data (skb , dst , skb -> len );
2476
2501
}
2477
2502
2478
- /* post changes to long_term_buff *dst before VIOS accessing it */
2479
- dma_wmb ();
2480
-
2481
2503
tx_pool -> consumer_index =
2482
2504
(tx_pool -> consumer_index + 1 ) % tx_pool -> num_buffers ;
2483
2505
@@ -2540,6 +2562,18 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2540
2562
tx_crq .v1 .flags1 |= IBMVNIC_TX_LSO ;
2541
2563
tx_crq .v1 .mss = cpu_to_be16 (skb_shinfo (skb )-> gso_size );
2542
2564
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 ;
2543
2577
}
2544
2578
2545
2579
if ((* hdrs >> 7 ) & 1 )
@@ -2549,23 +2583,25 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
2549
2583
tx_buff -> num_entries = num_entries ;
2550
2584
/* flush buffer if current entry can not fit */
2551
2585
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 );
2553
2587
if (lpar_rc != H_SUCCESS )
2554
2588
goto tx_flush_err ;
2555
2589
}
2556
2590
2557
2591
indir_arr [0 ] = tx_crq ;
2558
2592
memcpy (& ind_bufp -> indir_arr [ind_bufp -> index ], & indir_arr [0 ],
2559
2593
num_entries * sizeof (struct ibmvnic_generic_scrq ));
2594
+
2560
2595
ind_bufp -> index += num_entries ;
2561
2596
if (__netdev_tx_sent_queue (txq , skb -> len ,
2562
2597
netdev_xmit_more () &&
2563
2598
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 );
2565
2600
if (lpar_rc != H_SUCCESS )
2566
2601
goto tx_err ;
2567
2602
}
2568
2603
2604
+ early_exit :
2569
2605
if (atomic_add_return (num_entries , & tx_scrq -> used )
2570
2606
>= adapter -> req_tx_entries_per_subcrq ) {
2571
2607
netdev_dbg (netdev , "Stopping queue %d\n" , queue_num );
@@ -3527,9 +3563,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget)
3527
3563
}
3528
3564
3529
3565
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 ))
3533
3568
replenish_rx_pool (adapter , & adapter -> rx_pool [scrq_num ]);
3534
3569
if (frames_processed < budget ) {
3535
3570
if (napi_complete_done (napi , frames_processed )) {
@@ -4169,20 +4204,17 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
4169
4204
struct ibmvnic_sub_crq_queue * scrq )
4170
4205
{
4171
4206
struct device * dev = & adapter -> vdev -> dev ;
4207
+ int num_packets = 0 , total_bytes = 0 ;
4172
4208
struct ibmvnic_tx_pool * tx_pool ;
4173
4209
struct ibmvnic_tx_buff * txbuff ;
4174
4210
struct netdev_queue * txq ;
4175
4211
union sub_crq * next ;
4176
- int index ;
4177
- int i ;
4212
+ int index , i ;
4178
4213
4179
4214
restart_loop :
4180
4215
while (pending_scrq (adapter , scrq )) {
4181
4216
unsigned int pool = scrq -> pool_index ;
4182
4217
int num_entries = 0 ;
4183
- int total_bytes = 0 ;
4184
- int num_packets = 0 ;
4185
-
4186
4218
next = ibmvnic_next_scrq (adapter , scrq );
4187
4219
for (i = 0 ; i < next -> tx_comp .num_comps ; i ++ ) {
4188
4220
index = be32_to_cpu (next -> tx_comp .correlators [i ]);
@@ -4218,8 +4250,6 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
4218
4250
/* remove tx_comp scrq*/
4219
4251
next -> tx_comp .first = 0 ;
4220
4252
4221
- txq = netdev_get_tx_queue (adapter -> netdev , scrq -> pool_index );
4222
- netdev_tx_completed_queue (txq , num_packets , total_bytes );
4223
4253
4224
4254
if (atomic_sub_return (num_entries , & scrq -> used ) <=
4225
4255
(adapter -> req_tx_entries_per_subcrq / 2 ) &&
@@ -4244,6 +4274,9 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
4244
4274
goto restart_loop ;
4245
4275
}
4246
4276
4277
+ txq = netdev_get_tx_queue (adapter -> netdev , scrq -> pool_index );
4278
+ netdev_tx_completed_queue (txq , num_packets , total_bytes );
4279
+
4247
4280
return 0 ;
4248
4281
}
4249
4282
0 commit comments