diff options
Diffstat (limited to 'drivers/net/ethernet/ibm')
| -rw-r--r-- | drivers/net/ethernet/ibm/ehea/ehea_qmr.c | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/emac/core.c | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/emac/core.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/emac/zmii.c | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/emac/zmii.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/ibmveth.c | 26 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 192 | ||||
| -rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.h | 2 | 
8 files changed, 202 insertions, 36 deletions
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c index 6e70658d50c4..db45373ea31c 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_qmr.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_qmr.c @@ -670,13 +670,10 @@ int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages)  static int ehea_is_hugepage(unsigned long pfn)  { -	int page_order; -  	if (pfn & EHEA_HUGEPAGE_PFN_MASK)  		return 0; -	page_order = compound_order(pfn_to_page(pfn)); -	if (page_order + PAGE_SHIFT != EHEA_HUGEPAGESHIFT) +	if (page_shift(pfn_to_page(pfn)) != EHEA_HUGEPAGESHIFT)  		return 0;  	return 1; diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 9e43c9ace9c2..2e40425d8a34 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2849,6 +2849,7 @@ static int emac_init_config(struct emac_instance *dev)  {  	struct device_node *np = dev->ofdev->dev.of_node;  	const void *p; +	int err;  	/* Read config from device-tree */  	if (emac_read_uint_prop(np, "mal-device", &dev->mal_ph, 1)) @@ -2897,8 +2898,8 @@ static int emac_init_config(struct emac_instance *dev)  		dev->mal_burst_size = 256;  	/* PHY mode needs some decoding */ -	dev->phy_mode = of_get_phy_mode(np); -	if (dev->phy_mode < 0) +	err = of_get_phy_mode(np, &dev->phy_mode); +	if (err)  		dev->phy_mode = PHY_INTERFACE_MODE_NA;  	/* Check EMAC version */ diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index e9cda024cbf6..89a1b0fea158 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -171,7 +171,7 @@ struct emac_instance {  	struct mal_commac		commac;  	/* PHY infos */ -	int				phy_mode; +	phy_interface_t			phy_mode;  	u32				phy_map;  	u32				phy_address;  	u32				phy_feat_exc; diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c index b9e821de2ac6..57a25c7a9e70 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.c +++ b/drivers/net/ethernet/ibm/emac/zmii.c @@ -78,7 +78,8 @@ static inline u32 zmii_mode_mask(int mode, int input)  	}  } -int zmii_attach(struct platform_device *ofdev, int input, int *mode) +int zmii_attach(struct platform_device *ofdev, int input, +		phy_interface_t *mode)  {  	struct zmii_instance *dev = platform_get_drvdata(ofdev);  	struct zmii_regs __iomem *p = dev->base; diff --git a/drivers/net/ethernet/ibm/emac/zmii.h b/drivers/net/ethernet/ibm/emac/zmii.h index 41d46e9b87ba..65daedc78594 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.h +++ b/drivers/net/ethernet/ibm/emac/zmii.h @@ -50,7 +50,8 @@ struct zmii_instance {  int zmii_init(void);  void zmii_exit(void); -int zmii_attach(struct platform_device *ofdev, int input, int *mode); +int zmii_attach(struct platform_device *ofdev, int input, +		phy_interface_t *mode);  void zmii_detach(struct platform_device *ofdev, int input);  void zmii_get_mdio(struct platform_device *ofdev, int input);  void zmii_put_mdio(struct platform_device *ofdev, int input); diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index c5be4ebd8437..84121aab7ff1 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1011,6 +1011,29 @@ static int ibmveth_send(struct ibmveth_adapter *adapter,  	return 0;  } +static int ibmveth_is_packet_unsupported(struct sk_buff *skb, +					 struct net_device *netdev) +{ +	struct ethhdr *ether_header; +	int ret = 0; + +	ether_header = eth_hdr(skb); + +	if (ether_addr_equal(ether_header->h_dest, netdev->dev_addr)) { +		netdev_dbg(netdev, "veth doesn't support loopback packets, dropping packet.\n"); +		netdev->stats.tx_dropped++; +		ret = -EOPNOTSUPP; +	} + +	if (!ether_addr_equal(ether_header->h_source, netdev->dev_addr)) { +		netdev_dbg(netdev, "source packet MAC address does not match veth device's, dropping packet.\n"); +		netdev->stats.tx_dropped++; +		ret = -EOPNOTSUPP; +	} + +	return ret; +} +  static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,  				      struct net_device *netdev)  { @@ -1022,6 +1045,9 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,  	dma_addr_t dma_addr;  	unsigned long mss = 0; +	if (ibmveth_is_packet_unsupported(skb, netdev)) +		goto out; +  	/* veth doesn't handle frag_list, so linearize the skb.  	 * When GRO is enabled SKB's can have frag_list.  	 */ diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 0686ded7ad3a..830791ab4619 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -159,6 +159,40 @@ static long h_reg_sub_crq(unsigned long unit_address, unsigned long token,  	return rc;  } +/** + * ibmvnic_wait_for_completion - Check device state and wait for completion + * @adapter: private device data + * @comp_done: completion structure to wait for + * @timeout: time to wait in milliseconds + * + * Wait for a completion signal or until the timeout limit is reached + * while checking that the device is still active. + */ +static int ibmvnic_wait_for_completion(struct ibmvnic_adapter *adapter, +				       struct completion *comp_done, +				       unsigned long timeout) +{ +	struct net_device *netdev; +	unsigned long div_timeout; +	u8 retry; + +	netdev = adapter->netdev; +	retry = 5; +	div_timeout = msecs_to_jiffies(timeout / retry); +	while (true) { +		if (!adapter->crq.active) { +			netdev_err(netdev, "Device down!\n"); +			return -ENODEV; +		} +		if (!retry--) +			break; +		if (wait_for_completion_timeout(comp_done, div_timeout)) +			return 0; +	} +	netdev_err(netdev, "Operation timed out.\n"); +	return -ETIMEDOUT; +} +  static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,  				struct ibmvnic_long_term_buff *ltb, int size)  { @@ -176,21 +210,35 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,  	ltb->map_id = adapter->map_id;  	adapter->map_id++; -	init_completion(&adapter->fw_done); +	mutex_lock(&adapter->fw_lock); +	adapter->fw_done_rc = 0; +	reinit_completion(&adapter->fw_done);  	rc = send_request_map(adapter, ltb->addr,  			      ltb->size, ltb->map_id);  	if (rc) {  		dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); +		mutex_unlock(&adapter->fw_lock); +		return rc; +	} + +	rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000); +	if (rc) { +		dev_err(dev, +			"Long term map request aborted or timed out,rc = %d\n", +			rc); +		dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); +		mutex_unlock(&adapter->fw_lock);  		return rc;  	} -	wait_for_completion(&adapter->fw_done);  	if (adapter->fw_done_rc) {  		dev_err(dev, "Couldn't map long term buffer,rc = %d\n",  			adapter->fw_done_rc);  		dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); +		mutex_unlock(&adapter->fw_lock);  		return -1;  	} +	mutex_unlock(&adapter->fw_lock);  	return 0;  } @@ -211,22 +259,37 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,  static int reset_long_term_buff(struct ibmvnic_adapter *adapter,  				struct ibmvnic_long_term_buff *ltb)  { +	struct device *dev = &adapter->vdev->dev;  	int rc;  	memset(ltb->buff, 0, ltb->size); -	init_completion(&adapter->fw_done); +	mutex_lock(&adapter->fw_lock); +	adapter->fw_done_rc = 0; + +	reinit_completion(&adapter->fw_done);  	rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id); -	if (rc) +	if (rc) { +		mutex_unlock(&adapter->fw_lock); +		return rc; +	} + +	rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000); +	if (rc) { +		dev_info(dev, +			 "Reset failed, long term map request timed out or aborted\n"); +		mutex_unlock(&adapter->fw_lock);  		return rc; -	wait_for_completion(&adapter->fw_done); +	}  	if (adapter->fw_done_rc) { -		dev_info(&adapter->vdev->dev, +		dev_info(dev,  			 "Reset failed, attempting to free and reallocate buffer\n");  		free_long_term_buff(adapter, ltb); +		mutex_unlock(&adapter->fw_lock);  		return alloc_long_term_buff(adapter, ltb, ltb->size);  	} +	mutex_unlock(&adapter->fw_lock);  	return 0;  } @@ -943,13 +1006,25 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)  	if (adapter->vpd->buff)  		len = adapter->vpd->len; -	init_completion(&adapter->fw_done); +	mutex_lock(&adapter->fw_lock); +	adapter->fw_done_rc = 0; +	reinit_completion(&adapter->fw_done); +  	crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;  	crq.get_vpd_size.cmd = GET_VPD_SIZE;  	rc = ibmvnic_send_crq(adapter, &crq); -	if (rc) +	if (rc) { +		mutex_unlock(&adapter->fw_lock);  		return rc; -	wait_for_completion(&adapter->fw_done); +	} + +	rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000); +	if (rc) { +		dev_err(dev, "Could not retrieve VPD size, rc = %d\n", rc); +		mutex_unlock(&adapter->fw_lock); +		return rc; +	} +	mutex_unlock(&adapter->fw_lock);  	if (!adapter->vpd->len)  		return -ENODATA; @@ -976,7 +1051,10 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)  		return -ENOMEM;  	} +	mutex_lock(&adapter->fw_lock); +	adapter->fw_done_rc = 0;  	reinit_completion(&adapter->fw_done); +  	crq.get_vpd.first = IBMVNIC_CRQ_CMD;  	crq.get_vpd.cmd = GET_VPD;  	crq.get_vpd.ioba = cpu_to_be32(adapter->vpd->dma_addr); @@ -985,10 +1063,20 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)  	if (rc) {  		kfree(adapter->vpd->buff);  		adapter->vpd->buff = NULL; +		mutex_unlock(&adapter->fw_lock); +		return rc; +	} + +	rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000); +	if (rc) { +		dev_err(dev, "Unable to retrieve VPD, rc = %d\n", rc); +		kfree(adapter->vpd->buff); +		adapter->vpd->buff = NULL; +		mutex_unlock(&adapter->fw_lock);  		return rc;  	} -	wait_for_completion(&adapter->fw_done); +	mutex_unlock(&adapter->fw_lock);  	return 0;  } @@ -1689,20 +1777,25 @@ static int __ibmvnic_set_mac(struct net_device *netdev, u8 *dev_addr)  	crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;  	ether_addr_copy(&crq.change_mac_addr.mac_addr[0], dev_addr); -	init_completion(&adapter->fw_done); +	mutex_lock(&adapter->fw_lock); +	adapter->fw_done_rc = 0; +	reinit_completion(&adapter->fw_done); +  	rc = ibmvnic_send_crq(adapter, &crq);  	if (rc) {  		rc = -EIO; +		mutex_unlock(&adapter->fw_lock);  		goto err;  	} -	wait_for_completion(&adapter->fw_done); +	rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);  	/* netdev->dev_addr is changed in handle_change_mac_rsp function */ -	if (adapter->fw_done_rc) { +	if (rc || adapter->fw_done_rc) {  		rc = -EIO; +		mutex_unlock(&adapter->fw_lock);  		goto err;  	} - +	mutex_unlock(&adapter->fw_lock);  	return 0;  err:  	ether_addr_copy(adapter->mac_addr, netdev->dev_addr); @@ -2316,12 +2409,19 @@ static int wait_for_reset(struct ibmvnic_adapter *adapter)  	adapter->fallback.rx_entries = adapter->req_rx_add_entries_per_subcrq;  	adapter->fallback.tx_entries = adapter->req_tx_entries_per_subcrq; -	init_completion(&adapter->reset_done); +	reinit_completion(&adapter->reset_done);  	adapter->wait_for_reset = true;  	rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM); -	if (rc) -		return rc; -	wait_for_completion(&adapter->reset_done); + +	if (rc) { +		ret = rc; +		goto out; +	} +	rc = ibmvnic_wait_for_completion(adapter, &adapter->reset_done, 60000); +	if (rc) { +		ret = -ENODEV; +		goto out; +	}  	ret = 0;  	if (adapter->reset_done_rc) { @@ -2332,13 +2432,21 @@ static int wait_for_reset(struct ibmvnic_adapter *adapter)  		adapter->desired.rx_entries = adapter->fallback.rx_entries;  		adapter->desired.tx_entries = adapter->fallback.tx_entries; -		init_completion(&adapter->reset_done); +		reinit_completion(&adapter->reset_done);  		adapter->wait_for_reset = true;  		rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM); -		if (rc) -			return ret; -		wait_for_completion(&adapter->reset_done); +		if (rc) { +			ret = rc; +			goto out; +		} +		rc = ibmvnic_wait_for_completion(adapter, &adapter->reset_done, +						 60000); +		if (rc) { +			ret = -ENODEV; +			goto out; +		}  	} +out:  	adapter->wait_for_reset = false;  	return ret; @@ -2603,11 +2711,13 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,  	    cpu_to_be32(sizeof(struct ibmvnic_statistics));  	/* Wait for data to be written */ -	init_completion(&adapter->stats_done); +	reinit_completion(&adapter->stats_done);  	rc = ibmvnic_send_crq(adapter, &crq);  	if (rc)  		return; -	wait_for_completion(&adapter->stats_done); +	rc = ibmvnic_wait_for_completion(adapter, &adapter->stats_done, 10000); +	if (rc) +		return;  	for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)  		data[i] = be64_to_cpu(IBMVNIC_GET_STAT(adapter, @@ -4408,11 +4518,24 @@ static int send_query_phys_parms(struct ibmvnic_adapter *adapter)  	memset(&crq, 0, sizeof(crq));  	crq.query_phys_parms.first = IBMVNIC_CRQ_CMD;  	crq.query_phys_parms.cmd = QUERY_PHYS_PARMS; -	init_completion(&adapter->fw_done); + +	mutex_lock(&adapter->fw_lock); +	adapter->fw_done_rc = 0; +	reinit_completion(&adapter->fw_done); +  	rc = ibmvnic_send_crq(adapter, &crq); -	if (rc) +	if (rc) { +		mutex_unlock(&adapter->fw_lock);  		return rc; -	wait_for_completion(&adapter->fw_done); +	} + +	rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000); +	if (rc) { +		mutex_unlock(&adapter->fw_lock); +		return rc; +	} + +	mutex_unlock(&adapter->fw_lock);  	return adapter->fw_done_rc ? -EIO : 0;  } @@ -4505,6 +4628,15 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,  	case IBMVNIC_CRQ_XPORT_EVENT:  		netif_carrier_off(netdev);  		adapter->crq.active = false; +		/* terminate any thread waiting for a response +		 * from the device +		 */ +		if (!completion_done(&adapter->fw_done)) { +			adapter->fw_done_rc = -EIO; +			complete(&adapter->fw_done); +		} +		if (!completion_done(&adapter->stats_done)) +			complete(&adapter->stats_done);  		if (test_bit(0, &adapter->resetting))  			adapter->force_reset_recovery = true;  		if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) { @@ -4959,7 +5091,11 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)  			  __ibmvnic_delayed_reset);  	INIT_LIST_HEAD(&adapter->rwi_list);  	spin_lock_init(&adapter->rwi_lock); +	mutex_init(&adapter->fw_lock);  	init_completion(&adapter->init_done); +	init_completion(&adapter->fw_done); +	init_completion(&adapter->reset_done); +	init_completion(&adapter->stats_done);  	clear_bit(0, &adapter->resetting);  	do { @@ -5017,6 +5153,7 @@ ibmvnic_stats_fail:  ibmvnic_init_fail:  	release_sub_crqs(adapter, 1);  	release_crq_queue(adapter); +	mutex_destroy(&adapter->fw_lock);  	free_netdev(netdev);  	return rc; @@ -5041,6 +5178,7 @@ static int ibmvnic_remove(struct vio_dev *dev)  	adapter->state = VNIC_REMOVED;  	rtnl_unlock(); +	mutex_destroy(&adapter->fw_lock);  	device_remove_file(&dev->dev, &dev_attr_failover);  	free_netdev(netdev);  	dev_set_drvdata(&dev->dev, NULL); diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index ebc39248b334..60eccaf91b12 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -1026,6 +1026,8 @@ struct ibmvnic_adapter {  	int init_done_rc;  	struct completion fw_done; +	/* Used for serialization of device commands */ +	struct mutex fw_lock;  	int fw_done_rc;  	struct completion reset_done;  |