diff options
Diffstat (limited to 'drivers/net')
192 files changed, 1617 insertions, 914 deletions
| diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 62ee439d5882..53a1cb551def 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -756,6 +756,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)  	struct net_device *dev = dev_id;  	struct arcnet_local *lp;  	int recbuf, status, diagstatus, didsomething, boguscount; +	unsigned long flags;  	int retval = IRQ_NONE;  	arc_printk(D_DURING, dev, "\n"); @@ -765,7 +766,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)  	lp = netdev_priv(dev);  	BUG_ON(!lp); -	spin_lock(&lp->lock); +	spin_lock_irqsave(&lp->lock, flags);  	/* RESET flag was enabled - if device is not running, we must  	 * clear it right away (but nothing else). @@ -774,7 +775,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)  		if (lp->hw.status(dev) & RESETflag)  			lp->hw.command(dev, CFLAGScmd | RESETclear);  		lp->hw.intmask(dev, 0); -		spin_unlock(&lp->lock); +		spin_unlock_irqrestore(&lp->lock, flags);  		return retval;  	} @@ -998,7 +999,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)  	udelay(1);  	lp->hw.intmask(dev, lp->intmask); -	spin_unlock(&lp->lock); +	spin_unlock_irqrestore(&lp->lock, flags);  	return retval;  }  EXPORT_SYMBOL(arcnet_interrupt); diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 2056878fb087..4fa2e46b48d3 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -212,7 +212,7 @@ static int ack_tx(struct net_device *dev, int acked)  	ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */  	ackpkt->soft.cap.mes.ack = acked; -	arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n", +	arc_printk(D_PROTO, dev, "Acknowledge for cap packet %x.\n",  		   *((int *)&ackpkt->soft.cap.cookie[0]));  	ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 239de38fbd6a..47f80b83dcf4 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -135,6 +135,7 @@ static int com20020pci_probe(struct pci_dev *pdev,  	for (i = 0; i < ci->devcount; i++) {  		struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];  		struct com20020_dev *card; +		int dev_id_mask = 0xf;  		dev = alloc_arcdev(device);  		if (!dev) { @@ -166,6 +167,7 @@ static int com20020pci_probe(struct pci_dev *pdev,  		arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);  		arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT); +		SET_NETDEV_DEV(dev, &pdev->dev);  		dev->base_addr = ioaddr;  		dev->dev_addr[0] = node;  		dev->irq = pdev->irq; @@ -179,8 +181,8 @@ static int com20020pci_probe(struct pci_dev *pdev,  		/* Get the dev_id from the PLX rotary coder */  		if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15)) -			dev->dev_id = 0xc; -		dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4; +			dev_id_mask = 0x3; +		dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;  		snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 13d9ad4b3f5c..78043a9c5981 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -246,8 +246,6 @@ int com20020_found(struct net_device *dev, int shared)  		return -ENODEV;  	} -	dev->base_addr = ioaddr; -  	arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",  		   lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index c5fd4259da33..e5386ab706ec 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -90,10 +90,13 @@ enum ad_link_speed_type {  	AD_LINK_SPEED_100MBPS,  	AD_LINK_SPEED_1000MBPS,  	AD_LINK_SPEED_2500MBPS, +	AD_LINK_SPEED_5000MBPS,  	AD_LINK_SPEED_10000MBPS, +	AD_LINK_SPEED_14000MBPS,  	AD_LINK_SPEED_20000MBPS,  	AD_LINK_SPEED_25000MBPS,  	AD_LINK_SPEED_40000MBPS, +	AD_LINK_SPEED_50000MBPS,  	AD_LINK_SPEED_56000MBPS,  	AD_LINK_SPEED_100000MBPS,  }; @@ -259,10 +262,13 @@ static inline int __check_agg_selection_timer(struct port *port)   *     %AD_LINK_SPEED_100MBPS,   *     %AD_LINK_SPEED_1000MBPS,   *     %AD_LINK_SPEED_2500MBPS, + *     %AD_LINK_SPEED_5000MBPS,   *     %AD_LINK_SPEED_10000MBPS + *     %AD_LINK_SPEED_14000MBPS,   *     %AD_LINK_SPEED_20000MBPS   *     %AD_LINK_SPEED_25000MBPS   *     %AD_LINK_SPEED_40000MBPS + *     %AD_LINK_SPEED_50000MBPS   *     %AD_LINK_SPEED_56000MBPS   *     %AD_LINK_SPEED_100000MBPS   */ @@ -296,10 +302,18 @@ static u16 __get_link_speed(struct port *port)  			speed = AD_LINK_SPEED_2500MBPS;  			break; +		case SPEED_5000: +			speed = AD_LINK_SPEED_5000MBPS; +			break; +  		case SPEED_10000:  			speed = AD_LINK_SPEED_10000MBPS;  			break; +		case SPEED_14000: +			speed = AD_LINK_SPEED_14000MBPS; +			break; +  		case SPEED_20000:  			speed = AD_LINK_SPEED_20000MBPS;  			break; @@ -312,6 +326,10 @@ static u16 __get_link_speed(struct port *port)  			speed = AD_LINK_SPEED_40000MBPS;  			break; +		case SPEED_50000: +			speed = AD_LINK_SPEED_50000MBPS; +			break; +  		case SPEED_56000:  			speed = AD_LINK_SPEED_56000MBPS;  			break; @@ -707,9 +725,15 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)  		case AD_LINK_SPEED_2500MBPS:  			bandwidth = nports * 2500;  			break; +		case AD_LINK_SPEED_5000MBPS: +			bandwidth = nports * 5000; +			break;  		case AD_LINK_SPEED_10000MBPS:  			bandwidth = nports * 10000;  			break; +		case AD_LINK_SPEED_14000MBPS: +			bandwidth = nports * 14000; +			break;  		case AD_LINK_SPEED_20000MBPS:  			bandwidth = nports * 20000;  			break; @@ -719,6 +743,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)  		case AD_LINK_SPEED_40000MBPS:  			bandwidth = nports * 40000;  			break; +		case AD_LINK_SPEED_50000MBPS: +			bandwidth = nports * 50000; +			break;  		case AD_LINK_SPEED_56000MBPS:  			bandwidth = nports * 56000;  			break; @@ -2577,7 +2604,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,  		return -1;  	ad_info->aggregator_id = aggregator->aggregator_identifier; -	ad_info->ports = aggregator->num_of_ports; +	ad_info->ports = __agg_active_ports(aggregator);  	ad_info->actor_key = aggregator->actor_oper_aggregator_key;  	ad_info->partner_key = aggregator->partner_oper_aggregator_key;  	ether_addr_copy(ad_info->partner_system, diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2be78807fd6e..8ab6bdbe1682 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2612,11 +2612,13 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)  	bond_for_each_slave_rcu(bond, slave, iter) {  		unsigned long trans_start = dev_trans_start(slave->dev); +		slave->new_link = BOND_LINK_NOCHANGE; +  		if (slave->link != BOND_LINK_UP) {  			if (bond_time_in_interval(bond, trans_start, 1) &&  			    bond_time_in_interval(bond, slave->last_rx, 1)) { -				slave->link  = BOND_LINK_UP; +				slave->new_link = BOND_LINK_UP;  				slave_state_changed = 1;  				/* primary_slave has no meaning in round-robin @@ -2643,7 +2645,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)  			if (!bond_time_in_interval(bond, trans_start, 2) ||  			    !bond_time_in_interval(bond, slave->last_rx, 2)) { -				slave->link  = BOND_LINK_DOWN; +				slave->new_link = BOND_LINK_DOWN;  				slave_state_changed = 1;  				if (slave->link_failure_count < UINT_MAX) @@ -2674,6 +2676,11 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)  		if (!rtnl_trylock())  			goto re_arm; +		bond_for_each_slave(bond, slave, iter) { +			if (slave->new_link != BOND_LINK_NOCHANGE) +				slave->link = slave->new_link; +		} +  		if (slave_state_changed) {  			bond_slave_state_change(bond);  			if (BOND_MODE(bond) == BOND_MODE_XOR) @@ -4185,7 +4192,6 @@ static void bond_destructor(struct net_device *bond_dev)  	struct bonding *bond = netdev_priv(bond_dev);  	if (bond->wq)  		destroy_workqueue(bond->wq); -	free_netdev(bond_dev);  }  void bond_setup(struct net_device *bond_dev) @@ -4205,7 +4211,8 @@ void bond_setup(struct net_device *bond_dev)  	bond_dev->netdev_ops = &bond_netdev_ops;  	bond_dev->ethtool_ops = &bond_ethtool_ops; -	bond_dev->destructor = bond_destructor; +	bond_dev->needs_free_netdev = true; +	bond_dev->priv_destructor = bond_destructor;  	SET_NETDEV_DEVTYPE(bond_dev, &bond_type); @@ -4271,10 +4278,10 @@ static int bond_check_params(struct bond_params *params)  	int arp_validate_value, fail_over_mac_value, primary_reselect_value, i;  	struct bond_opt_value newval;  	const struct bond_opt_value *valptr; -	int arp_all_targets_value; +	int arp_all_targets_value = 0;  	u16 ad_actor_sys_prio = 0;  	u16 ad_user_port_key = 0; -	__be32 arp_target[BOND_MAX_ARP_TARGETS]; +	__be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0 };  	int arp_ip_count;  	int bond_mode	= BOND_MODE_ROUNDROBIN;  	int xmit_hashtype = BOND_XMIT_POLICY_LAYER2; @@ -4501,7 +4508,6 @@ static int bond_check_params(struct bond_params *params)  		arp_validate_value = 0;  	} -	arp_all_targets_value = 0;  	if (arp_all_targets) {  		bond_opt_initstr(&newval, arp_all_targets);  		valptr = bond_opt_parse(bond_opt_get(BOND_OPT_ARP_ALL_TARGETS), @@ -4730,7 +4736,7 @@ int bond_create(struct net *net, const char *name)  	rtnl_unlock();  	if (res < 0) -		bond_destructor(bond_dev); +		free_netdev(bond_dev);  	return res;  } diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index ddabce759456..71a7c3b44fdd 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -1121,7 +1121,7 @@ static void cfhsi_setup(struct net_device *dev)  	dev->flags = IFF_POINTOPOINT | IFF_NOARP;  	dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ;  	dev->priv_flags |= IFF_NO_QUEUE; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	dev->netdev_ops = &cfhsi_netdevops;  	for (i = 0; i < CFHSI_PRIO_LAST; ++i)  		skb_queue_head_init(&cfhsi->qhead[i]); diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index c2dea4916e5d..76e1d3545105 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -428,7 +428,7 @@ static void caifdev_setup(struct net_device *dev)  	dev->flags = IFF_POINTOPOINT | IFF_NOARP;  	dev->mtu = CAIF_MAX_MTU;  	dev->priv_flags |= IFF_NO_QUEUE; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	skb_queue_head_init(&serdev->head);  	serdev->common.link_select = CAIF_LINK_LOW_LATENCY;  	serdev->common.use_frag = true; diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index 3a529fbe539f..fc21afe852b9 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -712,7 +712,7 @@ static void cfspi_setup(struct net_device *dev)  	dev->flags = IFF_NOARP | IFF_POINTOPOINT;  	dev->priv_flags |= IFF_NO_QUEUE;  	dev->mtu = SPI_MAX_PAYLOAD_SIZE; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	skb_queue_head_init(&cfspi->qhead);  	skb_queue_head_init(&cfspi->chead);  	cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW; diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index 6122768c8644..1794ea0420b7 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c @@ -617,7 +617,7 @@ static void cfv_netdev_setup(struct net_device *netdev)  	netdev->tx_queue_len = 100;  	netdev->flags = IFF_POINTOPOINT | IFF_NOARP;  	netdev->mtu = CFV_DEF_MTU_SIZE; -	netdev->destructor = free_netdev; +	netdev->needs_free_netdev = true;  }  /* Create debugfs counters for the device */ diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 611d16a7061d..ae4ed03dc642 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -391,6 +391,9 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,  	can_update_state_error_stats(dev, new_state);  	priv->state = new_state; +	if (!cf) +		return; +  	if (unlikely(new_state == CAN_STATE_BUS_OFF)) {  		cf->can_id |= CAN_ERR_BUSOFF;  		return; diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c index 0d57be5ea97b..85268be0c913 100644 --- a/drivers/net/can/peak_canfd/peak_canfd.c +++ b/drivers/net/can/peak_canfd/peak_canfd.c @@ -489,7 +489,7 @@ int peak_canfd_handle_msgs_list(struct peak_canfd_priv *priv,  				struct pucan_rx_msg *msg_list, int msg_count)  {  	void *msg_ptr = msg_list; -	int i, msg_size; +	int i, msg_size = 0;  	for (i = 0; i < msg_count; i++) {  		msg_size = peak_canfd_handle_msg(priv, msg_ptr); diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index eb7173713bbc..6a6e896e52fa 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -417,7 +417,7 @@ static int slc_open(struct net_device *dev)  static void slc_free_netdev(struct net_device *dev)  {  	int i = dev->base_addr; -	free_netdev(dev); +  	slcan_devs[i] = NULL;  } @@ -436,7 +436,8 @@ static const struct net_device_ops slc_netdev_ops = {  static void slc_setup(struct net_device *dev)  {  	dev->netdev_ops		= &slc_netdev_ops; -	dev->destructor		= slc_free_netdev; +	dev->needs_free_netdev	= true; +	dev->priv_destructor	= slc_free_netdev;  	dev->hard_header_len	= 0;  	dev->addr_len		= 0; @@ -761,8 +762,6 @@ static void __exit slcan_exit(void)  		if (sl->tty) {  			printk(KERN_ERR "%s: tty discipline still running\n",  			       dev->name); -			/* Intentionally leak the control block. */ -			dev->destructor = NULL;  		}  		unregister_netdev(dev); diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index eecee7f8dfb7..afcc1312dbaf 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -265,6 +265,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev)  			     sizeof(*dm),  			     1000); +	kfree(dm); +  	return rc;  } diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 57913dbbae0a..1ca76e03e965 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -908,8 +908,6 @@ static int peak_usb_probe(struct usb_interface *intf,  	const struct peak_usb_adapter *peak_usb_adapter = NULL;  	int i, err = -ENOMEM; -	usb_dev = interface_to_usbdev(intf); -  	/* get corresponding PCAN-USB adapter */  	for (i = 0; i < ARRAY_SIZE(peak_usb_adapters_list); i++)  		if (peak_usb_adapters_list[i]->device_id == usb_id_product) { @@ -920,7 +918,7 @@ static int peak_usb_probe(struct usb_interface *intf,  	if (!peak_usb_adapter) {  		/* should never come except device_id bad usage in this file */  		pr_err("%s: didn't find device id. 0x%x in devices list\n", -			PCAN_USB_DRIVER_NAME, usb_dev->descriptor.idProduct); +			PCAN_USB_DRIVER_NAME, usb_id_product);  		return -ENODEV;  	} diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index facca33d53e9..a8cb33264ff1 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -152,7 +152,7 @@ static const struct net_device_ops vcan_netdev_ops = {  static void vcan_setup(struct net_device *dev)  {  	dev->type		= ARPHRD_CAN; -	dev->mtu		= CAN_MTU; +	dev->mtu		= CANFD_MTU;  	dev->hard_header_len	= 0;  	dev->addr_len		= 0;  	dev->tx_queue_len	= 0; @@ -163,7 +163,7 @@ static void vcan_setup(struct net_device *dev)  		dev->flags |= IFF_ECHO;  	dev->netdev_ops		= &vcan_netdev_ops; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  }  static struct rtnl_link_ops vcan_link_ops __read_mostly = { diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 7fbb24795681..cfe889e8f172 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -150,13 +150,13 @@ static const struct net_device_ops vxcan_netdev_ops = {  static void vxcan_setup(struct net_device *dev)  {  	dev->type		= ARPHRD_CAN; -	dev->mtu		= CAN_MTU; +	dev->mtu		= CANFD_MTU;  	dev->hard_header_len	= 0;  	dev->addr_len		= 0;  	dev->tx_queue_len	= 0;  	dev->flags		= (IFF_NOARP|IFF_ECHO);  	dev->netdev_ops		= &vxcan_netdev_ops; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  }  /* forward declaration for rtnl_create_link() */ diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 19581d783d8e..d034d8cd7d22 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -849,6 +849,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,  		mv88e6xxx_g1_stats_read(chip, reg, &low);  		if (s->sizeof_stat == 8)  			mv88e6xxx_g1_stats_read(chip, reg + 1, &high); +		break; +	default: +		return UINT64_MAX;  	}  	value = (((u64)high) << 16) | low;  	return value; diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 96046bb12ca1..14c0be98e0a4 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -114,13 +114,13 @@ static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,  	return -EOPNOTSUPP;  } -int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, -			   int src_port, u16 data) +static inline int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, +					 int src_dev, int src_port, u16 data)  {  	return -EOPNOTSUPP;  } -int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip) +static inline int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)  {  	return -EOPNOTSUPP;  } diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 149244aac20a..9905b52fe293 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -328,7 +328,6 @@ static void dummy_free_netdev(struct net_device *dev)  	struct dummy_priv *priv = netdev_priv(dev);  	kfree(priv->vfinfo); -	free_netdev(dev);  }  static void dummy_setup(struct net_device *dev) @@ -338,7 +337,8 @@ static void dummy_setup(struct net_device *dev)  	/* Initialize the device structure. */  	dev->netdev_ops = &dummy_netdev_ops;  	dev->ethtool_ops = &dummy_ethtool_ops; -	dev->destructor = dummy_free_netdev; +	dev->needs_free_netdev = true; +	dev->priv_destructor = dummy_free_netdev;  	/* Fill in device structure with ethernet-generic values. */  	dev->flags |= IFF_NOARP; diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c index b0a3b85fc6f8..db02bc2fb4b2 100644 --- a/drivers/net/ethernet/8390/ax88796.c +++ b/drivers/net/ethernet/8390/ax88796.c @@ -748,13 +748,13 @@ static int ax_init_dev(struct net_device *dev)  	ret = ax_mii_init(dev);  	if (ret) -		goto out_irq; +		goto err_out;  	ax_NS8390_init(dev, 0);  	ret = register_netdev(dev);  	if (ret) -		goto out_irq; +		goto err_out;  	netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",  		    ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr, @@ -762,9 +762,6 @@ static int ax_init_dev(struct net_device *dev)  	return 0; - out_irq: -	/* cleanup irq */ -	free_irq(dev->irq, dev);   err_out:  	return ret;  } diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 08d11cede9c9..f5b237e0bd60 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -61,6 +61,8 @@  #define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF +#define ENA_REGS_ADMIN_INTR_MASK 1 +  /*****************************************************************************/  /*****************************************************************************/  /*****************************************************************************/ @@ -232,11 +234,9 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu  	tail_masked = admin_queue->sq.tail & queue_size_mask;  	/* In case of queue FULL */ -	cnt = admin_queue->sq.tail - admin_queue->sq.head; +	cnt = atomic_read(&admin_queue->outstanding_cmds);  	if (cnt >= admin_queue->q_depth) { -		pr_debug("admin queue is FULL (tail %d head %d depth: %d)\n", -			 admin_queue->sq.tail, admin_queue->sq.head, -			 admin_queue->q_depth); +		pr_debug("admin queue is full.\n");  		admin_queue->stats.out_of_space++;  		return ERR_PTR(-ENOSPC);  	} @@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status)  static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx,  						     struct ena_com_admin_queue *admin_queue)  { -	unsigned long flags; -	u32 start_time; +	unsigned long flags, timeout;  	int ret; -	start_time = ((u32)jiffies_to_usecs(jiffies)); +	timeout = jiffies + ADMIN_CMD_TIMEOUT_US; + +	while (1) { +		spin_lock_irqsave(&admin_queue->q_lock, flags); +		ena_com_handle_admin_completion(admin_queue); +		spin_unlock_irqrestore(&admin_queue->q_lock, flags); + +		if (comp_ctx->status != ENA_CMD_SUBMITTED) +			break; -	while (comp_ctx->status == ENA_CMD_SUBMITTED) { -		if ((((u32)jiffies_to_usecs(jiffies)) - start_time) > -		    ADMIN_CMD_TIMEOUT_US) { +		if (time_is_before_jiffies(timeout)) {  			pr_err("Wait for completion (polling) timeout\n");  			/* ENA didn't have any completion */  			spin_lock_irqsave(&admin_queue->q_lock, flags); @@ -528,10 +533,6 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c  			goto err;  		} -		spin_lock_irqsave(&admin_queue->q_lock, flags); -		ena_com_handle_admin_completion(admin_queue); -		spin_unlock_irqrestore(&admin_queue->q_lock, flags); -  		msleep(100);  	} @@ -1455,6 +1456,12 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev)  void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)  { +	u32 mask_value = 0; + +	if (polling) +		mask_value = ENA_REGS_ADMIN_INTR_MASK; + +	writel(mask_value, ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF);  	ena_dev->admin_queue.polling = polling;  } diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 67b2338f8fb3..3ee55e2fd694 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -80,7 +80,6 @@ static const struct ena_stats ena_stats_tx_strings[] = {  	ENA_STAT_TX_ENTRY(tx_poll),  	ENA_STAT_TX_ENTRY(doorbells),  	ENA_STAT_TX_ENTRY(prepare_ctx_err), -	ENA_STAT_TX_ENTRY(missing_tx_comp),  	ENA_STAT_TX_ENTRY(bad_req_id),  }; @@ -94,6 +93,7 @@ static const struct ena_stats ena_stats_rx_strings[] = {  	ENA_STAT_RX_ENTRY(dma_mapping_err),  	ENA_STAT_RX_ENTRY(bad_desc_num),  	ENA_STAT_RX_ENTRY(rx_copybreak_pkt), +	ENA_STAT_RX_ENTRY(empty_rx_ring),  };  static const struct ena_stats ena_stats_ena_com_strings[] = { diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 7c1214d78855..4f16ed38bcf3 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -190,6 +190,7 @@ static void ena_init_io_rings(struct ena_adapter *adapter)  		rxr->sgl_size = adapter->max_rx_sgl_size;  		rxr->smoothed_interval =  			ena_com_get_nonadaptive_moderation_interval_rx(ena_dev); +		rxr->empty_rx_queue = 0;  	}  } @@ -1078,6 +1079,26 @@ inline void ena_adjust_intr_moderation(struct ena_ring *rx_ring,  	rx_ring->per_napi_bytes = 0;  } +static inline void ena_unmask_interrupt(struct ena_ring *tx_ring, +					struct ena_ring *rx_ring) +{ +	struct ena_eth_io_intr_reg intr_reg; + +	/* Update intr register: rx intr delay, +	 * tx intr delay and interrupt unmask +	 */ +	ena_com_update_intr_reg(&intr_reg, +				rx_ring->smoothed_interval, +				tx_ring->smoothed_interval, +				true); + +	/* It is a shared MSI-X. +	 * Tx and Rx CQ have pointer to it. +	 * So we use one of them to reach the intr reg +	 */ +	ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg); +} +  static inline void ena_update_ring_numa_node(struct ena_ring *tx_ring,  					     struct ena_ring *rx_ring)  { @@ -1108,7 +1129,6 @@ static int ena_io_poll(struct napi_struct *napi, int budget)  {  	struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);  	struct ena_ring *tx_ring, *rx_ring; -	struct ena_eth_io_intr_reg intr_reg;  	u32 tx_work_done;  	u32 rx_work_done; @@ -1149,22 +1169,9 @@ static int ena_io_poll(struct napi_struct *napi, int budget)  			if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev))  				ena_adjust_intr_moderation(rx_ring, tx_ring); -			/* Update intr register: rx intr delay, -			 * tx intr delay and interrupt unmask -			 */ -			ena_com_update_intr_reg(&intr_reg, -						rx_ring->smoothed_interval, -						tx_ring->smoothed_interval, -						true); - -			/* It is a shared MSI-X. -			 * Tx and Rx CQ have pointer to it. -			 * So we use one of them to reach the intr reg -			 */ -			ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg); +			ena_unmask_interrupt(tx_ring, rx_ring);  		} -  		ena_update_ring_numa_node(tx_ring, rx_ring);  		ret = rx_work_done; @@ -1485,6 +1492,11 @@ static int ena_up_complete(struct ena_adapter *adapter)  	ena_napi_enable_all(adapter); +	/* Enable completion queues interrupt */ +	for (i = 0; i < adapter->num_queues; i++) +		ena_unmask_interrupt(&adapter->tx_ring[i], +				     &adapter->rx_ring[i]); +  	/* schedule napi in case we had pending packets  	 * from the last time we disable napi  	 */ @@ -1532,6 +1544,7 @@ static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid)  			  "Failed to get TX queue handlers. TX queue num %d rc: %d\n",  			  qid, rc);  		ena_com_destroy_io_queue(ena_dev, ena_qid); +		return rc;  	}  	ena_com_update_numa_node(tx_ring->ena_com_io_cq, ctx.numa_node); @@ -1596,6 +1609,7 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid)  			  "Failed to get RX queue handlers. RX queue num %d rc: %d\n",  			  qid, rc);  		ena_com_destroy_io_queue(ena_dev, ena_qid); +		return rc;  	}  	ena_com_update_numa_node(rx_ring->ena_com_io_cq, ctx.numa_node); @@ -1981,6 +1995,7 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)  	tx_info->tx_descs = nb_hw_desc;  	tx_info->last_jiffies = jiffies; +	tx_info->print_once = 0;  	tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use,  		tx_ring->ring_size); @@ -2550,13 +2565,44 @@ err:  		"Reset attempt failed. Can not reset the device\n");  } -static void check_for_missing_tx_completions(struct ena_adapter *adapter) +static int check_missing_comp_in_queue(struct ena_adapter *adapter, +				       struct ena_ring *tx_ring)  {  	struct ena_tx_buffer *tx_buf;  	unsigned long last_jiffies; +	u32 missed_tx = 0; +	int i; + +	for (i = 0; i < tx_ring->ring_size; i++) { +		tx_buf = &tx_ring->tx_buffer_info[i]; +		last_jiffies = tx_buf->last_jiffies; +		if (unlikely(last_jiffies && +			     time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) { +			if (!tx_buf->print_once) +				netif_notice(adapter, tx_err, adapter->netdev, +					     "Found a Tx that wasn't completed on time, qid %d, index %d.\n", +					     tx_ring->qid, i); + +			tx_buf->print_once = 1; +			missed_tx++; + +			if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) { +				netif_err(adapter, tx_err, adapter->netdev, +					  "The number of lost tx completions is above the threshold (%d > %d). Reset the device\n", +					  missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS); +				set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); +				return -EIO; +			} +		} +	} + +	return 0; +} + +static void check_for_missing_tx_completions(struct ena_adapter *adapter) +{  	struct ena_ring *tx_ring; -	int i, j, budget; -	u32 missed_tx; +	int i, budget, rc;  	/* Make sure the driver doesn't turn the device in other process */  	smp_rmb(); @@ -2572,31 +2618,9 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter)  	for (i = adapter->last_monitored_tx_qid; i < adapter->num_queues; i++) {  		tx_ring = &adapter->tx_ring[i]; -		for (j = 0; j < tx_ring->ring_size; j++) { -			tx_buf = &tx_ring->tx_buffer_info[j]; -			last_jiffies = tx_buf->last_jiffies; -			if (unlikely(last_jiffies && time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) { -				netif_notice(adapter, tx_err, adapter->netdev, -					     "Found a Tx that wasn't completed on time, qid %d, index %d.\n", -					     tx_ring->qid, j); - -				u64_stats_update_begin(&tx_ring->syncp); -				missed_tx = tx_ring->tx_stats.missing_tx_comp++; -				u64_stats_update_end(&tx_ring->syncp); - -				/* Clear last jiffies so the lost buffer won't -				 * be counted twice. -				 */ -				tx_buf->last_jiffies = 0; - -				if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) { -					netif_err(adapter, tx_err, adapter->netdev, -						  "The number of lost tx completion is above the threshold (%d > %d). Reset the device\n", -						  missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS); -					set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); -				} -			} -		} +		rc = check_missing_comp_in_queue(adapter, tx_ring); +		if (unlikely(rc)) +			return;  		budget--;  		if (!budget) @@ -2606,6 +2630,58 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter)  	adapter->last_monitored_tx_qid = i % adapter->num_queues;  } +/* trigger napi schedule after 2 consecutive detections */ +#define EMPTY_RX_REFILL 2 +/* For the rare case where the device runs out of Rx descriptors and the + * napi handler failed to refill new Rx descriptors (due to a lack of memory + * for example). + * This case will lead to a deadlock: + * The device won't send interrupts since all the new Rx packets will be dropped + * The napi handler won't allocate new Rx descriptors so the device will be + * able to send new packets. + * + * This scenario can happen when the kernel's vm.min_free_kbytes is too small. + * It is recommended to have at least 512MB, with a minimum of 128MB for + * constrained environment). + * + * When such a situation is detected - Reschedule napi + */ +static void check_for_empty_rx_ring(struct ena_adapter *adapter) +{ +	struct ena_ring *rx_ring; +	int i, refill_required; + +	if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags)) +		return; + +	if (test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) +		return; + +	for (i = 0; i < adapter->num_queues; i++) { +		rx_ring = &adapter->rx_ring[i]; + +		refill_required = +			ena_com_sq_empty_space(rx_ring->ena_com_io_sq); +		if (unlikely(refill_required == (rx_ring->ring_size - 1))) { +			rx_ring->empty_rx_queue++; + +			if (rx_ring->empty_rx_queue >= EMPTY_RX_REFILL) { +				u64_stats_update_begin(&rx_ring->syncp); +				rx_ring->rx_stats.empty_rx_ring++; +				u64_stats_update_end(&rx_ring->syncp); + +				netif_err(adapter, drv, adapter->netdev, +					  "trigger refill for ring %d\n", i); + +				napi_schedule(rx_ring->napi); +				rx_ring->empty_rx_queue = 0; +			} +		} else { +			rx_ring->empty_rx_queue = 0; +		} +	} +} +  /* Check for keep alive expiration */  static void check_for_missing_keep_alive(struct ena_adapter *adapter)  { @@ -2660,6 +2736,8 @@ static void ena_timer_service(unsigned long data)  	check_for_missing_tx_completions(adapter); +	check_for_empty_rx_ring(adapter); +  	if (debug_area)  		ena_dump_stats_to_buf(adapter, debug_area); @@ -2840,6 +2918,11 @@ static void ena_release_bars(struct ena_com_dev *ena_dev, struct pci_dev *pdev)  {  	int release_bars; +	if (ena_dev->mem_bar) +		devm_iounmap(&pdev->dev, ena_dev->mem_bar); + +	devm_iounmap(&pdev->dev, ena_dev->reg_bar); +  	release_bars = pci_select_bars(pdev, IORESOURCE_MEM) & ENA_BAR_MASK;  	pci_release_selected_regions(pdev, release_bars);  } @@ -2927,8 +3010,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		goto err_free_ena_dev;  	} -	ena_dev->reg_bar = ioremap(pci_resource_start(pdev, ENA_REG_BAR), -				   pci_resource_len(pdev, ENA_REG_BAR)); +	ena_dev->reg_bar = devm_ioremap(&pdev->dev, +					pci_resource_start(pdev, ENA_REG_BAR), +					pci_resource_len(pdev, ENA_REG_BAR));  	if (!ena_dev->reg_bar) {  		dev_err(&pdev->dev, "failed to remap regs bar\n");  		rc = -EFAULT; @@ -2948,8 +3032,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	ena_set_push_mode(pdev, ena_dev, &get_feat_ctx);  	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) { -		ena_dev->mem_bar = ioremap_wc(pci_resource_start(pdev, ENA_MEM_BAR), -					      pci_resource_len(pdev, ENA_MEM_BAR)); +		ena_dev->mem_bar = devm_ioremap_wc(&pdev->dev, +						   pci_resource_start(pdev, ENA_MEM_BAR), +						   pci_resource_len(pdev, ENA_MEM_BAR));  		if (!ena_dev->mem_bar) {  			rc = -EFAULT;  			goto err_device_destroy; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 0e22bce6239d..a4d3d5e21068 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -45,7 +45,7 @@  #define DRV_MODULE_VER_MAJOR	1  #define DRV_MODULE_VER_MINOR	1 -#define DRV_MODULE_VER_SUBMINOR 2 +#define DRV_MODULE_VER_SUBMINOR 7  #define DRV_MODULE_NAME		"ena"  #ifndef DRV_MODULE_VERSION @@ -146,7 +146,18 @@ struct ena_tx_buffer {  	u32 tx_descs;  	/* num of buffers used by this skb */  	u32 num_of_bufs; -	/* Save the last jiffies to detect missing tx packets */ + +	/* Used for detect missing tx packets to limit the number of prints */ +	u32 print_once; +	/* Save the last jiffies to detect missing tx packets +	 * +	 * sets to non zero value on ena_start_xmit and set to zero on +	 * napi and timer_Service_routine. +	 * +	 * while this value is not protected by lock, +	 * a given packet is not expected to be handled by ena_start_xmit +	 * and by napi/timer_service at the same time. +	 */  	unsigned long last_jiffies;  	struct ena_com_buf bufs[ENA_PKT_MAX_BUFS];  } ____cacheline_aligned; @@ -170,7 +181,6 @@ struct ena_stats_tx {  	u64 napi_comp;  	u64 tx_poll;  	u64 doorbells; -	u64 missing_tx_comp;  	u64 bad_req_id;  }; @@ -184,6 +194,7 @@ struct ena_stats_rx {  	u64 dma_mapping_err;  	u64 bad_desc_num;  	u64 rx_copybreak_pkt; +	u64 empty_rx_ring;  };  struct ena_ring { @@ -231,6 +242,7 @@ struct ena_ring {  		struct ena_stats_tx tx_stats;  		struct ena_stats_rx rx_stats;  	}; +	int empty_rx_queue;  } ____cacheline_aligned;  struct ena_stats_dev { diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c index b3bc87fe3764..0a98c369df20 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-desc.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-desc.c @@ -324,7 +324,7 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,  			      struct xgbe_ring *ring,  			      struct xgbe_ring_data *rdata)  { -	int order, ret; +	int ret;  	if (!ring->rx_hdr_pa.pages) {  		ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0); @@ -333,9 +333,8 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,  	}  	if (!ring->rx_buf_pa.pages) { -		order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0);  		ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC, -				       order); +				       PAGE_ALLOC_COSTLY_ORDER);  		if (ret)  			return ret;  	} diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 4ee15ff06a44..faeb4935ef3e 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -200,29 +200,18 @@ err_exit:  static int hw_atl_a0_hw_offload_set(struct aq_hw_s *self,  				    struct aq_nic_cfg_s *aq_nic_cfg)  { -	int err = 0; -  	/* TX checksums offloads*/  	tpo_ipv4header_crc_offload_en_set(self, 1);  	tpo_tcp_udp_crc_offload_en_set(self, 1); -	if (err < 0) -		goto err_exit;  	/* RX checksums offloads*/  	rpo_ipv4header_crc_offload_en_set(self, 1);  	rpo_tcp_udp_crc_offload_en_set(self, 1); -	if (err < 0) -		goto err_exit;  	/* LSO offloads*/  	tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); -	if (err < 0) -		goto err_exit; - -	err = aq_hw_err_from_flags(self); -err_exit: -	return err; +	return aq_hw_err_from_flags(self);  }  static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 42150708191d..1bceb7358e5c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -200,25 +200,18 @@ err_exit:  static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,  				    struct aq_nic_cfg_s *aq_nic_cfg)  { -	int err = 0;  	unsigned int i;  	/* TX checksums offloads*/  	tpo_ipv4header_crc_offload_en_set(self, 1);  	tpo_tcp_udp_crc_offload_en_set(self, 1); -	if (err < 0) -		goto err_exit;  	/* RX checksums offloads*/  	rpo_ipv4header_crc_offload_en_set(self, 1);  	rpo_tcp_udp_crc_offload_en_set(self, 1); -	if (err < 0) -		goto err_exit;  	/* LSO offloads*/  	tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); -	if (err < 0) -		goto err_exit;  /* LRO offloads */  	{ @@ -245,10 +238,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,  		rpo_lro_en_set(self, aq_nic_cfg->is_lro ? 0xFFFFFFFFU : 0U);  	} -	err = aq_hw_err_from_flags(self); - -err_exit: -	return err; +	return aq_hw_err_from_flags(self);  }  static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h index b8e3d88f0879..a66aee51ab5b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h @@ -193,9 +193,6 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,  			     struct aq_hw_caps_s *aq_hw_caps,  			     u32 *regs_buff); -int hw_atl_utils_hw_get_settings(struct aq_hw_s *self, -				 struct ethtool_cmd *cmd); -  int hw_atl_utils_hw_set_power(struct aq_hw_s *self,  			      unsigned int power_state); diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 63f2deec2a52..77a1c03255de 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -1353,6 +1353,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&  		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {  		printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n"); +		err = -EIO;  		goto err_dma;  	} @@ -1366,10 +1367,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	 * pcibios_set_master to do the needed arch specific settings */  	pci_set_master(pdev); -	err = -ENOMEM;  	netdev = alloc_etherdev(sizeof(struct atl2_adapter)); -	if (!netdev) +	if (!netdev) { +		err = -ENOMEM;  		goto err_alloc_etherdev; +	}  	SET_NETDEV_DEV(netdev, &pdev->dev); @@ -1408,8 +1410,6 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (err)  		goto err_sw_init; -	err = -EIO; -  	netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;  	netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 099b374c1b17..5274501428e4 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2026,9 +2026,12 @@ static int bcm_sysport_probe(struct platform_device *pdev)  	priv->num_rx_desc_words = params->num_rx_desc_words;  	priv->irq0 = platform_get_irq(pdev, 0); -	if (!priv->is_lite) +	if (!priv->is_lite) {  		priv->irq1 = platform_get_irq(pdev, 1); -	priv->wol_irq = platform_get_irq(pdev, 2); +		priv->wol_irq = platform_get_irq(pdev, 2); +	} else { +		priv->wol_irq = platform_get_irq(pdev, 1); +	}  	if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) {  		dev_err(&pdev->dev, "invalid interrupts\n");  		ret = -EINVAL; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index eccb3d1b6abb..f619c4cac51f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1926,7 +1926,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,  	}  	/* select a non-FCoE queue */ -	return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp); +	return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);  }  void bnx2x_set_num_queues(struct bnx2x *bp) @@ -3883,15 +3883,26 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)  		/* when transmitting in a vf, start bd must hold the ethertype  		 * for fw to enforce it  		 */ +		u16 vlan_tci = 0;  #ifndef BNX2X_STOP_ON_ERROR -		if (IS_VF(bp)) +		if (IS_VF(bp)) {  #endif -			tx_start_bd->vlan_or_ethertype = -				cpu_to_le16(ntohs(eth->h_proto)); +			/* Still need to consider inband vlan for enforced */ +			if (__vlan_get_tag(skb, &vlan_tci)) { +				tx_start_bd->vlan_or_ethertype = +					cpu_to_le16(ntohs(eth->h_proto)); +			} else { +				tx_start_bd->bd_flags.as_bitfield |= +					(X_ETH_INBAND_VLAN << +					 ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT); +				tx_start_bd->vlan_or_ethertype = +					cpu_to_le16(vlan_tci); +			}  #ifndef BNX2X_STOP_ON_ERROR -		else +		} else {  			/* used by FW for packet accounting */  			tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod); +		}  #endif  	} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index a851f95c307a..349a46593abf 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -12729,7 +12729,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)  	} else {  		/* If no mc addresses are required, flush the configuration */  		rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL); -		if (rc) +		if (rc < 0)  			BNX2X_ERR("Failed to clear multicast configuration %d\n",  				  rc);  	} diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index bdfd53b46bc5..9ca994d0bab6 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -901,6 +901,8 @@ static void bnx2x_vf_flr(struct bnx2x *bp, struct bnx2x_virtf *vf)  	/* release VF resources */  	bnx2x_vf_free_resc(bp, vf); +	vf->malicious = false; +  	/* re-open the mailbox */  	bnx2x_vf_enable_mbx(bp, vf->abs_vfid);  	return; @@ -1822,9 +1824,11 @@ get_vf:  		   vf->abs_vfid, qidx);  		bnx2x_vf_handle_rss_update_eqe(bp, vf);  	case EVENT_RING_OPCODE_VF_FLR: -	case EVENT_RING_OPCODE_MALICIOUS_VF:  		/* Do nothing for now */  		return 0; +	case EVENT_RING_OPCODE_MALICIOUS_VF: +		vf->malicious = true; +		return 0;  	}  	return 0; @@ -1905,6 +1909,13 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)  			continue;  		} +		if (vf->malicious) { +			DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS), +			       "vf %d malicious so no stats for it\n", +			       vf->abs_vfid); +			continue; +		} +  		DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),  		       "add addresses for vf %d\n", vf->abs_vfid);  		for_each_vfq(vf, j) { @@ -3042,7 +3053,7 @@ void bnx2x_vf_pci_dealloc(struct bnx2x *bp)  {  	BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,  		       sizeof(struct bnx2x_vf_mbx_msg)); -	BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping, +	BNX2X_PCI_FREE(bp->pf2vf_bulletin, bp->pf2vf_bulletin_mapping,  		       sizeof(union pf_vf_bulletin));  } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h index 888d0b6632e8..53466f6cebab 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h @@ -141,6 +141,7 @@ struct bnx2x_virtf {  #define VF_RESET	3	/* VF FLR'd, pending cleanup */  	bool flr_clnup_stage;	/* true during flr cleanup */ +	bool malicious;		/* true if FW indicated so, until FLR */  	/* dma */  	dma_addr_t fw_stat_map; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index b56c54d68d5e..74e8e215524d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1301,10 +1301,11 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,  		cp_cons = NEXT_CMP(cp_cons);  	} -	if (unlikely(agg_bufs > MAX_SKB_FRAGS)) { +	if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) {  		bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs); -		netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", -			    agg_bufs, (int)MAX_SKB_FRAGS); +		if (agg_bufs > MAX_SKB_FRAGS) +			netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", +				    agg_bufs, (int)MAX_SKB_FRAGS);  		return NULL;  	} @@ -1562,6 +1563,45 @@ next_rx_no_prod:  	return rc;  } +/* In netpoll mode, if we are using a combined completion ring, we need to + * discard the rx packets and recycle the buffers. + */ +static int bnxt_force_rx_discard(struct bnxt *bp, struct bnxt_napi *bnapi, +				 u32 *raw_cons, u8 *event) +{ +	struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; +	u32 tmp_raw_cons = *raw_cons; +	struct rx_cmp_ext *rxcmp1; +	struct rx_cmp *rxcmp; +	u16 cp_cons; +	u8 cmp_type; + +	cp_cons = RING_CMP(tmp_raw_cons); +	rxcmp = (struct rx_cmp *) +			&cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + +	tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons); +	cp_cons = RING_CMP(tmp_raw_cons); +	rxcmp1 = (struct rx_cmp_ext *) +			&cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + +	if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons)) +		return -EBUSY; + +	cmp_type = RX_CMP_TYPE(rxcmp); +	if (cmp_type == CMP_TYPE_RX_L2_CMP) { +		rxcmp1->rx_cmp_cfa_code_errors_v2 |= +			cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR); +	} else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) { +		struct rx_tpa_end_cmp_ext *tpa_end1; + +		tpa_end1 = (struct rx_tpa_end_cmp_ext *)rxcmp1; +		tpa_end1->rx_tpa_end_cmp_errors_v2 |= +			cpu_to_le32(RX_TPA_END_CMP_ERRORS); +	} +	return bnxt_rx_pkt(bp, bnapi, raw_cons, event); +} +  #define BNXT_GET_EVENT_PORT(data)	\  	((data) &			\  	 ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK) @@ -1744,7 +1784,11 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)  			if (unlikely(tx_pkts > bp->tx_wake_thresh))  				rx_pkts = budget;  		} else if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) { -			rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event); +			if (likely(budget)) +				rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event); +			else +				rc = bnxt_force_rx_discard(bp, bnapi, &raw_cons, +							   &event);  			if (likely(rc >= 0))  				rx_pkts += rc;  			else if (rc == -EBUSY)	/* partial completion */ @@ -6663,12 +6707,11 @@ static void bnxt_poll_controller(struct net_device *dev)  	struct bnxt *bp = netdev_priv(dev);  	int i; -	for (i = 0; i < bp->cp_nr_rings; i++) { -		struct bnxt_irq *irq = &bp->irq_tbl[i]; +	/* Only process tx rings/combined rings in netpoll mode. */ +	for (i = 0; i < bp->tx_nr_rings; i++) { +		struct bnxt_tx_ring_info *txr = &bp->tx_ring[i]; -		disable_irq(irq->vector); -		irq->handler(irq->vector, bp->bnapi[i]); -		enable_irq(irq->vector); +		napi_schedule(&txr->bnapi->napi);  	}  }  #endif @@ -7630,8 +7673,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	dev->min_mtu = ETH_ZLEN;  	dev->max_mtu = BNXT_MAX_MTU; -	bnxt_dcb_init(bp); -  #ifdef CONFIG_BNXT_SRIOV  	init_waitqueue_head(&bp->sriov_cfg_wait);  #endif @@ -7669,6 +7710,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	bnxt_hwrm_func_qcfg(bp);  	bnxt_hwrm_port_led_qcaps(bp);  	bnxt_ethtool_init(bp); +	bnxt_dcb_init(bp);  	bnxt_set_rx_skb_mode(bp, false);  	bnxt_set_tpa_flags(bp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 3ef42dbc6327..d46a85041083 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -374,12 +374,16 @@ struct rx_tpa_end_cmp_ext {  	__le32 rx_tpa_end_cmp_errors_v2;  	#define RX_TPA_END_CMP_V2				(0x1 << 0) -	#define RX_TPA_END_CMP_ERRORS				(0x7fff << 1) +	#define RX_TPA_END_CMP_ERRORS				(0x3 << 1)  	#define RX_TPA_END_CMPL_ERRORS_SHIFT			 1  	u32 rx_tpa_end_cmp_start_opaque;  }; +#define TPA_END_ERRORS(rx_tpa_end_ext)					\ +	((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 &			\ +	 cpu_to_le32(RX_TPA_END_CMP_ERRORS)) +  #define DB_IDX_MASK						0xffffff  #define DB_IDX_VALID						(0x1 << 26)  #define DB_IRQ_DIS						(0x1 << 27) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index 46de2f8ff024..5c6dd0ce209f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -553,8 +553,10 @@ static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)  	if ((mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE))  		return 1; -	if ((mode & DCB_CAP_DCBX_HOST) && BNXT_VF(bp)) -		return 1; +	if (mode & DCB_CAP_DCBX_HOST) { +		if (BNXT_VF(bp) || (bp->flags & BNXT_FLAG_FW_LLDP_AGENT)) +			return 1; +	}  	if (mode == bp->dcbx_cap)  		return 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 38a5c6764bb5..53309f659951 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2171,9 +2171,10 @@ static int cxgb_up(struct adapter *adap)  {  	int err; +	mutex_lock(&uld_mutex);  	err = setup_sge_queues(adap);  	if (err) -		goto out; +		goto rel_lock;  	err = setup_rss(adap);  	if (err)  		goto freeq; @@ -2196,23 +2197,28 @@ static int cxgb_up(struct adapter *adap)  		if (err)  			goto irq_err;  	} +  	enable_rx(adap);  	t4_sge_start(adap);  	t4_intr_enable(adap);  	adap->flags |= FULL_INIT_DONE; +	mutex_unlock(&uld_mutex); +  	notify_ulds(adap, CXGB4_STATE_UP);  #if IS_ENABLED(CONFIG_IPV6)  	update_clip(adap);  #endif  	/* Initialize hash mac addr list*/  	INIT_LIST_HEAD(&adap->mac_hlist); - out:  	return err; +   irq_err:  	dev_err(adap->pdev_dev, "request_irq failed, err %d\n", err);   freeq:  	t4_free_sge_resources(adap); -	goto out; + rel_lock: +	mutex_unlock(&uld_mutex); +	return err;  }  static void cxgb_down(struct adapter *adapter) @@ -2771,6 +2777,9 @@ void t4_fatal_err(struct adapter *adap)  {  	int port; +	if (pci_channel_offline(adap->pdev)) +		return; +  	/* Disable the SGE since ULDs are going to free resources that  	 * could be exposed to the adapter.  RDMA MWs for example...  	 */ @@ -3882,9 +3891,10 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,  	spin_lock(&adap->stats_lock);  	for_each_port(adap, i) {  		struct net_device *dev = adap->port[i]; - -		netif_device_detach(dev); -		netif_carrier_off(dev); +		if (dev) { +			netif_device_detach(dev); +			netif_carrier_off(dev); +		}  	}  	spin_unlock(&adap->stats_lock);  	disable_interrupts(adap); @@ -3963,12 +3973,13 @@ static void eeh_resume(struct pci_dev *pdev)  	rtnl_lock();  	for_each_port(adap, i) {  		struct net_device *dev = adap->port[i]; - -		if (netif_running(dev)) { -			link_start(dev); -			cxgb_set_rxmode(dev); +		if (dev) { +			if (netif_running(dev)) { +				link_start(dev); +				cxgb_set_rxmode(dev); +			} +			netif_device_attach(dev);  		} -		netif_device_attach(dev);  	}  	rtnl_unlock();  } @@ -4516,7 +4527,7 @@ static void dummy_setup(struct net_device *dev)  	/* Initialize the device structure. */  	dev->netdev_ops = &cxgb4_mgmt_netdev_ops;  	dev->ethtool_ops = &cxgb4_mgmt_ethtool_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  }  static int config_mgmt_dev(struct pci_dev *pdev) diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index aded42b96f6d..3a34aa629f7d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -4557,8 +4557,13 @@ void t4_intr_enable(struct adapter *adapter)   */  void t4_intr_disable(struct adapter *adapter)  { -	u32 whoami = t4_read_reg(adapter, PL_WHOAMI_A); -	u32 pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ? +	u32 whoami, pf; + +	if (pci_channel_offline(adapter->pdev)) +		return; + +	whoami = t4_read_reg(adapter, PL_WHOAMI_A); +	pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?  			SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);  	t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE_A), 0); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h index fa376444e57c..f2d623a7aee0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h @@ -37,7 +37,7 @@  #define T4FW_VERSION_MAJOR 0x01  #define T4FW_VERSION_MINOR 0x10 -#define T4FW_VERSION_MICRO 0x21 +#define T4FW_VERSION_MICRO 0x2D  #define T4FW_VERSION_BUILD 0x00  #define T4FW_MIN_VERSION_MAJOR 0x01 @@ -46,7 +46,7 @@  #define T5FW_VERSION_MAJOR 0x01  #define T5FW_VERSION_MINOR 0x10 -#define T5FW_VERSION_MICRO 0x21 +#define T5FW_VERSION_MICRO 0x2D  #define T5FW_VERSION_BUILD 0x00  #define T5FW_MIN_VERSION_MAJOR 0x00 @@ -55,7 +55,7 @@  #define T6FW_VERSION_MAJOR 0x01  #define T6FW_VERSION_MINOR 0x10 -#define T6FW_VERSION_MICRO 0x21 +#define T6FW_VERSION_MICRO 0x2D  #define T6FW_VERSION_BUILD 0x00  #define T6FW_MIN_VERSION_MAJOR 0x00 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index f3a09ab55900..4eee18ce9be4 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -5078,9 +5078,11 @@ static netdev_features_t be_features_check(struct sk_buff *skb,  	struct be_adapter *adapter = netdev_priv(dev);  	u8 l4_hdr = 0; -	/* The code below restricts offload features for some tunneled packets. +	/* The code below restricts offload features for some tunneled and +	 * Q-in-Q packets.  	 * Offload features for normal (non tunnel) packets are unchanged.  	 */ +	features = vlan_features_check(skb, features);  	if (!skb->encapsulation ||  	    !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))  		return features; diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index e863ba74d005..8bb0db990c8f 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -739,6 +739,8 @@ static int ethoc_open(struct net_device *dev)  	if (ret)  		return ret; +	napi_enable(&priv->napi); +  	ethoc_init_ring(priv, dev->mem_start);  	ethoc_reset(priv); @@ -754,7 +756,6 @@ static int ethoc_open(struct net_device *dev)  	priv->old_duplex = -1;  	phy_start(dev->phydev); -	napi_enable(&priv->napi);  	if (netif_msg_ifup(priv)) {  		dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n", diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index 6ac336b546e6..1536356e2ea8 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -1174,11 +1174,17 @@ static int ftmac100_remove(struct platform_device *pdev)  	return 0;  } +static const struct of_device_id ftmac100_of_ids[] = { +	{ .compatible = "andestech,atmac100" }, +	{ } +}; +  static struct platform_driver ftmac100_driver = {  	.probe		= ftmac100_probe,  	.remove		= ftmac100_remove,  	.driver		= {  		.name	= DRV_NAME, +		.of_match_table = ftmac100_of_ids  	},  }; @@ -1202,3 +1208,4 @@ module_exit(ftmac100_exit);  MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");  MODULE_DESCRIPTION("FTMAC100 driver");  MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, ftmac100_of_ids); diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 9a520e4f0df9..290ad0563320 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2647,7 +2647,7 @@ static int dpaa_eth_probe(struct platform_device *pdev)  	priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */  	/* device used for DMA mapping */ -	arch_setup_dma_ops(dev, 0, 0, NULL, false); +	set_dma_ops(dev, get_dma_ops(&pdev->dev));  	err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));  	if (err) {  		dev_err(dev, "dma_coerce_mask_and_coherent() failed\n"); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 56a563f90b0b..f7c8649fd28f 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3192,7 +3192,7 @@ static int fec_reset_phy(struct platform_device *pdev)  {  	int err, phy_reset;  	bool active_high = false; -	int msec = 1; +	int msec = 1, phy_post_delay = 0;  	struct device_node *np = pdev->dev.of_node;  	if (!np) @@ -3209,6 +3209,11 @@ static int fec_reset_phy(struct platform_device *pdev)  	else if (!gpio_is_valid(phy_reset))  		return 0; +	err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay); +	/* valid reset duration should be less than 1s */ +	if (!err && phy_post_delay > 1000) +		return -EINVAL; +  	active_high = of_property_read_bool(np, "phy-reset-active-high");  	err = devm_gpio_request_one(&pdev->dev, phy_reset, @@ -3226,6 +3231,15 @@ static int fec_reset_phy(struct platform_device *pdev)  	gpio_set_value_cansleep(phy_reset, !active_high); +	if (!phy_post_delay) +		return 0; + +	if (phy_post_delay > 20) +		msleep(phy_post_delay); +	else +		usleep_range(phy_post_delay * 1000, +			     phy_post_delay * 1000 + 1000); +  	return 0;  }  #else /* CONFIG_OF */ diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig index dc0850b3b517..8870a9a798ca 100644 --- a/drivers/net/ethernet/freescale/fman/Kconfig +++ b/drivers/net/ethernet/freescale/fman/Kconfig @@ -2,6 +2,7 @@ config FSL_FMAN  	tristate "FMan support"  	depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST  	select GENERIC_ALLOCATOR +	depends on HAS_DMA  	select PHYLIB  	default n  	help diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 0b31f8502ada..6e67d22fd0d5 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -623,6 +623,8 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,  		goto no_mem;  	} +	set_dma_ops(&pdev->dev, get_dma_ops(priv->dev)); +  	ret = platform_device_add_data(pdev, &data, sizeof(data));  	if (ret)  		goto err; diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 446c7b374ff5..a10de1e9c157 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -381,7 +381,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)  {  	const struct of_device_id *id =  		of_match_device(fsl_pq_mdio_match, &pdev->dev); -	const struct fsl_pq_mdio_data *data = id->data; +	const struct fsl_pq_mdio_data *data;  	struct device_node *np = pdev->dev.of_node;  	struct resource res;  	struct device_node *tbi; @@ -389,6 +389,13 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)  	struct mii_bus *new_bus;  	int err; +	if (!id) { +		dev_err(&pdev->dev, "Failed to match device\n"); +		return -ENODEV; +	} + +	data = id->data; +  	dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible);  	new_bus = mdiobus_alloc_size(sizeof(*priv)); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index b8fab149690f..e95795b3c841 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -288,9 +288,15 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)  		/* Force 1000M Link, Default is 0x0200 */  		phy_write(phy_dev, 7, 0x20C); -		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0); -		/* Enable PHY loop-back */ +		/* Powerup Fiber */ +		phy_write(phy_dev, HNS_PHY_PAGE_REG, 1); +		val = phy_read(phy_dev, COPPER_CONTROL_REG); +		val &= ~PHY_POWER_DOWN; +		phy_write(phy_dev, COPPER_CONTROL_REG, val); + +		/* Enable Phy Loopback */ +		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);  		val = phy_read(phy_dev, COPPER_CONTROL_REG);  		val |= PHY_LOOP_BACK;  		val &= ~PHY_POWER_DOWN; @@ -299,6 +305,12 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)  		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);  		phy_write(phy_dev, 1, 0x400);  		phy_write(phy_dev, 7, 0x200); + +		phy_write(phy_dev, HNS_PHY_PAGE_REG, 1); +		val = phy_read(phy_dev, COPPER_CONTROL_REG); +		val |= PHY_POWER_DOWN; +		phy_write(phy_dev, COPPER_CONTROL_REG, val); +  		phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);  		phy_write(phy_dev, 9, 0xF00); diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 508923f39ccf..259e69a52ec5 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -343,6 +343,7 @@ static int emac_reset(struct emac_instance *dev)  {  	struct emac_regs __iomem *p = dev->emacp;  	int n = 20; +	bool __maybe_unused try_internal_clock = false;  	DBG(dev, "reset" NL); @@ -355,6 +356,7 @@ static int emac_reset(struct emac_instance *dev)  	}  #ifdef CONFIG_PPC_DCR_NATIVE +do_retry:  	/*  	 * PPC460EX/GT Embedded Processor Advanced User's Manual  	 * section 28.10.1 Mode Register 0 (EMACx_MR0) states: @@ -362,10 +364,19 @@ static int emac_reset(struct emac_instance *dev)  	 * of the EMAC. If none is present, select the internal clock  	 * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).  	 * After a soft reset, select the external clock. +	 * +	 * The AR8035-A PHY Meraki MR24 does not provide a TX Clk if the +	 * ethernet cable is not attached. This causes the reset to timeout +	 * and the PHY detection code in emac_init_phy() is unable to +	 * communicate and detect the AR8035-A PHY. As a result, the emac +	 * driver bails out early and the user has no ethernet. +	 * In order to stay compatible with existing configurations, the +	 * driver will temporarily switch to the internal clock, after +	 * the first reset fails.  	 */  	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { -		if (dev->phy_address == 0xffffffff && -		    dev->phy_map == 0xffffffff) { +		if (try_internal_clock || (dev->phy_address == 0xffffffff && +					   dev->phy_map == 0xffffffff)) {  			/* No PHY: select internal loop clock before reset */  			dcri_clrset(SDR0, SDR0_ETH_CFG,  				    0, SDR0_ETH_CFG_ECS << dev->cell_index); @@ -383,8 +394,15 @@ static int emac_reset(struct emac_instance *dev)  #ifdef CONFIG_PPC_DCR_NATIVE  	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { -		if (dev->phy_address == 0xffffffff && -		    dev->phy_map == 0xffffffff) { +		if (!n && !try_internal_clock) { +			/* first attempt has timed out. */ +			n = 20; +			try_internal_clock = true; +			goto do_retry; +		} + +		if (try_internal_clock || (dev->phy_address == 0xffffffff && +					   dev->phy_map == 0xffffffff)) {  			/* No PHY: restore external clock source after reset */  			dcri_clrset(SDR0, SDR0_ETH_CFG,  				    SDR0_ETH_CFG_ECS << dev->cell_index, 0); @@ -2460,20 +2478,24 @@ static int emac_mii_bus_reset(struct mii_bus *bus)  	return emac_reset(dev);  } +static int emac_mdio_phy_start_aneg(struct mii_phy *phy, +				    struct phy_device *phy_dev) +{ +	phy_dev->autoneg = phy->autoneg; +	phy_dev->speed = phy->speed; +	phy_dev->duplex = phy->duplex; +	phy_dev->advertising = phy->advertising; +	return phy_start_aneg(phy_dev); +} +  static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise)  {  	struct net_device *ndev = phy->dev;  	struct emac_instance *dev = netdev_priv(ndev); -	dev->phy.autoneg = AUTONEG_ENABLE; -	dev->phy.speed = SPEED_1000; -	dev->phy.duplex = DUPLEX_FULL; -	dev->phy.advertising = advertise;  	phy->autoneg = AUTONEG_ENABLE; -	phy->speed = dev->phy.speed; -	phy->duplex = dev->phy.duplex;  	phy->advertising = advertise; -	return phy_start_aneg(dev->phy_dev); +	return emac_mdio_phy_start_aneg(phy, dev->phy_dev);  }  static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd) @@ -2481,13 +2503,10 @@ static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)  	struct net_device *ndev = phy->dev;  	struct emac_instance *dev = netdev_priv(ndev); -	dev->phy.autoneg =  AUTONEG_DISABLE; -	dev->phy.speed = speed; -	dev->phy.duplex = fd;  	phy->autoneg = AUTONEG_DISABLE;  	phy->speed = speed;  	phy->duplex = fd; -	return phy_start_aneg(dev->phy_dev); +	return emac_mdio_phy_start_aneg(phy, dev->phy_dev);  }  static int emac_mdio_poll_link(struct mii_phy *phy) @@ -2509,16 +2528,17 @@ static int emac_mdio_read_link(struct mii_phy *phy)  {  	struct net_device *ndev = phy->dev;  	struct emac_instance *dev = netdev_priv(ndev); +	struct phy_device *phy_dev = dev->phy_dev;  	int res; -	res = phy_read_status(dev->phy_dev); +	res = phy_read_status(phy_dev);  	if (res)  		return res; -	dev->phy.speed = phy->speed; -	dev->phy.duplex = phy->duplex; -	dev->phy.pause = phy->pause; -	dev->phy.asym_pause = phy->asym_pause; +	phy->speed = phy_dev->speed; +	phy->duplex = phy_dev->duplex; +	phy->pause = phy_dev->pause; +	phy->asym_pause = phy_dev->asym_pause;  	return 0;  } @@ -2528,13 +2548,6 @@ static int emac_mdio_init_phy(struct mii_phy *phy)  	struct emac_instance *dev = netdev_priv(ndev);  	phy_start(dev->phy_dev); -	dev->phy.autoneg = phy->autoneg; -	dev->phy.speed = phy->speed; -	dev->phy.duplex = phy->duplex; -	dev->phy.advertising = phy->advertising; -	dev->phy.pause = phy->pause; -	dev->phy.asym_pause = phy->asym_pause; -  	return phy_init_hw(dev->phy_dev);  } diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 4f2d329dba99..c0fbeb387db4 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -81,7 +81,7 @@  static const char ibmvnic_driver_name[] = "ibmvnic";  static const char ibmvnic_driver_string[] = "IBM System i/p Virtual NIC Driver"; -MODULE_AUTHOR("Santiago Leon <santi_leon@yahoo.com>"); +MODULE_AUTHOR("Santiago Leon");  MODULE_DESCRIPTION("IBM System i/p Virtual NIC Driver");  MODULE_LICENSE("GPL");  MODULE_VERSION(IBMVNIC_DRIVER_VERSION); @@ -1468,6 +1468,11 @@ static void ibmvnic_netpoll_controller(struct net_device *dev)  }  #endif +static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu) +{ +	return -EOPNOTSUPP; +} +  static const struct net_device_ops ibmvnic_netdev_ops = {  	.ndo_open		= ibmvnic_open,  	.ndo_stop		= ibmvnic_close, @@ -1479,6 +1484,7 @@ static const struct net_device_ops ibmvnic_netdev_ops = {  #ifdef CONFIG_NET_POLL_CONTROLLER  	.ndo_poll_controller	= ibmvnic_netpoll_controller,  #endif +	.ndo_change_mtu		= ibmvnic_change_mtu,  };  /* ethtool functions */ diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index cdde3cc28fb5..44d9610f7a15 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -399,6 +399,7 @@ struct i40e_pf {  #define I40E_FLAG_RX_CSUM_ENABLED		BIT_ULL(1)  #define I40E_FLAG_MSI_ENABLED			BIT_ULL(2)  #define I40E_FLAG_MSIX_ENABLED			BIT_ULL(3) +#define I40E_FLAG_HW_ATR_EVICT_ENABLED		BIT_ULL(4)  #define I40E_FLAG_RSS_ENABLED			BIT_ULL(6)  #define I40E_FLAG_VMDQ_ENABLED			BIT_ULL(7)  #define I40E_FLAG_IWARP_ENABLED			BIT_ULL(10) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 7a8eb486b9ea..894c8e57ba00 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -224,7 +224,7 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {  	I40E_PRIV_FLAG("LinkPolling", I40E_FLAG_LINK_POLLING_ENABLED, 0),  	I40E_PRIV_FLAG("flow-director-atr", I40E_FLAG_FD_ATR_ENABLED, 0),  	I40E_PRIV_FLAG("veb-stats", I40E_FLAG_VEB_STATS_ENABLED, 0), -	I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_CAPABLE, 0), +	I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_ENABLED, 0),  	I40E_PRIV_FLAG("legacy-rx", I40E_FLAG_LEGACY_RX, 0),  }; @@ -4092,7 +4092,7 @@ flags_complete:  	/* Only allow ATR evict on hardware that is capable of handling it */  	if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) -		pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE; +		pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_ENABLED;  	if (changed_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT) {  		u16 sw_flags = 0, valid_flags = 0; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d5c9c9e06ff5..a7a4b28b4144 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -295,7 +295,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)   **/  void i40e_service_event_schedule(struct i40e_pf *pf)  { -	if (!test_bit(__I40E_VSI_DOWN, pf->state) && +	if (!test_bit(__I40E_DOWN, pf->state) &&  	    !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))  		queue_work(i40e_wq, &pf->service_task);  } @@ -3611,7 +3611,7 @@ static irqreturn_t i40e_intr(int irq, void *data)  		 * this is not a performance path and napi_schedule()  		 * can deal with rescheduling.  		 */ -		if (!test_bit(__I40E_VSI_DOWN, pf->state)) +		if (!test_bit(__I40E_DOWN, pf->state))  			napi_schedule_irqoff(&q_vector->napi);  	} @@ -3687,7 +3687,7 @@ static irqreturn_t i40e_intr(int irq, void *data)  enable_intr:  	/* re-enable interrupt causes */  	wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask); -	if (!test_bit(__I40E_VSI_DOWN, pf->state)) { +	if (!test_bit(__I40E_DOWN, pf->state)) {  		i40e_service_event_schedule(pf);  		i40e_irq_dynamic_enable_icr0(pf, false);  	} @@ -6203,7 +6203,7 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)  {  	/* if interface is down do nothing */ -	if (test_bit(__I40E_VSI_DOWN, pf->state)) +	if (test_bit(__I40E_DOWN, pf->state))  		return;  	if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state)) @@ -6344,7 +6344,7 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)  	int i;  	/* if interface is down do nothing */ -	if (test_bit(__I40E_VSI_DOWN, pf->state) || +	if (test_bit(__I40E_DOWN, pf->state) ||  	    test_bit(__I40E_CONFIG_BUSY, pf->state))  		return; @@ -6399,9 +6399,9 @@ static void i40e_reset_subtask(struct i40e_pf *pf)  		reset_flags |= BIT(__I40E_GLOBAL_RESET_REQUESTED);  		clear_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state);  	} -	if (test_bit(__I40E_VSI_DOWN_REQUESTED, pf->state)) { -		reset_flags |= BIT(__I40E_VSI_DOWN_REQUESTED); -		clear_bit(__I40E_VSI_DOWN_REQUESTED, pf->state); +	if (test_bit(__I40E_DOWN_REQUESTED, pf->state)) { +		reset_flags |= BIT(__I40E_DOWN_REQUESTED); +		clear_bit(__I40E_DOWN_REQUESTED, pf->state);  	}  	/* If there's a recovery already waiting, it takes @@ -6415,7 +6415,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf)  	/* If we're already down or resetting, just bail */  	if (reset_flags && -	    !test_bit(__I40E_VSI_DOWN, pf->state) && +	    !test_bit(__I40E_DOWN, pf->state) &&  	    !test_bit(__I40E_CONFIG_BUSY, pf->state)) {  		rtnl_lock();  		i40e_do_reset(pf, reset_flags, true); @@ -7002,7 +7002,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)  	u32 val;  	int v; -	if (test_bit(__I40E_VSI_DOWN, pf->state)) +	if (test_bit(__I40E_DOWN, pf->state))  		goto clear_recovery;  	dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n"); @@ -8821,11 +8821,12 @@ static int i40e_sw_init(struct i40e_pf *pf)  		    (pf->hw.aq.api_min_ver > 4))) {  		/* Supported in FW API version higher than 1.4 */  		pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE; -		pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE; -	} else { -		pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;  	} +	/* Enable HW ATR eviction if possible */ +	if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) +		pf->flags |= I40E_FLAG_HW_ATR_EVICT_ENABLED; +  	pf->eeprom_version = 0xDEAD;  	pf->lan_veb = I40E_NO_VEB;  	pf->lan_vsi = I40E_NO_VSI; @@ -9767,7 +9768,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)  		return -ENODEV;  	}  	if (vsi == pf->vsi[pf->lan_vsi] && -	    !test_bit(__I40E_VSI_DOWN, pf->state)) { +	    !test_bit(__I40E_DOWN, pf->state)) {  		dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");  		return -ENODEV;  	} @@ -11003,7 +11004,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	}  	pf->next_vsi = 0;  	pf->pdev = pdev; -	set_bit(__I40E_VSI_DOWN, pf->state); +	set_bit(__I40E_DOWN, pf->state);  	hw = &pf->hw;  	hw->back = pf; @@ -11293,7 +11294,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	 * before setting up the misc vector or we get a race and the vector  	 * ends up disabled forever.  	 */ -	clear_bit(__I40E_VSI_DOWN, pf->state); +	clear_bit(__I40E_DOWN, pf->state);  	/* In case of MSIX we are going to setup the misc vector right here  	 * to handle admin queue events etc. In case of legacy and MSI @@ -11448,7 +11449,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	/* Unwind what we've done if something failed in the setup */  err_vsis: -	set_bit(__I40E_VSI_DOWN, pf->state); +	set_bit(__I40E_DOWN, pf->state);  	i40e_clear_interrupt_scheme(pf);  	kfree(pf->vsi);  err_switch_setup: @@ -11500,7 +11501,7 @@ static void i40e_remove(struct pci_dev *pdev)  	/* no more scheduling of any task */  	set_bit(__I40E_SUSPENDED, pf->state); -	set_bit(__I40E_VSI_DOWN, pf->state); +	set_bit(__I40E_DOWN, pf->state);  	if (pf->service_timer.data)  		del_timer_sync(&pf->service_timer);  	if (pf->service_task.func) @@ -11740,7 +11741,7 @@ static void i40e_shutdown(struct pci_dev *pdev)  	struct i40e_hw *hw = &pf->hw;  	set_bit(__I40E_SUSPENDED, pf->state); -	set_bit(__I40E_VSI_DOWN, pf->state); +	set_bit(__I40E_DOWN, pf->state);  	rtnl_lock();  	i40e_prep_for_reset(pf, true);  	rtnl_unlock(); @@ -11789,7 +11790,7 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)  	int retval = 0;  	set_bit(__I40E_SUSPENDED, pf->state); -	set_bit(__I40E_VSI_DOWN, pf->state); +	set_bit(__I40E_DOWN, pf->state);  	if (pf->wol_en && (pf->flags & I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE))  		i40e_enable_mc_magic_wake(pf); @@ -11841,7 +11842,7 @@ static int i40e_resume(struct pci_dev *pdev)  	/* handling the reset will rebuild the device state */  	if (test_and_clear_bit(__I40E_SUSPENDED, pf->state)) { -		clear_bit(__I40E_VSI_DOWN, pf->state); +		clear_bit(__I40E_DOWN, pf->state);  		rtnl_lock();  		i40e_reset_and_rebuild(pf, false, true);  		rtnl_unlock(); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 29321a6167a6..77115c25d96f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1854,7 +1854,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,  #if (PAGE_SIZE < 8192)  	unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;  #else -	unsigned int truesize = SKB_DATA_ALIGN(size); +	unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + +				SKB_DATA_ALIGN(I40E_SKB_PAD + size);  #endif  	struct sk_buff *skb; @@ -2340,7 +2341,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,  	/* Due to lack of space, no more new filters can be programmed */  	if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))  		return; -	if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) { +	if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) {  		/* HW ATR eviction will take care of removing filters on FIN  		 * and RST packets.  		 */ @@ -2402,7 +2403,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,  			I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &  			I40E_TXD_FLTR_QW1_CNTINDEX_MASK; -	if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) +	if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED)  		dtype_cmd |= I40E_TXD_FLTR_QW1_ATR_MASK;  	fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 95c23fbaa211..0fb38ca78900 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -3017,10 +3017,12 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,  					   VLAN_VID_MASK));  	} +	spin_unlock_bh(&vsi->mac_filter_hash_lock);  	if (vlan_id || qos)  		ret = i40e_vsi_add_pvid(vsi, vlanprio);  	else  		i40e_vsi_remove_pvid(vsi); +	spin_lock_bh(&vsi->mac_filter_hash_lock);  	if (vlan_id) {  		dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n", diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index dfe241a12ad0..12b02e530503 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1190,7 +1190,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,  #if (PAGE_SIZE < 8192)  	unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;  #else -	unsigned int truesize = SKB_DATA_ALIGN(size); +	unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + +				SKB_DATA_ALIGN(I40E_SKB_PAD + size);  #endif  	struct sk_buff *skb; diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index 9b875d776b29..33c901622ed5 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -3719,7 +3719,7 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,  				    dma_addr_t *dma_addr,  				    phys_addr_t *phys_addr)  { -	int cpu = smp_processor_id(); +	int cpu = get_cpu();  	*dma_addr = mvpp2_percpu_read(priv, cpu,  				      MVPP2_BM_PHY_ALLOC_REG(bm_pool->id)); @@ -3740,6 +3740,8 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,  		if (sizeof(phys_addr_t) == 8)  			*phys_addr |= (u64)phys_addr_highbits << 32;  	} + +	put_cpu();  }  /* Free all buffers from the pool */ @@ -3920,18 +3922,12 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)  	return bm;  } -/* Get pool number from a BM cookie */ -static inline int mvpp2_bm_cookie_pool_get(unsigned long cookie) -{ -	return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF; -} -  /* Release buffer to BM */  static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,  				     dma_addr_t buf_dma_addr,  				     phys_addr_t buf_phys_addr)  { -	int cpu = smp_processor_id(); +	int cpu = get_cpu();  	if (port->priv->hw_version == MVPP22) {  		u32 val = 0; @@ -3958,15 +3954,15 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,  			   MVPP2_BM_VIRT_RLS_REG, buf_phys_addr);  	mvpp2_percpu_write(port->priv, cpu,  			   MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr); + +	put_cpu();  }  /* Refill BM pool */ -static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm, +static void mvpp2_pool_refill(struct mvpp2_port *port, int pool,  			      dma_addr_t dma_addr,  			      phys_addr_t phys_addr)  { -	int pool = mvpp2_bm_cookie_pool_get(bm); -  	mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);  } @@ -4186,8 +4182,6 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port)  {  	u32 val; -	return; -  	/* Only GOP port 0 has an XLG MAC */  	if (port->gop_id == 0) {  		val = readl(port->base + MVPP22_XLG_CTRL3_REG); @@ -4515,21 +4509,6 @@ static void mvpp2_rxq_offset_set(struct mvpp2_port *port,  	mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);  } -/* Obtain BM cookie information from descriptor */ -static u32 mvpp2_bm_cookie_build(struct mvpp2_port *port, -				 struct mvpp2_rx_desc *rx_desc) -{ -	int cpu = smp_processor_id(); -	int pool; - -	pool = (mvpp2_rxdesc_status_get(port, rx_desc) & -		MVPP2_RXD_BM_POOL_ID_MASK) >> -		MVPP2_RXD_BM_POOL_ID_OFFS; - -	return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) | -	       ((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS); -} -  /* Tx descriptors helper methods */  /* Get pointer to next Tx descriptor to be processed (send) by HW */ @@ -4757,7 +4736,7 @@ static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)  static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,  				   struct mvpp2_rx_queue *rxq)  { -	int cpu = smp_processor_id(); +	int cpu = get_cpu();  	if (rxq->pkts_coal > MVPP2_OCCUPIED_THRESH_MASK)  		rxq->pkts_coal = MVPP2_OCCUPIED_THRESH_MASK; @@ -4765,6 +4744,8 @@ static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_THRESH_REG,  			   rxq->pkts_coal); + +	put_cpu();  }  static u32 mvpp2_usec_to_cycles(u32 usec, unsigned long clk_hz) @@ -4945,7 +4926,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,  	mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);  	/* Set Rx descriptors queue starting address - indirect access */ -	cpu = smp_processor_id(); +	cpu = get_cpu();  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);  	if (port->priv->hw_version == MVPP21)  		rxq_dma = rxq->descs_dma; @@ -4954,6 +4935,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, rxq_dma);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_INDEX_REG, 0); +	put_cpu();  	/* Set Offset */  	mvpp2_rxq_offset_set(port, rxq->id, NET_SKB_PAD); @@ -4980,9 +4962,13 @@ static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,  	for (i = 0; i < rx_received; i++) {  		struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq); -		u32 bm = mvpp2_bm_cookie_build(port, rx_desc); +		u32 status = mvpp2_rxdesc_status_get(port, rx_desc); +		int pool; + +		pool = (status & MVPP2_RXD_BM_POOL_ID_MASK) >> +			MVPP2_RXD_BM_POOL_ID_OFFS; -		mvpp2_pool_refill(port, bm, +		mvpp2_pool_refill(port, pool,  				  mvpp2_rxdesc_dma_addr_get(port, rx_desc),  				  mvpp2_rxdesc_cookie_get(port, rx_desc));  	} @@ -5012,10 +4998,11 @@ static void mvpp2_rxq_deinit(struct mvpp2_port *port,  	 * free descriptor number  	 */  	mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0); -	cpu = smp_processor_id(); +	cpu = get_cpu();  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, 0);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, 0); +	put_cpu();  }  /* Create and initialize a Tx queue */ @@ -5038,7 +5025,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,  	txq->last_desc = txq->size - 1;  	/* Set Tx descriptors queue starting address - indirect access */ -	cpu = smp_processor_id(); +	cpu = get_cpu();  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG,  			   txq->descs_dma); @@ -5063,6 +5050,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG,  			   MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |  			   MVPP2_PREF_BUF_THRESH(desc_per_txq / 2)); +	put_cpu();  	/* WRR / EJP configuration - indirect access */  	tx_port_num = mvpp2_egress_port(port); @@ -5133,10 +5121,11 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,  	mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);  	/* Set Tx descriptors queue starting address and size */ -	cpu = smp_processor_id(); +	cpu = get_cpu();  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG, 0);  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_SIZE_REG, 0); +	put_cpu();  }  /* Cleanup Tx ports */ @@ -5146,7 +5135,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)  	int delay, pending, cpu;  	u32 val; -	cpu = smp_processor_id(); +	cpu = get_cpu();  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);  	val = mvpp2_percpu_read(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG);  	val |= MVPP2_TXQ_DRAIN_EN_MASK; @@ -5173,6 +5162,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)  	val &= ~MVPP2_TXQ_DRAIN_EN_MASK;  	mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG, val); +	put_cpu();  	for_each_present_cpu(cpu) {  		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu); @@ -5420,7 +5410,7 @@ static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,  /* Reuse skb if possible, or allocate a new skb and add it to BM pool */  static int mvpp2_rx_refill(struct mvpp2_port *port, -			   struct mvpp2_bm_pool *bm_pool, u32 bm) +			   struct mvpp2_bm_pool *bm_pool, int pool)  {  	dma_addr_t dma_addr;  	phys_addr_t phys_addr; @@ -5432,7 +5422,7 @@ static int mvpp2_rx_refill(struct mvpp2_port *port,  	if (!buf)  		return -ENOMEM; -	mvpp2_pool_refill(port, bm, dma_addr, phys_addr); +	mvpp2_pool_refill(port, pool, dma_addr, phys_addr);  	return 0;  } @@ -5490,7 +5480,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,  		unsigned int frag_size;  		dma_addr_t dma_addr;  		phys_addr_t phys_addr; -		u32 bm, rx_status; +		u32 rx_status;  		int pool, rx_bytes, err;  		void *data; @@ -5502,8 +5492,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,  		phys_addr = mvpp2_rxdesc_cookie_get(port, rx_desc);  		data = (void *)phys_to_virt(phys_addr); -		bm = mvpp2_bm_cookie_build(port, rx_desc); -		pool = mvpp2_bm_cookie_pool_get(bm); +		pool = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >> +			MVPP2_RXD_BM_POOL_ID_OFFS;  		bm_pool = &port->priv->bm_pools[pool];  		/* In case of an error, release the requested buffer pointer @@ -5516,7 +5506,7 @@ err_drop_frame:  			dev->stats.rx_errors++;  			mvpp2_rx_error(port, rx_desc);  			/* Return the buffer to the pool */ -			mvpp2_pool_refill(port, bm, dma_addr, phys_addr); +			mvpp2_pool_refill(port, pool, dma_addr, phys_addr);  			continue;  		} @@ -5531,7 +5521,7 @@ err_drop_frame:  			goto err_drop_frame;  		} -		err = mvpp2_rx_refill(port, bm_pool, bm); +		err = mvpp2_rx_refill(port, bm_pool, pool);  		if (err) {  			netdev_err(port->dev, "failed to refill BM pools\n");  			goto err_drop_frame; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index ae5fdc2df654..ffbcb27c05e5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1562,11 +1562,6 @@ static int mlx4_en_flow_replace(struct net_device *dev,  		qpn = priv->drop_qp.qpn;  	else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {  		qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1); -		if (qpn < priv->rss_map.base_qpn || -		    qpn >= priv->rss_map.base_qpn + priv->rx_ring_num) { -			en_warn(priv, "rxnfc: QP (0x%x) doesn't exist\n", qpn); -			return -EINVAL; -		}  	} else {  		if (cmd->fs.ring_cookie >= priv->rx_ring_num) {  			en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n", diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 703205475524..83aab1e4c8c8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2862,12 +2862,10 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)  	int port = 0;  	if (msi_x) { -		int nreq = dev->caps.num_ports * num_online_cpus() + 1; - -		nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, -			     nreq); -		if (nreq > MAX_MSIX) -			nreq = MAX_MSIX; +		int nreq = min3(dev->caps.num_ports * +				(int)num_online_cpus() + 1, +				dev->caps.num_eqs - dev->caps.reserved_eqs, +				MAX_MSIX);  		entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);  		if (!entries) diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 1a670b681555..0710b3677464 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -35,6 +35,7 @@  #include <linux/etherdevice.h>  #include <linux/mlx4/cmd.h> +#include <linux/mlx4/qp.h>  #include <linux/export.h>  #include "mlx4.h" @@ -985,16 +986,21 @@ int mlx4_flow_attach(struct mlx4_dev *dev,  	if (IS_ERR(mailbox))  		return PTR_ERR(mailbox); +	if (!mlx4_qp_lookup(dev, rule->qpn)) { +		mlx4_err_rule(dev, "QP doesn't exist\n", rule); +		ret = -EINVAL; +		goto out; +	} +  	trans_rule_ctrl_to_hw(rule, mailbox->buf);  	size += sizeof(struct mlx4_net_trans_rule_hw_ctrl);  	list_for_each_entry(cur, &rule->list, list) {  		ret = parse_trans_rule(dev, cur, mailbox->buf + size); -		if (ret < 0) { -			mlx4_free_cmd_mailbox(dev, mailbox); -			return ret; -		} +		if (ret < 0) +			goto out; +  		size += ret;  	} @@ -1021,6 +1027,7 @@ int mlx4_flow_attach(struct mlx4_dev *dev,  		}  	} +out:  	mlx4_free_cmd_mailbox(dev, mailbox);  	return ret; diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 2d6abd4662b1..5a310d313e94 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -384,6 +384,19 @@ static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)  		__mlx4_qp_free_icm(dev, qpn);  } +struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn) +{ +	struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; +	struct mlx4_qp *qp; + +	spin_lock(&qp_table->lock); + +	qp = __mlx4_qp_lookup(dev, qpn); + +	spin_unlock(&qp_table->lock); +	return qp; +} +  int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp)  {  	struct mlx4_priv *priv = mlx4_priv(dev); @@ -471,6 +484,12 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,  	}  	if (attr & MLX4_UPDATE_QP_QOS_VPORT) { +		if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP)) { +			mlx4_warn(dev, "Granular QoS per VF is not enabled\n"); +			err = -EOPNOTSUPP; +			goto out; +		} +  		qp_mask |= 1ULL << MLX4_UPD_QP_MASK_QOS_VPP;  		cmd->qp_context.qos_vport = params->qos_vport;  	} diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 07516545474f..812783865205 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -5255,6 +5255,13 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)  	mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);  } +static void update_qos_vpp(struct mlx4_update_qp_context *ctx, +			   struct mlx4_vf_immed_vlan_work *work) +{ +	ctx->qp_mask |= cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_QOS_VPP); +	ctx->qp_context.qos_vport = work->qos_vport; +} +  void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)  {  	struct mlx4_vf_immed_vlan_work *work = @@ -5369,11 +5376,10 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)  					qp->sched_queue & 0xC7;  				upd_context->qp_context.pri_path.sched_queue |=  					((work->qos & 0x7) << 3); -				upd_context->qp_mask |= -					cpu_to_be64(1ULL << -						    MLX4_UPD_QP_MASK_QOS_VPP); -				upd_context->qp_context.qos_vport = -					work->qos_vport; + +				if (dev->caps.flags2 & +				    MLX4_DEV_CAP_FLAG2_QOS_VPP) +					update_qos_vpp(upd_context, work);  			}  			err = mlx4_cmd(dev, mailbox->dma, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index fc52d742b7f7..27251a78075c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -13,7 +13,7 @@ config MLX5_CORE  config MLX5_CORE_EN  	bool "Mellanox Technologies ConnectX-4 Ethernet support" -	depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE +	depends on NETDEVICES && ETHERNET && INET && PCI && MLX5_CORE  	depends on IPV6=y || IPV6=n || MLX5_CORE=m  	imply PTP_1588_CLOCK  	default n diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 5bdaf3d545b2..10d282841f5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -774,7 +774,7 @@ static void cb_timeout_handler(struct work_struct *work)  	mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",  		       mlx5_command_str(msg_to_opcode(ent->in)),  		       msg_to_opcode(ent->in)); -	mlx5_cmd_comp_handler(dev, 1UL << ent->idx); +	mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);  }  static void cmd_work_handler(struct work_struct *work) @@ -804,6 +804,7 @@ static void cmd_work_handler(struct work_struct *work)  	}  	cmd->ent_arr[ent->idx] = ent; +	set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);  	lay = get_inst(cmd, ent->idx);  	ent->lay = lay;  	memset(lay, 0, sizeof(*lay)); @@ -825,6 +826,20 @@ static void cmd_work_handler(struct work_struct *work)  	if (ent->callback)  		schedule_delayed_work(&ent->cb_timeout_work, cb_timeout); +	/* Skip sending command to fw if internal error */ +	if (pci_channel_offline(dev->pdev) || +	    dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { +		u8 status = 0; +		u32 drv_synd; + +		ent->ret = mlx5_internal_err_ret_value(dev, msg_to_opcode(ent->in), &drv_synd, &status); +		MLX5_SET(mbox_out, ent->out, status, status); +		MLX5_SET(mbox_out, ent->out, syndrome, drv_synd); + +		mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true); +		return; +	} +  	/* ring doorbell after the descriptor is valid */  	mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);  	wmb(); @@ -835,7 +850,7 @@ static void cmd_work_handler(struct work_struct *work)  		poll_timeout(ent);  		/* make sure we read the descriptor after ownership is SW */  		rmb(); -		mlx5_cmd_comp_handler(dev, 1UL << ent->idx); +		mlx5_cmd_comp_handler(dev, 1UL << ent->idx, (ent->ret == -ETIMEDOUT));  	}  } @@ -879,7 +894,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)  		wait_for_completion(&ent->done);  	} else if (!wait_for_completion_timeout(&ent->done, timeout)) {  		ent->ret = -ETIMEDOUT; -		mlx5_cmd_comp_handler(dev, 1UL << ent->idx); +		mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);  	}  	err = ent->ret; @@ -1375,7 +1390,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)  	}  } -void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec) +void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced)  {  	struct mlx5_cmd *cmd = &dev->cmd;  	struct mlx5_cmd_work_ent *ent; @@ -1395,6 +1410,19 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)  			struct semaphore *sem;  			ent = cmd->ent_arr[i]; + +			/* if we already completed the command, ignore it */ +			if (!test_and_clear_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, +						&ent->state)) { +				/* only real completion can free the cmd slot */ +				if (!forced) { +					mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n", +						      ent->idx); +					free_ent(cmd, ent->idx); +				} +				continue; +			} +  			if (ent->callback)  				cancel_delayed_work(&ent->cb_timeout_work);  			if (ent->page_queue) @@ -1417,7 +1445,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)  				mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",  					      ent->ret, deliv_status_to_str(ent->status), ent->status);  			} -			free_ent(cmd, ent->idx); + +			/* only real completion will free the entry slot */ +			if (!forced) +				free_ent(cmd, ent->idx);  			if (ent->callback) {  				ds = ent->ts2 - ent->ts1; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 0099a3e397bc..944fc1742464 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -458,13 +458,15 @@ struct mlx5e_mpw_info {  struct mlx5e_rx_am_stats {  	int ppms; /* packets per msec */ +	int bpms; /* bytes per msec */  	int epms; /* events per msec */  };  struct mlx5e_rx_am_sample { -	ktime_t		time; -	unsigned int	pkt_ctr; -	u16		event_ctr; +	ktime_t	time; +	u32	pkt_ctr; +	u32	byte_ctr; +	u16	event_ctr;  };  struct mlx5e_rx_am { /* Adaptive Moderation */ @@ -1003,7 +1005,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv);  void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv);  void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt); -int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn); +int mlx5e_create_ttc_table(struct mlx5e_priv *priv);  void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);  int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index ce7b09d72ff6..16486dff1493 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -794,7 +794,6 @@ static void get_supported(u32 eth_proto_cap,  	ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);  	ptys2ethtool_supported_link(supported, eth_proto_cap);  	ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause); -	ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Asym_Pause);  }  static void get_advertising(u32 eth_proto_cap, u8 tx_pause, @@ -804,7 +803,7 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,  	unsigned long *advertising = link_ksettings->link_modes.advertising;  	ptys2ethtool_adver_link(advertising, eth_proto_cap); -	if (tx_pause) +	if (rx_pause)  		ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);  	if (tx_pause ^ rx_pause)  		ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause); @@ -849,6 +848,8 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,  	struct mlx5e_priv *priv    = netdev_priv(netdev);  	struct mlx5_core_dev *mdev = priv->mdev;  	u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0}; +	u32 rx_pause = 0; +	u32 tx_pause = 0;  	u32 eth_proto_cap;  	u32 eth_proto_admin;  	u32 eth_proto_lp; @@ -871,11 +872,13 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,  	an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);  	an_status        = MLX5_GET(ptys_reg, out, an_status); +	mlx5_query_port_pause(mdev, &rx_pause, &tx_pause); +  	ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);  	ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);  	get_supported(eth_proto_cap, link_ksettings); -	get_advertising(eth_proto_admin, 0, 0, link_ksettings); +	get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings);  	get_speed_duplex(netdev, eth_proto_oper, link_ksettings);  	eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; @@ -1239,11 +1242,11 @@ static int mlx5e_get_ts_info(struct net_device *dev,  				 SOF_TIMESTAMPING_RX_HARDWARE |  				 SOF_TIMESTAMPING_RAW_HARDWARE; -	info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) | -			 (BIT(1) << HWTSTAMP_TX_ON); +	info->tx_types = BIT(HWTSTAMP_TX_OFF) | +			 BIT(HWTSTAMP_TX_ON); -	info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) | -			   (BIT(1) << HWTSTAMP_FILTER_ALL); +	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | +			   BIT(HWTSTAMP_FILTER_ALL);  	return 0;  } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index 576d6787b484..53ed58320a24 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -800,7 +800,7 @@ void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)  	mlx5e_destroy_flow_table(&ttc->ft);  } -int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn) +int mlx5e_create_ttc_table(struct mlx5e_priv *priv)  {  	struct mlx5e_ttc_table *ttc = &priv->fs.ttc;  	struct mlx5_flow_table_attr ft_attr = {}; @@ -810,7 +810,6 @@ int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)  	ft_attr.max_fte = MLX5E_TTC_TABLE_SIZE;  	ft_attr.level = MLX5E_TTC_FT_LEVEL;  	ft_attr.prio = MLX5E_NIC_PRIO; -	ft_attr.underlay_qpn = underlay_qpn;  	ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);  	if (IS_ERR(ft->t)) { @@ -1147,7 +1146,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)  		priv->netdev->hw_features &= ~NETIF_F_NTUPLE;  	} -	err = mlx5e_create_ttc_table(priv, 0); +	err = mlx5e_create_ttc_table(priv);  	if (err) {  		netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",  			   err); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index a61b71b6fff3..277f4de30375 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2976,7 +2976,7 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)  	new_channels.params = priv->channels.params;  	new_channels.params.num_tc = tc ? tc : 1; -	if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { +	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {  		priv->channels.params = new_channels.params;  		goto out;  	} @@ -4241,7 +4241,8 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,  	return netdev;  err_cleanup_nic: -	profile->cleanup(priv); +	if (profile->cleanup) +		profile->cleanup(priv);  	free_netdev(netdev);  	return NULL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 79462c0368a0..46984a52a94b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -791,6 +791,8 @@ static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,  	params->tx_max_inline         = mlx5e_get_max_inline_cap(mdev);  	params->num_tc                = 1;  	params->lro_wqe_sz            = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ; + +	mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode);  }  static void mlx5e_build_rep_netdev(struct net_device *netdev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 7b1566f0ae58..66b5fec15313 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1041,6 +1041,8 @@ void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq)  #define MLX5_IB_GRH_BYTES       40  #define MLX5_IPOIB_ENCAP_LEN    4  #define MLX5_GID_SIZE           16 +#define MLX5_IPOIB_PSEUDO_LEN   20 +#define MLX5_IPOIB_HARD_LEN     (MLX5_IPOIB_PSEUDO_LEN + MLX5_IPOIB_ENCAP_LEN)  static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,  					 struct mlx5_cqe64 *cqe, @@ -1048,6 +1050,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,  					 struct sk_buff *skb)  {  	struct net_device *netdev = rq->netdev; +	char *pseudo_header;  	u8 *dgid;  	u8 g; @@ -1076,8 +1079,11 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,  	if (likely(netdev->features & NETIF_F_RXHASH))  		mlx5e_skb_set_hash(cqe, skb); +	/* 20 bytes of ipoib header and 4 for encap existing */ +	pseudo_header = skb_push(skb, MLX5_IPOIB_PSEUDO_LEN); +	memset(pseudo_header, 0, MLX5_IPOIB_PSEUDO_LEN);  	skb_reset_mac_header(skb); -	skb_pull(skb, MLX5_IPOIB_ENCAP_LEN); +	skb_pull(skb, MLX5_IPOIB_HARD_LEN);  	skb->dev = netdev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c index 02dd3a95ed8f..acf32fe952cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c @@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct mlx5e_rx_am *am)  	mlx5e_am_step(am);  } +#define IS_SIGNIFICANT_DIFF(val, ref) \ +	(((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */ +  static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,  				  struct mlx5e_rx_am_stats *prev)  { -	int diff; - -	if (!prev->ppms) -		return curr->ppms ? MLX5E_AM_STATS_BETTER : +	if (!prev->bpms) +		return curr->bpms ? MLX5E_AM_STATS_BETTER :  				    MLX5E_AM_STATS_SAME; -	diff = curr->ppms - prev->ppms; -	if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */ -		return (diff > 0) ? MLX5E_AM_STATS_BETTER : -				    MLX5E_AM_STATS_WORSE; +	if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms)) +		return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER : +						   MLX5E_AM_STATS_WORSE; -	if (!prev->epms) -		return curr->epms ? MLX5E_AM_STATS_WORSE : -				    MLX5E_AM_STATS_SAME; +	if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms)) +		return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER : +						   MLX5E_AM_STATS_WORSE; -	diff = curr->epms - prev->epms; -	if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */ -		return (diff < 0) ? MLX5E_AM_STATS_BETTER : -				    MLX5E_AM_STATS_WORSE; +	if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms)) +		return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER : +						   MLX5E_AM_STATS_WORSE;  	return MLX5E_AM_STATS_SAME;  } @@ -266,10 +265,13 @@ static void mlx5e_am_sample(struct mlx5e_rq *rq,  {  	s->time	     = ktime_get();  	s->pkt_ctr   = rq->stats.packets; +	s->byte_ctr  = rq->stats.bytes;  	s->event_ctr = rq->cq.event_ctr;  }  #define MLX5E_AM_NEVENTS 64 +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) +#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))  static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,  				struct mlx5e_rx_am_sample *end, @@ -277,13 +279,17 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,  {  	/* u32 holds up to 71 minutes, should be enough */  	u32 delta_us = ktime_us_delta(end->time, start->time); -	unsigned int npkts = end->pkt_ctr - start->pkt_ctr; +	u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr); +	u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr, +			     start->byte_ctr);  	if (!delta_us)  		return; -	curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us; -	curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us; +	curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us); +	curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us); +	curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC, +					delta_us);  }  void mlx5e_rx_am_work(struct work_struct *work) @@ -308,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq)  	switch (am->state) {  	case MLX5E_AM_MEASURE_IN_PROGRESS: -		nevents = rq->cq.event_ctr - am->start_sample.event_ctr; +		nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr, +				  am->start_sample.event_ctr);  		if (nevents < MLX5E_AM_NEVENTS)  			break;  		mlx5e_am_sample(rq, &end_sample); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 53e4992d6511..f81c3aa60b46 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -417,20 +417,13 @@ struct mlx5e_stats {  };  static const struct counter_desc mlx5e_pme_status_desc[] = { -	{ "module_plug", 0 },  	{ "module_unplug", 8 },  };  static const struct counter_desc mlx5e_pme_error_desc[] = { -	{ "module_pwr_budget_exd", 0 },  /* power budget exceed */ -	{ "module_long_range", 8 },      /* long range for non MLNX cable */ -	{ "module_bus_stuck", 16 },      /* bus stuck (I2C or data shorted) */ -	{ "module_no_eeprom", 24 },      /* no eeprom/retry time out */ -	{ "module_enforce_part", 32 },   /* enforce part number list */ -	{ "module_unknown_id", 40 },     /* unknown identifier */ -	{ "module_high_temp", 48 },      /* high temperature */ +	{ "module_bus_stuck", 16 },       /* bus stuck (I2C or data shorted) */ +	{ "module_high_temp", 48 },       /* high temperature */  	{ "module_bad_shorted", 56 },    /* bad or shorted cable/module */ -	{ "module_unknown_status", 64 },  };  #endif /* __MLX5_EN_STATS_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 11c27e4fadf6..9df9fc0d26f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -43,6 +43,7 @@  #include <net/tc_act/tc_vlan.h>  #include <net/tc_act/tc_tunnel_key.h>  #include <net/tc_act/tc_pedit.h> +#include <net/tc_act/tc_csum.h>  #include <net/vxlan.h>  #include <net/arp.h>  #include "en.h" @@ -384,7 +385,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,  		if (e->flags & MLX5_ENCAP_ENTRY_VALID)  			mlx5_encap_dealloc(priv->mdev, e->encap_id); -		hlist_del_rcu(&e->encap_hlist); +		hash_del_rcu(&e->encap_hlist);  		kfree(e->encap_header);  		kfree(e);  	} @@ -894,7 +895,6 @@ static struct mlx5_fields fields[] = {  	{MLX5_ACTION_IN_FIELD_OUT_SMAC_15_0,  2, offsetof(struct pedit_headers, eth.h_source[4])},  	{MLX5_ACTION_IN_FIELD_OUT_ETHERTYPE,  2, offsetof(struct pedit_headers, eth.h_proto)}, -	{MLX5_ACTION_IN_FIELD_OUT_IP_DSCP, 1, offsetof(struct pedit_headers, ip4.tos)},  	{MLX5_ACTION_IN_FIELD_OUT_IP_TTL,  1, offsetof(struct pedit_headers, ip4.ttl)},  	{MLX5_ACTION_IN_FIELD_OUT_SIPV4,   4, offsetof(struct pedit_headers, ip4.saddr)},  	{MLX5_ACTION_IN_FIELD_OUT_DIPV4,   4, offsetof(struct pedit_headers, ip4.daddr)}, @@ -925,11 +925,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,  				struct mlx5e_tc_flow_parse_attr *parse_attr)  {  	struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals; -	int i, action_size, nactions, max_actions, first, last; +	int i, action_size, nactions, max_actions, first, last, first_z;  	void *s_masks_p, *a_masks_p, *vals_p; -	u32 s_mask, a_mask, val;  	struct mlx5_fields *f;  	u8 cmd, field_bsize; +	u32 s_mask, a_mask;  	unsigned long mask;  	void *action; @@ -946,7 +946,8 @@ static int offload_pedit_fields(struct pedit_headers *masks,  	for (i = 0; i < ARRAY_SIZE(fields); i++) {  		f = &fields[i];  		/* avoid seeing bits set from previous iterations */ -		s_mask = a_mask = mask = val = 0; +		s_mask = 0; +		a_mask = 0;  		s_masks_p = (void *)set_masks + f->offset;  		a_masks_p = (void *)add_masks + f->offset; @@ -981,12 +982,12 @@ static int offload_pedit_fields(struct pedit_headers *masks,  			memset(a_masks_p, 0, f->size);  		} -		memcpy(&val, vals_p, f->size); -  		field_bsize = f->size * BITS_PER_BYTE; + +		first_z = find_first_zero_bit(&mask, field_bsize);  		first = find_first_bit(&mask, field_bsize);  		last  = find_last_bit(&mask, field_bsize); -		if (first > 0 || last != (field_bsize - 1)) { +		if (first > 0 || last != (field_bsize - 1) || first_z < last) {  			printk(KERN_WARNING "mlx5: partial rewrite (mask %lx) is currently not offloaded\n",  			       mask);  			return -EOPNOTSUPP; @@ -1002,11 +1003,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,  		}  		if (field_bsize == 32) -			MLX5_SET(set_action_in, action, data, ntohl(val)); +			MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p));  		else if (field_bsize == 16) -			MLX5_SET(set_action_in, action, data, ntohs(val)); +			MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p));  		else if (field_bsize == 8) -			MLX5_SET(set_action_in, action, data, val); +			MLX5_SET(set_action_in, action, data, *(u8 *)vals_p);  		action += action_size;  		nactions++; @@ -1109,6 +1110,28 @@ out_err:  	return err;  } +static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags) +{ +	u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP | +			 TCA_CSUM_UPDATE_FLAG_UDP; + +	/*  The HW recalcs checksums only if re-writing headers */ +	if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) { +		netdev_warn(priv->netdev, +			    "TC csum action is only offloaded with pedit\n"); +		return false; +	} + +	if (update_flags & ~prot_flags) { +		netdev_warn(priv->netdev, +			    "can't offload TC csum action for some header/s - flags %#x\n", +			    update_flags); +		return false; +	} + +	return true; +} +  static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,  				struct mlx5e_tc_flow_parse_attr *parse_attr,  				struct mlx5e_tc_flow *flow) @@ -1149,6 +1172,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,  			continue;  		} +		if (is_tcf_csum(a)) { +			if (csum_offload_supported(priv, attr->action, +						   tcf_csum_update_flags(a))) +				continue; + +			return -EOPNOTSUPP; +		} +  		if (is_tcf_skbedit_mark(a)) {  			u32 mark = tcf_skbedit_mark(a); @@ -1651,6 +1682,14 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,  			continue;  		} +		if (is_tcf_csum(a)) { +			if (csum_offload_supported(priv, attr->action, +						   tcf_csum_update_flags(a))) +				continue; + +			return -EOPNOTSUPP; +		} +  		if (is_tcf_mirred_egress_redirect(a)) {  			int ifindex = tcf_mirred_ifindex(a);  			struct net_device *out_dev, *encap_dev = NULL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index ea5d8d37a75c..33eae5ad2fb0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -422,7 +422,7 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr)  			break;  		case MLX5_EVENT_TYPE_CMD: -			mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector)); +			mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false);  			break;  		case MLX5_EVENT_TYPE_PORT_CHANGE: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index f991f669047e..a53e982a6863 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -906,21 +906,34 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)  	return 0;  } -int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode) +static int mlx5_devlink_eswitch_check(struct devlink *devlink)  { -	struct mlx5_core_dev *dev; -	u16 cur_mlx5_mode, mlx5_mode = 0; +	struct mlx5_core_dev *dev = devlink_priv(devlink); -	dev = devlink_priv(devlink); +	if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) +		return -EOPNOTSUPP;  	if (!MLX5_CAP_GEN(dev, vport_group_manager))  		return -EOPNOTSUPP; -	cur_mlx5_mode = dev->priv.eswitch->mode; - -	if (cur_mlx5_mode == SRIOV_NONE) +	if (dev->priv.eswitch->mode == SRIOV_NONE)  		return -EOPNOTSUPP; +	return 0; +} + +int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode) +{ +	struct mlx5_core_dev *dev = devlink_priv(devlink); +	u16 cur_mlx5_mode, mlx5_mode = 0; +	int err; + +	err = mlx5_devlink_eswitch_check(devlink); +	if (err) +		return err; + +	cur_mlx5_mode = dev->priv.eswitch->mode; +  	if (esw_mode_from_devlink(mode, &mlx5_mode))  		return -EINVAL; @@ -937,15 +950,12 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)  int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)  { -	struct mlx5_core_dev *dev; - -	dev = devlink_priv(devlink); - -	if (!MLX5_CAP_GEN(dev, vport_group_manager)) -		return -EOPNOTSUPP; +	struct mlx5_core_dev *dev = devlink_priv(devlink); +	int err; -	if (dev->priv.eswitch->mode == SRIOV_NONE) -		return -EOPNOTSUPP; +	err = mlx5_devlink_eswitch_check(devlink); +	if (err) +		return err;  	return esw_mode_to_devlink(dev->priv.eswitch->mode, mode);  } @@ -954,15 +964,12 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)  {  	struct mlx5_core_dev *dev = devlink_priv(devlink);  	struct mlx5_eswitch *esw = dev->priv.eswitch; -	int num_vports = esw->enabled_vports;  	int err, vport;  	u8 mlx5_mode; -	if (!MLX5_CAP_GEN(dev, vport_group_manager)) -		return -EOPNOTSUPP; - -	if (esw->mode == SRIOV_NONE) -		return -EOPNOTSUPP; +	err = mlx5_devlink_eswitch_check(devlink); +	if (err) +		return err;  	switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {  	case MLX5_CAP_INLINE_MODE_NOT_REQUIRED: @@ -985,7 +992,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)  	if (err)  		goto out; -	for (vport = 1; vport < num_vports; vport++) { +	for (vport = 1; vport < esw->enabled_vports; vport++) {  		err = mlx5_modify_nic_vport_min_inline(dev, vport, mlx5_mode);  		if (err) {  			esw_warn(dev, "Failed to set min inline on vport %d\n", @@ -1010,12 +1017,11 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)  {  	struct mlx5_core_dev *dev = devlink_priv(devlink);  	struct mlx5_eswitch *esw = dev->priv.eswitch; +	int err; -	if (!MLX5_CAP_GEN(dev, vport_group_manager)) -		return -EOPNOTSUPP; - -	if (esw->mode == SRIOV_NONE) -		return -EOPNOTSUPP; +	err = mlx5_devlink_eswitch_check(devlink); +	if (err) +		return err;  	return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);  } @@ -1062,11 +1068,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap)  	struct mlx5_eswitch *esw = dev->priv.eswitch;  	int err; -	if (!MLX5_CAP_GEN(dev, vport_group_manager)) -		return -EOPNOTSUPP; - -	if (esw->mode == SRIOV_NONE) -		return -EOPNOTSUPP; +	err = mlx5_devlink_eswitch_check(devlink); +	if (err) +		return err;  	if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&  	    (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) || @@ -1105,12 +1109,11 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap)  {  	struct mlx5_core_dev *dev = devlink_priv(devlink);  	struct mlx5_eswitch *esw = dev->priv.eswitch; +	int err; -	if (!MLX5_CAP_GEN(dev, vport_group_manager)) -		return -EOPNOTSUPP; - -	if (esw->mode == SRIOV_NONE) -		return -EOPNOTSUPP; +	err = mlx5_devlink_eswitch_check(devlink); +	if (err) +		return err;  	*encap = esw->offloads.encap;  	return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 19e3d2fc2099..fcec7bedd3cd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -40,28 +40,25 @@  #include "eswitch.h"  int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, -			    struct mlx5_flow_table *ft) +			    struct mlx5_flow_table *ft, u32 underlay_qpn)  {  	u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {0};  	u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};  	if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) && -	    ft->underlay_qpn == 0) +	    underlay_qpn == 0)  		return 0;  	MLX5_SET(set_flow_table_root_in, in, opcode,  		 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);  	MLX5_SET(set_flow_table_root_in, in, table_type, ft->type);  	MLX5_SET(set_flow_table_root_in, in, table_id, ft->id); +	MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn);  	if (ft->vport) {  		MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport);  		MLX5_SET(set_flow_table_root_in, in, other_vport, 1);  	} -	if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) && -	    ft->underlay_qpn != 0) -		MLX5_SET(set_flow_table_root_in, in, underlay_qpn, ft->underlay_qpn); -  	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));  } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 8fad80688536..0f98a7cf4877 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -71,7 +71,8 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,  			unsigned int index);  int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, -			    struct mlx5_flow_table *ft); +			    struct mlx5_flow_table *ft, +			    u32 underlay_qpn);  int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id);  int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index b8a176503d38..8f5125ccd8d4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -650,7 +650,7 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio  	if (ft->level >= min_level)  		return 0; -	err = mlx5_cmd_update_root_ft(root->dev, ft); +	err = mlx5_cmd_update_root_ft(root->dev, ft, root->underlay_qpn);  	if (err)  		mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",  			       ft->id); @@ -818,8 +818,6 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa  		goto unlock_root;  	} -	ft->underlay_qpn = ft_attr->underlay_qpn; -  	tree_init_node(&ft->node, 1, del_flow_table);  	log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;  	next_ft = find_next_chained_ft(fs_prio); @@ -864,7 +862,7 @@ struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace  	ft_attr.level   = level;  	ft_attr.prio    = prio; -	return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, 0); +	return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, vport);  }  struct mlx5_flow_table* @@ -1489,7 +1487,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)  	new_root_ft = find_next_ft(ft);  	if (new_root_ft) { -		int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft); +		int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft, +						  root->underlay_qpn);  		if (err) {  			mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n", @@ -2062,3 +2061,21 @@ err:  	mlx5_cleanup_fs(dev);  	return err;  } + +int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn) +{ +	struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns; + +	root->underlay_qpn = underlay_qpn; +	return 0; +} +EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn); + +int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn) +{ +	struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns; + +	root->underlay_qpn = 0; +	return 0; +} +EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 81eafc7b9dd9..990acee6fb09 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -118,7 +118,6 @@ struct mlx5_flow_table {  	/* FWD rules that point on this flow table */  	struct list_head		fwd_rules;  	u32				flags; -	u32				underlay_qpn;  };  struct mlx5_fc_cache { @@ -195,6 +194,7 @@ struct mlx5_flow_root_namespace {  	struct mlx5_flow_table		*root_ft;  	/* Should be held when chaining flow tables */  	struct mutex			chain_lock; +	u32				underlay_qpn;  };  int mlx5_init_fc_stats(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index d0515391d33b..f27f84ffbc85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -90,7 +90,7 @@ static void trigger_cmd_completions(struct mlx5_core_dev *dev)  	spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);  	mlx5_core_dbg(dev, "vector 0x%llx\n", vector); -	mlx5_cmd_comp_handler(dev, vector); +	mlx5_cmd_comp_handler(dev, vector, true);  	return;  no_trig: @@ -275,10 +275,8 @@ static void poll_health(unsigned long data)  	struct mlx5_core_health *health = &dev->priv.health;  	u32 count; -	if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { -		mod_timer(&health->timer, get_next_poll_jiffies()); -		return; -	} +	if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) +		goto out;  	count = ioread32be(health->health_counter);  	if (count == health->prev) @@ -290,8 +288,6 @@ static void poll_health(unsigned long data)  	if (health->miss_counter == MAX_MISSES) {  		dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n");  		print_health_info(dev); -	} else { -		mod_timer(&health->timer, get_next_poll_jiffies());  	}  	if (in_fatal(dev) && !health->sick) { @@ -305,6 +301,9 @@ static void poll_health(unsigned long data)  				"new health works are not permitted at this stage\n");  		spin_unlock(&health->wq_lock);  	} + +out: +	mod_timer(&health->timer, get_next_poll_jiffies());  }  void mlx5_start_health_poll(struct mlx5_core_dev *dev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c index 019c230da498..cc1858752e70 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib.c @@ -66,6 +66,10 @@ static void mlx5i_init(struct mlx5_core_dev *mdev,  	mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev)); +	/* Override RQ params as IPoIB supports only LINKED LIST RQ for now */ +	mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST); +	priv->channels.params.lro_en = false; +  	mutex_init(&priv->state_lock);  	netdev->hw_features    |= NETIF_F_SG; @@ -156,6 +160,8 @@ out:  static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp)  { +	mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn); +  	mlx5_core_destroy_qp(mdev, qp);  } @@ -170,6 +176,8 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv)  		return err;  	} +	mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn); +  	err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]);  	if (err) {  		mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err); @@ -189,7 +197,6 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)  static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)  { -	struct mlx5i_priv *ipriv = priv->ppriv;  	int err;  	priv->fs.ns = mlx5_get_flow_namespace(priv->mdev, @@ -205,7 +212,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)  		priv->netdev->hw_features &= ~NETIF_F_NTUPLE;  	} -	err = mlx5e_create_ttc_table(priv, ipriv->qp.qpn); +	err = mlx5e_create_ttc_table(priv);  	if (err) {  		netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",  			   err); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 0c123d571b4c..13be264587f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -175,8 +175,9 @@ static struct mlx5_profile profile[] = {  	},  }; -#define FW_INIT_TIMEOUT_MILI	2000 -#define FW_INIT_WAIT_MS		2 +#define FW_INIT_TIMEOUT_MILI		2000 +#define FW_INIT_WAIT_MS			2 +#define FW_PRE_INIT_TIMEOUT_MILI	10000  static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)  { @@ -537,8 +538,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)  	/* disable cmdif checksum */  	MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0); -	/* If the HCA supports 4K UARs use it */ -	if (MLX5_CAP_GEN_MAX(dev, uar_4k)) +	/* Enable 4K UAR only when HCA supports it and page size is bigger +	 * than 4K. +	 */ +	if (MLX5_CAP_GEN_MAX(dev, uar_4k) && PAGE_SIZE > 4096)  		MLX5_SET(cmd_hca_cap, set_hca_cap, uar_4k, 1);  	MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12); @@ -612,7 +615,6 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)  	struct mlx5_priv *priv  = &mdev->priv;  	struct msix_entry *msix = priv->msix_arr;  	int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector; -	int err;  	if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {  		mlx5_core_warn(mdev, "zalloc_cpumask_var failed"); @@ -622,18 +624,11 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)  	cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),  			priv->irq_info[i].mask); -	err = irq_set_affinity_hint(irq, priv->irq_info[i].mask); -	if (err) { -		mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x", -			       irq); -		goto err_clear_mask; -	} +	if (IS_ENABLED(CONFIG_SMP) && +	    irq_set_affinity_hint(irq, priv->irq_info[i].mask)) +		mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);  	return 0; - -err_clear_mask: -	free_cpumask_var(priv->irq_info[i].mask); -	return err;  }  static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i) @@ -1019,6 +1014,15 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,  	 */  	dev->state = MLX5_DEVICE_STATE_UP; +	/* wait for firmware to accept initialization segments configurations +	 */ +	err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI); +	if (err) { +		dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n", +			FW_PRE_INIT_TIMEOUT_MILI); +		goto out; +	} +  	err = mlx5_cmd_init(dev);  	if (err) {  		dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c index ea56f6ade6b4..5f0a7bc692a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c @@ -199,10 +199,11 @@ static int mlxsw_sp_erif_entry_get(struct mlxsw_sp *mlxsw_sp,  	entry->counter_valid = false;  	entry->counter = 0; +	entry->index = mlxsw_sp_rif_index(rif); +  	if (!counters_enabled)  		return 0; -	entry->index = mlxsw_sp_rif_index(rif);  	err = mlxsw_sp_rif_counter_value_get(mlxsw_sp, rif,  					     MLXSW_SP_RIF_COUNTER_EGRESS,  					     &cnt); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 33cec1cc1642..0744452a0b18 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -206,6 +206,9 @@ void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,  {  	unsigned int *p_counter_index; +	if (!mlxsw_sp_rif_counter_valid_get(rif, dir)) +		return; +  	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);  	if (WARN_ON(!p_counter_index))  		return; @@ -3331,6 +3334,9 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,  	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);  	u16 vid = vlan_dev_vlan_id(vlan_dev); +	if (netif_is_bridge_port(vlan_dev)) +		return 0; +  	if (mlxsw_sp_port_dev_check(real_dev))  		return mlxsw_sp_inetaddr_vport_event(vlan_dev, real_dev, event,  						     vid); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0d8411f1f954..f4bb0c0b7c1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1497,8 +1497,7 @@ do_fdb_op:  	err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,  				      adding, true);  	if (err) { -		if (net_ratelimit()) -			netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n"); +		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n");  		return;  	} @@ -1558,8 +1557,7 @@ do_fdb_op:  	err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,  					  adding, true);  	if (err) { -		if (net_ratelimit()) -			netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n"); +		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n");  		return;  	} diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index b8d5270359cd..e30676515529 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c @@ -247,7 +247,7 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)  	cmd.req.arg3 = 0;  	if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) -		netxen_issue_cmd(adapter, &cmd); +		rcode = netxen_issue_cmd(adapter, &cmd);  	if (rcode != NX_RCODE_SUCCESS)  		return -EIO; diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c index 483241b4b05d..a672f6a860dc 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_debug.c +++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c @@ -2956,7 +2956,7 @@ static u32 qed_grc_dump_ctx_data(struct qed_hwfn *p_hwfn,  				qed_wr(p_hwfn,  				       p_ptt,  				       s_storm_defs[storm_id].cm_ctx_wr_addr, -				       BIT(9) | lid); +				       (i << 9) | lid);  				*(dump_buf + offset) = qed_rd(p_hwfn,  							      p_ptt,  							      rd_reg_addr); diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c index 67200c5498ab..0a8fde629991 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c +++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c @@ -983,7 +983,7 @@ void qed_set_rfs_mode_disable(struct qed_hwfn *p_hwfn,  	memset(&camline, 0, sizeof(union gft_cam_line_union));  	qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id,  	       camline.cam_line_mapped.camline); -	memset(&ramline, 0, sizeof(union gft_cam_line_union)); +	memset(&ramline, 0, sizeof(ramline));  	for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) {  		u32 hw_addr = PRS_REG_GFT_PROFILE_MASK_RAM; diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 537d1236a4fe..715b3aaf83ac 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1730,7 +1730,8 @@ void qed_get_protocol_stats(struct qed_dev *cdev,  		qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);  		break;  	default: -		DP_ERR(cdev, "Invalid protocol type = %d\n", type); +		DP_VERBOSE(cdev, QED_MSG_SP, +			   "Invalid protocol type = %d\n", type);  		return;  	}  } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 49bad00a0f8f..81312924df14 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -37,8 +37,8 @@  #define _QLCNIC_LINUX_MAJOR 5  #define _QLCNIC_LINUX_MINOR 3 -#define _QLCNIC_LINUX_SUBVERSION 65 -#define QLCNIC_LINUX_VERSIONID  "5.3.65" +#define _QLCNIC_LINUX_SUBVERSION 66 +#define QLCNIC_LINUX_VERSIONID  "5.3.66"  #define QLCNIC_DRV_IDC_VER  0x01  #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\  		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -1824,22 +1824,44 @@ struct qlcnic_hardware_ops {  	u32 (*get_cap_size)(void *, int);  	void (*set_sys_info)(void *, int, u32);  	void (*store_cap_mask)(void *, u32); +	bool (*encap_rx_offload) (struct qlcnic_adapter *adapter); +	bool (*encap_tx_offload) (struct qlcnic_adapter *adapter);  };  extern struct qlcnic_nic_template qlcnic_vf_ops; -static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter) +static inline bool qlcnic_83xx_encap_tx_offload(struct qlcnic_adapter *adapter)  {  	return adapter->ahw->extra_capability[0] &  	       QLCNIC_83XX_FW_CAPAB_ENCAP_TX_OFFLOAD;  } -static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter) +static inline bool qlcnic_83xx_encap_rx_offload(struct qlcnic_adapter *adapter)  {  	return adapter->ahw->extra_capability[0] &  	       QLCNIC_83XX_FW_CAPAB_ENCAP_RX_OFFLOAD;  } +static inline bool qlcnic_82xx_encap_tx_offload(struct qlcnic_adapter *adapter) +{ +	return false; +} + +static inline bool qlcnic_82xx_encap_rx_offload(struct qlcnic_adapter *adapter) +{ +        return false; +} + +static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter) +{ +        return adapter->ahw->hw_ops->encap_rx_offload(adapter); +} + +static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter) +{ +        return adapter->ahw->hw_ops->encap_tx_offload(adapter); +} +  static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter)  {  	return adapter->nic_ops->start_firmware(adapter); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 718bf58a7da6..f7080d0ab874 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -242,6 +242,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {  	.get_cap_size			= qlcnic_83xx_get_cap_size,  	.set_sys_info			= qlcnic_83xx_set_sys_info,  	.store_cap_mask			= qlcnic_83xx_store_cap_mask, +	.encap_rx_offload		= qlcnic_83xx_encap_rx_offload, +	.encap_tx_offload		= qlcnic_83xx_encap_tx_offload,  };  static struct qlcnic_nic_template qlcnic_83xx_ops = { @@ -3168,6 +3170,40 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,  	return 0;  } +void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter) +{ +	struct qlcnic_hardware_context *ahw = adapter->ahw; +	struct qlcnic_cmd_args cmd; +	u32 config; +	int err; + +	err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS); +	if (err) +		return; + +	err = qlcnic_issue_cmd(adapter, &cmd); +	if (err) { +		dev_info(&adapter->pdev->dev, +			 "Get Link Status Command failed: 0x%x\n", err); +		goto out; +	} else { +		config = cmd.rsp.arg[3]; + +		switch (QLC_83XX_SFP_MODULE_TYPE(config)) { +		case QLC_83XX_MODULE_FIBRE_1000BASE_SX: +		case QLC_83XX_MODULE_FIBRE_1000BASE_LX: +		case QLC_83XX_MODULE_FIBRE_1000BASE_CX: +		case QLC_83XX_MODULE_TP_1000BASE_T: +			ahw->port_type = QLCNIC_GBE; +			break; +		default: +			ahw->port_type = QLCNIC_XGBE; +		} +	} +out: +	qlcnic_free_mbx_args(&cmd); +} +  int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)  {  	u8 pci_func; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 3dfe8e27b51c..b75a81246856 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -637,6 +637,7 @@ void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,  int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *,  			       struct ethtool_pauseparam *);  int qlcnic_83xx_test_link(struct qlcnic_adapter *); +void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter);  int qlcnic_83xx_reg_test(struct qlcnic_adapter *);  int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);  int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 9a869c15d8bf..7f7deeaf1cf0 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -486,6 +486,9 @@ static int qlcnic_set_link_ksettings(struct net_device *dev,  	u32 ret = 0;  	struct qlcnic_adapter *adapter = netdev_priv(dev); +	if (qlcnic_83xx_check(adapter)) +		qlcnic_83xx_get_port_type(adapter); +  	if (adapter->ahw->port_type != QLCNIC_GBE)  		return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 838cc0ceafd8..7848cf04b29a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -341,7 +341,7 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)  			}  			return -EIO;  		} -		usleep_range(1000, 1500); +		udelay(1200);  	}  	if (id_reg) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index b6628aaa6e4a..1b5f7d57b6f8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -632,6 +632,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {  	.get_cap_size			= qlcnic_82xx_get_cap_size,  	.set_sys_info			= qlcnic_82xx_set_sys_info,  	.store_cap_mask			= qlcnic_82xx_store_cap_mask, +	.encap_rx_offload               = qlcnic_82xx_encap_rx_offload, +	.encap_tx_offload               = qlcnic_82xx_encap_tx_offload,  };  static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 2f656f395f39..c58180f40844 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -77,6 +77,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {  	.free_mac_list			= qlcnic_sriov_vf_free_mac_list,  	.enable_sds_intr		= qlcnic_83xx_enable_sds_intr,  	.disable_sds_intr		= qlcnic_83xx_disable_sds_intr, +	.encap_rx_offload               = qlcnic_83xx_encap_rx_offload, +	.encap_tx_offload               = qlcnic_83xx_encap_tx_offload,  };  static struct qlcnic_nic_template qlcnic_sriov_vf_ops = { diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index cc065ffbe4b5..bcd4708b3745 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -931,7 +931,7 @@ int emac_mac_up(struct emac_adapter *adpt)  	emac_mac_config(adpt);  	emac_mac_rx_descs_refill(adpt, &adpt->rx_q); -	adpt->phydev->irq = PHY_IGNORE_INTERRUPT; +	adpt->phydev->irq = PHY_POLL;  	ret = phy_connect_direct(netdev, adpt->phydev, emac_adjust_link,  				 PHY_INTERFACE_MODE_SGMII);  	if (ret) { diff --git a/drivers/net/ethernet/qualcomm/emac/emac-phy.c b/drivers/net/ethernet/qualcomm/emac/emac-phy.c index 441c19366489..18461fcb9815 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-phy.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-phy.c @@ -13,15 +13,11 @@  /* Qualcomm Technologies, Inc. EMAC PHY Controller driver.   */ -#include <linux/module.h> -#include <linux/of.h> -#include <linux/of_net.h>  #include <linux/of_mdio.h>  #include <linux/phy.h>  #include <linux/iopoll.h>  #include <linux/acpi.h>  #include "emac.h" -#include "emac-mac.h"  /* EMAC base register offsets */  #define EMAC_MDIO_CTRL                                        0x001414 @@ -52,62 +48,10 @@  #define MDIO_WAIT_TIMES                                           1000 -#define EMAC_LINK_SPEED_DEFAULT (\ -		EMAC_LINK_SPEED_10_HALF  |\ -		EMAC_LINK_SPEED_10_FULL  |\ -		EMAC_LINK_SPEED_100_HALF |\ -		EMAC_LINK_SPEED_100_FULL |\ -		EMAC_LINK_SPEED_1GB_FULL) - -/** - * emac_phy_mdio_autopoll_disable() - disable mdio autopoll - * @adpt: the emac adapter - * - * The autopoll feature takes over the MDIO bus.  In order for - * the PHY driver to be able to talk to the PHY over the MDIO - * bus, we need to temporarily disable the autopoll feature. - */ -static int emac_phy_mdio_autopoll_disable(struct emac_adapter *adpt) -{ -	u32 val; - -	/* disable autopoll */ -	emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, MDIO_AP_EN, 0); - -	/* wait for any mdio polling to complete */ -	if (!readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, val, -				!(val & MDIO_BUSY), 100, MDIO_WAIT_TIMES * 100)) -		return 0; - -	/* failed to disable; ensure it is enabled before returning */ -	emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN); - -	return -EBUSY; -} - -/** - * emac_phy_mdio_autopoll_disable() - disable mdio autopoll - * @adpt: the emac adapter - * - * The EMAC has the ability to poll the external PHY on the MDIO - * bus for link state changes.  This eliminates the need for the - * driver to poll the phy.  If if the link state does change, - * the EMAC issues an interrupt on behalf of the PHY. - */ -static void emac_phy_mdio_autopoll_enable(struct emac_adapter *adpt) -{ -	emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN); -} -  static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)  {  	struct emac_adapter *adpt = bus->priv;  	u32 reg; -	int ret; - -	ret = emac_phy_mdio_autopoll_disable(adpt); -	if (ret) -		return ret;  	emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,  			  (addr << PHY_ADDR_SHFT)); @@ -122,24 +66,15 @@ static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)  	if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,  			       !(reg & (MDIO_START | MDIO_BUSY)),  			       100, MDIO_WAIT_TIMES * 100)) -		ret = -EIO; -	else -		ret = (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK; +		return -EIO; -	emac_phy_mdio_autopoll_enable(adpt); - -	return ret; +	return (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK;  }  static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)  {  	struct emac_adapter *adpt = bus->priv;  	u32 reg; -	int ret; - -	ret = emac_phy_mdio_autopoll_disable(adpt); -	if (ret) -		return ret;  	emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,  			  (addr << PHY_ADDR_SHFT)); @@ -155,11 +90,9 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)  	if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,  			       !(reg & (MDIO_START | MDIO_BUSY)), 100,  			       MDIO_WAIT_TIMES * 100)) -		ret = -EIO; +		return -EIO; -	emac_phy_mdio_autopoll_enable(adpt); - -	return ret; +	return 0;  }  /* Configure the MDIO bus and connect the external PHY */ diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 28a8cdc36485..98a326faea29 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -50,19 +50,7 @@  #define DMAR_DLY_CNT_DEF				    15  #define DMAW_DLY_CNT_DEF				     4 -#define IMR_NORMAL_MASK         (\ -		ISR_ERROR       |\ -		ISR_GPHY_LINK   |\ -		ISR_TX_PKT      |\ -		GPHY_WAKEUP_INT) - -#define IMR_EXTENDED_MASK       (\ -		SW_MAN_INT      |\ -		ISR_OVER        |\ -		ISR_ERROR       |\ -		ISR_GPHY_LINK   |\ -		ISR_TX_PKT      |\ -		GPHY_WAKEUP_INT) +#define IMR_NORMAL_MASK		(ISR_ERROR | ISR_OVER | ISR_TX_PKT)  #define ISR_TX_PKT      (\  	TX_PKT_INT      |\ @@ -70,10 +58,6 @@  	TX_PKT_INT2     |\  	TX_PKT_INT3) -#define ISR_GPHY_LINK        (\ -	GPHY_LINK_UP_INT     |\ -	GPHY_LINK_DOWN_INT) -  #define ISR_OVER        (\  	RFD0_UR_INT     |\  	RFD1_UR_INT     |\ @@ -187,10 +171,6 @@ irqreturn_t emac_isr(int _irq, void *data)  	if (status & ISR_OVER)  		net_warn_ratelimited("warning: TX/RX overflow\n"); -	/* link event */ -	if (status & ISR_GPHY_LINK) -		phy_mac_interrupt(adpt->phydev, !!(status & GPHY_LINK_UP_INT)); -  exit:  	/* enable the interrupt */  	writel(irq->mask, adpt->base + EMAC_INT_MASK); diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 513e6c74e199..24ca7df15d07 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -296,8 +296,9 @@ qcaspi_receive(struct qcaspi *qca)  	/* Allocate rx SKB if we don't have one available. */  	if (!qca->rx_skb) { -		qca->rx_skb = netdev_alloc_skb(net_dev, -					       net_dev->mtu + VLAN_ETH_HLEN); +		qca->rx_skb = netdev_alloc_skb_ip_align(net_dev, +							net_dev->mtu + +							VLAN_ETH_HLEN);  		if (!qca->rx_skb) {  			netdev_dbg(net_dev, "out of RX resources\n");  			qca->stats.out_of_mem++; @@ -377,7 +378,7 @@ qcaspi_receive(struct qcaspi *qca)  					qca->rx_skb, qca->rx_skb->dev);  				qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;  				netif_rx_ni(qca->rx_skb); -				qca->rx_skb = netdev_alloc_skb(net_dev, +				qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,  					net_dev->mtu + VLAN_ETH_HLEN);  				if (!qca->rx_skb) {  					netdev_dbg(net_dev, "out of RX resources\n"); @@ -759,7 +760,8 @@ qcaspi_netdev_init(struct net_device *dev)  	if (!qca->rx_buffer)  		return -ENOBUFS; -	qca->rx_skb = netdev_alloc_skb(dev, qca->net_dev->mtu + VLAN_ETH_HLEN); +	qca->rx_skb = netdev_alloc_skb_ip_align(dev, qca->net_dev->mtu + +						VLAN_ETH_HLEN);  	if (!qca->rx_skb) {  		kfree(qca->rx_buffer);  		netdev_info(qca->net_dev, "Failed to allocate RX sk_buff.\n"); diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 3cd7989c007d..784782da3a85 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -230,18 +230,6 @@ static void ravb_ring_free(struct net_device *ndev, int q)  	int ring_size;  	int i; -	/* Free RX skb ringbuffer */ -	if (priv->rx_skb[q]) { -		for (i = 0; i < priv->num_rx_ring[q]; i++) -			dev_kfree_skb(priv->rx_skb[q][i]); -	} -	kfree(priv->rx_skb[q]); -	priv->rx_skb[q] = NULL; - -	/* Free aligned TX buffers */ -	kfree(priv->tx_align[q]); -	priv->tx_align[q] = NULL; -  	if (priv->rx_ring[q]) {  		for (i = 0; i < priv->num_rx_ring[q]; i++) {  			struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; @@ -270,6 +258,18 @@ static void ravb_ring_free(struct net_device *ndev, int q)  		priv->tx_ring[q] = NULL;  	} +	/* Free RX skb ringbuffer */ +	if (priv->rx_skb[q]) { +		for (i = 0; i < priv->num_rx_ring[q]; i++) +			dev_kfree_skb(priv->rx_skb[q][i]); +	} +	kfree(priv->rx_skb[q]); +	priv->rx_skb[q] = NULL; + +	/* Free aligned TX buffers */ +	kfree(priv->tx_align[q]); +	priv->tx_align[q] = NULL; +  	/* Free TX skb ringbuffer.  	 * SKBs are freed by ravb_tx_free() call above.  	 */ diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index f68c4db656ed..2d686ccf971b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -3220,7 +3220,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)  	/* MDIO bus init */  	ret = sh_mdio_init(mdp, pd);  	if (ret) { -		dev_err(&ndev->dev, "failed to initialise MDIO\n"); +		if (ret != -EPROBE_DEFER) +			dev_err(&pdev->dev, "MDIO init failed: %d\n", ret);  		goto out_release;  	} diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index 2ae852454780..a9ce82d3e9cf 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c @@ -1505,8 +1505,8 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,  		*index = entry->index;  		resolved = false;  	} else if (removing) { -		ofdpa_neigh_del(trans, found);  		*index = found->index; +		ofdpa_neigh_del(trans, found);  	} else if (updating) {  		ofdpa_neigh_update(found, trans, NULL, false);  		resolved = !is_zero_ether_addr(found->eth_dst); diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 78efb2822b86..78f9e43420e0 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -4172,7 +4172,7 @@ found:  	 * recipients  	 */  	if (is_mc_recip) { -		MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN); +		MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);  		unsigned int depth, i;  		memset(inbuf, 0, sizeof(inbuf)); @@ -4320,7 +4320,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,  			efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);  		} else {  			efx_mcdi_display_error(efx, MC_CMD_FILTER_OP, -					       MC_CMD_FILTER_OP_IN_LEN, +					       MC_CMD_FILTER_OP_EXT_IN_LEN,  					       NULL, 0, rc);  		}  	} @@ -4453,7 +4453,7 @@ static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx,  				      struct efx_filter_spec *spec)  {  	struct efx_ef10_filter_table *table = efx->filter_state; -	MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN); +	MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);  	struct efx_filter_spec *saved_spec;  	unsigned int hash, i, depth = 1;  	bool replacing = false; @@ -4940,7 +4940,7 @@ not_restored:  static void efx_ef10_filter_table_remove(struct efx_nic *efx)  {  	struct efx_ef10_filter_table *table = efx->filter_state; -	MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN); +	MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);  	struct efx_filter_spec *spec;  	unsigned int filter_idx;  	int rc; @@ -5105,6 +5105,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,  	/* Insert/renew filters */  	for (i = 0; i < addr_count; i++) { +		EFX_WARN_ON_PARANOID(ids[i] != EFX_EF10_FILTER_ID_INVALID);  		efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);  		efx_filter_set_eth_local(&spec, vlan->vid, addr_list[i].addr);  		rc = efx_ef10_filter_insert(efx, &spec, true); @@ -5122,11 +5123,11 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,  				}  				return rc;  			} else { -				/* mark as not inserted, and carry on */ -				rc = EFX_EF10_FILTER_ID_INVALID; +				/* keep invalid ID, and carry on */  			} +		} else { +			ids[i] = efx_ef10_filter_get_unsafe_id(rc);  		} -		ids[i] = efx_ef10_filter_get_unsafe_id(rc);  	}  	if (multicast && rollback) { diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index b7e4345c990d..019cef1d3cf7 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -661,8 +661,6 @@ restore_filters:  		up_write(&vf->efx->filter_sem);  		mutex_unlock(&vf->efx->mac_lock); -		up_write(&vf->efx->filter_sem); -  		rc2 = efx_net_open(vf->efx->net_dev);  		if (rc2)  			goto reset_nic; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 7b916aa21bde..4d7fb8af880d 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -18,8 +18,12 @@  #include "mcdi.h"  enum { -	EFX_REV_SIENA_A0 = 0, -	EFX_REV_HUNT_A0 = 1, +	/* Revisions 0-2 were Falcon A0, A1 and B0 respectively. +	 * They are not supported by this driver but these revision numbers +	 * form part of the ethtool API for register dumping. +	 */ +	EFX_REV_SIENA_A0 = 3, +	EFX_REV_HUNT_A0 = 4,  };  static inline int efx_nic_rev(struct efx_nic *efx) diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c index 489ef146201e..6a9c954492f2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c +++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c @@ -37,6 +37,7 @@  #define TSE_PCS_CONTROL_AN_EN_MASK			BIT(12)  #define TSE_PCS_CONTROL_REG				0x00  #define TSE_PCS_CONTROL_RESTART_AN_MASK			BIT(9) +#define TSE_PCS_CTRL_AUTONEG_SGMII			0x1140  #define TSE_PCS_IF_MODE_REG				0x28  #define TSE_PCS_LINK_TIMER_0_REG			0x24  #define TSE_PCS_LINK_TIMER_1_REG			0x26 @@ -65,6 +66,7 @@  #define TSE_PCS_SW_RESET_TIMEOUT			100  #define TSE_PCS_USE_SGMII_AN_MASK			BIT(1)  #define TSE_PCS_USE_SGMII_ENA				BIT(0) +#define TSE_PCS_IF_USE_SGMII				0x03  #define SGMII_ADAPTER_CTRL_REG				0x00  #define SGMII_ADAPTER_DISABLE				0x0001 @@ -101,7 +103,9 @@ int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs)  {  	int ret = 0; -	writew(TSE_PCS_USE_SGMII_ENA, base + TSE_PCS_IF_MODE_REG); +	writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG); + +	writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG);  	writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG);  	writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index aa6476439aee..e0ef02f9503b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -214,13 +214,13 @@ static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)  {  	/* Context type from W/B descriptor must be zero */  	if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE) -		return -EINVAL; +		return 0;  	/* Tx Timestamp Status is 1 so des0 and des1'll have valid values */  	if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS) -		return 0; +		return 1; -	return 1; +	return 0;  }  static inline u64 dwmac4_get_timestamp(void *desc, u32 ats) @@ -282,7 +282,10 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)  		}  	}  exit: -	return ret; +	if (likely(ret == 0)) +		return 1; + +	return 0;  }  static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index cd8c60132390..6e4cbc6ce0ef 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -434,14 +434,14 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,  		return;  	/* check tx tstamp status */ -	if (!priv->hw->desc->get_tx_timestamp_status(p)) { +	if (priv->hw->desc->get_tx_timestamp_status(p)) {  		/* get the valid tstamp */  		ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);  		memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));  		shhwtstamp.hwtstamp = ns_to_ktime(ns); -		netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns); +		netdev_dbg(priv->dev, "get valid TX hw timestamp %llu\n", ns);  		/* pass tstamp to stack */  		skb_tstamp_tx(skb, &shhwtstamp);  	} @@ -468,19 +468,19 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,  		return;  	/* Check if timestamp is available */ -	if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { +	if (priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {  		/* For GMAC4, the valid timestamp is from CTX next desc. */  		if (priv->plat->has_gmac4)  			ns = priv->hw->desc->get_timestamp(np, priv->adv_ts);  		else  			ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); -		netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns); +		netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);  		shhwtstamp = skb_hwtstamps(skb);  		memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));  		shhwtstamp->hwtstamp = ns_to_ktime(ns);  	} else  { -		netdev_err(priv->dev, "cannot get RX hw timestamp\n"); +		netdev_dbg(priv->dev, "cannot get RX hw timestamp\n");  	}  } @@ -546,7 +546,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)  			/* PTP v1, UDP, any kind of event packet */  			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;  			/* take time stamp for all event messages */ -			snap_type_sel = PTP_TCR_SNAPTYPSEL_1; +			if (priv->plat->has_gmac4) +				snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; +			else +				snap_type_sel = PTP_TCR_SNAPTYPSEL_1;  			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;  			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; @@ -578,7 +581,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)  			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;  			ptp_v2 = PTP_TCR_TSVER2ENA;  			/* take time stamp for all event messages */ -			snap_type_sel = PTP_TCR_SNAPTYPSEL_1; +			if (priv->plat->has_gmac4) +				snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; +			else +				snap_type_sel = PTP_TCR_SNAPTYPSEL_1;  			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;  			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; @@ -612,7 +618,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)  			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;  			ptp_v2 = PTP_TCR_TSVER2ENA;  			/* take time stamp for all event messages */ -			snap_type_sel = PTP_TCR_SNAPTYPSEL_1; +			if (priv->plat->has_gmac4) +				snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; +			else +				snap_type_sel = PTP_TCR_SNAPTYPSEL_1;  			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;  			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; @@ -1208,7 +1217,7 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)  	u32 rx_count = priv->plat->rx_queues_to_use;  	unsigned int bfsize = 0;  	int ret = -ENOMEM; -	u32 queue; +	int queue;  	int i;  	if (priv->hw->mode->set_16kib_bfsize) @@ -2724,7 +2733,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,  		priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size,  			0, 1, -			(last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), +			(last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE),  			0, 0);  		tmp_len -= TSO_MAX_BUFF_SIZE; @@ -2822,7 +2831,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)  	tx_q->tx_skbuff_dma[first_entry].buf = des;  	tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb); -	tx_q->tx_skbuff[first_entry] = skb;  	first->des0 = cpu_to_le32(des); @@ -2856,6 +2864,14 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)  	tx_q->tx_skbuff_dma[tx_q->cur_tx].last_segment = true; +	/* Only the last descriptor gets to point to the skb. */ +	tx_q->tx_skbuff[tx_q->cur_tx] = skb; + +	/* We've used all descriptors we need for this skb, however, +	 * advance cur_tx so that it references a fresh descriptor. +	 * ndo_start_xmit will fill this descriptor the next time it's +	 * called and stmmac_tx_clean may clean up to this descriptor. +	 */  	tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);  	if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) { @@ -2947,7 +2963,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)  	int i, csum_insertion = 0, is_jumbo = 0;  	u32 queue = skb_get_queue_mapping(skb);  	int nfrags = skb_shinfo(skb)->nr_frags; -	unsigned int entry, first_entry; +	int entry; +	unsigned int first_entry;  	struct dma_desc *desc, *first;  	struct stmmac_tx_queue *tx_q;  	unsigned int enh_desc; @@ -2988,8 +3005,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)  	first = desc; -	tx_q->tx_skbuff[first_entry] = skb; -  	enh_desc = priv->plat->enh_desc;  	/* To program the descriptors according to the size of the frame */  	if (enh_desc) @@ -3037,8 +3052,15 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)  						skb->len);  	} -	entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); +	/* Only the last descriptor gets to point to the skb. */ +	tx_q->tx_skbuff[entry] = skb; +	/* We've used all descriptors we need for this skb, however, +	 * advance cur_tx so that it references a fresh descriptor. +	 * ndo_start_xmit will fill this descriptor the next time it's +	 * called and stmmac_tx_clean may clean up to this descriptor. +	 */ +	entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);  	tx_q->cur_tx = entry;  	if (netif_msg_pktdata(priv)) { @@ -3725,7 +3747,7 @@ static void sysfs_display_ring(void *head, int size, int extend_desc,  			ep++;  		} else {  			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", -				   i, (unsigned int)virt_to_phys(ep), +				   i, (unsigned int)virt_to_phys(p),  				   le32_to_cpu(p->des0), le32_to_cpu(p->des1),  				   le32_to_cpu(p->des2), le32_to_cpu(p->des3));  			p++; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h index 48fb72fc423c..f4b31d69f60e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h @@ -59,7 +59,8 @@  /* Enable Snapshot for Messages Relevant to Master */  #define	PTP_TCR_TSMSTRENA	BIT(15)  /* Select PTP packets for Taking Snapshots */ -#define	PTP_TCR_SNAPTYPSEL_1	GENMASK(17, 16) +#define	PTP_TCR_SNAPTYPSEL_1	BIT(16) +#define	PTP_GMAC4_TCR_SNAPTYPSEL_1	GENMASK(17, 16)  /* Enable MAC address for PTP Frame Filtering */  #define	PTP_TCR_TSENMACADDR	BIT(18) diff --git a/drivers/net/ethernet/sun/ldmvsw.c b/drivers/net/ethernet/sun/ldmvsw.c index 5a90fed06260..5b56c24b6ed2 100644 --- a/drivers/net/ethernet/sun/ldmvsw.c +++ b/drivers/net/ethernet/sun/ldmvsw.c @@ -411,13 +411,14 @@ static int vsw_port_remove(struct vio_dev *vdev)  	if (port) {  		del_timer_sync(&port->vio.timer); +		del_timer_sync(&port->clean_timer);  		napi_disable(&port->napi); +		unregister_netdev(port->dev);  		list_del_rcu(&port->list);  		synchronize_rcu(); -		del_timer_sync(&port->clean_timer);  		spin_lock_irqsave(&port->vp->lock, flags);  		sunvnet_port_rm_txq_common(port);  		spin_unlock_irqrestore(&port->vp->lock, flags); @@ -427,7 +428,6 @@ static int vsw_port_remove(struct vio_dev *vdev)  		dev_set_drvdata(&vdev->dev, NULL); -		unregister_netdev(port->dev);  		free_netdev(port->dev);  	} diff --git a/drivers/net/ethernet/ti/cpsw-common.c b/drivers/net/ethernet/ti/cpsw-common.c index 1562ab4151e1..56ba411421f0 100644 --- a/drivers/net/ethernet/ti/cpsw-common.c +++ b/drivers/net/ethernet/ti/cpsw-common.c @@ -90,7 +90,7 @@ int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)  	if (of_device_is_compatible(dev->of_node, "ti,dm816-emac"))  		return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr); -	if (of_machine_is_compatible("ti,am4372")) +	if (of_machine_is_compatible("ti,am43"))  		return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);  	if (of_machine_is_compatible("ti,dra7")) diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 729a7da90b5b..e6222e535019 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1353,9 +1353,10 @@ int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe)  	tx_pipe->dma_channel = knav_dma_open_channel(dev,  				tx_pipe->dma_chan_name, &config); -	if (IS_ERR_OR_NULL(tx_pipe->dma_channel)) { +	if (IS_ERR(tx_pipe->dma_channel)) {  		dev_err(dev, "failed opening tx chan(%s)\n",  			tx_pipe->dma_chan_name); +		ret = PTR_ERR(tx_pipe->dma_channel);  		goto err;  	} @@ -1673,9 +1674,10 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)  	netcp->rx_channel = knav_dma_open_channel(netcp->netcp_device->device,  					netcp->dma_chan_name, &config); -	if (IS_ERR_OR_NULL(netcp->rx_channel)) { +	if (IS_ERR(netcp->rx_channel)) {  		dev_err(netcp->ndev_dev, "failed opening rx chan(%s\n",  			netcp->dma_chan_name); +		ret = PTR_ERR(netcp->rx_channel);  		goto fail;  	} diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 897176fc5043..dd92950a4615 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2651,7 +2651,6 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)  	case HWTSTAMP_FILTER_NONE:  		cpts_rx_enable(cpts, 0);  		break; -	case HWTSTAMP_FILTER_ALL:  	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:  	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:  	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index dec5d563ab19..199459bd6961 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1007,7 +1007,7 @@ static void geneve_setup(struct net_device *dev)  	dev->netdev_ops = &geneve_netdev_ops;  	dev->ethtool_ops = &geneve_ethtool_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	SET_NETDEV_DEVTYPE(dev, &geneve_type); @@ -1133,7 +1133,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,  	/* make enough headroom for basic scenario */  	encap_len = GENEVE_BASE_HLEN + ETH_HLEN; -	if (ip_tunnel_info_af(info) == AF_INET) { +	if (!metadata && ip_tunnel_info_af(info) == AF_INET) {  		encap_len += sizeof(struct iphdr);  		dev->max_mtu -= sizeof(struct iphdr);  	} else { @@ -1293,7 +1293,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)  	if (nla_put_u32(skb, IFLA_GENEVE_ID, vni))  		goto nla_put_failure; -	if (ip_tunnel_info_af(info) == AF_INET) { +	if (rtnl_dereference(geneve->sock4)) {  		if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE,  				    info->key.u.ipv4.dst))  			goto nla_put_failure; @@ -1302,8 +1302,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)  			       !!(info->key.tun_flags & TUNNEL_CSUM)))  			goto nla_put_failure; +	} +  #if IS_ENABLED(CONFIG_IPV6) -	} else { +	if (rtnl_dereference(geneve->sock6)) {  		if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6,  				     &info->key.u.ipv6.dst))  			goto nla_put_failure; @@ -1315,8 +1317,8 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)  		if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,  			       !geneve->use_udp6_rx_checksums))  			goto nla_put_failure; -#endif  	} +#endif  	if (nla_put_u8(skb, IFLA_GENEVE_TTL, info->key.ttl) ||  	    nla_put_u8(skb, IFLA_GENEVE_TOS, info->key.tos) || diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 4fea1b3dfbb4..ca110cd2a4e4 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -611,7 +611,7 @@ static const struct net_device_ops gtp_netdev_ops = {  static void gtp_link_setup(struct net_device *dev)  {  	dev->netdev_ops		= >p_netdev_ops; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  	dev->hard_header_len = 0;  	dev->addr_len = 0; @@ -873,7 +873,7 @@ static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[])  	/* Check if there's an existing gtpX device to configure */  	dev = dev_get_by_index_rcu(net, nla_get_u32(nla[GTPA_LINK])); -	if (dev->netdev_ops == >p_netdev_ops) +	if (dev && dev->netdev_ops == >p_netdev_ops)  		gtp = netdev_priv(dev);  	put_net(net); diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 922bf440e9f1..021a8ec411ab 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -311,7 +311,7 @@ static void sp_setup(struct net_device *dev)  {  	/* Finish setting up the DEVICE info. */  	dev->netdev_ops		= &sp_netdev_ops; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  	dev->mtu		= SIXP_MTU;  	dev->hard_header_len	= AX25_MAX_HEADER_LEN;  	dev->header_ops 	= &ax25_header_ops; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index f62e7f325cf9..78a6414c5fd9 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -476,7 +476,7 @@ static const struct net_device_ops bpq_netdev_ops = {  static void bpq_setup(struct net_device *dev)  {  	dev->netdev_ops	     = &bpq_netdev_ops; -	dev->destructor	     = free_netdev; +	dev->needs_free_netdev = true;  	memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);  	memcpy(dev->dev_addr,  &ax25_defaddr, AX25_ADDR_LEN); diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index 8c3633c1d078..97e3bc60c3e7 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -576,6 +576,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)  	case HDLCDRVCTL_CALIBRATE:  		if(!capable(CAP_SYS_RAWIO))  			return -EPERM; +		if (s->par.bitrate <= 0) +			return -EINVAL;  		if (bi.data.calibrate > INT_MAX / s->par.bitrate)  			return -EINVAL;  		s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 262b2ea576a3..6066f1bcaf2d 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -171,6 +171,8 @@ struct rndis_device {  	spinlock_t request_lock;  	struct list_head req_list; +	struct work_struct mcast_work; +  	u8 hw_mac_adr[ETH_ALEN];  	u8 rss_key[NETVSC_HASH_KEYLEN];  	u16 ind_table[ITAB_NUM]; @@ -201,6 +203,7 @@ int rndis_filter_open(struct netvsc_device *nvdev);  int rndis_filter_close(struct netvsc_device *nvdev);  int rndis_filter_device_add(struct hv_device *dev,  			    struct netvsc_device_info *info); +void rndis_filter_update(struct netvsc_device *nvdev);  void rndis_filter_device_remove(struct hv_device *dev,  				struct netvsc_device *nvdev);  int rndis_filter_set_rss_param(struct rndis_device *rdev, @@ -211,7 +214,6 @@ int rndis_filter_receive(struct net_device *ndev,  			 struct vmbus_channel *channel,  			 void *data, u32 buflen); -int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);  int rndis_filter_set_device_mac(struct net_device *ndev, char *mac);  void netvsc_switch_datapath(struct net_device *nv_dev, bool vf); @@ -696,7 +698,6 @@ struct net_device_context {  	/* list protection */  	spinlock_t lock; -	struct work_struct work;  	u32 msg_enable; /* debug level */  	u32 tx_checksum_mask; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 4421a6d00375..643c539a08ba 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -56,37 +56,12 @@ static int debug = -1;  module_param(debug, int, S_IRUGO);  MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -static void do_set_multicast(struct work_struct *w) -{ -	struct net_device_context *ndevctx = -		container_of(w, struct net_device_context, work); -	struct hv_device *device_obj = ndevctx->device_ctx; -	struct net_device *ndev = hv_get_drvdata(device_obj); -	struct netvsc_device *nvdev = rcu_dereference(ndevctx->nvdev); -	struct rndis_device *rdev; - -	if (!nvdev) -		return; - -	rdev = nvdev->extension; -	if (rdev == NULL) -		return; - -	if (ndev->flags & IFF_PROMISC) -		rndis_filter_set_packet_filter(rdev, -			NDIS_PACKET_TYPE_PROMISCUOUS); -	else -		rndis_filter_set_packet_filter(rdev, -			NDIS_PACKET_TYPE_BROADCAST | -			NDIS_PACKET_TYPE_ALL_MULTICAST | -			NDIS_PACKET_TYPE_DIRECTED); -} -  static void netvsc_set_multicast_list(struct net_device *net)  {  	struct net_device_context *net_device_ctx = netdev_priv(net); +	struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); -	schedule_work(&net_device_ctx->work); +	rndis_filter_update(nvdev);  }  static int netvsc_open(struct net_device *net) @@ -123,8 +98,6 @@ static int netvsc_close(struct net_device *net)  	netif_tx_disable(net); -	/* Make sure netvsc_set_multicast_list doesn't re-enable filter! */ -	cancel_work_sync(&net_device_ctx->work);  	ret = rndis_filter_close(nvdev);  	if (ret != 0) {  		netdev_err(net, "unable to close device (ret %d).\n", ret); @@ -803,7 +776,7 @@ static int netvsc_set_channels(struct net_device *net,  	    channels->rx_count || channels->tx_count || channels->other_count)  		return -EINVAL; -	if (count > net->num_tx_queues || count > net->num_rx_queues) +	if (count > net->num_tx_queues || count > VRSS_CHANNEL_MAX)  		return -EINVAL;  	if (!nvdev || nvdev->destroy) @@ -1028,7 +1001,7 @@ static const struct {  static int netvsc_get_sset_count(struct net_device *dev, int string_set)  {  	struct net_device_context *ndc = netdev_priv(dev); -	struct netvsc_device *nvdev = rcu_dereference(ndc->nvdev); +	struct netvsc_device *nvdev = rtnl_dereference(ndc->nvdev);  	if (!nvdev)  		return -ENODEV; @@ -1158,11 +1131,22 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,  }  #ifdef CONFIG_NET_POLL_CONTROLLER -static void netvsc_poll_controller(struct net_device *net) +static void netvsc_poll_controller(struct net_device *dev)  { -	/* As netvsc_start_xmit() works synchronous we don't have to -	 * trigger anything here. -	 */ +	struct net_device_context *ndc = netdev_priv(dev); +	struct netvsc_device *ndev; +	int i; + +	rcu_read_lock(); +	ndev = rcu_dereference(ndc->nvdev); +	if (ndev) { +		for (i = 0; i < ndev->num_chn; i++) { +			struct netvsc_channel *nvchan = &ndev->chan_table[i]; + +			napi_schedule(&nvchan->napi); +		} +	} +	rcu_read_unlock();  }  #endif @@ -1219,7 +1203,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,  	rndis_dev = ndev->extension;  	if (indir) {  		for (i = 0; i < ITAB_NUM; i++) -			if (indir[i] >= dev->num_rx_queues) +			if (indir[i] >= VRSS_CHANNEL_MAX)  				return -EINVAL;  		for (i = 0; i < ITAB_NUM; i++) @@ -1552,7 +1536,6 @@ static int netvsc_probe(struct hv_device *dev,  	hv_set_drvdata(dev, net);  	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change); -	INIT_WORK(&net_device_ctx->work, do_set_multicast);  	spin_lock_init(&net_device_ctx->lock);  	INIT_LIST_HEAD(&net_device_ctx->reconfig_events); @@ -1622,7 +1605,6 @@ static int netvsc_remove(struct hv_device *dev)  	netif_device_detach(net);  	cancel_delayed_work_sync(&ndev_ctx->dwork); -	cancel_work_sync(&ndev_ctx->work);  	/*  	 * Call to the vsc driver to let it know that the device is being diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index f9d5b0b8209a..cb79cd081f42 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -31,6 +31,7 @@  #include "hyperv_net.h" +static void rndis_set_multicast(struct work_struct *w);  #define RNDIS_EXT_LEN PAGE_SIZE  struct rndis_request { @@ -76,6 +77,7 @@ static struct rndis_device *get_rndis_device(void)  	spin_lock_init(&device->request_lock);  	INIT_LIST_HEAD(&device->req_list); +	INIT_WORK(&device->mcast_work, rndis_set_multicast);  	device->state = RNDIS_DEV_UNINITIALIZED; @@ -815,7 +817,8 @@ static int rndis_filter_query_link_speed(struct rndis_device *dev)  	return ret;  } -int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter) +static int rndis_filter_set_packet_filter(struct rndis_device *dev, +					  u32 new_filter)  {  	struct rndis_request *request;  	struct rndis_set_request *set; @@ -846,6 +849,28 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)  	return ret;  } +static void rndis_set_multicast(struct work_struct *w) +{ +	struct rndis_device *rdev +		= container_of(w, struct rndis_device, mcast_work); + +	if (rdev->ndev->flags & IFF_PROMISC) +		rndis_filter_set_packet_filter(rdev, +					       NDIS_PACKET_TYPE_PROMISCUOUS); +	else +		rndis_filter_set_packet_filter(rdev, +					       NDIS_PACKET_TYPE_BROADCAST | +					       NDIS_PACKET_TYPE_ALL_MULTICAST | +					       NDIS_PACKET_TYPE_DIRECTED); +} + +void rndis_filter_update(struct netvsc_device *nvdev) +{ +	struct rndis_device *rdev = nvdev->extension; + +	schedule_work(&rdev->mcast_work); +} +  static int rndis_filter_init_device(struct rndis_device *dev)  {  	struct rndis_request *request; @@ -973,6 +998,9 @@ static int rndis_filter_close_device(struct rndis_device *dev)  	if (dev->state != RNDIS_DEV_DATAINITIALIZED)  		return 0; +	/* Make sure rndis_set_multicast doesn't re-enable filter! */ +	cancel_work_sync(&dev->mcast_work); +  	ret = rndis_filter_set_packet_filter(dev, 0);  	if (ret == -ENODEV)  		ret = 0; diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 312fce7302d3..144ea5ae8ab4 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -207,7 +207,6 @@ static void ifb_dev_free(struct net_device *dev)  		__skb_queue_purge(&txp->tq);  	}  	kfree(dp->tx_private); -	free_netdev(dev);  }  static void ifb_setup(struct net_device *dev) @@ -230,7 +229,8 @@ static void ifb_setup(struct net_device *dev)  	dev->priv_flags &= ~IFF_TX_SKB_SHARING;  	netif_keep_dst(dev);  	eth_hw_addr_random(dev); -	dev->destructor = ifb_dev_free; +	dev->needs_free_netdev = true; +	dev->priv_destructor = ifb_dev_free;  }  static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 618ed88fad0f..7c7680c8f0e3 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -632,7 +632,7 @@ void ipvlan_link_setup(struct net_device *dev)  	dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);  	dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;  	dev->netdev_ops = &ipvlan_netdev_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	dev->header_ops = &ipvlan_header_ops;  	dev->ethtool_ops = &ipvlan_ethtool_ops;  } diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 8716b8c07feb..6f3c805f7211 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)           * are "42101001.sb" or "42101002.sb"           */          sprintf(stir421x_fw_name, "4210%4X.sb", -                self->usbdev->descriptor.bcdDevice); +		le16_to_cpu(self->usbdev->descriptor.bcdDevice));          ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);          if (ret < 0)                  return ret; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 224f65cb576b..30612497643c 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -159,7 +159,6 @@ static void loopback_dev_free(struct net_device *dev)  {  	dev_net(dev)->loopback_dev = NULL;  	free_percpu(dev->lstats); -	free_netdev(dev);  }  static const struct net_device_ops loopback_ops = { @@ -196,7 +195,8 @@ static void loopback_setup(struct net_device *dev)  	dev->ethtool_ops	= &loopback_ethtool_ops;  	dev->header_ops		= ð_header_ops;  	dev->netdev_ops		= &loopback_ops; -	dev->destructor		= loopback_dev_free; +	dev->needs_free_netdev	= true; +	dev->priv_destructor	= loopback_dev_free;  }  /* Setup and register the loopback device. */ diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index cdc347be68f2..79411675f0e6 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -2996,7 +2996,6 @@ static void macsec_free_netdev(struct net_device *dev)  	free_percpu(macsec->secy.tx_sc.stats);  	dev_put(real_dev); -	free_netdev(dev);  }  static void macsec_setup(struct net_device *dev) @@ -3006,7 +3005,8 @@ static void macsec_setup(struct net_device *dev)  	dev->max_mtu = ETH_MAX_MTU;  	dev->priv_flags |= IFF_NO_QUEUE;  	dev->netdev_ops = &macsec_netdev_ops; -	dev->destructor = macsec_free_netdev; +	dev->needs_free_netdev = true; +	dev->priv_destructor = macsec_free_netdev;  	SET_NETDEV_DEVTYPE(dev, &macsec_type);  	eth_zero_addr(dev->broadcast); diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index b34eaaae03fd..72b801803aa4 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -39,16 +39,20 @@  #define MACVLAN_HASH_SIZE	(1<<MACVLAN_HASH_BITS)  #define MACVLAN_BC_QUEUE_LEN	1000 +#define MACVLAN_F_PASSTHRU	1 +#define MACVLAN_F_ADDRCHANGE	2 +  struct macvlan_port {  	struct net_device	*dev;  	struct hlist_head	vlan_hash[MACVLAN_HASH_SIZE];  	struct list_head	vlans;  	struct sk_buff_head	bc_queue;  	struct work_struct	bc_work; -	bool 			passthru; +	u32			flags;  	int			count;  	struct hlist_head	vlan_source_hash[MACVLAN_HASH_SIZE];  	DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ); +	unsigned char           perm_addr[ETH_ALEN];  };  struct macvlan_source_entry { @@ -66,6 +70,31 @@ struct macvlan_skb_cb {  static void macvlan_port_destroy(struct net_device *dev); +static inline bool macvlan_passthru(const struct macvlan_port *port) +{ +	return port->flags & MACVLAN_F_PASSTHRU; +} + +static inline void macvlan_set_passthru(struct macvlan_port *port) +{ +	port->flags |= MACVLAN_F_PASSTHRU; +} + +static inline bool macvlan_addr_change(const struct macvlan_port *port) +{ +	return port->flags & MACVLAN_F_ADDRCHANGE; +} + +static inline void macvlan_set_addr_change(struct macvlan_port *port) +{ +	port->flags |= MACVLAN_F_ADDRCHANGE; +} + +static inline void macvlan_clear_addr_change(struct macvlan_port *port) +{ +	port->flags &= ~MACVLAN_F_ADDRCHANGE; +} +  /* Hash Ethernet address */  static u32 macvlan_eth_hash(const unsigned char *addr)  { @@ -181,11 +210,12 @@ static void macvlan_hash_change_addr(struct macvlan_dev *vlan,  static bool macvlan_addr_busy(const struct macvlan_port *port,  			      const unsigned char *addr)  { -	/* Test to see if the specified multicast address is +	/* Test to see if the specified address is  	 * currently in use by the underlying device or  	 * another macvlan.  	 */ -	if (ether_addr_equal_64bits(port->dev->dev_addr, addr)) +	if (!macvlan_passthru(port) && !macvlan_addr_change(port) && +	    ether_addr_equal_64bits(port->dev->dev_addr, addr))  		return true;  	if (macvlan_hash_lookup(port, addr)) @@ -445,7 +475,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)  	}  	macvlan_forward_source(skb, port, eth->h_source); -	if (port->passthru) +	if (macvlan_passthru(port))  		vlan = list_first_or_null_rcu(&port->vlans,  					      struct macvlan_dev, list);  	else @@ -574,7 +604,7 @@ static int macvlan_open(struct net_device *dev)  	struct net_device *lowerdev = vlan->lowerdev;  	int err; -	if (vlan->port->passthru) { +	if (macvlan_passthru(vlan->port)) {  		if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC)) {  			err = dev_set_promiscuity(lowerdev, 1);  			if (err < 0) @@ -649,7 +679,7 @@ static int macvlan_stop(struct net_device *dev)  	dev_uc_unsync(lowerdev, dev);  	dev_mc_unsync(lowerdev, dev); -	if (vlan->port->passthru) { +	if (macvlan_passthru(vlan->port)) {  		if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))  			dev_set_promiscuity(lowerdev, -1);  		goto hash_del; @@ -672,6 +702,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)  {  	struct macvlan_dev *vlan = netdev_priv(dev);  	struct net_device *lowerdev = vlan->lowerdev; +	struct macvlan_port *port = vlan->port;  	int err;  	if (!(dev->flags & IFF_UP)) { @@ -682,7 +713,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)  		if (macvlan_addr_busy(vlan->port, addr))  			return -EBUSY; -		if (!vlan->port->passthru) { +		if (!macvlan_passthru(port)) {  			err = dev_uc_add(lowerdev, addr);  			if (err)  				return err; @@ -692,6 +723,15 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)  		macvlan_hash_change_addr(vlan, addr);  	} +	if (macvlan_passthru(port) && !macvlan_addr_change(port)) { +		/* Since addr_change isn't set, we are here due to lower +		 * device change.  Save the lower-dev address so we can +		 * restore it later. +		 */ +		ether_addr_copy(vlan->port->perm_addr, +				lowerdev->dev_addr); +	} +	macvlan_clear_addr_change(port);  	return 0;  } @@ -703,7 +743,12 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p)  	if (!is_valid_ether_addr(addr->sa_data))  		return -EADDRNOTAVAIL; +	/* If the addresses are the same, this is a no-op */ +	if (ether_addr_equal(dev->dev_addr, addr->sa_data)) +		return 0; +  	if (vlan->mode == MACVLAN_MODE_PASSTHRU) { +		macvlan_set_addr_change(vlan->port);  		dev_set_mac_address(vlan->lowerdev, addr);  		return 0;  	} @@ -789,10 +834,12 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)   */  static struct lock_class_key macvlan_netdev_addr_lock_key; -#define ALWAYS_ON_FEATURES \ -	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX | \ +#define ALWAYS_ON_OFFLOADS \ +	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \  	 NETIF_F_GSO_ROBUST) +#define ALWAYS_ON_FEATURES (ALWAYS_ON_OFFLOADS | NETIF_F_LLTX) +  #define MACVLAN_FEATURES \  	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \  	 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \ @@ -827,6 +874,7 @@ static int macvlan_init(struct net_device *dev)  	dev->features		|= ALWAYS_ON_FEATURES;  	dev->hw_features	|= NETIF_F_LRO;  	dev->vlan_features	= lowerdev->vlan_features & MACVLAN_FEATURES; +	dev->vlan_features	|= ALWAYS_ON_OFFLOADS;  	dev->gso_max_size	= lowerdev->gso_max_size;  	dev->gso_max_segs	= lowerdev->gso_max_segs;  	dev->hard_header_len	= lowerdev->hard_header_len; @@ -925,7 +973,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],  	/* Support unicast filter only on passthru devices.  	 * Multicast filter should be allowed on all devices.  	 */ -	if (!vlan->port->passthru && is_unicast_ether_addr(addr)) +	if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))  		return -EOPNOTSUPP;  	if (flags & NLM_F_REPLACE) @@ -949,7 +997,7 @@ static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],  	/* Support unicast filter only on passthru devices.  	 * Multicast filter should be allowed on all devices.  	 */ -	if (!vlan->port->passthru && is_unicast_ether_addr(addr)) +	if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))  		return -EOPNOTSUPP;  	if (is_unicast_ether_addr(addr)) @@ -1089,7 +1137,7 @@ void macvlan_common_setup(struct net_device *dev)  	netif_keep_dst(dev);  	dev->priv_flags	       |= IFF_UNICAST_FLT;  	dev->netdev_ops		= &macvlan_netdev_ops; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  	dev->header_ops		= &macvlan_hard_header_ops;  	dev->ethtool_ops	= &macvlan_ethtool_ops;  } @@ -1117,8 +1165,8 @@ static int macvlan_port_create(struct net_device *dev)  	if (port == NULL)  		return -ENOMEM; -	port->passthru = false;  	port->dev = dev; +	ether_addr_copy(port->perm_addr, dev->dev_addr);  	INIT_LIST_HEAD(&port->vlans);  	for (i = 0; i < MACVLAN_HASH_SIZE; i++)  		INIT_HLIST_HEAD(&port->vlan_hash[i]); @@ -1158,6 +1206,18 @@ static void macvlan_port_destroy(struct net_device *dev)  		kfree_skb(skb);  	} +	/* If the lower device address has been changed by passthru +	 * macvlan, put it back. +	 */ +	if (macvlan_passthru(port) && +	    !ether_addr_equal(port->dev->dev_addr, port->perm_addr)) { +		struct sockaddr sa; + +		sa.sa_family = port->dev->type; +		memcpy(&sa.sa_data, port->perm_addr, port->dev->addr_len); +		dev_set_mac_address(port->dev, &sa); +	} +  	kfree(port);  } @@ -1323,7 +1383,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,  	port = macvlan_port_get_rtnl(lowerdev);  	/* Only 1 macvlan device can be created in passthru mode */ -	if (port->passthru) { +	if (macvlan_passthru(port)) {  		/* The macvlan port must be not created this time,  		 * still goto destroy_macvlan_port for readability.  		 */ @@ -1349,7 +1409,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,  			err = -EINVAL;  			goto destroy_macvlan_port;  		} -		port->passthru = true; +		macvlan_set_passthru(port);  		eth_hw_addr_inherit(dev, lowerdev);  	} @@ -1431,7 +1491,7 @@ static int macvlan_changelink(struct net_device *dev,  	if (data && data[IFLA_MACVLAN_FLAGS]) {  		__u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);  		bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC; -		if (vlan->port->passthru && promisc) { +		if (macvlan_passthru(vlan->port) && promisc) {  			int err;  			if (flags & MACVLAN_FLAG_NOPROMISC) @@ -1594,7 +1654,7 @@ static int macvlan_device_event(struct notifier_block *unused,  		}  		break;  	case NETDEV_CHANGEADDR: -		if (!port->passthru) +		if (!macvlan_passthru(port))  			return NOTIFY_DONE;  		vlan = list_first_entry_or_null(&port->vlans, diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 06ee6395117f..0e27920c2b6b 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -358,7 +358,7 @@ static ssize_t enabled_store(struct config_item *item,  		if (err)  			goto out_unlock; -		pr_info("netconsole: network logging started\n"); +		pr_info("network logging started\n");  	} else {	/* false */  		/* We need to disable the netconsole before cleaning it up  		 * otherwise we might end up in write_msg() with diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c index b91603835d26..c4b3362da4a2 100644 --- a/drivers/net/nlmon.c +++ b/drivers/net/nlmon.c @@ -113,7 +113,7 @@ static void nlmon_setup(struct net_device *dev)  	dev->netdev_ops	= &nlmon_ops;  	dev->ethtool_ops = &nlmon_ethtool_ops; -	dev->destructor	= free_netdev; +	dev->needs_free_netdev = true;  	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |  			NETIF_F_HIGHDMA | NETIF_F_LLTX; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 60ffc9da6a28..3ab6c58d4be6 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -108,7 +108,7 @@ config MDIO_MOXART  config MDIO_OCTEON  	tristate "Octeon and some ThunderX SOCs MDIO buses"  	depends on 64BIT -	depends on HAS_IOMEM +	depends on HAS_IOMEM && OF_MDIO  	select MDIO_CAVIUM  	help  	  This module provides a driver for the Octeon and ThunderX MDIO @@ -127,6 +127,7 @@ config MDIO_THUNDER  	tristate "ThunderX SOCs MDIO buses"  	depends on 64BIT  	depends on PCI +	depends on !(MDIO_DEVICE=y && PHYLIB=m)  	select MDIO_CAVIUM  	help  	  This driver supports the MDIO interfaces found on Cavium diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index ed0d10f54f26..c3065236ffcc 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -908,7 +908,7 @@ static void decode_txts(struct dp83640_private *dp83640,  	if (overflow) {  		pr_debug("tx timestamp queue overflow, count %d\n", overflow);  		while (skb) { -			skb_complete_tx_timestamp(skb, NULL); +			kfree_skb(skb);  			skb = skb_dequeue(&dp83640->tx_queue);  		}  		return; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 272b051a0199..57297ba23987 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -255,34 +255,6 @@ static int marvell_config_aneg(struct phy_device *phydev)  {  	int err; -	/* The Marvell PHY has an errata which requires -	 * that certain registers get written in order -	 * to restart autonegotiation */ -	err = phy_write(phydev, MII_BMCR, BMCR_RESET); - -	if (err < 0) -		return err; - -	err = phy_write(phydev, 0x1d, 0x1f); -	if (err < 0) -		return err; - -	err = phy_write(phydev, 0x1e, 0x200c); -	if (err < 0) -		return err; - -	err = phy_write(phydev, 0x1d, 0x5); -	if (err < 0) -		return err; - -	err = phy_write(phydev, 0x1e, 0); -	if (err < 0) -		return err; - -	err = phy_write(phydev, 0x1e, 0x100); -	if (err < 0) -		return err; -  	err = marvell_set_polarity(phydev, phydev->mdix_ctrl);  	if (err < 0)  		return err; @@ -316,6 +288,42 @@ static int marvell_config_aneg(struct phy_device *phydev)  	return 0;  } +static int m88e1101_config_aneg(struct phy_device *phydev) +{ +	int err; + +	/* This Marvell PHY has an errata which requires +	 * that certain registers get written in order +	 * to restart autonegotiation +	 */ +	err = phy_write(phydev, MII_BMCR, BMCR_RESET); + +	if (err < 0) +		return err; + +	err = phy_write(phydev, 0x1d, 0x1f); +	if (err < 0) +		return err; + +	err = phy_write(phydev, 0x1e, 0x200c); +	if (err < 0) +		return err; + +	err = phy_write(phydev, 0x1d, 0x5); +	if (err < 0) +		return err; + +	err = phy_write(phydev, 0x1e, 0); +	if (err < 0) +		return err; + +	err = phy_write(phydev, 0x1e, 0x100); +	if (err < 0) +		return err; + +	return marvell_config_aneg(phydev); +} +  static int m88e1111_config_aneg(struct phy_device *phydev)  {  	int err; @@ -1119,8 +1127,6 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)  		if (adv < 0)  			return adv; -		lpa &= adv; -  		if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)  			phydev->duplex = DUPLEX_FULL;  		else @@ -1892,7 +1898,7 @@ static struct phy_driver marvell_drivers[] = {  		.flags = PHY_HAS_INTERRUPT,  		.probe = marvell_probe,  		.config_init = &marvell_config_init, -		.config_aneg = &marvell_config_aneg, +		.config_aneg = &m88e1101_config_aneg,  		.read_status = &genphy_read_status,  		.ack_interrupt = &marvell_ack_interrupt,  		.config_intr = &marvell_config_intr, diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 963838d4fac1..599ce24c514f 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -122,10 +122,9 @@ int mdio_mux_init(struct device *dev,  	pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);  	if (pb == NULL) {  		ret_val = -ENOMEM; -		goto err_parent_bus; +		goto err_pb_kz;  	} -  	pb->switch_data = data;  	pb->switch_fn = switch_fn;  	pb->current_child = -1; @@ -154,6 +153,7 @@ int mdio_mux_init(struct device *dev,  		cb->mii_bus = mdiobus_alloc();  		if (!cb->mii_bus) {  			ret_val = -ENOMEM; +			devm_kfree(dev, cb);  			of_node_put(child_bus_node);  			break;  		} @@ -170,7 +170,6 @@ int mdio_mux_init(struct device *dev,  			mdiobus_free(cb->mii_bus);  			devm_kfree(dev, cb);  		} else { -			of_node_get(child_bus_node);  			cb->next = pb->children;  			pb->children = cb;  		} @@ -181,9 +180,11 @@ int mdio_mux_init(struct device *dev,  		return 0;  	} +	devm_kfree(dev, pb); +err_pb_kz:  	/* balance the reference of_mdio_find_bus() took */ -	put_device(&pb->mii_bus->dev); - +	if (!mux_bus) +		put_device(&parent_bus->dev);  err_parent_bus:  	of_node_put(parent_bus_node);  	return ret_val; diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index a898e5c4ef1b..f99c21f78b63 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -364,9 +364,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)  	mutex_init(&bus->mdio_lock); -	if (bus->reset) -		bus->reset(bus); -  	/* de-assert bus level PHY GPIO resets */  	if (bus->num_reset_gpios > 0) {  		bus->reset_gpiod = devm_kcalloc(&bus->dev, @@ -396,6 +393,9 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)  		}  	} +	if (bus->reset) +		bus->reset(bus); +  	for (i = 0; i < PHY_MAX_ADDR; i++) {  		if ((bus->phy_mask & (1 << i)) == 0) {  			struct phy_device *phydev; @@ -658,6 +658,18 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)  	return 0;  } +static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env) +{ +	int rc; + +	/* Some devices have extra OF data and an OF-style MODALIAS */ +	rc = of_device_uevent_modalias(dev, env); +	if (rc != -ENODEV) +		return rc; + +	return 0; +} +  #ifdef CONFIG_PM  static int mdio_bus_suspend(struct device *dev)  { @@ -708,6 +720,7 @@ static const struct dev_pm_ops mdio_bus_pm_ops = {  struct bus_type mdio_bus_type = {  	.name		= "mdio_bus",  	.match		= mdio_bus_match, +	.uevent		= mdio_uevent,  	.pm		= MDIO_BUS_PM_OPS,  };  EXPORT_SYMBOL(mdio_bus_type); diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 6a5fd18f062c..8b2038844ba9 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -268,23 +268,12 @@ out:  	return ret;  } -static int kszphy_config_init(struct phy_device *phydev) +/* Some config bits need to be set again on resume, handle them here. */ +static int kszphy_config_reset(struct phy_device *phydev)  {  	struct kszphy_priv *priv = phydev->priv; -	const struct kszphy_type *type;  	int ret; -	if (!priv) -		return 0; - -	type = priv->type; - -	if (type->has_broadcast_disable) -		kszphy_broadcast_disable(phydev); - -	if (type->has_nand_tree_disable) -		kszphy_nand_tree_disable(phydev); -  	if (priv->rmii_ref_clk_sel) {  		ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);  		if (ret) { @@ -295,11 +284,30 @@ static int kszphy_config_init(struct phy_device *phydev)  	}  	if (priv->led_mode >= 0) -		kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode); +		kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);  	return 0;  } +static int kszphy_config_init(struct phy_device *phydev) +{ +	struct kszphy_priv *priv = phydev->priv; +	const struct kszphy_type *type; + +	if (!priv) +		return 0; + +	type = priv->type; + +	if (type->has_broadcast_disable) +		kszphy_broadcast_disable(phydev); + +	if (type->has_nand_tree_disable) +		kszphy_nand_tree_disable(phydev); + +	return kszphy_config_reset(phydev); +} +  static int ksz8041_config_init(struct phy_device *phydev)  {  	struct device_node *of_node = phydev->mdio.dev.of_node; @@ -611,6 +619,8 @@ static int ksz9031_read_status(struct phy_device *phydev)  	if ((regval & 0xFF) == 0xFF) {  		phy_init_hw(phydev);  		phydev->link = 0; +		if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev)) +			phydev->drv->config_intr(phydev);  	}  	return 0; @@ -700,8 +710,14 @@ static int kszphy_suspend(struct phy_device *phydev)  static int kszphy_resume(struct phy_device *phydev)  { +	int ret; +  	genphy_resume(phydev); +	ret = kszphy_config_reset(phydev); +	if (ret) +		return ret; +  	/* Enable PHY Interrupts */  	if (phy_interrupt_is_valid(phydev)) {  		phydev->interrupts = PHY_INTERRUPT_ENABLED; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 82ab8fb82587..eebb0e1c70ff 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -54,6 +54,8 @@ static const char *phy_speed_to_str(int speed)  		return "5Gbps";  	case SPEED_10000:  		return "10Gbps"; +	case SPEED_14000: +		return "14Gbps";  	case SPEED_20000:  		return "20Gbps";  	case SPEED_25000: @@ -241,7 +243,7 @@ static const struct phy_setting settings[] = {   * phy_lookup_setting - lookup a PHY setting   * @speed: speed to match   * @duplex: duplex to match - * @feature: allowed link modes + * @features: allowed link modes   * @exact: an exact match is required   *   * Search the settings array for a setting that matches the speed and diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 1da31dc47f86..74b907206aa7 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -629,7 +629,7 @@ static void sl_uninit(struct net_device *dev)  static void sl_free_netdev(struct net_device *dev)  {  	int i = dev->base_addr; -	free_netdev(dev); +  	slip_devs[i] = NULL;  } @@ -651,7 +651,8 @@ static const struct net_device_ops sl_netdev_ops = {  static void sl_setup(struct net_device *dev)  {  	dev->netdev_ops		= &sl_netdev_ops; -	dev->destructor		= sl_free_netdev; +	dev->needs_free_netdev	= true; +	dev->priv_destructor	= sl_free_netdev;  	dev->hard_header_len	= 0;  	dev->addr_len		= 0; @@ -1369,8 +1370,6 @@ static void __exit slip_exit(void)  		if (sl->tty) {  			printk(KERN_ERR "%s: tty discipline still running\n",  			       dev->name); -			/* Intentionally leak the control block. */ -			dev->destructor = NULL;  		}  		unregister_netdev(dev); diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 6c5d5ef46f75..fba8c136aa7c 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1643,7 +1643,6 @@ static void team_destructor(struct net_device *dev)  	struct team *team = netdev_priv(dev);  	free_percpu(team->pcpu_stats); -	free_netdev(dev);  }  static int team_open(struct net_device *dev) @@ -2079,7 +2078,8 @@ static void team_setup(struct net_device *dev)  	dev->netdev_ops = &team_netdev_ops;  	dev->ethtool_ops = &team_ethtool_ops; -	dev->destructor	= team_destructor; +	dev->needs_free_netdev = true; +	dev->priv_destructor = team_destructor;  	dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);  	dev->priv_flags |= IFF_NO_QUEUE;  	dev->priv_flags |= IFF_TEAM; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index bbd707b9ef7a..9ee7d4275640 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1560,7 +1560,6 @@ static void tun_free_netdev(struct net_device *dev)  	free_percpu(tun->pcpu_stats);  	tun_flow_uninit(tun);  	security_tun_dev_free_security(tun->security); -	free_netdev(dev);  }  static void tun_setup(struct net_device *dev) @@ -1571,7 +1570,8 @@ static void tun_setup(struct net_device *dev)  	tun->group = INVALID_GID;  	dev->ethtool_ops = &tun_ethtool_ops; -	dev->destructor = tun_free_netdev; +	dev->needs_free_netdev = true; +	dev->priv_destructor = tun_free_netdev;  	/* We prefer our own queue length */  	dev->tx_queue_len = TUN_READQ_SIZE;  } diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 51cf60092a18..4037ab27734a 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1722,6 +1722,18 @@ static const struct driver_info lenovo_info = {  	.tx_fixup = ax88179_tx_fixup,  }; +static const struct driver_info belkin_info = { +	.description = "Belkin USB Ethernet Adapter", +	.bind	= ax88179_bind, +	.unbind = ax88179_unbind, +	.status = ax88179_status, +	.link_reset = ax88179_link_reset, +	.reset	= ax88179_reset, +	.flags	= FLAG_ETHER | FLAG_FRAMING_AX, +	.rx_fixup = ax88179_rx_fixup, +	.tx_fixup = ax88179_tx_fixup, +}; +  static const struct usb_device_id products[] = {  {  	/* ASIX AX88179 10/100/1000 */ @@ -1751,6 +1763,10 @@ static const struct usb_device_id products[] = {  	/* Lenovo OneLinkDock Gigabit LAN */  	USB_DEVICE(0x17ef, 0x304b),  	.driver_info = (unsigned long)&lenovo_info, +}, { +	/* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */ +	USB_DEVICE(0x050d, 0x0128), +	.driver_info = (unsigned long)&belkin_info,  },  	{ },  }; diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index eb52de8205f0..c7a350bbaaa7 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -298,7 +298,7 @@ static void usbpn_setup(struct net_device *dev)  	dev->addr_len		= 1;  	dev->tx_queue_len	= 3; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  }  /* diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index f3ae88fdf332..8ab281b478f2 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -310,6 +310,26 @@ skip:  		return -ENODEV;  	} +	return 0; + +bad_desc: +	dev_info(&dev->udev->dev, "bad CDC descriptors\n"); +	return -ENODEV; +} +EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); + + +/* like usbnet_generic_cdc_bind() but handles filter initialization + * correctly + */ +int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf) +{ +	int rv; + +	rv = usbnet_generic_cdc_bind(dev, intf); +	if (rv < 0) +		goto bail_out; +  	/* Some devices don't initialise properly. In particular  	 * the packet filter is not reset. There are devices that  	 * don't do reset all the way. So the packet filter should @@ -317,13 +337,10 @@ skip:  	 */  	usbnet_cdc_update_filter(dev); -	return 0; - -bad_desc: -	dev_info(&dev->udev->dev, "bad CDC descriptors\n"); -	return -ENODEV; +bail_out: +	return rv;  } -EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); +EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);  void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)  { @@ -417,7 +434,7 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)  	BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)  			< sizeof(struct cdc_state))); -	status = usbnet_generic_cdc_bind(dev, intf); +	status = usbnet_ether_cdc_bind(dev, intf);  	if (status < 0)  		return status; diff --git a/drivers/net/usb/ch9200.c b/drivers/net/usb/ch9200.c index c4f1c363e24b..9df3c1ffff35 100644 --- a/drivers/net/usb/ch9200.c +++ b/drivers/net/usb/ch9200.c @@ -310,8 +310,8 @@ static int get_mac_address(struct usbnet *dev, unsigned char *data)  	int rd_mac_len = 0;  	netdev_dbg(dev->net, "get_mac_address:\n\tusbnet VID:%0x PID:%0x\n", -		   dev->udev->descriptor.idVendor, -		   dev->udev->descriptor.idProduct); +		   le16_to_cpu(dev->udev->descriptor.idVendor), +		   le16_to_cpu(dev->udev->descriptor.idProduct));  	memset(mac_addr, 0, sizeof(mac_addr));  	rd_mac_len = control_read(dev, REQUEST_READ, 0, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index d7165767ca9d..32a22f4e8356 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -123,7 +123,7 @@ static void qmimux_setup(struct net_device *dev)  	dev->addr_len        = 0;  	dev->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;  	dev->netdev_ops      = &qmimux_netdev_ops; -	dev->destructor      = free_netdev; +	dev->needs_free_netdev = true;  }  static struct net_device *qmimux_find_dev(struct usbnet *dev, u8 mux_id) @@ -1192,10 +1192,14 @@ static const struct usb_device_id products[] = {  	{QMI_FIXED_INTF(0x1199, 0x9056, 8)},	/* Sierra Wireless Modem */  	{QMI_FIXED_INTF(0x1199, 0x9057, 8)},  	{QMI_FIXED_INTF(0x1199, 0x9061, 8)},	/* Sierra Wireless Modem */ +	{QMI_FIXED_INTF(0x1199, 0x9063, 8)},	/* Sierra Wireless EM7305 */ +	{QMI_FIXED_INTF(0x1199, 0x9063, 10)},	/* Sierra Wireless EM7305 */  	{QMI_FIXED_INTF(0x1199, 0x9071, 8)},	/* Sierra Wireless MC74xx */  	{QMI_FIXED_INTF(0x1199, 0x9071, 10)},	/* Sierra Wireless MC74xx */  	{QMI_FIXED_INTF(0x1199, 0x9079, 8)},	/* Sierra Wireless EM74xx */  	{QMI_FIXED_INTF(0x1199, 0x9079, 10)},	/* Sierra Wireless EM74xx */ +	{QMI_FIXED_INTF(0x1199, 0x907b, 8)},	/* Sierra Wireless EM74xx */ +	{QMI_FIXED_INTF(0x1199, 0x907b, 10)},	/* Sierra Wireless EM74xx */  	{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},	/* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */  	{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},	/* Alcatel L800MA */  	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */ @@ -1204,6 +1208,8 @@ static const struct usb_device_id products[] = {  	{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},	/* Telit ME910 */  	{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},	/* Telit LE920 */  	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)},	/* Telit LE920, LE920A4 */ +	{QMI_FIXED_INTF(0x1c9e, 0x9801, 3)},	/* Telewell TW-3G HSPA+ */ +	{QMI_FIXED_INTF(0x1c9e, 0x9803, 4)},	/* Telewell TW-3G HSPA+ */  	{QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},	/* XS Stick W100-2 from 4G Systems */  	{QMI_FIXED_INTF(0x0b3c, 0xc000, 4)},	/* Olivetti Olicard 100 */  	{QMI_FIXED_INTF(0x0b3c, 0xc001, 4)},	/* Olivetti Olicard 120 */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index ddc62cb69be8..1a419a45e2a2 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -4368,6 +4368,8 @@ static u8 rtl_get_version(struct usb_interface *intf)  		break;  	} +	dev_dbg(&intf->dev, "Detected version 0x%04x\n", version); +  	return version;  } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 765400b62168..2dfca96a63b6 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -681,7 +681,7 @@ static int smsc95xx_set_features(struct net_device *netdev,  	if (ret < 0)  		return ret; -	if (features & NETIF_F_HW_CSUM) +	if (features & NETIF_F_IP_CSUM)  		read_buf |= Tx_COE_EN_;  	else  		read_buf &= ~Tx_COE_EN_; @@ -1279,12 +1279,19 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)  	spin_lock_init(&pdata->mac_cr_lock); +	/* LAN95xx devices do not alter the computed checksum of 0 to 0xffff. +	 * RFC 2460, ipv6 UDP calculated checksum yields a result of zero must +	 * be changed to 0xffff. RFC 768, ipv4 UDP computed checksum is zero, +	 * it is transmitted as all ones. The zero transmitted checksum means +	 * transmitter generated no checksum. Hence, enable csum offload only +	 * for ipv4 packets. +	 */  	if (DEFAULT_TX_CSUM_ENABLE) -		dev->net->features |= NETIF_F_HW_CSUM; +		dev->net->features |= NETIF_F_IP_CSUM;  	if (DEFAULT_RX_CSUM_ENABLE)  		dev->net->features |= NETIF_F_RXCSUM; -	dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM; +	dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;  	smsc95xx_init_mac_address(dev); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 38f0f03a29c8..364fa9d11d1a 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -222,7 +222,6 @@ static int veth_dev_init(struct net_device *dev)  static void veth_dev_free(struct net_device *dev)  {  	free_percpu(dev->vstats); -	free_netdev(dev);  }  #ifdef CONFIG_NET_POLL_CONTROLLER @@ -317,7 +316,8 @@ static void veth_setup(struct net_device *dev)  			       NETIF_F_HW_VLAN_STAG_TX |  			       NETIF_F_HW_VLAN_CTAG_RX |  			       NETIF_F_HW_VLAN_STAG_RX); -	dev->destructor = veth_dev_free; +	dev->needs_free_netdev = true; +	dev->priv_destructor = veth_dev_free;  	dev->max_mtu = ETH_MAX_MTU;  	dev->hw_features = VETH_FEATURES; @@ -383,7 +383,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,  		tbp = tb;  	} -	if (tbp[IFLA_IFNAME]) { +	if (ifmp && tbp[IFLA_IFNAME]) {  		nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);  		name_assign_type = NET_NAME_USER;  	} else { @@ -402,7 +402,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,  		return PTR_ERR(peer);  	} -	if (tbp[IFLA_ADDRESS] == NULL) +	if (!ifmp || !tbp[IFLA_ADDRESS])  		eth_hw_addr_random(peer);  	if (ifmp && (dev->ifindex != 0)) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 9320d96a1632..143d8a95a60d 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -869,7 +869,7 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq,  	unsigned int len;  	len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len), -				rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len); +				rq->min_buf_len, PAGE_SIZE - hdr_len);  	return ALIGN(len, L1_CACHE_BYTES);  } @@ -1797,6 +1797,7 @@ static void virtnet_freeze_down(struct virtio_device *vdev)  	flush_work(&vi->config_work);  	netif_device_detach(vi->dev); +	netif_tx_disable(vi->dev);  	cancel_delayed_work_sync(&vi->refill);  	if (netif_running(vi->dev)) { @@ -1989,6 +1990,7 @@ static const struct net_device_ops virtnet_netdev = {  	.ndo_poll_controller = virtnet_netpoll,  #endif  	.ndo_xdp		= virtnet_xdp, +	.ndo_features_check	= passthru_features_check,  };  static void virtnet_config_changed_work(struct work_struct *work) @@ -2143,7 +2145,8 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu  	unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len;  	unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size); -	return max(min_buf_len, hdr_len); +	return max(max(min_buf_len, hdr_len) - hdr_len, +		   (unsigned int)GOOD_PACKET_LEN);  }  static int virtnet_find_vqs(struct virtnet_info *vi) diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 25bc764ae7dc..d1c7029ded7c 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2962,6 +2962,11 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter)  	/* we need to enable NAPI, otherwise dev_close will deadlock */  	for (i = 0; i < adapter->num_rx_queues; i++)  		napi_enable(&adapter->rx_queue[i].napi); +	/* +	 * Need to clear the quiesce bit to ensure that vmxnet3_close +	 * can quiesce the device properly +	 */ +	clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);  	dev_close(adapter->netdev);  } diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index ceda5861da78..022c0b5f9844 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -36,12 +36,14 @@  #include <net/addrconf.h>  #include <net/l3mdev.h>  #include <net/fib_rules.h> +#include <net/netns/generic.h>  #define DRV_NAME	"vrf"  #define DRV_VERSION	"1.0"  #define FIB_RULE_PREF  1000       /* default preference for FIB rules */ -static bool add_fib_rules = true; + +static unsigned int vrf_net_id;  struct net_vrf {  	struct rtable __rcu	*rth; @@ -989,6 +991,7 @@ static u32 vrf_fib_table(const struct net_device *dev)  static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)  { +	kfree_skb(skb);  	return 0;  } @@ -998,7 +1001,7 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook,  {  	struct net *net = dev_net(dev); -	if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0) +	if (nf_hook(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) != 1)  		skb = NULL;    /* kfree_skb(skb) handled by nf code */  	return skb; @@ -1347,7 +1350,7 @@ static void vrf_setup(struct net_device *dev)  	dev->netdev_ops = &vrf_netdev_ops;  	dev->l3mdev_ops = &vrf_l3mdev_ops;  	dev->ethtool_ops = &vrf_ethtool_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	/* Fill in device structure with ethernet-generic values. */  	eth_hw_addr_random(dev); @@ -1393,6 +1396,8 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,  		       struct nlattr *tb[], struct nlattr *data[])  {  	struct net_vrf *vrf = netdev_priv(dev); +	bool *add_fib_rules; +	struct net *net;  	int err;  	if (!data || !data[IFLA_VRF_TABLE]) @@ -1408,13 +1413,15 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,  	if (err)  		goto out; -	if (add_fib_rules) { +	net = dev_net(dev); +	add_fib_rules = net_generic(net, vrf_net_id); +	if (*add_fib_rules) {  		err = vrf_add_fib_rules(dev);  		if (err) {  			unregister_netdevice(dev);  			goto out;  		} -		add_fib_rules = false; +		*add_fib_rules = false;  	}  out: @@ -1497,16 +1504,38 @@ static struct notifier_block vrf_notifier_block __read_mostly = {  	.notifier_call = vrf_device_event,  }; +/* Initialize per network namespace state */ +static int __net_init vrf_netns_init(struct net *net) +{ +	bool *add_fib_rules = net_generic(net, vrf_net_id); + +	*add_fib_rules = true; + +	return 0; +} + +static struct pernet_operations vrf_net_ops __net_initdata = { +	.init = vrf_netns_init, +	.id   = &vrf_net_id, +	.size = sizeof(bool), +}; +  static int __init vrf_init_module(void)  {  	int rc;  	register_netdevice_notifier(&vrf_notifier_block); -	rc = rtnl_link_register(&vrf_link_ops); +	rc = register_pernet_subsys(&vrf_net_ops);  	if (rc < 0)  		goto error; +	rc = rtnl_link_register(&vrf_link_ops); +	if (rc < 0) { +		unregister_pernet_subsys(&vrf_net_ops); +		goto error; +	} +  	return 0;  error: diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c index 7f0136f2dd9d..c28bdce14fd5 100644 --- a/drivers/net/vsockmon.c +++ b/drivers/net/vsockmon.c @@ -135,7 +135,7 @@ static void vsockmon_setup(struct net_device *dev)  	dev->netdev_ops	= &vsockmon_ops;  	dev->ethtool_ops = &vsockmon_ethtool_ops; -	dev->destructor	= free_netdev; +	dev->needs_free_netdev = true;  	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |  			NETIF_F_HIGHDMA | NETIF_F_LLTX; diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 328b4712683c..5fa798a5c9a6 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -59,6 +59,8 @@ static const u8 all_zeros_mac[ETH_ALEN + 2];  static int vxlan_sock_add(struct vxlan_dev *vxlan); +static void vxlan_vs_del_dev(struct vxlan_dev *vxlan); +  /* per-network namespace private data for this module */  struct vxlan_net {  	struct list_head  vxlan_list; @@ -740,6 +742,22 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f)  	call_rcu(&f->rcu, vxlan_fdb_free);  } +static void vxlan_dst_free(struct rcu_head *head) +{ +	struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); + +	dst_cache_destroy(&rd->dst_cache); +	kfree(rd); +} + +static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, +				  struct vxlan_rdst *rd) +{ +	list_del_rcu(&rd->list); +	vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); +	call_rcu(&rd->rcu, vxlan_dst_free); +} +  static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,  			   union vxlan_addr *ip, __be16 *port, __be32 *src_vni,  			   __be32 *vni, u32 *ifindex) @@ -864,9 +882,7 @@ static int __vxlan_fdb_delete(struct vxlan_dev *vxlan,  	 * otherwise destroy the fdb entry  	 */  	if (rd && !list_is_singular(&f->remotes)) { -		list_del_rcu(&rd->list); -		vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); -		kfree_rcu(rd, rcu); +		vxlan_fdb_dst_destroy(vxlan, f, rd);  		goto out;  	} @@ -1067,6 +1083,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)  	rcu_assign_pointer(vxlan->vn4_sock, NULL);  	synchronize_net(); +	vxlan_vs_del_dev(vxlan); +  	if (__vxlan_sock_release_prep(sock4)) {  		udp_tunnel_sock_release(sock4->sock);  		kfree(sock4); @@ -2342,6 +2360,15 @@ static void vxlan_cleanup(unsigned long arg)  	mod_timer(&vxlan->age_timer, next_timer);  } +static void vxlan_vs_del_dev(struct vxlan_dev *vxlan) +{ +	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + +	spin_lock(&vn->sock_lock); +	hlist_del_init_rcu(&vxlan->hlist); +	spin_unlock(&vn->sock_lock); +} +  static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)  {  	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); @@ -2584,7 +2611,7 @@ static void vxlan_setup(struct net_device *dev)  	eth_hw_addr_random(dev);  	ether_setup(dev); -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	SET_NETDEV_DEVTYPE(dev, &vxlan_type);  	dev->features	|= NETIF_F_LLTX; @@ -3286,15 +3313,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],  static void vxlan_dellink(struct net_device *dev, struct list_head *head)  {  	struct vxlan_dev *vxlan = netdev_priv(dev); -	struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);  	vxlan_flush(vxlan, true); -	spin_lock(&vn->sock_lock); -	if (!hlist_unhashed(&vxlan->hlist)) -		hlist_del_rcu(&vxlan->hlist); -	spin_unlock(&vn->sock_lock); -  	gro_cells_destroy(&vxlan->gro_cells);  	list_del(&vxlan->next);  	unregister_netdevice_queue(dev, head); diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 65ee2a6f248c..a0d76f70c428 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -475,7 +475,7 @@ static void dlci_setup(struct net_device *dev)  	dev->flags		= 0;  	dev->header_ops		= &dlci_header_ops;  	dev->netdev_ops		= &dlci_netdev_ops; -	dev->destructor		= free_netdev; +	dev->needs_free_netdev	= true;  	dlp->receive		= dlci_receive; diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index eb915281197e..78596e42a3f3 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -1106,7 +1106,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)  		return -EIO;  	} -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	*get_dev_p(pvc, type) = dev;  	if (!used) {  		state(hdlc)->dce_changed = 1; diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 9df9ed62beff..63f749078a1f 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -306,7 +306,7 @@ static const struct net_device_ops lapbeth_netdev_ops = {  static void lapbeth_setup(struct net_device *dev)  {  	dev->netdev_ops	     = &lapbeth_netdev_ops; -	dev->destructor	     = free_netdev; +	dev->needs_free_netdev = true;  	dev->type            = ARPHRD_X25;  	dev->hard_header_len = 3;  	dev->mtu             = 1000; diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 91ee542de3d7..b90c77ef792e 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1287,7 +1287,7 @@ void init_netdev(struct net_device *dev)  	struct ath6kl *ar = ath6kl_priv(dev);  	dev->netdev_ops = &ath6kl_netdev_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;  	dev->needed_headroom = ETH_HLEN; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index d5e993dc9b23..517a315e259b 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1271,6 +1271,8 @@ static int wcn36xx_remove(struct platform_device *pdev)  	qcom_smem_state_put(wcn->tx_enable_state);  	qcom_smem_state_put(wcn->tx_rings_empty_state); +	rpmsg_destroy_ept(wcn->smd_channel); +  	iounmap(wcn->dxe_base);  	iounmap(wcn->ccu_base); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index cd1d6730eab7..617199c0e5a0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5225,7 +5225,6 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)  	if (vif)  		brcmf_free_vif(vif); -	free_netdev(ndev);  }  static bool brcmf_is_linkup(const struct brcmf_event_msg *e) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index a3d82368f1a9..511d190c6cca 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -624,7 +624,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,  		if (!ndev)  			return ERR_PTR(-ENOMEM); -		ndev->destructor = brcmf_cfg80211_free_netdev; +		ndev->needs_free_netdev = true; +		ndev->priv_destructor = brcmf_cfg80211_free_netdev;  		ifp = netdev_priv(ndev);  		ifp->ndev = ndev;  		/* store mapping ifidx to bsscfgidx */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index c7c1e9906500..d231042f19d6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -442,7 +442,7 @@ struct brcmf_fw {  	const char *nvram_name;  	u16 domain_nr;  	u16 bus_nr; -	void (*done)(struct device *dev, const struct firmware *fw, +	void (*done)(struct device *dev, int err, const struct firmware *fw,  		     void *nvram_image, u32 nvram_len);  }; @@ -477,52 +477,51 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)  	if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))  		goto fail; -	fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); +	fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);  	kfree(fwctx);  	return;  fail:  	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));  	release_firmware(fwctx->code); -	device_release_driver(fwctx->dev); +	fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);  	kfree(fwctx);  }  static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)  {  	struct brcmf_fw *fwctx = ctx; -	int ret; +	int ret = 0;  	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); -	if (!fw) +	if (!fw) { +		ret = -ENOENT;  		goto fail; - -	/* only requested code so done here */ -	if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { -		fwctx->done(fwctx->dev, fw, NULL, 0); -		kfree(fwctx); -		return;  	} +	/* only requested code so done here */ +	if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) +		goto done; +  	fwctx->code = fw;  	ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,  				      fwctx->dev, GFP_KERNEL, fwctx,  				      brcmf_fw_request_nvram_done); -	if (!ret) -		return; - -	brcmf_fw_request_nvram_done(NULL, fwctx); +	/* pass NULL to nvram callback for bcm47xx fallback */ +	if (ret) +		brcmf_fw_request_nvram_done(NULL, fwctx);  	return;  fail:  	brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); -	device_release_driver(fwctx->dev); +done: +	fwctx->done(fwctx->dev, ret, fw, NULL, 0);  	kfree(fwctx);  }  int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,  				const char *code, const char *nvram, -				void (*fw_cb)(struct device *dev, +				void (*fw_cb)(struct device *dev, int err,  					      const struct firmware *fw,  					      void *nvram_image, u32 nvram_len),  				u16 domain_nr, u16 bus_nr) @@ -555,7 +554,7 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,  int brcmf_fw_get_firmwares(struct device *dev, u16 flags,  			   const char *code, const char *nvram, -			   void (*fw_cb)(struct device *dev, +			   void (*fw_cb)(struct device *dev, int err,  					 const struct firmware *fw,  					 void *nvram_image, u32 nvram_len))  { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index d3c9f0d52ae3..8fa4b7e1ab3d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -73,13 +73,13 @@ void brcmf_fw_nvram_free(void *nvram);   */  int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,  				const char *code, const char *nvram, -				void (*fw_cb)(struct device *dev, +				void (*fw_cb)(struct device *dev, int err,  					      const struct firmware *fw,  					      void *nvram_image, u32 nvram_len),  				u16 domain_nr, u16 bus_nr);  int brcmf_fw_get_firmwares(struct device *dev, u16 flags,  			   const char *code, const char *nvram, -			   void (*fw_cb)(struct device *dev, +			   void (*fw_cb)(struct device *dev, int err,  					 const struct firmware *fw,  					 void *nvram_image, u32 nvram_len)); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 72373e59308e..f59642b2c935 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -2145,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)  	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);  	struct brcmf_fws_mac_descriptor *entry; -	if (!ifp->ndev || fws->fcmode == BRCMF_FWS_FCMODE_NONE) +	if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))  		return;  	entry = &fws->desc.iface[ifp->ifidx]; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index f36b96dc6acd..f878706613e6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1650,16 +1650,23 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {  	.write32 = brcmf_pcie_buscore_write32,  }; -static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, +static void brcmf_pcie_setup(struct device *dev, int ret, +			     const struct firmware *fw,  			     void *nvram, u32 nvram_len)  { -	struct brcmf_bus *bus = dev_get_drvdata(dev); -	struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie; -	struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo; +	struct brcmf_bus *bus; +	struct brcmf_pciedev *pcie_bus_dev; +	struct brcmf_pciedev_info *devinfo;  	struct brcmf_commonring **flowrings; -	int ret;  	u32 i; +	/* check firmware loading result */ +	if (ret) +		goto fail; + +	bus = dev_get_drvdata(dev); +	pcie_bus_dev = bus->bus_priv.pcie; +	devinfo = pcie_bus_dev->devinfo;  	brcmf_pcie_attach(devinfo);  	/* Some of the firmwares have the size of the memory of the device diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index fc64b8913aa6..5653d6dd38f6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3422,7 +3422,7 @@ static int brcmf_sdio_bus_preinit(struct device *dev)  		/* otherwise, set txglomalign */  		value = sdiodev->settings->bus.sdio.sd_sgentry_align;  		/* SDIO ADMA requires at least 32 bit alignment */ -		value = max_t(u32, value, 4); +		value = max_t(u32, value, ALIGNMENT);  		err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,  					   sizeof(u32));  	} @@ -3982,21 +3982,26 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {  	.get_memdump = brcmf_sdio_bus_get_memdump,  }; -static void brcmf_sdio_firmware_callback(struct device *dev, +static void brcmf_sdio_firmware_callback(struct device *dev, int err,  					 const struct firmware *code,  					 void *nvram, u32 nvram_len)  { -	struct brcmf_bus *bus_if = dev_get_drvdata(dev); -	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; -	struct brcmf_sdio *bus = sdiodev->bus; -	int err = 0; +	struct brcmf_bus *bus_if; +	struct brcmf_sdio_dev *sdiodev; +	struct brcmf_sdio *bus;  	u8 saveclk; -	brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); +	brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); +	bus_if = dev_get_drvdata(dev); +	sdiodev = bus_if->bus_priv.sdio; +	if (err) +		goto fail;  	if (!bus_if->drvr)  		return; +	bus = sdiodev->bus; +  	/* try to download image and nvram to the dongle */  	bus->alp_only = true;  	err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); @@ -4083,6 +4088,7 @@ release:  fail:  	brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);  	device_release_driver(dev); +	device_release_driver(&sdiodev->func[2]->dev);  }  struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index e4d545f9edee..0eea48e73331 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -1159,17 +1159,18 @@ fail:  	return ret;  } -static void brcmf_usb_probe_phase2(struct device *dev, +static void brcmf_usb_probe_phase2(struct device *dev, int ret,  				   const struct firmware *fw,  				   void *nvram, u32 nvlen)  {  	struct brcmf_bus *bus = dev_get_drvdata(dev); -	struct brcmf_usbdev_info *devinfo; -	int ret; +	struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo; + +	if (ret) +		goto error;  	brcmf_dbg(USB, "Start fw downloading\n"); -	devinfo = bus->bus_priv.usb->devinfo;  	ret = check_file(fw->data);  	if (ret < 0) {  		brcmf_err("invalid firmware\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c index 3b3e076571d6..45e2efc70d19 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-7000.c @@ -79,8 +79,8 @@  /* Lowest firmware API version supported */  #define IWL7260_UCODE_API_MIN	17  #define IWL7265_UCODE_API_MIN	17 -#define IWL7265D_UCODE_API_MIN	17 -#define IWL3168_UCODE_API_MIN	20 +#define IWL7265D_UCODE_API_MIN	22 +#define IWL3168_UCODE_API_MIN	22  /* NVM versions */  #define IWL7260_NVM_VERSION		0x0a1d diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index b9718c0cf174..89137717c1fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c @@ -74,8 +74,8 @@  #define IWL8265_UCODE_API_MAX	30  /* Lowest firmware API version supported */ -#define IWL8000_UCODE_API_MIN	17 -#define IWL8265_UCODE_API_MIN	20 +#define IWL8000_UCODE_API_MIN	22 +#define IWL8265_UCODE_API_MIN	22  /* NVM versions */  #define IWL8000_NVM_VERSION		0x0a1d diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 306bc967742e..77efbb78e867 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -370,6 +370,7 @@  #define MON_DMARB_RD_DATA_ADDR		(0xa03c5c)  #define DBGC_IN_SAMPLE			(0xa03c00) +#define DBGC_OUT_CTRL			(0xa03c0c)  /* enable the ID buf for read */  #define WFPM_PS_CTL_CLR			0xA0300C diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h index 1b7d265ffb0a..a10c6aae9ab9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h @@ -307,6 +307,11 @@ enum {  /* Bit 1-3: LQ command color. Used to match responses to LQ commands */  #define LQ_FLAG_COLOR_POS               1  #define LQ_FLAG_COLOR_MSK               (7 << LQ_FLAG_COLOR_POS) +#define LQ_FLAG_COLOR_GET(_f)		(((_f) & LQ_FLAG_COLOR_MSK) >>\ +					 LQ_FLAG_COLOR_POS) +#define LQ_FLAGS_COLOR_INC(_c)		((((_c) + 1) << LQ_FLAG_COLOR_POS) &\ +					 LQ_FLAG_COLOR_MSK) +#define LQ_FLAG_COLOR_SET(_f, _c)	((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK))  /* Bit 4-5: Tx RTS BW Signalling   * (0) No RTS BW signalling diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h index 81b98915b1a4..1360ebfdc51b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h @@ -519,8 +519,11 @@ struct agg_tx_status {   * bit-7 invalid rate indication   */  #define TX_RES_INIT_RATE_INDEX_MSK 0x0f +#define TX_RES_RATE_TABLE_COLOR_POS 4  #define TX_RES_RATE_TABLE_COLOR_MSK 0x70  #define TX_RES_INV_RATE_INDEX_MSK 0x80 +#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\ +				       TX_RES_RATE_TABLE_COLOR_POS)  #define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)  #define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 7b86a4f1b574..c8712e6eea74 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -1002,14 +1002,6 @@ int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,  	return 0;  } -static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm) -{ -	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) -		iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); -	else -		iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1); -} -  int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)  {  	u8 *ptr; @@ -1023,10 +1015,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)  	/* EARLY START - firmware's configuration is hard coded */  	if ((!mvm->fw->dbg_conf_tlv[conf_id] ||  	     !mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) && -	    conf_id == FW_DBG_START_FROM_ALIVE) { -		iwl_mvm_restart_early_start(mvm); +	    conf_id == FW_DBG_START_FROM_ALIVE)  		return 0; -	}  	if (!mvm->fw->dbg_conf_tlv[conf_id])  		return -EINVAL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 0f1831b41915..fd2fc46e2fe5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1040,7 +1040,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,  		struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6;  		struct iwl_mac_beacon_cmd_v7 beacon_cmd;  	} u = {}; -	struct iwl_mac_beacon_cmd beacon_cmd; +	struct iwl_mac_beacon_cmd beacon_cmd = {};  	struct ieee80211_tx_info *info;  	u32 beacon_skb_len;  	u32 rate, tx_flags; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 4e74a6b90e70..52f8d7a6a7dc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1730,8 +1730,11 @@ int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq);   */  static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)  { +	u32 cmd_queue = iwl_mvm_is_dqa_supported(mvm) ? IWL_MVM_DQA_CMD_QUEUE : +		IWL_MVM_CMD_QUEUE; +  	return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) & -		~BIT(IWL_MVM_CMD_QUEUE)); +		~BIT(cmd_queue));  }  static inline @@ -1753,6 +1756,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)  	if (!iwl_mvm_has_new_tx_api(mvm))  		iwl_free_fw_paging(mvm);  	mvm->ucode_loaded = false; +	mvm->fw_dbg_conf = FW_DBG_INVALID;  	iwl_trans_stop_device(mvm->trans);  } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 9ffff6ed8133..3da5ec40aaea 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1149,21 +1149,37 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)  	mutex_lock(&mvm->mutex); -	/* stop recording */  	if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { +		/* stop recording */  		iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); + +		iwl_mvm_fw_error_dump(mvm); + +		/* start recording again if the firmware is not crashed */ +		if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) && +		    mvm->fw->dbg_dest_tlv) +			iwl_clear_bits_prph(mvm->trans, +					    MON_BUFF_SAMPLE_CTL, 0x100);  	} else { +		u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE); +		u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL); + +		/* stop recording */  		iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0); -		/* wait before we collect the data till the DBGC stop */  		udelay(100); -	} +		iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0); +		/* wait before we collect the data till the DBGC stop */ +		udelay(500); -	iwl_mvm_fw_error_dump(mvm); +		iwl_mvm_fw_error_dump(mvm); -	/* start recording again if the firmware is not crashed */ -	WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) && -		     mvm->fw->dbg_dest_tlv && -		     iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf)); +		/* start recording again if the firmware is not crashed */ +		if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) && +		    mvm->fw->dbg_dest_tlv) { +			iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample); +			iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl); +		} +	}  	mutex_unlock(&mvm->mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 7788eefcd2bd..aa785cf3cf68 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -2,7 +2,7 @@   *   * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH - * Copyright(c) 2016 Intel Deutschland GmbH + * Copyright(c) 2016 - 2017 Intel Deutschland GmbH   *   * This program is free software; you can redistribute it and/or modify it   * under the terms of version 2 of the GNU General Public License as @@ -1083,34 +1083,6 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,  		rs_get_lower_rate_in_column(lq_sta, rate);  } -/* Check if both rates are identical - * allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B - * with a rate indicating STBC/BFER and ANT_AB. - */ -static inline bool rs_rate_equal(struct rs_rate *a, -				 struct rs_rate *b, -				 bool allow_ant_mismatch) - -{ -	bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) && -		(a->bfer == b->bfer); - -	if (allow_ant_mismatch) { -		if (a->stbc || a->bfer) { -			WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d", -				  a->stbc, a->bfer, a->ant); -			ant_match |= (b->ant == ANT_A || b->ant == ANT_B); -		} else if (b->stbc || b->bfer) { -			WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d", -				  b->stbc, b->bfer, b->ant); -			ant_match |= (a->ant == ANT_A || a->ant == ANT_B); -		} -	} - -	return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) && -		(a->ldpc == b->ldpc) && (a->index == b->index) && ant_match; -} -  /* Check if both rates share the same column */  static inline bool rs_rate_column_match(struct rs_rate *a,  					struct rs_rate *b) @@ -1182,12 +1154,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  	u32 lq_hwrate;  	struct rs_rate lq_rate, tx_resp_rate;  	struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl; -	u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0]; +	u32 tlc_info = (uintptr_t)info->status.status_driver_data[0]; +	u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK; +	u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);  	u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];  	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);  	struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta; -	bool allow_ant_mismatch = fw_has_api(&mvm->fw->ucode_capa, -					     IWL_UCODE_TLV_API_LQ_SS_PARAMS);  	/* Treat uninitialized rate scaling data same as non-existing. */  	if (!lq_sta) { @@ -1262,10 +1234,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  	rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate);  	/* Here we actually compare this rate to the latest LQ command */ -	if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) { +	if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {  		IWL_DEBUG_RATE(mvm, -			       "initial tx resp rate 0x%x does not match 0x%x\n", -			       tx_resp_hwrate, lq_hwrate); +			       "tx resp color 0x%x does not match 0x%x\n", +			       lq_color, LQ_FLAG_COLOR_GET(table->flags));  		/*  		 * Since rates mis-match, the last LQ command may have failed. @@ -3326,6 +3298,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,  	u8 valid_tx_ant = 0;  	struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;  	bool toggle_ant = false; +	u32 color;  	memcpy(&rate, initial_rate, sizeof(rate)); @@ -3380,6 +3353,9 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,  				 num_rates, num_retries, valid_tx_ant,  				 toggle_ant); +	/* update the color of the LQ command (as a counter at bits 1-3) */ +	color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags)); +	lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color);  }  struct rs_bfer_active_iter_data { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h index ee207f2c0a90..3abde1cb0303 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h @@ -2,6 +2,7 @@   *   * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.   * Copyright(c) 2015 Intel Mobile Communications GmbH + * Copyright(c) 2017 Intel Deutschland GmbH   *   * This program is free software; you can redistribute it and/or modify it   * under the terms of version 2 of the GNU General Public License as @@ -357,6 +358,20 @@ struct iwl_lq_sta {  	} pers;  }; +/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp + * Note, it's iwlmvm <-> mac80211 interface. + * bits 0-7: reduced tx power + * bits 8-10: LQ command's color + */ +#define RS_DRV_DATA_TXP_MSK 0xff +#define RS_DRV_DATA_LQ_COLOR_POS 8 +#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS) +#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\ +				      RS_DRV_DATA_LQ_COLOR_POS) +#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\ +				  (((uintptr_t)_p) |\ +				   ((_c) << RS_DRV_DATA_LQ_COLOR_POS))) +  /* Initialize station's rate scaling information after adding station */  void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,  			  enum nl80211_band band, bool init); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index f5c786ddc526..614d67810d05 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2120,7 +2120,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  	if (!iwl_mvm_is_dqa_supported(mvm))  		return 0; -	if (WARN_ON(vif->type != NL80211_IFTYPE_AP)) +	if (WARN_ON(vif->type != NL80211_IFTYPE_AP && +		    vif->type != NL80211_IFTYPE_ADHOC))  		return -ENOTSUPP;  	/* @@ -2155,6 +2156,16 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)  		mvmvif->cab_queue = queue;  	} else if (!fw_has_api(&mvm->fw->ucode_capa,  			       IWL_UCODE_TLV_API_STA_TYPE)) { +		/* +		 * In IBSS, ieee80211_check_queues() sets the cab_queue to be +		 * invalid, so make sure we use the queue we want. +		 * Note that this is done here as we want to avoid making DQA +		 * changes in mac80211 layer. +		 */ +		if (vif->type == NL80211_IFTYPE_ADHOC) { +			vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; +			mvmvif->cab_queue = vif->cab_queue; +		}  		iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,  				   &cfg, timeout);  	} @@ -3321,18 +3332,15 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,  	/* Get the station from the mvm local station table */  	mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta); -	if (!mvm_sta) { -		IWL_ERR(mvm, "Failed to find station\n"); -		return -EINVAL; -	} -	sta_id = mvm_sta->sta_id; +	if (mvm_sta) +		sta_id = mvm_sta->sta_id;  	IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",  		      keyconf->keyidx, sta_id); -	if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || -	    keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || -	    keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) +	if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || +			keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || +			keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256))  		return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);  	if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 2716cb5483bf..ad62b67dceb2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -313,6 +313,7 @@ enum iwl_mvm_agg_state {   *	This is basically (last acked packet++).   * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the   *	Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA). + * @lq_color: the color of the LQ command as it appears in tx response.   * @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed.   * @state: state of the BA agreement establishment / tear down.   * @txq_id: Tx queue used by the BA session / DQA @@ -331,6 +332,7 @@ struct iwl_mvm_tid_data {  	u16 next_reclaimed;  	/* The rest is Tx AGG related */  	u32 rate_n_flags; +	u8 lq_color;  	bool amsdu_in_ampdu_allowed;  	enum iwl_mvm_agg_state state;  	u16 txq_id; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index f9cbd197246f..506d58104e1c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -790,11 +790,13 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,  	struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata);  	int ret; -	if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) -		return -EIO; -  	mutex_lock(&mvm->mutex); +	if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) { +		ret = -EIO; +		goto unlock; +	} +  	if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) {  		ret = -EINVAL;  		goto unlock; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index bcaceb64a6e8..f21901cd4a4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1323,6 +1323,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,  	struct iwl_mvm_sta *mvmsta;  	struct sk_buff_head skbs;  	u8 skb_freed = 0; +	u8 lq_color;  	u16 next_reclaimed, seq_ctl;  	bool is_ndp = false; @@ -1405,8 +1406,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,  		info->status.tx_time =  			le16_to_cpu(tx_resp->wireless_media_time);  		BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1); +		lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info);  		info->status.status_driver_data[0] = -				(void *)(uintptr_t)tx_resp->reduced_tpc; +			RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc);  		ieee80211_tx_status(mvm->hw, skb);  	} @@ -1638,6 +1640,9 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,  			le32_to_cpu(tx_resp->initial_rate);  		mvmsta->tid_data[tid].tx_time =  			le16_to_cpu(tx_resp->wireless_media_time); +		mvmsta->tid_data[tid].lq_color = +			(tx_resp->tlc_info & TX_RES_RATE_TABLE_COLOR_MSK) >> +			TX_RES_RATE_TABLE_COLOR_POS;  	}  	rcu_read_unlock(); @@ -1707,6 +1712,11 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,  	iwl_mvm_check_ratid_empty(mvm, sta, tid);  	freed = 0; + +	/* pack lq color from tid_data along the reduced txp */ +	ba_info->status.status_driver_data[0] = +		RS_DRV_DATA_PACK(tid_data->lq_color, +				 ba_info->status.status_driver_data[0]);  	ba_info->status.status_driver_data[1] = (void *)(uintptr_t)rate;  	skb_queue_walk(&reclaimed_skbs, skb) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 70acf850a9f1..93cbc7a69bcd 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2803,7 +2803,8 @@ static struct iwl_trans_dump_data  #ifdef CONFIG_PM_SLEEP  static int iwl_trans_pcie_suspend(struct iwl_trans *trans)  { -	if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) +	if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 && +	    (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))  		return iwl_pci_fw_enter_d0i3(trans);  	return 0; @@ -2811,7 +2812,8 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans)  static void iwl_trans_pcie_resume(struct iwl_trans *trans)  { -	if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) +	if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 && +	    (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))  		iwl_pci_fw_exit_d0i3(trans);  }  #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 9fb46a6f47cf..9c9bfbbabdf1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -906,7 +906,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,  	if (WARN_ON(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp))) {  		ret = -EINVAL; -		goto error; +		goto error_free_resp;  	}  	rsp = (void *)hcmd.resp_pkt->data; @@ -915,13 +915,13 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,  	if (qid > ARRAY_SIZE(trans_pcie->txq)) {  		WARN_ONCE(1, "queue index %d unsupported", qid);  		ret = -EIO; -		goto error; +		goto error_free_resp;  	}  	if (test_and_set_bit(qid, trans_pcie->queue_used)) {  		WARN_ONCE(1, "queue %d already used", qid);  		ret = -EIO; -		goto error; +		goto error_free_resp;  	}  	txq->id = qid; @@ -934,8 +934,11 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,  			   (txq->write_ptr) | (qid << 16));  	IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d\n", qid); +	iwl_free_resp(&hcmd);  	return qid; +error_free_resp: +	iwl_free_resp(&hcmd);  error:  	iwl_pcie_gen2_txq_free_memory(trans, txq);  	return ret; diff --git a/drivers/net/wireless/intersil/hostap/hostap_main.c b/drivers/net/wireless/intersil/hostap/hostap_main.c index 544fc09dcb62..1372b20f931e 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_main.c +++ b/drivers/net/wireless/intersil/hostap/hostap_main.c @@ -73,7 +73,7 @@ struct net_device * hostap_add_interface(struct local_info *local,  	dev->mem_end = mdev->mem_end;  	hostap_setup_dev(dev, local, type); -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	sprintf(dev->name, "%s%s", prefix, name);  	if (!rtnl_locked) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 002b25cff5b6..c854a557998b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2861,7 +2861,7 @@ static const struct net_device_ops hwsim_netdev_ops = {  static void hwsim_mon_setup(struct net_device *dev)  {  	dev->netdev_ops = &hwsim_netdev_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	ether_setup(dev);  	dev->priv_flags |= IFF_NO_QUEUE;  	dev->type = ARPHRD_IEEE80211_RADIOTAP; diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index dd87b9ff64c3..39b6b5e3f6e0 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1280,7 +1280,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,  			      struct net_device *dev)  {  	dev->netdev_ops = &mwifiex_netdev_ops; -	dev->destructor = free_netdev; +	dev->needs_free_netdev = true;  	/* Initialize private structure */  	priv->current_key_index = 0;  	priv->media_connected = false; diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 530586be05b4..5b1d2e8402d9 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -199,6 +199,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */  	unsigned long   remaining_credit;  	struct timer_list credit_timeout;  	u64 credit_window_start; +	bool rate_limited;  	/* Statistics */  	struct xenvif_stats stats; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 8397f6c92451..e322a862ddfe 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -106,7 +106,11 @@ static int xenvif_poll(struct napi_struct *napi, int budget)  	if (work_done < budget) {  		napi_complete_done(napi, work_done); -		xenvif_napi_schedule_or_enable_events(queue); +		/* If the queue is rate-limited, it shall be +		 * rescheduled in the timer callback. +		 */ +		if (likely(!queue->rate_limited)) +			xenvif_napi_schedule_or_enable_events(queue);  	}  	return work_done; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 602d408fa25e..5042ff8d449a 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -180,6 +180,7 @@ static void tx_add_credit(struct xenvif_queue *queue)  		max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */  	queue->remaining_credit = min(max_credit, max_burst); +	queue->rate_limited = false;  }  void xenvif_tx_credit_callback(unsigned long data) @@ -686,8 +687,10 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)  		msecs_to_jiffies(queue->credit_usec / 1000);  	/* Timer could already be pending in rare cases. */ -	if (timer_pending(&queue->credit_timeout)) +	if (timer_pending(&queue->credit_timeout)) { +		queue->rate_limited = true;  		return true; +	}  	/* Passed the point where we can replenish credit? */  	if (time_after_eq64(now, next_credit)) { @@ -702,6 +705,7 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)  		mod_timer(&queue->credit_timeout,  			  next_credit);  		queue->credit_window_start = next_credit; +		queue->rate_limited = true;  		return true;  	} diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 6ffc482550c1..7b61adb6270c 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1934,8 +1934,7 @@ abort_transaction_no_dev_fatal:  	xennet_disconnect_backend(info);  	xennet_destroy_queues(info);   out: -	unregister_netdev(info->netdev); -	xennet_free_netdev(info->netdev); +	device_unregister(&dev->dev);  	return err;  } | 
