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:
Коммит
e7a9fe7b0d
|
@ -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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче