ACK: [SRU][Jammy][Kinetic][PATCH 1/1] s390/qeth: cache link_info for ethtool

Thadeu Lima de Souza Cascardo cascardo at canonical.com
Mon Sep 12 17:03:49 UTC 2022


On Mon, Sep 12, 2022 at 12:27:41PM -0400, Joseph Salisbury wrote:
> From: Alexandra Winter <wintera at linux.ibm.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1984103
> 
> Since
> commit e6e771b3d897 ("s390/qeth: detach netdevice while card is offline")
> there was a timing window during recovery, that qeth_query_card_info could
> be sent to the card, even before it was ready for it, leading to a failing
> card recovery. There is evidence that this window was hit, as not all
> callers of get_link_ksettings() check for netif_device_present.
> 
> Use cached values in qeth_get_link_ksettings(), instead of calling
> qeth_query_card_info() and falling back to default values in case it
> fails. Link info is already updated when the card goes online, e.g. after
> STARTLAN (physical link up). Set the link info to default values, when the
> card goes offline or at STOPLAN (physical link down). A follow-on patch
> will improve values reported for link down.
> 

I wonder where that follow-on patch is. In any case, this seems better than
leaving the card in a uncoverable state. And seems to still work.

Acked-by: Thadeu Lima de Souza Cascardo <cascardo at canonical.com>

> Fixes: e6e771b3d897 ("s390/qeth: detach netdevice while card is offline")
> Signed-off-by: Alexandra Winter <wintera at linux.ibm.com>
> Reviewed-by: Thorsten Winkler <twinkler at linux.ibm.com>
> Link: https://lore.kernel.org/r/20220805155714.59609-1-wintera@linux.ibm.com
> Signed-off-by: Jakub Kicinski <kuba at kernel.org>
> (cherry picked from commit 7a07a29e4f6713b224f3bcde5f835e777301bdb8)
> Signed-off-by: Joseph Salisbury <joseph.salisbury at canonical.com>
> ---
>  drivers/s390/net/qeth_core_main.c | 168 +++++++++---------------------
>  drivers/s390/net/qeth_ethtool.c   |  12 +--
>  2 files changed, 48 insertions(+), 132 deletions(-)
> 
> diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
> index 35d4b398c197..8bd9fd51208c 100644
> --- a/drivers/s390/net/qeth_core_main.c
> +++ b/drivers/s390/net/qeth_core_main.c
> @@ -763,6 +763,49 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
>  				 ipa_name, com, CARD_DEVID(card));
>  }
>  
> +static void qeth_default_link_info(struct qeth_card *card)
> +{
> +	struct qeth_link_info *link_info = &card->info.link_info;
> +
> +	QETH_CARD_TEXT(card, 2, "dftlinfo");
> +	link_info->duplex = DUPLEX_FULL;
> +
> +	if (IS_IQD(card) || IS_VM_NIC(card)) {
> +		link_info->speed = SPEED_10000;
> +		link_info->port = PORT_FIBRE;
> +		link_info->link_mode = QETH_LINK_MODE_FIBRE_SHORT;
> +	} else {
> +		switch (card->info.link_type) {
> +		case QETH_LINK_TYPE_FAST_ETH:
> +		case QETH_LINK_TYPE_LANE_ETH100:
> +			link_info->speed = SPEED_100;
> +			link_info->port = PORT_TP;
> +			break;
> +		case QETH_LINK_TYPE_GBIT_ETH:
> +		case QETH_LINK_TYPE_LANE_ETH1000:
> +			link_info->speed = SPEED_1000;
> +			link_info->port = PORT_FIBRE;
> +			break;
> +		case QETH_LINK_TYPE_10GBIT_ETH:
> +			link_info->speed = SPEED_10000;
> +			link_info->port = PORT_FIBRE;
> +			break;
> +		case QETH_LINK_TYPE_25GBIT_ETH:
> +			link_info->speed = SPEED_25000;
> +			link_info->port = PORT_FIBRE;
> +			break;
> +		default:
> +			dev_info(&card->gdev->dev,
> +				 "Unknown link type %x\n",
> +				 card->info.link_type);
> +			link_info->speed = SPEED_UNKNOWN;
> +			link_info->port = PORT_OTHER;
> +		}
> +
> +		link_info->link_mode = QETH_LINK_MODE_UNKNOWN;
> +	}
> +}
> +
>  static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
>  						struct qeth_ipa_cmd *cmd)
>  {
> @@ -790,6 +833,7 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
>  				 netdev_name(card->dev), card->info.chpid);
>  			qeth_issue_ipa_msg(cmd, cmd->hdr.return_code, card);
>  			netif_carrier_off(card->dev);
> +			qeth_default_link_info(card);
>  		}
>  		return NULL;
>  	case IPA_CMD_STARTLAN:
> @@ -4744,92 +4788,6 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
>  	return rc;
>  }
>  
> -static int qeth_query_card_info_cb(struct qeth_card *card,
> -				   struct qeth_reply *reply, unsigned long data)
> -{
> -	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
> -	struct qeth_link_info *link_info = reply->param;
> -	struct qeth_query_card_info *card_info;
> -
> -	QETH_CARD_TEXT(card, 2, "qcrdincb");
> -	if (qeth_setadpparms_inspect_rc(cmd))
> -		return -EIO;
> -
> -	card_info = &cmd->data.setadapterparms.data.card_info;
> -	netdev_dbg(card->dev,
> -		   "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
> -		   card_info->card_type, card_info->port_mode,
> -		   card_info->port_speed);
> -
> -	switch (card_info->port_mode) {
> -	case CARD_INFO_PORTM_FULLDUPLEX:
> -		link_info->duplex = DUPLEX_FULL;
> -		break;
> -	case CARD_INFO_PORTM_HALFDUPLEX:
> -		link_info->duplex = DUPLEX_HALF;
> -		break;
> -	default:
> -		link_info->duplex = DUPLEX_UNKNOWN;
> -	}
> -
> -	switch (card_info->card_type) {
> -	case CARD_INFO_TYPE_1G_COPPER_A:
> -	case CARD_INFO_TYPE_1G_COPPER_B:
> -		link_info->speed = SPEED_1000;
> -		link_info->port = PORT_TP;
> -		break;
> -	case CARD_INFO_TYPE_1G_FIBRE_A:
> -	case CARD_INFO_TYPE_1G_FIBRE_B:
> -		link_info->speed = SPEED_1000;
> -		link_info->port = PORT_FIBRE;
> -		break;
> -	case CARD_INFO_TYPE_10G_FIBRE_A:
> -	case CARD_INFO_TYPE_10G_FIBRE_B:
> -		link_info->speed = SPEED_10000;
> -		link_info->port = PORT_FIBRE;
> -		break;
> -	default:
> -		switch (card_info->port_speed) {
> -		case CARD_INFO_PORTS_10M:
> -			link_info->speed = SPEED_10;
> -			break;
> -		case CARD_INFO_PORTS_100M:
> -			link_info->speed = SPEED_100;
> -			break;
> -		case CARD_INFO_PORTS_1G:
> -			link_info->speed = SPEED_1000;
> -			break;
> -		case CARD_INFO_PORTS_10G:
> -			link_info->speed = SPEED_10000;
> -			break;
> -		case CARD_INFO_PORTS_25G:
> -			link_info->speed = SPEED_25000;
> -			break;
> -		default:
> -			link_info->speed = SPEED_UNKNOWN;
> -		}
> -
> -		link_info->port = PORT_OTHER;
> -	}
> -
> -	return 0;
> -}
> -
> -int qeth_query_card_info(struct qeth_card *card,
> -			 struct qeth_link_info *link_info)
> -{
> -	struct qeth_cmd_buffer *iob;
> -
> -	QETH_CARD_TEXT(card, 2, "qcrdinfo");
> -	if (!qeth_adp_supported(card, IPA_SETADP_QUERY_CARD_INFO))
> -		return -EOPNOTSUPP;
> -	iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0);
> -	if (!iob)
> -		return -ENOMEM;
> -
> -	return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb, link_info);
> -}
> -
>  static int qeth_init_link_info_oat_cb(struct qeth_card *card,
>  				      struct qeth_reply *reply_priv,
>  				      unsigned long data)
> @@ -4839,6 +4797,7 @@ static int qeth_init_link_info_oat_cb(struct qeth_card *card,
>  	struct qeth_query_oat_physical_if *phys_if;
>  	struct qeth_query_oat_reply *reply;
>  
> +	QETH_CARD_TEXT(card, 2, "qoatincb");
>  	if (qeth_setadpparms_inspect_rc(cmd))
>  		return -EIO;
>  
> @@ -4918,41 +4877,7 @@ static int qeth_init_link_info_oat_cb(struct qeth_card *card,
>  
>  static void qeth_init_link_info(struct qeth_card *card)
>  {
> -	card->info.link_info.duplex = DUPLEX_FULL;
> -
> -	if (IS_IQD(card) || IS_VM_NIC(card)) {
> -		card->info.link_info.speed = SPEED_10000;
> -		card->info.link_info.port = PORT_FIBRE;
> -		card->info.link_info.link_mode = QETH_LINK_MODE_FIBRE_SHORT;
> -	} else {
> -		switch (card->info.link_type) {
> -		case QETH_LINK_TYPE_FAST_ETH:
> -		case QETH_LINK_TYPE_LANE_ETH100:
> -			card->info.link_info.speed = SPEED_100;
> -			card->info.link_info.port = PORT_TP;
> -			break;
> -		case QETH_LINK_TYPE_GBIT_ETH:
> -		case QETH_LINK_TYPE_LANE_ETH1000:
> -			card->info.link_info.speed = SPEED_1000;
> -			card->info.link_info.port = PORT_FIBRE;
> -			break;
> -		case QETH_LINK_TYPE_10GBIT_ETH:
> -			card->info.link_info.speed = SPEED_10000;
> -			card->info.link_info.port = PORT_FIBRE;
> -			break;
> -		case QETH_LINK_TYPE_25GBIT_ETH:
> -			card->info.link_info.speed = SPEED_25000;
> -			card->info.link_info.port = PORT_FIBRE;
> -			break;
> -		default:
> -			dev_info(&card->gdev->dev, "Unknown link type %x\n",
> -				 card->info.link_type);
> -			card->info.link_info.speed = SPEED_UNKNOWN;
> -			card->info.link_info.port = PORT_OTHER;
> -		}
> -
> -		card->info.link_info.link_mode = QETH_LINK_MODE_UNKNOWN;
> -	}
> +	qeth_default_link_info(card);
>  
>  	/* Get more accurate data via QUERY OAT: */
>  	if (qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) {
> @@ -5461,6 +5386,7 @@ int qeth_set_offline(struct qeth_card *card, const struct qeth_discipline *disc,
>  	qeth_clear_working_pool_list(card);
>  	qeth_flush_local_addrs(card);
>  	card->info.promisc_mode = 0;
> +	qeth_default_link_info(card);
>  
>  	rc  = qeth_stop_channel(&card->data);
>  	rc2 = qeth_stop_channel(&card->write);
> diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c
> index b0b36b2132fe..9eba0a32e9f9 100644
> --- a/drivers/s390/net/qeth_ethtool.c
> +++ b/drivers/s390/net/qeth_ethtool.c
> @@ -428,8 +428,8 @@ static int qeth_get_link_ksettings(struct net_device *netdev,
>  				   struct ethtool_link_ksettings *cmd)
>  {
>  	struct qeth_card *card = netdev->ml_priv;
> -	struct qeth_link_info link_info;
>  
> +	QETH_CARD_TEXT(card, 4, "ethtglks");
>  	cmd->base.speed = card->info.link_info.speed;
>  	cmd->base.duplex = card->info.link_info.duplex;
>  	cmd->base.port = card->info.link_info.port;
> @@ -439,16 +439,6 @@ static int qeth_get_link_ksettings(struct net_device *netdev,
>  	cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
>  	cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
>  
> -	/* Check if we can obtain more accurate information.	 */
> -	if (!qeth_query_card_info(card, &link_info)) {
> -		if (link_info.speed != SPEED_UNKNOWN)
> -			cmd->base.speed = link_info.speed;
> -		if (link_info.duplex != DUPLEX_UNKNOWN)
> -			cmd->base.duplex = link_info.duplex;
> -		if (link_info.port != PORT_OTHER)
> -			cmd->base.port = link_info.port;
> -	}
> -
>  	qeth_set_ethtool_link_modes(cmd, card->info.link_info.link_mode);
>  
>  	return 0;
> -- 
> 2.34.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team



More information about the kernel-team mailing list