Merge branch 's390-qeth-fixes'

Julian Wiedmann says:

====================
s390/qeth: fixes 2019-06-05

one more shot...  now with patch 2 fixed up so that it uses the
dst entry returned from dst_check().

From the v1 cover letter:

Please apply the following set of qeth fixes to -net.

- The first two patches fix issues in the L3 driver's cast type
  selection for transmitted skbs.
- Alexandra adds a sanity check when retrieving VLAN information from
  neighbour address events.
- The last patch adds some missing error handling for qeth's new
  multiqueue code.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-06-05 11:48:57 -07:00
Родитель fdf71426e7 bd966839bd
Коммит e7a9fe7b0d
3 изменённых файлов: 44 добавлений и 12 удалений

Просмотреть файл

@ -1274,16 +1274,20 @@ static int qeth_setup_channel(struct qeth_channel *channel, bool alloc_buffers)
return 0; return 0;
} }
static void qeth_osa_set_output_queues(struct qeth_card *card, bool single) static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
{ {
unsigned int count = single ? 1 : card->dev->num_tx_queues; unsigned int count = single ? 1 : card->dev->num_tx_queues;
int rc;
rtnl_lock(); rtnl_lock();
netif_set_real_num_tx_queues(card->dev, count); rc = netif_set_real_num_tx_queues(card->dev, count);
rtnl_unlock(); rtnl_unlock();
if (rc)
return rc;
if (card->qdio.no_out_queues == count) if (card->qdio.no_out_queues == count)
return; return 0;
if (atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED) if (atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED)
qeth_free_qdio_queues(card); qeth_free_qdio_queues(card);
@ -1293,12 +1297,14 @@ static void qeth_osa_set_output_queues(struct qeth_card *card, bool single)
card->qdio.default_out_queue = single ? 0 : QETH_DEFAULT_QUEUE; card->qdio.default_out_queue = single ? 0 : QETH_DEFAULT_QUEUE;
card->qdio.no_out_queues = count; card->qdio.no_out_queues = count;
return 0;
} }
static int qeth_update_from_chp_desc(struct qeth_card *card) static int qeth_update_from_chp_desc(struct qeth_card *card)
{ {
struct ccw_device *ccwdev; struct ccw_device *ccwdev;
struct channel_path_desc_fmt0 *chp_dsc; struct channel_path_desc_fmt0 *chp_dsc;
int rc = 0;
QETH_DBF_TEXT(SETUP, 2, "chp_desc"); QETH_DBF_TEXT(SETUP, 2, "chp_desc");
@ -1311,12 +1317,12 @@ static int qeth_update_from_chp_desc(struct qeth_card *card)
if (IS_OSD(card) || IS_OSX(card)) if (IS_OSD(card) || IS_OSX(card))
/* CHPP field bit 6 == 1 -> single queue */ /* CHPP field bit 6 == 1 -> single queue */
qeth_osa_set_output_queues(card, chp_dsc->chpp & 0x02); rc = qeth_osa_set_output_queues(card, chp_dsc->chpp & 0x02);
kfree(chp_dsc); kfree(chp_dsc);
QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues);
QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level);
return 0; return rc;
} }
static void qeth_init_qdio_info(struct qeth_card *card) static void qeth_init_qdio_info(struct qeth_card *card)
@ -5597,8 +5603,12 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
dev->hw_features |= NETIF_F_SG; dev->hw_features |= NETIF_F_SG;
dev->vlan_features |= NETIF_F_SG; dev->vlan_features |= NETIF_F_SG;
if (IS_IQD(card)) { if (IS_IQD(card)) {
netif_set_real_num_tx_queues(dev, QETH_IQD_MIN_TXQ);
dev->features |= NETIF_F_SG; dev->features |= NETIF_F_SG;
if (netif_set_real_num_tx_queues(dev,
QETH_IQD_MIN_TXQ)) {
free_netdev(dev);
return NULL;
}
} }
} }

Просмотреть файл

@ -1680,7 +1680,7 @@ static void qeth_bridgeport_an_set_cb(void *priv,
l2entry = (struct qdio_brinfo_entry_l2 *)entry; l2entry = (struct qdio_brinfo_entry_l2 *)entry;
code = IPA_ADDR_CHANGE_CODE_MACADDR; code = IPA_ADDR_CHANGE_CODE_MACADDR;
if (l2entry->addr_lnid.lnid) if (l2entry->addr_lnid.lnid < VLAN_N_VID)
code |= IPA_ADDR_CHANGE_CODE_VLANID; code |= IPA_ADDR_CHANGE_CODE_VLANID;
qeth_bridge_emit_host_event(card, anev_reg_unreg, code, qeth_bridge_emit_host_event(card, anev_reg_unreg, code,
(struct net_if_token *)&l2entry->nit, (struct net_if_token *)&l2entry->nit,

Просмотреть файл

@ -1888,13 +1888,20 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int qeth_l3_get_cast_type(struct sk_buff *skb) static int qeth_l3_get_cast_type(struct sk_buff *skb)
{ {
int ipv = qeth_get_ip_version(skb);
struct neighbour *n = NULL; struct neighbour *n = NULL;
struct dst_entry *dst; struct dst_entry *dst;
rcu_read_lock(); rcu_read_lock();
dst = skb_dst(skb); dst = skb_dst(skb);
if (dst) if (dst) {
n = dst_neigh_lookup_skb(dst, skb); struct rt6_info *rt = (struct rt6_info *) dst;
dst = dst_check(dst, (ipv == 6) ? rt6_get_cookie(rt) : 0);
if (dst)
n = dst_neigh_lookup_skb(dst, skb);
}
if (n) { if (n) {
int cast_type = n->type; int cast_type = n->type;
@ -1909,8 +1916,10 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
rcu_read_unlock(); rcu_read_unlock();
/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */ /* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
switch (qeth_get_ip_version(skb)) { switch (ipv) {
case 4: case 4:
if (ipv4_is_lbcast(ip_hdr(skb)->daddr))
return RTN_BROADCAST;
return ipv4_is_multicast(ip_hdr(skb)->daddr) ? return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
RTN_MULTICAST : RTN_UNICAST; RTN_MULTICAST : RTN_UNICAST;
case 6: case 6:
@ -1940,6 +1949,7 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3; struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
struct vlan_ethhdr *veth = vlan_eth_hdr(skb); struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
struct qeth_card *card = queue->card; struct qeth_card *card = queue->card;
struct dst_entry *dst;
hdr->hdr.l3.length = data_len; hdr->hdr.l3.length = data_len;
@ -1985,15 +1995,27 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
} }
rcu_read_lock(); rcu_read_lock();
dst = skb_dst(skb);
if (ipv == 4) { if (ipv == 4) {
struct rtable *rt = skb_rtable(skb); struct rtable *rt;
if (dst)
dst = dst_check(dst, 0);
rt = (struct rtable *) dst;
*((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ? *((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ?
rt_nexthop(rt, ip_hdr(skb)->daddr) : rt_nexthop(rt, ip_hdr(skb)->daddr) :
ip_hdr(skb)->daddr; ip_hdr(skb)->daddr;
} else { } else {
/* IPv6 */ /* IPv6 */
const struct rt6_info *rt = skb_rt6_info(skb); struct rt6_info *rt;
if (dst) {
rt = (struct rt6_info *) dst;
dst = dst_check(dst, rt6_get_cookie(rt));
}
rt = (struct rt6_info *) dst;
if (rt && !ipv6_addr_any(&rt->rt6i_gateway)) if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway; l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway;