From 6bbfece5a4fbb4436eed124f4768473fff6e90e4 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:09 +0100 Subject: [PATCH 1/8] s390/qeth: remove dead code in qeth_l3_iqd_read_initial_mac() card->info.unique_id is always 0 for IQD devices, so don't bother with copying it into the 0-initialized cmd. Signed-off-by: Julian Wiedmann Reviewed-by: Alexandra Winter Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 317d56647a4a3..1c953981f73fb 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -930,7 +930,6 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card) { int rc = 0; struct qeth_cmd_buffer *iob; - struct qeth_ipa_cmd *cmd; QETH_CARD_TEXT(card, 2, "hsrmac"); @@ -938,9 +937,6 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card) IPA_DATA_SIZEOF(create_destroy_addr)); if (!iob) return -ENOMEM; - cmd = __ipa_cmd(iob); - *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) = - card->info.unique_id; rc = qeth_send_ipa_cmd(card, iob, qeth_l3_iqd_read_initial_mac_cb, NULL); From 9c6dc7af853382f119714889ba3de37b44a9fc0d Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:10 +0100 Subject: [PATCH 2/8] s390/qeth: clean up CREATE_ADDR cmd code Properly define the cmd's struct to get rid of some casts and accesses at magic offsets. Signed-off-by: Julian Wiedmann Reviewed-by: Alexandra Winter Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_mpc.h | 5 +++-- drivers/s390/net/qeth_l3_main.c | 10 +++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 3865f7258449f..3a3cebdaf9484 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -550,8 +550,9 @@ struct qeth_ipacmd_setadpparms { /* CREATE_ADDR IPA Command: ***********************************************/ struct qeth_create_destroy_address { - __u8 unique_id[8]; -} __attribute__ ((packed)); + u8 mac_addr[ETH_ALEN]; + u16 uid; +}; /* SET DIAGNOSTIC ASSIST IPA Command: *************************************/ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 1c953981f73fb..667a10d6495da 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -922,7 +922,7 @@ static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, return -EIO; ether_addr_copy(card->dev->dev_addr, - cmd->data.create_destroy_addr.unique_id); + cmd->data.create_destroy_addr.mac_addr); return 0; } @@ -949,8 +949,7 @@ static int qeth_l3_get_unique_id_cb(struct qeth_card *card, struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; if (cmd->hdr.return_code == 0) { - card->info.unique_id = *((__u16 *) - &cmd->data.create_destroy_addr.unique_id[6]); + card->info.unique_id = cmd->data.create_destroy_addr.uid; return 0; } @@ -964,7 +963,6 @@ static int qeth_l3_get_unique_id(struct qeth_card *card) { int rc = 0; struct qeth_cmd_buffer *iob; - struct qeth_ipa_cmd *cmd; QETH_CARD_TEXT(card, 2, "guniqeid"); @@ -978,10 +976,8 @@ static int qeth_l3_get_unique_id(struct qeth_card *card) IPA_DATA_SIZEOF(create_destroy_addr)); if (!iob) return -ENOMEM; - cmd = __ipa_cmd(iob); - *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) = - card->info.unique_id; + __ipa_cmd(iob)->data.create_destroy_addr.uid = card->info.unique_id; rc = qeth_send_ipa_cmd(card, iob, qeth_l3_get_unique_id_cb, NULL); return rc; } From 13bf829581c7d7dadb5b531caa4de681ab03cbc1 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:11 +0100 Subject: [PATCH 3/8] s390/qeth: validate device-provided MAC address It's good practice to not blindly trust what the HW offers. Signed-off-by: Julian Wiedmann Reviewed-by: Alexandra Winter Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 667a10d6495da..1000e18c10905 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -920,6 +920,8 @@ static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, if (cmd->hdr.return_code) return -EIO; + if (!is_valid_ether_addr(cmd->data.create_destroy_addr.mac_addr)) + return -EADDRNOTAVAIL; ether_addr_copy(card->dev->dev_addr, cmd->data.create_destroy_addr.mac_addr); From d74e5e84f25c825fe6ac78d6e7ca2139fc3f1cf6 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:12 +0100 Subject: [PATCH 4/8] s390/qeth: remove unused cmd definitions Looks like these were never used, ever since the driver was initially added. Signed-off-by: Julian Wiedmann Reviewed-by: Alexandra Winter Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_mpc.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 3a3cebdaf9484..6f304fdbb073c 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -93,10 +93,6 @@ enum qeth_link_types { QETH_LINK_TYPE_LANE = 0x88, }; -/* - * Routing stuff - */ -#define RESET_ROUTING_FLAG 0x10 /* indicate that routing type shall be set */ enum qeth_routing_types { /* TODO: set to bit flag used in IPA Command */ NO_ROUTER = 0, @@ -427,7 +423,6 @@ struct qeth_ipacmd_setassparms { struct qeth_arp_cache_entry arp_entry; struct qeth_arp_query_data query_arp; struct qeth_tso_start_data tso; - __u8 ip[16]; } data; } __attribute__ ((packed)); From 7f23d55f4958d11577f6cf54d5d3baced25ecaea Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:13 +0100 Subject: [PATCH 5/8] s390/qeth: reset seqnos on connection startup This let's us start every new IDX connection with clean seqnos. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 5efcaa43615bb..ba1e50ed50ec8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1624,17 +1624,16 @@ static void qeth_set_blkt_defaults(struct qeth_card *card) } } -static void qeth_init_tokens(struct qeth_card *card) +static void qeth_idx_init(struct qeth_card *card) { + memset(&card->seqno, 0, sizeof(card->seqno)); + card->token.issuer_rm_w = 0x00010103UL; card->token.cm_filter_w = 0x00010108UL; card->token.cm_connection_w = 0x0001010aUL; card->token.ulp_filter_w = 0x0001010bUL; card->token.ulp_connection_w = 0x0001010dUL; -} -static void qeth_init_func_level(struct qeth_card *card) -{ switch (card->info.type) { case QETH_CARD_TYPE_IQD: card->info.func_level = QETH_IDX_FUNC_LEVEL_IQD; @@ -4952,9 +4951,9 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok) else goto retry; } + qeth_determine_capabilities(card); - qeth_init_tokens(card); - qeth_init_func_level(card); + qeth_idx_init(card); rc = qeth_idx_activate_read_channel(card); if (rc == -EINTR) { From 3a5bad64db30a07459eb2f15ce6a4b995474350d Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:14 +0100 Subject: [PATCH 6/8] s390/qeth: don't re-start read cmd when IDX has terminated Once the IDX connection is down, there's no point in trying to issue more IOs. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index ba1e50ed50ec8..626da96981775 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -742,7 +742,7 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, /* fall through */ default: qeth_clear_ipacmd_list(card); - goto out; + goto err_idx; } cmd = __ipa_reply(iob); @@ -795,8 +795,9 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, memcpy(&card->seqno.pdu_hdr_ack, QETH_PDU_HEADER_SEQ_NO(iob->data), QETH_SEQ_NO_LENGTH); - qeth_put_cmd(iob); __qeth_issue_next_read(card); +err_idx: + qeth_put_cmd(iob); } static int qeth_set_thread_start_bit(struct qeth_card *card, From 3d35dbe6224e60a249dd492b0f757828db559c52 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:15 +0100 Subject: [PATCH 7/8] s390/qeth: don't check for IFF_UP when scheduling napi Trust the napi_disable() in qeth_stop() to handle this. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 626da96981775..cbd2b4c46ea4d 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3405,8 +3405,7 @@ static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, { struct qeth_card *card = (struct qeth_card *)card_ptr; - if (card->dev->flags & IFF_UP) - napi_schedule_irqoff(&card->napi); + napi_schedule_irqoff(&card->napi); } int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) From 562cf7736363c0b8a98f482cc7f6a19177d8fcea Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 27 Feb 2020 18:08:16 +0100 Subject: [PATCH 8/8] s390/qeth: support configurable RX copybreak Implement the ethtool hooks for the ETHTOOL_RX_COPYBREAK tunable. The copybreak is stored into netdev_priv, so that we automatically go back to the default value if the netdev is re-allocated. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 10 ++++++---- drivers/s390/net/qeth_core_main.c | 17 +++++++++++------ drivers/s390/net/qeth_ethtool.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 9575a627a1e18..b7d64690ea389 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -189,6 +189,8 @@ struct qeth_vnicc_info { #define QETH_IQD_MIN_TXQ 2 /* One for ucast, one for mcast. */ #define QETH_IQD_MCAST_TXQ 0 #define QETH_IQD_MIN_UCAST_TXQ 1 + +#define QETH_RX_COPYBREAK (PAGE_SIZE >> 1) #define QETH_IN_BUF_SIZE_DEFAULT 65536 #define QETH_IN_BUF_COUNT_DEFAULT 64 #define QETH_IN_BUF_COUNT_HSDEFAULT 128 @@ -219,9 +221,6 @@ struct qeth_vnicc_info { #define QETH_HIGH_WATERMARK_PACK 5 #define QETH_WATERMARK_PACK_FUZZ 1 -/* large receive scatter gather copy break */ -#define QETH_RX_SG_CB (PAGE_SIZE >> 1) - struct qeth_hdr_layer3 { __u8 id; __u8 flags; @@ -711,7 +710,6 @@ struct qeth_card_options { struct qeth_vnicc_info vnicc; /* VNICC options */ int fake_broadcast; enum qeth_discipline_id layer; - int rx_sg_cb; enum qeth_ipa_isolation_modes isolation; enum qeth_ipa_isolation_modes prev_isolation; int sniffer; @@ -770,6 +768,10 @@ struct qeth_switch_info { __u32 settings; }; +struct qeth_priv { + unsigned int rx_copybreak; +}; + #define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT struct qeth_card { diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index cbd2b4c46ea4d..1bcac50bb3954 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1257,7 +1257,6 @@ static void qeth_set_initial_options(struct qeth_card *card) { card->options.route4.type = NO_ROUTER; card->options.route6.type = NO_ROUTER; - card->options.rx_sg_cb = QETH_RX_SG_CB; card->options.isolation = ISOLATION_MODE_NONE; card->options.cq = QETH_CQ_DISABLED; card->options.layer = QETH_DISCIPLINE_UNDETERMINED; @@ -5268,6 +5267,7 @@ static int qeth_extract_skb(struct qeth_card *card, int *__offset) { struct qdio_buffer_element *element = *__element; + struct qeth_priv *priv = netdev_priv(card->dev); struct qdio_buffer *buffer = qethbuffer->buffer; struct napi_struct *napi = &card->napi; unsigned int linear_len = 0; @@ -5343,7 +5343,7 @@ static int qeth_extract_skb(struct qeth_card *card, } use_rx_sg = (card->options.cq == QETH_CQ_ENABLED) || - (skb_len > card->options.rx_sg_cb && + (skb_len > READ_ONCE(priv->rx_copybreak) && !atomic_read(&card->force_alloc_skb) && !IS_OSN(card)); @@ -5892,25 +5892,30 @@ static void qeth_clear_dbf_list(void) static struct net_device *qeth_alloc_netdev(struct qeth_card *card) { struct net_device *dev; + struct qeth_priv *priv; switch (card->info.type) { case QETH_CARD_TYPE_IQD: - dev = alloc_netdev_mqs(0, "hsi%d", NET_NAME_UNKNOWN, + dev = alloc_netdev_mqs(sizeof(*priv), "hsi%d", NET_NAME_UNKNOWN, ether_setup, QETH_MAX_QUEUES, 1); break; case QETH_CARD_TYPE_OSM: - dev = alloc_etherdev(0); + dev = alloc_etherdev(sizeof(*priv)); break; case QETH_CARD_TYPE_OSN: - dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN, ether_setup); + dev = alloc_netdev(sizeof(*priv), "osn%d", NET_NAME_UNKNOWN, + ether_setup); break; default: - dev = alloc_etherdev_mqs(0, QETH_MAX_QUEUES, 1); + dev = alloc_etherdev_mqs(sizeof(*priv), QETH_MAX_QUEUES, 1); } if (!dev) return NULL; + priv = netdev_priv(dev); + priv->rx_copybreak = QETH_RX_COPYBREAK; + dev->ml_priv = card; dev->watchdog_timeo = QETH_TX_TIMEOUT; dev->min_mtu = IS_OSN(card) ? 64 : 576; diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index ab59bc975719d..9052c72d5b8fb 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -175,6 +175,35 @@ static void qeth_get_channels(struct net_device *dev, channels->combined_count = 0; } +static int qeth_get_tunable(struct net_device *dev, + const struct ethtool_tunable *tuna, void *data) +{ + struct qeth_priv *priv = netdev_priv(dev); + + switch (tuna->id) { + case ETHTOOL_RX_COPYBREAK: + *(u32 *)data = priv->rx_copybreak; + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int qeth_set_tunable(struct net_device *dev, + const struct ethtool_tunable *tuna, + const void *data) +{ + struct qeth_priv *priv = netdev_priv(dev); + + switch (tuna->id) { + case ETHTOOL_RX_COPYBREAK: + WRITE_ONCE(priv->rx_copybreak, *(u32 *)data); + return 0; + default: + return -EOPNOTSUPP; + } +} + /* Helper function to fill 'advertising' and 'supported' which are the same. */ /* Autoneg and full-duplex are supported and advertised unconditionally. */ /* Always advertise and support all speeds up to specified, and only one */ @@ -381,6 +410,8 @@ const struct ethtool_ops qeth_ethtool_ops = { .get_sset_count = qeth_get_sset_count, .get_drvinfo = qeth_get_drvinfo, .get_channels = qeth_get_channels, + .get_tunable = qeth_get_tunable, + .set_tunable = qeth_set_tunable, .get_link_ksettings = qeth_get_link_ksettings, };