Skip to content

Commit d1163e9

Browse files
committed
Merge branch 'be2net-fixes'
Sathya Perla says: ==================== be2net: patch set This patch set contains 2 driver fixes to a Lancer HW issue and a fix to a double free bug. Pls apply to the "net" tree. Thanks! Patch 1 now enables filters only after creating RXQs. This is done as HW issues were observed on Lancer adapters if filters (flags, mac addrs etc) are enabled *before* creating RXQs. This patch changes the driver design by enabling filters in be_open() -- instead of be_setup() -- after RXQs are created and buffers posted. Patch 2 fixes an RX stall issue that was seen on Lancer adapters when RXQs are destroyed while they are in an "out of buffer" state. This patch fixes this issue by posting 64 buffers to each RXQ before destroying them in the close path. This is done after ensuring that no more new packets are selected for transfer to the RXQs by disabling interface filters. Patch 3 protects eqo->affinity_mask variable from being freed twice and resulting in a crash. It's now freed only when EQs haven't yet been destroyed. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 48900cb + 649886a commit d1163e9

File tree

2 files changed

+125
-67
lines changed

2 files changed

+125
-67
lines changed

drivers/net/ethernet/emulex/benet/be_cmds.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,11 @@ enum be_if_flags {
620620
BE_IF_FLAGS_VLAN_PROMISCUOUS |\
621621
BE_IF_FLAGS_MCAST_PROMISCUOUS)
622622

623+
#define BE_IF_EN_FLAGS (BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |\
624+
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_UNTAGGED)
625+
626+
#define BE_IF_ALL_FILT_FLAGS (BE_IF_EN_FLAGS | BE_IF_FLAGS_ALL_PROMISCUOUS)
627+
623628
/* An RX interface is an object with one or more MAC addresses and
624629
* filtering capabilities. */
625630
struct be_cmd_req_if_create {

drivers/net/ethernet/emulex/benet/be_main.c

Lines changed: 120 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
273273
if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
274274
return 0;
275275

276+
/* if device is not running, copy MAC to netdev->dev_addr */
277+
if (!netif_running(netdev))
278+
goto done;
279+
276280
/* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
277281
* privilege or if PF did not provision the new MAC address.
278282
* On BE3, this cmd will always fail if the VF doesn't have the
@@ -307,9 +311,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
307311
status = -EPERM;
308312
goto err;
309313
}
310-
311-
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
312-
dev_info(dev, "MAC address changed to %pM\n", mac);
314+
done:
315+
ether_addr_copy(netdev->dev_addr, addr->sa_data);
316+
dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
313317
return 0;
314318
err:
315319
dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data);
@@ -2447,10 +2451,24 @@ static void be_eq_clean(struct be_eq_obj *eqo)
24472451
be_eq_notify(eqo->adapter, eqo->q.id, false, true, num, 0);
24482452
}
24492453

2450-
static void be_rx_cq_clean(struct be_rx_obj *rxo)
2454+
/* Free posted rx buffers that were not used */
2455+
static void be_rxq_clean(struct be_rx_obj *rxo)
24512456
{
2452-
struct be_rx_page_info *page_info;
24532457
struct be_queue_info *rxq = &rxo->q;
2458+
struct be_rx_page_info *page_info;
2459+
2460+
while (atomic_read(&rxq->used) > 0) {
2461+
page_info = get_rx_page_info(rxo);
2462+
put_page(page_info->page);
2463+
memset(page_info, 0, sizeof(*page_info));
2464+
}
2465+
BUG_ON(atomic_read(&rxq->used));
2466+
rxq->tail = 0;
2467+
rxq->head = 0;
2468+
}
2469+
2470+
static void be_rx_cq_clean(struct be_rx_obj *rxo)
2471+
{
24542472
struct be_queue_info *rx_cq = &rxo->cq;
24552473
struct be_rx_compl_info *rxcp;
24562474
struct be_adapter *adapter = rxo->adapter;
@@ -2487,16 +2505,6 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo)
24872505

24882506
/* After cleanup, leave the CQ in unarmed state */
24892507
be_cq_notify(adapter, rx_cq->id, false, 0);
2490-
2491-
/* Then free posted rx buffers that were not used */
2492-
while (atomic_read(&rxq->used) > 0) {
2493-
page_info = get_rx_page_info(rxo);
2494-
put_page(page_info->page);
2495-
memset(page_info, 0, sizeof(*page_info));
2496-
}
2497-
BUG_ON(atomic_read(&rxq->used));
2498-
rxq->tail = 0;
2499-
rxq->head = 0;
25002508
}
25012509

25022510
static void be_tx_compl_clean(struct be_adapter *adapter)
@@ -2576,8 +2584,8 @@ static void be_evt_queues_destroy(struct be_adapter *adapter)
25762584
be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ);
25772585
napi_hash_del(&eqo->napi);
25782586
netif_napi_del(&eqo->napi);
2587+
free_cpumask_var(eqo->affinity_mask);
25792588
}
2580-
free_cpumask_var(eqo->affinity_mask);
25812589
be_queue_free(adapter, &eqo->q);
25822590
}
25832591
}
@@ -2594,13 +2602,7 @@ static int be_evt_queues_create(struct be_adapter *adapter)
25942602

25952603
for_all_evt_queues(adapter, eqo, i) {
25962604
int numa_node = dev_to_node(&adapter->pdev->dev);
2597-
if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL))
2598-
return -ENOMEM;
2599-
cpumask_set_cpu(cpumask_local_spread(i, numa_node),
2600-
eqo->affinity_mask);
2601-
netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
2602-
BE_NAPI_WEIGHT);
2603-
napi_hash_add(&eqo->napi);
2605+
26042606
aic = &adapter->aic_obj[i];
26052607
eqo->adapter = adapter;
26062608
eqo->idx = i;
@@ -2616,6 +2618,14 @@ static int be_evt_queues_create(struct be_adapter *adapter)
26162618
rc = be_cmd_eq_create(adapter, eqo);
26172619
if (rc)
26182620
return rc;
2621+
2622+
if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL))
2623+
return -ENOMEM;
2624+
cpumask_set_cpu(cpumask_local_spread(i, numa_node),
2625+
eqo->affinity_mask);
2626+
netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
2627+
BE_NAPI_WEIGHT);
2628+
napi_hash_add(&eqo->napi);
26192629
}
26202630
return 0;
26212631
}
@@ -3354,13 +3364,54 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
33543364
for_all_rx_queues(adapter, rxo, i) {
33553365
q = &rxo->q;
33563366
if (q->created) {
3367+
/* If RXQs are destroyed while in an "out of buffer"
3368+
* state, there is a possibility of an HW stall on
3369+
* Lancer. So, post 64 buffers to each queue to relieve
3370+
* the "out of buffer" condition.
3371+
* Make sure there's space in the RXQ before posting.
3372+
*/
3373+
if (lancer_chip(adapter)) {
3374+
be_rx_cq_clean(rxo);
3375+
if (atomic_read(&q->used) == 0)
3376+
be_post_rx_frags(rxo, GFP_KERNEL,
3377+
MAX_RX_POST);
3378+
}
3379+
33573380
be_cmd_rxq_destroy(adapter, q);
33583381
be_rx_cq_clean(rxo);
3382+
be_rxq_clean(rxo);
33593383
}
33603384
be_queue_free(adapter, q);
33613385
}
33623386
}
33633387

3388+
static void be_disable_if_filters(struct be_adapter *adapter)
3389+
{
3390+
be_cmd_pmac_del(adapter, adapter->if_handle,
3391+
adapter->pmac_id[0], 0);
3392+
3393+
be_clear_uc_list(adapter);
3394+
3395+
/* The IFACE flags are enabled in the open path and cleared
3396+
* in the close path. When a VF gets detached from the host and
3397+
* assigned to a VM the following happens:
3398+
* - VF's IFACE flags get cleared in the detach path
3399+
* - IFACE create is issued by the VF in the attach path
3400+
* Due to a bug in the BE3/Skyhawk-R FW
3401+
* (Lancer FW doesn't have the bug), the IFACE capability flags
3402+
* specified along with the IFACE create cmd issued by a VF are not
3403+
* honoured by FW. As a consequence, if a *new* driver
3404+
* (that enables/disables IFACE flags in open/close)
3405+
* is loaded in the host and an *old* driver is * used by a VM/VF,
3406+
* the IFACE gets created *without* the needed flags.
3407+
* To avoid this, disable RX-filter flags only for Lancer.
3408+
*/
3409+
if (lancer_chip(adapter)) {
3410+
be_cmd_rx_filter(adapter, BE_IF_ALL_FILT_FLAGS, OFF);
3411+
adapter->if_flags &= ~BE_IF_ALL_FILT_FLAGS;
3412+
}
3413+
}
3414+
33643415
static int be_close(struct net_device *netdev)
33653416
{
33663417
struct be_adapter *adapter = netdev_priv(netdev);
@@ -3373,6 +3424,8 @@ static int be_close(struct net_device *netdev)
33733424
if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
33743425
return 0;
33753426

3427+
be_disable_if_filters(adapter);
3428+
33763429
be_roce_dev_close(adapter);
33773430

33783431
if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
@@ -3392,7 +3445,6 @@ static int be_close(struct net_device *netdev)
33923445
be_tx_compl_clean(adapter);
33933446

33943447
be_rx_qs_destroy(adapter);
3395-
be_clear_uc_list(adapter);
33963448

33973449
for_all_evt_queues(adapter, eqo, i) {
33983450
if (msix_enabled(adapter))
@@ -3477,6 +3529,31 @@ static int be_rx_qs_create(struct be_adapter *adapter)
34773529
return 0;
34783530
}
34793531

3532+
static int be_enable_if_filters(struct be_adapter *adapter)
3533+
{
3534+
int status;
3535+
3536+
status = be_cmd_rx_filter(adapter, BE_IF_EN_FLAGS, ON);
3537+
if (status)
3538+
return status;
3539+
3540+
/* For BE3 VFs, the PF programs the initial MAC address */
3541+
if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
3542+
status = be_cmd_pmac_add(adapter, adapter->netdev->dev_addr,
3543+
adapter->if_handle,
3544+
&adapter->pmac_id[0], 0);
3545+
if (status)
3546+
return status;
3547+
}
3548+
3549+
if (adapter->vlans_added)
3550+
be_vid_config(adapter);
3551+
3552+
be_set_rx_mode(adapter->netdev);
3553+
3554+
return 0;
3555+
}
3556+
34803557
static int be_open(struct net_device *netdev)
34813558
{
34823559
struct be_adapter *adapter = netdev_priv(netdev);
@@ -3490,6 +3567,10 @@ static int be_open(struct net_device *netdev)
34903567
if (status)
34913568
goto err;
34923569

3570+
status = be_enable_if_filters(adapter);
3571+
if (status)
3572+
goto err;
3573+
34933574
status = be_irq_register(adapter);
34943575
if (status)
34953576
goto err;
@@ -3686,16 +3767,6 @@ static void be_cancel_err_detection(struct be_adapter *adapter)
36863767
}
36873768
}
36883769

3689-
static void be_mac_clear(struct be_adapter *adapter)
3690-
{
3691-
if (adapter->pmac_id) {
3692-
be_cmd_pmac_del(adapter, adapter->if_handle,
3693-
adapter->pmac_id[0], 0);
3694-
kfree(adapter->pmac_id);
3695-
adapter->pmac_id = NULL;
3696-
}
3697-
}
3698-
36993770
#ifdef CONFIG_BE2NET_VXLAN
37003771
static void be_disable_vxlan_offloads(struct be_adapter *adapter)
37013772
{
@@ -3770,8 +3841,8 @@ static int be_clear(struct be_adapter *adapter)
37703841
#ifdef CONFIG_BE2NET_VXLAN
37713842
be_disable_vxlan_offloads(adapter);
37723843
#endif
3773-
/* delete the primary mac along with the uc-mac list */
3774-
be_mac_clear(adapter);
3844+
kfree(adapter->pmac_id);
3845+
adapter->pmac_id = NULL;
37753846

37763847
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
37773848

@@ -3782,25 +3853,11 @@ static int be_clear(struct be_adapter *adapter)
37823853
return 0;
37833854
}
37843855

3785-
static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
3786-
u32 cap_flags, u32 vf)
3787-
{
3788-
u32 en_flags;
3789-
3790-
en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
3791-
BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
3792-
BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
3793-
3794-
en_flags &= cap_flags;
3795-
3796-
return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf);
3797-
}
3798-
37993856
static int be_vfs_if_create(struct be_adapter *adapter)
38003857
{
38013858
struct be_resources res = {0};
3859+
u32 cap_flags, en_flags, vf;
38023860
struct be_vf_cfg *vf_cfg;
3803-
u32 cap_flags, vf;
38043861
int status;
38053862

38063863
/* If a FW profile exists, then cap_flags are updated */
@@ -3821,8 +3878,12 @@ static int be_vfs_if_create(struct be_adapter *adapter)
38213878
}
38223879
}
38233880

3824-
status = be_if_create(adapter, &vf_cfg->if_handle,
3825-
cap_flags, vf + 1);
3881+
en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
3882+
BE_IF_FLAGS_BROADCAST |
3883+
BE_IF_FLAGS_MULTICAST |
3884+
BE_IF_FLAGS_PASS_L3L4_ERRORS);
3885+
status = be_cmd_if_create(adapter, cap_flags, en_flags,
3886+
&vf_cfg->if_handle, vf + 1);
38263887
if (status)
38273888
return status;
38283889
}
@@ -4194,15 +4255,8 @@ static int be_mac_setup(struct be_adapter *adapter)
41944255

41954256
memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
41964257
memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
4197-
} else {
4198-
/* Maybe the HW was reset; dev_addr must be re-programmed */
4199-
memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
42004258
}
42014259

4202-
/* For BE3-R VFs, the PF programs the initial MAC address */
4203-
if (!(BEx_chip(adapter) && be_virtfn(adapter)))
4204-
be_cmd_pmac_add(adapter, mac, adapter->if_handle,
4205-
&adapter->pmac_id[0], 0);
42064260
return 0;
42074261
}
42084262

@@ -4342,6 +4396,7 @@ static int be_func_init(struct be_adapter *adapter)
43424396
static int be_setup(struct be_adapter *adapter)
43434397
{
43444398
struct device *dev = &adapter->pdev->dev;
4399+
u32 en_flags;
43454400
int status;
43464401

43474402
status = be_func_init(adapter);
@@ -4364,8 +4419,11 @@ static int be_setup(struct be_adapter *adapter)
43644419
if (status)
43654420
goto err;
43664421

4367-
status = be_if_create(adapter, &adapter->if_handle,
4368-
be_if_cap_flags(adapter), 0);
4422+
/* will enable all the needed filter flags in be_open() */
4423+
en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
4424+
en_flags = en_flags & be_if_cap_flags(adapter);
4425+
status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
4426+
&adapter->if_handle, 0);
43694427
if (status)
43704428
goto err;
43714429

@@ -4391,11 +4449,6 @@ static int be_setup(struct be_adapter *adapter)
43914449
dev_err(dev, "Please upgrade firmware to version >= 4.0\n");
43924450
}
43934451

4394-
if (adapter->vlans_added)
4395-
be_vid_config(adapter);
4396-
4397-
be_set_rx_mode(adapter->netdev);
4398-
43994452
status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
44004453
adapter->rx_fc);
44014454
if (status)

0 commit comments

Comments
 (0)