diff options
Diffstat (limited to 'drivers/net/ethernet/cavium/liquidio/lio_main.c')
| -rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_main.c | 60 | 
1 files changed, 47 insertions, 13 deletions
| diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 927617cbf6a9..51583ae4b1eb 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -1421,7 +1421,7 @@ static bool fw_type_is_none(void)   */  static void octeon_destroy_resources(struct octeon_device *oct)  { -	int i; +	int i, refcount;  	struct msix_entry *msix_entries;  	struct octeon_device_priv *oct_priv =  		(struct octeon_device_priv *)oct->priv; @@ -1556,10 +1556,14 @@ static void octeon_destroy_resources(struct octeon_device *oct)  		/* fallthrough */  	case OCT_DEV_PCI_MAP_DONE: +		refcount = octeon_deregister_device(oct); +  		if (!fw_type_is_none()) { -			/* Soft reset the octeon device before exiting */ -			if (!OCTEON_CN23XX_PF(oct) || -			    (OCTEON_CN23XX_PF(oct) && !oct->octeon_id)) +			/* Soft reset the octeon device before exiting. +			 * Implementation note: here, we reset the device +			 * if it is a CN6XXX OR the last CN23XX device. +			 */ +			if (OCTEON_CN6XXX(oct) || !refcount)  				oct->fn_list.soft_reset(oct);  		} @@ -3020,6 +3024,7 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)  	case HWTSTAMP_FILTER_PTP_V2_EVENT:  	case HWTSTAMP_FILTER_PTP_V2_SYNC:  	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: +	case HWTSTAMP_FILTER_NTP_ALL:  		conf.rx_filter = HWTSTAMP_FILTER_ALL;  		break;  	default: @@ -3586,6 +3591,10 @@ static netdev_features_t liquidio_fix_features(struct net_device *netdev,  	    (lio->dev_capability & NETIF_F_LRO))  		request &= ~NETIF_F_LRO; +	if ((request & NETIF_F_HW_VLAN_CTAG_FILTER) && +	    !(lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER)) +		request &= ~NETIF_F_HW_VLAN_CTAG_FILTER; +  	return request;  } @@ -3598,14 +3607,14 @@ static int liquidio_set_features(struct net_device *netdev,  {  	struct lio *lio = netdev_priv(netdev); -	if (!((netdev->features ^ features) & NETIF_F_LRO)) -		return 0; - -	if ((features & NETIF_F_LRO) && (lio->dev_capability & NETIF_F_LRO)) +	if ((features & NETIF_F_LRO) && +	    (lio->dev_capability & NETIF_F_LRO) && +	    !(netdev->features & NETIF_F_LRO))  		liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,  				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);  	else if (!(features & NETIF_F_LRO) && -		 (lio->dev_capability & NETIF_F_LRO)) +		 (lio->dev_capability & NETIF_F_LRO) && +		 (netdev->features & NETIF_F_LRO))  		liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE,  				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6); @@ -3624,6 +3633,17 @@ static int liquidio_set_features(struct net_device *netdev,  		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,  					    OCTNET_CMD_RXCSUM_DISABLE); +	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) && +	    (lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER) && +	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) +		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL, +				     OCTNET_CMD_VLAN_FILTER_ENABLE); +	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) && +		 (lio->dev_capability & NETIF_F_HW_VLAN_CTAG_FILTER) && +		 (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) +		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL, +				     OCTNET_CMD_VLAN_FILTER_DISABLE); +  	return 0;  } @@ -3694,6 +3714,9 @@ static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac)  	struct octeon_device *oct = lio->oct_dev;  	int retval; +	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) +		return -EINVAL; +  	retval = __liquidio_set_vf_mac(netdev, vfidx, mac, true);  	if (!retval)  		cn23xx_tell_vf_its_macaddr_changed(oct, vfidx, mac); @@ -3876,7 +3899,7 @@ static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)  	union oct_link_status *ls;  	int i; -	if (recv_pkt->buffer_size[0] != sizeof(*ls)) { +	if (recv_pkt->buffer_size[0] != (sizeof(*ls) + OCT_DROQ_INFO_SIZE)) {  		dev_err(&oct->pci_dev->dev, "Malformed NIC_INFO, len=%d, ifidx=%d\n",  			recv_pkt->buffer_size[0],  			recv_pkt->rh.r_nic_info.gmxport); @@ -3884,7 +3907,8 @@ static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)  	}  	gmxport = recv_pkt->rh.r_nic_info.gmxport; -	ls = (union oct_link_status *)get_rbd(recv_pkt->buffer_ptr[0]); +	ls = (union oct_link_status *)(get_rbd(recv_pkt->buffer_ptr[0]) + +		OCT_DROQ_INFO_SIZE);  	octeon_swap_8B_data((u64 *)ls, (sizeof(union oct_link_status)) >> 3);  	for (i = 0; i < oct->ifcount; i++) { @@ -4191,7 +4215,8 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)  			liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,  					     OCTNIC_LROIPV4 | OCTNIC_LROIPV6); -		liquidio_set_feature(netdev, OCTNET_CMD_ENABLE_VLAN_FILTER, 0); +		liquidio_set_feature(netdev, OCTNET_CMD_VLAN_FILTER_CTL, +				     OCTNET_CMD_VLAN_FILTER_ENABLE);  		if ((debug != -1) && (debug & NETIF_MSG_HW))  			liquidio_set_feature(netdev, @@ -4441,7 +4466,7 @@ octeon_recv_vf_drv_notice(struct octeon_recv_info *recv_info, void *buf)  	u64 *data, vf_num;  	notice = recv_pkt->rh.r.ossp; -	data = (u64 *)get_rbd(recv_pkt->buffer_ptr[0]); +	data = (u64 *)(get_rbd(recv_pkt->buffer_ptr[0]) + OCT_DROQ_INFO_SIZE);  	/* the first 64-bit word of data is the vf_num */  	vf_num = data[0]; @@ -4511,6 +4536,15 @@ static int octeon_device_init(struct octeon_device *octeon_dev)  	atomic_set(&octeon_dev->status, OCT_DEV_PCI_MAP_DONE); +	/* Only add a reference after setting status 'OCT_DEV_PCI_MAP_DONE', +	 * since that is what is required for the reference to be removed +	 * during de-initialization (see 'octeon_destroy_resources'). +	 */ +	octeon_register_device(octeon_dev, octeon_dev->pci_dev->bus->number, +			       PCI_SLOT(octeon_dev->pci_dev->devfn), +			       PCI_FUNC(octeon_dev->pci_dev->devfn), +			       true); +  	octeon_dev->app_mode = CVM_DRV_INVALID_APP;  	if (OCTEON_CN23XX_PF(octeon_dev)) { |