Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 147a9088 authored by Shahed Shaikh's avatar Shahed Shaikh Committed by David S. Miller
Browse files

qlcnic: Fix updating netdev->features



o After change in EPORT features of 82xx adapter, netdev->features needs to
  be updated to reflect EPORT feature updates but driver was manipulating
  netdev->features at wrong place.
o This patch uses netdev_update_features() and .ndo_fix_features() to
  update netdev->features properly.

Signed-off-by: default avatarShahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0ce54ce4
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -907,8 +907,11 @@ struct qlcnic_ipaddr {
#define QLCNIC_FW_HANG			0x4000
#define QLCNIC_FW_HANG			0x4000
#define QLCNIC_FW_LRO_MSS_CAP		0x8000
#define QLCNIC_FW_LRO_MSS_CAP		0x8000
#define QLCNIC_TX_INTR_SHARED		0x10000
#define QLCNIC_TX_INTR_SHARED		0x10000
#define QLCNIC_APP_CHANGED_FLAGS	0x20000
#define QLCNIC_IS_MSI_FAMILY(adapter) \
#define QLCNIC_IS_MSI_FAMILY(adapter) \
	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
	((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
#define QLCNIC_IS_TSO_CAPABLE(adapter)  \
	((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)


#define QLCNIC_DEF_NUM_STS_DESC_RINGS	4
#define QLCNIC_DEF_NUM_STS_DESC_RINGS	4
#define QLCNIC_MSIX_TBL_SPACE		8192
#define QLCNIC_MSIX_TBL_SPACE		8192
@@ -1034,6 +1037,7 @@ struct qlcnic_adapter {
	spinlock_t rx_mac_learn_lock;
	spinlock_t rx_mac_learn_lock;
	u32 file_prd_off;	/*File fw product offset*/
	u32 file_prd_off;	/*File fw product offset*/
	u32 fw_version;
	u32 fw_version;
	u32 offload_flags;
	const struct firmware *fw;
	const struct firmware *fw;
};
};


@@ -1542,6 +1546,8 @@ void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, u16);
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter);
int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_read_mac_addr(struct qlcnic_adapter *);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
int qlcnic_setup_netdev(struct qlcnic_adapter *, struct net_device *, int);
void qlcnic_set_netdev_features(struct qlcnic_adapter *,
				struct qlcnic_esw_func_cfg *);
void qlcnic_sriov_vf_schedule_multi(struct net_device *);
void qlcnic_sriov_vf_schedule_multi(struct net_device *);
void qlcnic_vf_add_mc_list(struct net_device *, u16);
void qlcnic_vf_add_mc_list(struct net_device *, u16);


+45 −4
Original line number Original line Diff line number Diff line
@@ -973,16 +973,57 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
	return rc;
	return rc;
}
}


static netdev_features_t qlcnic_process_flags(struct qlcnic_adapter *adapter,
					      netdev_features_t features)
{
	u32 offload_flags = adapter->offload_flags;

	if (offload_flags & BIT_0) {
		features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM |
			    NETIF_F_IPV6_CSUM;
		adapter->rx_csum = 1;
		if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
			if (!(offload_flags & BIT_1))
				features &= ~NETIF_F_TSO;
			else
				features |= NETIF_F_TSO;

			if (!(offload_flags & BIT_2))
				features &= ~NETIF_F_TSO6;
			else
				features |= NETIF_F_TSO6;
		}
	} else {
		features &= ~(NETIF_F_RXCSUM |
			      NETIF_F_IP_CSUM |
			      NETIF_F_IPV6_CSUM);

		if (QLCNIC_IS_TSO_CAPABLE(adapter))
			features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
		adapter->rx_csum = 0;
	}

	return features;
}


netdev_features_t qlcnic_fix_features(struct net_device *netdev,
netdev_features_t qlcnic_fix_features(struct net_device *netdev,
	netdev_features_t features)
	netdev_features_t features)
{
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	netdev_features_t changed;


	if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) &&
	if (qlcnic_82xx_check(adapter) &&
	    qlcnic_82xx_check(adapter)) {
	    (adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
		netdev_features_t changed = features ^ netdev->features;
		if (adapter->flags & QLCNIC_APP_CHANGED_FLAGS) {
		features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM);
			features = qlcnic_process_flags(adapter, features);
		} else {
			changed = features ^ netdev->features;
			features ^= changed & (NETIF_F_RXCSUM |
					       NETIF_F_IP_CSUM |
					       NETIF_F_IPV6_CSUM |
					       NETIF_F_TSO |
					       NETIF_F_TSO6);
		}
	}
	}


	if (!(features & NETIF_F_RXCSUM))
	if (!(features & NETIF_F_RXCSUM))
+7 −42
Original line number Original line Diff line number Diff line
@@ -84,14 +84,9 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *);
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
				struct qlcnic_esw_func_cfg *);
static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16);
static int qlcnic_vlan_rx_add(struct net_device *, __be16, u16);
static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16);
static int qlcnic_vlan_rx_del(struct net_device *, __be16, u16);


#define QLCNIC_IS_TSO_CAPABLE(adapter)	\
	((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)

static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
{
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -1074,8 +1069,6 @@ void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,


	if (!esw_cfg->promisc_mode)
	if (!esw_cfg->promisc_mode)
		adapter->flags |= QLCNIC_PROMISC_DISABLED;
		adapter->flags |= QLCNIC_PROMISC_DISABLED;

	qlcnic_set_netdev_features(adapter, esw_cfg);
}
}


int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
@@ -1090,51 +1083,23 @@ int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
			return -EIO;
			return -EIO;
	qlcnic_set_vlan_config(adapter, &esw_cfg);
	qlcnic_set_vlan_config(adapter, &esw_cfg);
	qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
	qlcnic_set_eswitch_port_features(adapter, &esw_cfg);
	qlcnic_set_netdev_features(adapter, &esw_cfg);


	return 0;
	return 0;
}
}


static void
void qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
				struct qlcnic_esw_func_cfg *esw_cfg)
				struct qlcnic_esw_func_cfg *esw_cfg)
{
{
	struct net_device *netdev = adapter->netdev;
	struct net_device *netdev = adapter->netdev;
	unsigned long features, vlan_features;


	if (qlcnic_83xx_check(adapter))
	if (qlcnic_83xx_check(adapter))
		return;
		return;


	features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
	adapter->offload_flags = esw_cfg->offload_flags;
		    NETIF_F_IPV6_CSUM | NETIF_F_GRO);
	adapter->flags |= QLCNIC_APP_CHANGED_FLAGS;
	vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
	netdev_update_features(netdev);
			NETIF_F_IPV6_CSUM);
	adapter->flags &= ~QLCNIC_APP_CHANGED_FLAGS;

	if (QLCNIC_IS_TSO_CAPABLE(adapter)) {
		features |= (NETIF_F_TSO | NETIF_F_TSO6);
		vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
	}

	if (netdev->features & NETIF_F_LRO)
		features |= NETIF_F_LRO;

	if (esw_cfg->offload_flags & BIT_0) {
		netdev->features |= features;
		adapter->rx_csum = 1;
		if (!(esw_cfg->offload_flags & BIT_1)) {
			netdev->features &= ~NETIF_F_TSO;
			features &= ~NETIF_F_TSO;
		}
		if (!(esw_cfg->offload_flags & BIT_2)) {
			netdev->features &= ~NETIF_F_TSO6;
			features &= ~NETIF_F_TSO6;
		}
	} else {
		netdev->features &= ~features;
		features &= ~features;
		adapter->rx_csum = 0;
	}

	netdev->vlan_features = (features & vlan_features);
}
}


static int
static int
+3 −0
Original line number Original line Diff line number Diff line
@@ -544,6 +544,9 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
		switch (esw_cfg[i].op_mode) {
		switch (esw_cfg[i].op_mode) {
		case QLCNIC_PORT_DEFAULTS:
		case QLCNIC_PORT_DEFAULTS:
			qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
			qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
			rtnl_lock();
			qlcnic_set_netdev_features(adapter, &esw_cfg[i]);
			rtnl_unlock();
			break;
			break;
		case QLCNIC_ADD_VLAN:
		case QLCNIC_ADD_VLAN:
			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
			qlcnic_set_vlan_config(adapter, &esw_cfg[i]);