summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 12:31:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 12:31:59 -0700
commit5518b69b76680a4f2df96b1deca260059db0c2de (patch)
treef33cd1519c8efb4590500f2f9617400be233238c /drivers/s390
parent8ad06e56dcbc1984ef0ff8f6e3c19982c5809f73 (diff)
parent0e72582270c07850b92cac351c8b97d4f9c123b9 (diff)
downloadlinux-5518b69b76680a4f2df96b1deca260059db0c2de.tar.bz2
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Reasonably busy this cycle, but perhaps not as busy as in the 4.12 merge window: 1) Several optimizations for UDP processing under high load from Paolo Abeni. 2) Support pacing internally in TCP when using the sch_fq packet scheduler for this is not practical. From Eric Dumazet. 3) Support mutliple filter chains per qdisc, from Jiri Pirko. 4) Move to 1ms TCP timestamp clock, from Eric Dumazet. 5) Add batch dequeueing to vhost_net, from Jason Wang. 6) Flesh out more completely SCTP checksum offload support, from Davide Caratti. 7) More plumbing of extended netlink ACKs, from David Ahern, Pablo Neira Ayuso, and Matthias Schiffer. 8) Add devlink support to nfp driver, from Simon Horman. 9) Add RTM_F_FIB_MATCH flag to RTM_GETROUTE queries, from Roopa Prabhu. 10) Add stack depth tracking to BPF verifier and use this information in the various eBPF JITs. From Alexei Starovoitov. 11) Support XDP on qed device VFs, from Yuval Mintz. 12) Introduce BPF PROG ID for better introspection of installed BPF programs. From Martin KaFai Lau. 13) Add bpf_set_hash helper for TC bpf programs, from Daniel Borkmann. 14) For loads, allow narrower accesses in bpf verifier checking, from Yonghong Song. 15) Support MIPS in the BPF selftests and samples infrastructure, the MIPS eBPF JIT will be merged in via the MIPS GIT tree. From David Daney. 16) Support kernel based TLS, from Dave Watson and others. 17) Remove completely DST garbage collection, from Wei Wang. 18) Allow installing TCP MD5 rules using prefixes, from Ivan Delalande. 19) Add XDP support to Intel i40e driver, from Björn Töpel 20) Add support for TC flower offload in nfp driver, from Simon Horman, Pieter Jansen van Vuuren, Benjamin LaHaise, Jakub Kicinski, and Bert van Leeuwen. 21) IPSEC offloading support in mlx5, from Ilan Tayari. 22) Add HW PTP support to macb driver, from Rafal Ozieblo. 23) Networking refcount_t conversions, From Elena Reshetova. 24) Add sock_ops support to BPF, from Lawrence Brako. This is useful for tuning the TCP sockopt settings of a group of applications, currently via CGROUPs" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1899 commits) net: phy: dp83867: add workaround for incorrect RX_CTRL pin strap dt-bindings: phy: dp83867: provide a workaround for incorrect RX_CTRL pin strap cxgb4: Support for get_ts_info ethtool method cxgb4: Add PTP Hardware Clock (PHC) support cxgb4: time stamping interface for PTP nfp: default to chained metadata prepend format nfp: remove legacy MAC address lookup nfp: improve order of interfaces in breakout mode net: macb: remove extraneous return when MACB_EXT_DESC is defined bpf: add missing break in for the TCP_BPF_SNDCWND_CLAMP case bpf: fix return in load_bpf_file mpls: fix rtm policy in mpls_getroute net, ax25: convert ax25_cb.refcount from atomic_t to refcount_t net, ax25: convert ax25_route.refcount from atomic_t to refcount_t net, ax25: convert ax25_uid_assoc.refcount from atomic_t to refcount_t net, sctp: convert sctp_ep_common.refcnt from atomic_t to refcount_t net, sctp: convert sctp_transport.refcnt from atomic_t to refcount_t net, sctp: convert sctp_chunk.refcnt from atomic_t to refcount_t net, sctp: convert sctp_datamsg.refcnt from atomic_t to refcount_t net, sctp: convert sctp_auth_bytes.refcnt from atomic_t to refcount_t ...
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/ctcm_fsms.c19
-rw-r--r--drivers/s390/net/ctcm_main.c36
-rw-r--r--drivers/s390/net/ctcm_mpc.c46
-rw-r--r--drivers/s390/net/lcs.c2
-rw-r--r--drivers/s390/net/netiucv.c20
-rw-r--r--drivers/s390/net/qeth_core.h3
-rw-r--r--drivers/s390/net/qeth_core_main.c207
-rw-r--r--drivers/s390/net/qeth_core_mpc.c16
-rw-r--r--drivers/s390/net/qeth_core_mpc.h20
-rw-r--r--drivers/s390/net/qeth_core_sys.c2
-rw-r--r--drivers/s390/net/qeth_l2_main.c61
-rw-r--r--drivers/s390/net/qeth_l3.h1
-rw-r--r--drivers/s390/net/qeth_l3_main.c65
-rw-r--r--drivers/s390/net/qeth_l3_sys.c11
14 files changed, 304 insertions, 205 deletions
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
index 730d9619400e..570ae3b7adf6 100644
--- a/drivers/s390/net/ctcm_fsms.c
+++ b/drivers/s390/net/ctcm_fsms.c
@@ -217,7 +217,7 @@ void ctcm_purge_skb_queue(struct sk_buff_head *q)
CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __func__);
while ((skb = skb_dequeue(q))) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
}
}
@@ -271,7 +271,7 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
priv->stats.tx_bytes += 2;
first = 0;
}
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
}
spin_lock(&ch->collect_lock);
@@ -297,7 +297,7 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
skb_put(ch->trans_skb, skb->len), skb->len);
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
i++;
}
@@ -1248,7 +1248,7 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
priv->stats.tx_bytes += 2;
first = 0;
}
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
}
spin_lock(&ch->collect_lock);
@@ -1279,7 +1279,7 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
__func__, data_space);
while ((skb = skb_dequeue(&ch->collect_queue))) {
- memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
+ skb_put_data(ch->trans_skb, skb->data, skb->len);
p_header = (struct pdu *)
(skb_tail_pointer(ch->trans_skb) - skb->len);
p_header->pdu_flag = 0x00;
@@ -1298,7 +1298,7 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
data_space -= skb->len;
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
peekskb = skb_peek(&ch->collect_queue);
if (peekskb->len > data_space)
@@ -1431,13 +1431,12 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
break;
case MPCG_STATE_FLOWC:
case MPCG_STATE_READY:
- memcpy(skb_put(new_skb, block_len),
- skb->data, block_len);
+ skb_put_data(new_skb, skb->data, block_len);
skb_queue_tail(&ch->io_queue, new_skb);
tasklet_schedule(&ch->ch_tasklet);
break;
default:
- memcpy(skb_put(new_skb, len), skb->data, len);
+ skb_put_data(new_skb, skb->data, len);
skb_queue_tail(&ch->io_queue, new_skb);
tasklet_hi_schedule(&ch->ch_tasklet);
break;
@@ -1796,7 +1795,7 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg)
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
goto done;
} else {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
skb_queue_tail(&wch->io_queue, skb);
}
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index b1fa38a6733f..1563b1458e44 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -483,7 +483,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
spin_unlock_irqrestore(&ch->collect_lock, saveflags);
return -EBUSY;
} else {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
header.length = l;
header.type = be16_to_cpu(skb->protocol);
header.unused = 0;
@@ -500,7 +500,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
* Protect skb against beeing free'd by upper
* layers.
*/
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
ch->prof.txlen += skb->len;
header.length = skb->len + LL_HEADER_LENGTH;
header.type = be16_to_cpu(skb->protocol);
@@ -517,14 +517,14 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
if (hi) {
nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
if (!nskb) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
ctcm_clear_busy(ch->netdev);
return -ENOMEM;
} else {
- memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
- atomic_inc(&nskb->users);
- atomic_dec(&skb->users);
+ skb_put_data(nskb, skb->data, skb->len);
+ refcount_inc(&nskb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
skb = nskb;
}
@@ -542,7 +542,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
* Remove our header. It gets added
* again on retransmit.
*/
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
ctcm_clear_busy(ch->netdev);
return -ENOMEM;
@@ -553,7 +553,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->ccw[1].count = skb->len;
skb_copy_from_linear_data(skb,
skb_put(ch->trans_skb, skb->len), skb->len);
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
ccw_idx = 0;
} else {
@@ -638,7 +638,7 @@ static void ctcmpc_send_sweep_req(struct channel *rch)
header->th.th_seq_num = 0x00;
header->sw.th_last_seq = ch->th_seq_num;
- memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
+ skb_put_data(sweep_skb, header, TH_SWEEP_LENGTH);
kfree(header);
@@ -679,7 +679,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
spin_lock_irqsave(&ch->collect_lock, saveflags);
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
if (!p_header) {
@@ -716,7 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
* Protect skb against beeing free'd by upper
* layers.
*/
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
/*
* IDAL support in CTCM is broken, so we have to
@@ -728,9 +728,9 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
if (!nskb) {
goto nomem_exit;
} else {
- memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
- atomic_inc(&nskb->users);
- atomic_dec(&skb->users);
+ skb_put_data(nskb, skb->data, skb->len);
+ refcount_inc(&nskb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
skb = nskb;
}
@@ -809,8 +809,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
skb_reset_tail_pointer(ch->trans_skb);
ch->trans_skb->len = 0;
ch->ccw[1].count = skb->len;
- memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
- atomic_dec(&skb->users);
+ skb_put_data(ch->trans_skb, skb->data, skb->len);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
ccw_idx = 0;
CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
@@ -855,7 +855,7 @@ nomem_exit:
"%s(%s): MEMORY allocation ERROR\n",
CTCM_FUNTAIL, ch->id);
rc = -ENOMEM;
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
done:
@@ -960,7 +960,7 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
}
newskb->protocol = skb->protocol;
skb_reserve(newskb, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
- memcpy(skb_put(newskb, skb->len), skb->data, skb->len);
+ skb_put_data(newskb, skb->data, skb->len);
dev_kfree_skb_any(skb);
skb = newskb;
}
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index c103fc7efe9f..f8be39634f03 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -667,7 +667,7 @@ static void ctcmpc_send_sweep_resp(struct channel *rch)
header->th.th_seq_num = 0x00;
header->sw.th_last_seq = ch->th_seq_num;
- memcpy(skb_put(sweep_skb, TH_SWEEP_LENGTH), header, TH_SWEEP_LENGTH);
+ skb_put_data(sweep_skb, header, TH_SWEEP_LENGTH);
kfree(header);
@@ -974,9 +974,8 @@ void mpc_channel_action(struct channel *ch, int direction, int action)
skb_reset_tail_pointer(ch->xid_skb);
ch->xid_skb->len = 0;
- memcpy(skb_put(ch->xid_skb, grp->xid_skb->len),
- grp->xid_skb->data,
- grp->xid_skb->len);
+ skb_put_data(ch->xid_skb, grp->xid_skb->data,
+ grp->xid_skb->len);
ch->xid->xid2_dlc_type =
((CHANNEL_DIRECTION(ch->flags) == CTCM_READ)
@@ -1149,7 +1148,7 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
goto done;
}
- memcpy(skb_put(skb, new_len), pskb->data, new_len);
+ skb_put_data(skb, pskb->data, new_len);
skb_reset_mac_header(skb);
skb->dev = pskb->dev;
@@ -1297,16 +1296,15 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
/* base xid for all channels in group */
grp->xid_skb_data = grp->xid_skb->data;
grp->xid_th = (struct th_header *)grp->xid_skb->data;
- memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
- &thnorm, TH_HEADER_LENGTH);
+ skb_put_data(grp->xid_skb, &thnorm, TH_HEADER_LENGTH);
grp->xid = (struct xid2 *)skb_tail_pointer(grp->xid_skb);
- memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
+ skb_put_data(grp->xid_skb, &init_xid, XID2_LENGTH);
grp->xid->xid2_adj_id = jiffies | 0xfff00000;
grp->xid->xid2_sender_id = jiffies;
grp->xid_id = skb_tail_pointer(grp->xid_skb);
- memcpy(skb_put(grp->xid_skb, 4), "VTAM", 4);
+ skb_put_data(grp->xid_skb, "VTAM", 4);
grp->rcvd_xid_skb =
__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
@@ -1318,8 +1316,7 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv)
}
grp->rcvd_xid_data = grp->rcvd_xid_skb->data;
grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
- memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH),
- &thnorm, TH_HEADER_LENGTH);
+ skb_put_data(grp->rcvd_xid_skb, &thnorm, TH_HEADER_LENGTH);
grp->saved_xid2 = NULL;
priv->xid = grp->xid;
priv->mpcg = grp;
@@ -1410,8 +1407,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
skb_reset_tail_pointer(grp->rcvd_xid_skb);
grp->rcvd_xid_skb->len = 0;
grp->rcvd_xid_th = (struct th_header *)grp->rcvd_xid_skb->data;
- memcpy(skb_put(grp->rcvd_xid_skb, TH_HEADER_LENGTH), &thnorm,
- TH_HEADER_LENGTH);
+ skb_put_data(grp->rcvd_xid_skb, &thnorm, TH_HEADER_LENGTH);
if (grp->send_qllc_disc == 1) {
grp->send_qllc_disc = 0;
@@ -1590,8 +1586,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo)
grp->saved_xid2 =
(struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
- memcpy(skb_put(grp->rcvd_xid_skb,
- XID2_LENGTH), xid, XID2_LENGTH);
+ skb_put_data(grp->rcvd_xid_skb, xid, XID2_LENGTH);
grp->rcvd_xid_skb->data = grp->rcvd_xid_data;
skb_reset_tail_pointer(grp->rcvd_xid_skb);
@@ -1908,17 +1903,15 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
if (fsm_getstate(ch->fsm) == CH_XID7_PENDING1) {
fsm_newstate(ch->fsm, CH_XID7_PENDING2);
ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
- memcpy(skb_put(ch->xid_skb,
- TH_HEADER_LENGTH),
- &thdummy, TH_HEADER_LENGTH);
+ skb_put_data(ch->xid_skb, &thdummy,
+ TH_HEADER_LENGTH);
send = 1;
}
} else if (fsm_getstate(ch->fsm) < CH_XID7_PENDING2) {
fsm_newstate(ch->fsm, CH_XID7_PENDING2);
ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
- memcpy(skb_put(ch->xid_skb,
- TH_HEADER_LENGTH),
- &thnorm, TH_HEADER_LENGTH);
+ skb_put_data(ch->xid_skb, &thnorm,
+ TH_HEADER_LENGTH);
send = 1;
}
} else {
@@ -1926,17 +1919,16 @@ static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
if (grp->roll == YSIDE) {
if (fsm_getstate(ch->fsm) < CH_XID7_PENDING4) {
fsm_newstate(ch->fsm, CH_XID7_PENDING4);
- memcpy(skb_put(ch->xid_skb,
- TH_HEADER_LENGTH),
- &thnorm, TH_HEADER_LENGTH);
+ skb_put_data(ch->xid_skb, &thnorm,
+ TH_HEADER_LENGTH);
ch->ccw[8].cmd_code = CCW_CMD_WRITE_CTL;
send = 1;
}
} else if (fsm_getstate(ch->fsm) == CH_XID7_PENDING3) {
fsm_newstate(ch->fsm, CH_XID7_PENDING4);
ch->ccw[8].cmd_code = CCW_CMD_SENSE_CMD;
- memcpy(skb_put(ch->xid_skb, TH_HEADER_LENGTH),
- &thdummy, TH_HEADER_LENGTH);
+ skb_put_data(ch->xid_skb, &thdummy,
+ TH_HEADER_LENGTH);
send = 1;
}
}
@@ -2122,7 +2114,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev)
return -ENOMEM;
}
- memcpy(skb_put(skb, new_len), qllcptr, new_len);
+ skb_put_data(skb, qllcptr, new_len);
kfree(qllcptr);
if (skb_headroom(skb) < 4) {
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 589dba69db17..619da81dca70 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1796,7 +1796,7 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len)
card->stats.rx_dropped++;
return;
}
- memcpy(skb_put(skb, skb_len), skb_data, skb_len);
+ skb_put_data(skb, skb_data, skb_len);
skb->protocol = card->lan_type_trans(skb, card->dev);
card->stats.rx_bytes += skb_len;
card->stats.rx_packets++;
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index f1f6eb112531..7e0e6a4019f3 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -743,7 +743,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
conn->prof.tx_pending--;
if (single_flag) {
if ((skb = skb_dequeue(&conn->commit_queue))) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
if (privptr) {
privptr->stats.tx_packets++;
privptr->stats.tx_bytes +=
@@ -759,15 +759,14 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
spin_lock_irqsave(&conn->collect_lock, saveflags);
while ((skb = skb_dequeue(&conn->collect_queue))) {
header.next = conn->tx_buff->len + skb->len + NETIUCV_HDRLEN;
- memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header,
- NETIUCV_HDRLEN);
+ skb_put_data(conn->tx_buff, &header, NETIUCV_HDRLEN);
skb_copy_from_linear_data(skb,
skb_put(conn->tx_buff, skb->len),
skb->len);
txbytes += skb->len;
txpackets++;
stat_maxcq++;
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
}
if (conn->collect_len > conn->prof.maxmulti)
@@ -780,7 +779,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
}
header.next = 0;
- memcpy(skb_put(conn->tx_buff, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
+ skb_put_data(conn->tx_buff, &header, NETIUCV_HDRLEN);
conn->prof.send_stamp = jiffies;
txmsg.class = 0;
txmsg.tag = 0;
@@ -959,7 +958,7 @@ static void netiucv_purge_skb_queue(struct sk_buff_head *q)
struct sk_buff *skb;
while ((skb = skb_dequeue(q))) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
}
}
@@ -1177,7 +1176,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
IUCV_DBF_TEXT(data, 2,
"EBUSY from netiucv_transmit_skb\n");
} else {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
skb_queue_tail(&conn->collect_queue, skb);
conn->collect_len += l;
rc = 0;
@@ -1201,8 +1200,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
return rc;
} else {
skb_reserve(nskb, NETIUCV_HDRLEN);
- memcpy(skb_put(nskb, skb->len),
- skb->data, skb->len);
+ skb_put_data(nskb, skb->data, skb->len);
}
copied = 1;
}
@@ -1212,7 +1210,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
header.next = nskb->len + NETIUCV_HDRLEN;
memcpy(skb_push(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
header.next = 0;
- memcpy(skb_put(nskb, NETIUCV_HDRLEN), &header, NETIUCV_HDRLEN);
+ skb_put_data(nskb, &header, NETIUCV_HDRLEN);
fsm_newstate(conn->fsm, CONN_STATE_TX);
conn->prof.send_stamp = jiffies;
@@ -1247,7 +1245,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
} else {
if (copied)
dev_kfree_skb(skb);
- atomic_inc(&nskb->users);
+ refcount_inc(&nskb->users);
skb_queue_tail(&conn->commit_queue, nskb);
}
}
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 30bc6105aac3..7a0ffc71b25d 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -659,6 +659,7 @@ struct qeth_card_info {
int max_mtu;
int broadcast_capable;
int unique_id;
+ bool layer_enforced;
struct qeth_card_blkt blkt;
enum qeth_ipa_promisc_modes promisc_mode;
__u32 diagass_support;
@@ -696,6 +697,7 @@ struct qeth_osn_info {
};
enum qeth_discipline_id {
+ QETH_DISCIPLINE_UNDETERMINED = -1,
QETH_DISCIPLINE_LAYER3 = 0,
QETH_DISCIPLINE_LAYER2 = 1,
};
@@ -984,6 +986,7 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
int qeth_set_features(struct net_device *, netdev_features_t);
int qeth_recover_features(struct net_device *);
netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
+int qeth_vm_request_mac(struct qeth_card *card);
/* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 462b82eb17a9..4792cabb862e 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -27,6 +27,9 @@
#include <asm/io.h>
#include <asm/sysinfo.h>
#include <asm/compat.h>
+#include <asm/diag.h>
+#include <asm/cio.h>
+#include <asm/ccwdev.h>
#include "qeth_core.h"
@@ -1239,7 +1242,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR);
}
}
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
skb = skb_dequeue(&buf->skb_list);
}
@@ -1723,6 +1726,25 @@ static void qeth_configure_unitaddr(struct qeth_card *card, char *prcd)
(prcd[0x11] == _ascebc['M']));
}
+/* Determine whether the device requires a specific layer discipline */
+static enum qeth_discipline_id qeth_enforce_discipline(struct qeth_card *card)
+{
+ if (card->info.type == QETH_CARD_TYPE_OSM ||
+ card->info.type == QETH_CARD_TYPE_OSN) {
+ QETH_DBF_TEXT(SETUP, 3, "force l2");
+ return QETH_DISCIPLINE_LAYER2;
+ }
+
+ /* virtual HiperSocket is L3 only: */
+ if (card->info.guestlan && card->info.type == QETH_CARD_TYPE_IQD) {
+ QETH_DBF_TEXT(SETUP, 3, "force l3");
+ return QETH_DISCIPLINE_LAYER3;
+ }
+
+ QETH_DBF_TEXT(SETUP, 3, "force no");
+ return QETH_DISCIPLINE_UNDETERMINED;
+}
+
static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd)
{
QETH_DBF_TEXT(SETUP, 2, "cfgblkt");
@@ -3347,6 +3369,28 @@ static void qeth_handle_send_error(struct qeth_card *card,
(u16)qdio_err, (u8)sbalf15);
}
+/**
+ * qeth_prep_flush_pack_buffer - Prepares flushing of a packing buffer.
+ * @queue: queue to check for packing buffer
+ *
+ * Returns number of buffers that were prepared for flush.
+ */
+static int qeth_prep_flush_pack_buffer(struct qeth_qdio_out_q *queue)
+{
+ struct qeth_qdio_out_buffer *buffer;
+
+ buffer = queue->bufs[queue->next_buf_to_fill];
+ if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+ (buffer->next_element_to_fill > 0)) {
+ /* it's a packing buffer */
+ atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+ queue->next_buf_to_fill =
+ (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+ return 1;
+ }
+ return 0;
+}
+
/*
* Switched to packing state if the number of used buffers on a queue
* reaches a certain limit.
@@ -3373,9 +3417,6 @@ static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
*/
static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
{
- struct qeth_qdio_out_buffer *buffer;
- int flush_count = 0;
-
if (queue->do_pack) {
if (atomic_read(&queue->used_buffers)
<= QETH_LOW_WATERMARK_PACK) {
@@ -3384,42 +3425,9 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
if (queue->card->options.performance_stats)
queue->card->perf_stats.sc_p_dp++;
queue->do_pack = 0;
- /* flush packing buffers */
- buffer = queue->bufs[queue->next_buf_to_fill];
- if ((atomic_read(&buffer->state) ==
- QETH_QDIO_BUF_EMPTY) &&
- (buffer->next_element_to_fill > 0)) {
- atomic_set(&buffer->state,
- QETH_QDIO_BUF_PRIMED);
- flush_count++;
- queue->next_buf_to_fill =
- (queue->next_buf_to_fill + 1) %
- QDIO_MAX_BUFFERS_PER_Q;
- }
+ return qeth_prep_flush_pack_buffer(queue);
}
}
- return flush_count;
-}
-
-
-/*
- * Called to flush a packing buffer if no more pci flags are on the queue.
- * Checks if there is a packing buffer and prepares it to be flushed.
- * In that case returns 1, otherwise zero.
- */
-static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
-{
- struct qeth_qdio_out_buffer *buffer;
-
- buffer = queue->bufs[queue->next_buf_to_fill];
- if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
- (buffer->next_element_to_fill > 0)) {
- /* it's a packing buffer */
- atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
- queue->next_buf_to_fill =
- (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
- return 1;
- }
return 0;
}
@@ -3532,8 +3540,7 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
if (!flush_cnt &&
!atomic_read(&queue->set_pci_flags_count))
- flush_cnt +=
- qeth_flush_buffers_on_no_pci(queue);
+ flush_cnt += qeth_prep_flush_pack_buffer(queue);
if (queue->card->options.performance_stats &&
q_was_packing)
queue->card->perf_stats.bufs_sent_pack +=
@@ -3968,7 +3975,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
int flush_cnt = 0, hdr_len, large_send = 0;
buffer = buf->buffer;
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
skb_queue_tail(&buf->skb_list, skb);
/*check first on TSO ....*/
@@ -4099,7 +4106,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
flush_count);
atomic_set(&queue->state,
QETH_OUT_Q_UNLOCKED);
- return -EBUSY;
+ rc = -EBUSY;
+ goto out;
}
}
}
@@ -4118,19 +4126,21 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
* In that case we will enter this loop
*/
while (atomic_dec_return(&queue->state)) {
- flush_count = 0;
start_index = queue->next_buf_to_fill;
/* check if we can go back to non-packing state */
- flush_count += qeth_switch_to_nonpacking_if_needed(queue);
+ tmp = qeth_switch_to_nonpacking_if_needed(queue);
/*
* check if we need to flush a packing buffer to get a pci
* flag out on the queue
*/
- if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
- flush_count += qeth_flush_buffers_on_no_pci(queue);
- if (flush_count)
- qeth_flush_buffers(queue, start_index, flush_count);
+ if (!tmp && !atomic_read(&queue->set_pci_flags_count))
+ tmp = qeth_prep_flush_pack_buffer(queue);
+ if (tmp) {
+ qeth_flush_buffers(queue, start_index, tmp);
+ flush_count += tmp;
+ }
}
+out:
/* at this point the queue is UNLOCKED again */
if (queue->card->options.performance_stats && do_pack)
queue->card->perf_stats.bufs_sent_pack += flush_count;
@@ -4199,8 +4209,7 @@ int qeth_change_mtu(struct net_device *dev, int new_mtu)
sprintf(dbf_text, "%8x", new_mtu);
QETH_CARD_TEXT(card, 4, dbf_text);
- if ((!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) &&
- (!qeth_mtu_is_valid(card, new_mtu)))
+ if (!qeth_mtu_is_valid(card, new_mtu))
return -EINVAL;
dev->mtu = new_mtu;
return 0;
@@ -4767,6 +4776,64 @@ static int qeth_query_card_info(struct qeth_card *card,
(void *)carrier_info);
}
+/**
+ * qeth_vm_request_mac() - Request a hypervisor-managed MAC address
+ * @card: pointer to a qeth_card
+ *
+ * Returns
+ * 0, if a MAC address has been set for the card's netdevice
+ * a return code, for various error conditions
+ */
+int qeth_vm_request_mac(struct qeth_card *card)
+{
+ struct diag26c_mac_resp *response;
+ struct diag26c_mac_req *request;
+ struct ccw_dev_id id;
+ int rc;
+
+ QETH_DBF_TEXT(SETUP, 2, "vmreqmac");
+
+ if (!card->dev)
+ return -ENODEV;
+
+ request = kzalloc(sizeof(*request), GFP_KERNEL | GFP_DMA);
+ response = kzalloc(sizeof(*response), GFP_KERNEL | GFP_DMA);
+ if (!request || !response) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ ccw_device_get_id(CARD_DDEV(card), &id);
+ request->resp_buf_len = sizeof(*response);
+ request->resp_version = DIAG26C_VERSION2;
+ request->op_code = DIAG26C_GET_MAC;
+ request->devno = id.devno;
+
+ rc = diag26c(request, response, DIAG26C_MAC_SERVICES);
+ if (rc)
+ goto out;
+
+ if (request->resp_buf_len < sizeof(*response) ||
+ response->version != request->resp_version) {
+ rc = -EIO;
+ QETH_DBF_TEXT(SETUP, 2, "badresp");
+ QETH_DBF_HEX(SETUP, 2, &request->resp_buf_len,
+ sizeof(request->resp_buf_len));
+ } else if (!is_valid_ether_addr(response->mac)) {
+ rc = -EINVAL;
+ QETH_DBF_TEXT(SETUP, 2, "badmac");
+ QETH_DBF_HEX(SETUP, 2, response->mac, ETH_ALEN);
+ } else {
+ ether_addr_copy(card->dev->dev_addr, response->mac);
+ }
+
+out:
+ kfree(response);
+ kfree(request);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_vm_request_mac);
+
static inline int qeth_get_qdio_q_format(struct qeth_card *card)
{
if (card->info.type == QETH_CARD_TYPE_IQD)
@@ -5144,12 +5211,11 @@ static inline int qeth_create_skb_frag(struct qeth_qdio_buffer *qethbuffer,
skb_reserve(*pskb, ETH_HLEN);
if (data_len <= QETH_RX_PULL_LEN) {
- memcpy(skb_put(*pskb, data_len), element->addr + offset,
- data_len);
+ skb_put_data(*pskb, element->addr + offset, data_len);
} else {
get_page(page);
- memcpy(skb_put(*pskb, QETH_RX_PULL_LEN),
- element->addr + offset, QETH_RX_PULL_LEN);
+ skb_put_data(*pskb, element->addr + offset,
+ QETH_RX_PULL_LEN);
skb_fill_page_desc(*pskb, *pfrag, page,
offset + QETH_RX_PULL_LEN,
data_len - QETH_RX_PULL_LEN);
@@ -5245,8 +5311,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
&skb, offset, &frag, data_len))
goto no_mem;
} else {
- memcpy(skb_put(skb, data_len), data_ptr,
- data_len);
+ skb_put_data(skb, data_ptr, data_len);
}
}
skb_len -= data_len;
@@ -5501,6 +5566,7 @@ int qeth_core_load_discipline(struct qeth_card *card,
enum qeth_discipline_id discipline)
{
int rc = 0;
+
mutex_lock(&qeth_mod_mutex);
switch (discipline) {
case QETH_DISCIPLINE_LAYER3:
@@ -5511,7 +5577,10 @@ int qeth_core_load_discipline(struct qeth_card *card,
card->discipline = try_then_request_module(
symbol_get(qeth_l2_discipline), "qeth_l2");
break;
+ default:
+ break;
}
+
if (!card->discipline) {
dev_err(&card->gdev->dev, "There is no kernel module to "
"support discipline %d\n", discipline);
@@ -5614,6 +5683,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
struct qeth_card *card;
struct device *dev;
int rc;
+ enum qeth_discipline_id enforced_disc;
unsigned long flags;
char dbf_name[DBF_NAME_LEN];
@@ -5661,10 +5731,15 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
goto err_card;
}
- switch (card->info.type) {
- case QETH_CARD_TYPE_OSN:
- case QETH_CARD_TYPE_OSM:
- rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
+ qeth_determine_capabilities(card);
+ enforced_disc = qeth_enforce_discipline(card);
+ switch (enforced_disc) {
+ case QETH_DISCIPLINE_UNDETERMINED:
+ gdev->dev.type = &qeth_generic_devtype;
+ break;
+ default:
+ card->info.layer_enforced = true;
+ rc = qeth_core_load_discipline(card, enforced_disc);
if (rc)
goto err_card;
@@ -5675,16 +5750,11 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
if (rc)
goto err_disc;
break;
- default:
- gdev->dev.type = &qeth_generic_devtype;
- break;
}
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
list_add_tail(&card->list, &qeth_core_card_list.list);
write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
-
- qeth_determine_capabilities(card);
return 0;
err_disc:
@@ -5721,7 +5791,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
int rc = 0;
- int def_discipline;
+ enum qeth_discipline_id def_discipline;
if (!card->discipline) {
if (card->info.type == QETH_CARD_TYPE_IQD)
@@ -6406,11 +6476,8 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
features &= ~NETIF_F_IP_CSUM;
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
features &= ~NETIF_F_RXCSUM;
- if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
+ if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))
features &= ~NETIF_F_TSO;
- dev_info(&card->gdev->dev, "Outbound TSO not supported on %s\n",
- QETH_CARD_IFNAME(card));
- }
/* if the card isn't up, remove features that require hw changes */
if (card->state == CARD_STATE_DOWN ||
card->state == CARD_STATE_RECOVER)
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
index beb4bdc26de5..6dd7d05e5693 100644
--- a/drivers/s390/net/qeth_core_mpc.c
+++ b/drivers/s390/net/qeth_core_mpc.c
@@ -167,13 +167,21 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
{IPA_RC_IP_TABLE_FULL, "Add Addr IP Table Full - ipv6"},
{IPA_RC_UNKNOWN_ERROR, "IPA command failed - reason unknown"},
{IPA_RC_UNSUPPORTED_COMMAND, "Command not supported"},
+ {IPA_RC_TRACE_ALREADY_ACTIVE, "trace already active"},
+ {IPA_RC_INVALID_FORMAT, "invalid format or length"},
{IPA_RC_DUP_IPV6_REMOTE, "ipv6 address already registered remote"},
+ {IPA_RC_SBP_IQD_NOT_CONFIGURED, "Not configured for bridgeport"},
{IPA_RC_DUP_IPV6_HOME, "ipv6 address already registered"},
{IPA_RC_UNREGISTERED_ADDR, "Address not registered"},
{IPA_RC_NO_ID_AVAILABLE, "No identifiers available"},
{IPA_RC_ID_NOT_FOUND, "Identifier not found"},
+ {IPA_RC_SBP_IQD_ANO_DEV_PRIMARY, "Primary bridgeport exists already"},
+ {IPA_RC_SBP_IQD_CURRENT_SECOND, "Bridgeport is currently secondary"},
+ {IPA_RC_SBP_IQD_LIMIT_SECOND, "Limit of secondary bridgeports reached"},
{IPA_RC_INVALID_IP_VERSION, "IP version incorrect"},
+ {IPA_RC_SBP_IQD_CURRENT_PRIMARY, "Bridgeport is currently primary"},
{IPA_RC_LAN_FRAME_MISMATCH, "LAN and frame mismatch"},
+ {IPA_RC_SBP_IQD_NO_QDIO_QUEUES, "QDIO queues not established"},
{IPA_RC_L2_UNSUPPORTED_CMD, "Unsupported layer 2 command"},
{IPA_RC_L2_DUP_MAC, "Duplicate MAC address"},
{IPA_RC_L2_ADDR_TABLE_FULL, "Layer2 address table full"},
@@ -185,6 +193,14 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
{IPA_RC_L2_INVALID_VLAN_ID, "L2 invalid vlan id"},
{IPA_RC_L2_DUP_VLAN_ID, "L2 duplicate vlan id"},
{IPA_RC_L2_VLAN_ID_NOT_FOUND, "L2 vlan id not found"},
+ {IPA_RC_SBP_OSA_NOT_CONFIGURED, "Not configured for bridgeport"},
+ {IPA_RC_SBP_OSA_OS_MISMATCH, "OS mismatch"},
+ {IPA_RC_SBP_OSA_ANO_DEV_PRIMARY, "Primary bridgeport exists already"},
+ {IPA_RC_SBP_OSA_CURRENT_SECOND, "Bridgeport is currently secondary"},
+ {IPA_RC_SBP_OSA_LIMIT_SECOND, "Limit of secondary bridgeports reached"},
+ {IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN, "Not authorized by zManager"},
+ {IPA_RC_SBP_OSA_CURRENT_PRIMARY, "Bridgeport is currently primary"},
+ {IPA_RC_SBP_OSA_NO_QDIO_QUEUES, "QDIO queues not established"},
{IPA_RC_DATA_MISMATCH, "Data field mismatch (v4/v6 mixed)"},
{IPA_RC_INVALID_MTU_SIZE, "Invalid MTU size"},
{IPA_RC_INVALID_LANTYPE, "Invalid LAN type"},
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 4accb0a61ce0..912e0107de8f 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -142,12 +142,18 @@ enum qeth_ipa_return_codes {
IPA_RC_TRACE_ALREADY_ACTIVE = 0x0005,
IPA_RC_INVALID_FORMAT = 0x0006,
IPA_RC_DUP_IPV6_REMOTE = 0x0008,
+ IPA_RC_SBP_IQD_NOT_CONFIGURED = 0x000C,
IPA_RC_DUP_IPV6_HOME = 0x0010,
IPA_RC_UNREGISTERED_ADDR = 0x0011,
IPA_RC_NO_ID_AVAILABLE = 0x0012,
IPA_RC_ID_NOT_FOUND = 0x0013,
+ IPA_RC_SBP_IQD_ANO_DEV_PRIMARY = 0x0014,
+ IPA_RC_SBP_IQD_CURRENT_SECOND = 0x0018,
+ IPA_RC_SBP_IQD_LIMIT_SECOND = 0x001C,
IPA_RC_INVALID_IP_VERSION = 0x0020,
+ IPA_RC_SBP_IQD_CURRENT_PRIMARY = 0x0024,
IPA_RC_LAN_FRAME_MISMATCH = 0x0040,
+ IPA_RC_SBP_IQD_NO_QDIO_QUEUES = 0x00EB,
IPA_RC_L2_UNSUPPORTED_CMD = 0x2003,
IPA_RC_L2_DUP_MAC = 0x2005,
IPA_RC_L2_ADDR_TABLE_FULL = 0x2006,
@@ -159,6 +165,14 @@ enum qeth_ipa_return_codes {
IPA_RC_L2_INVALID_VLAN_ID = 0x2015,
IPA_RC_L2_DUP_VLAN_ID = 0x2016,
IPA_RC_L2_VLAN_ID_NOT_FOUND = 0x2017,
+ IPA_RC_SBP_OSA_NOT_CONFIGURED = 0x2B0C,
+ IPA_RC_SBP_OSA_OS_MISMATCH = 0x2B10,
+ IPA_RC_SBP_OSA_ANO_DEV_PRIMARY = 0x2B14,
+ IPA_RC_SBP_OSA_CURRENT_SECOND = 0x2B18,
+ IPA_RC_SBP_OSA_LIMIT_SECOND = 0x2B1C,
+ IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN = 0x2B20,
+ IPA_RC_SBP_OSA_CURRENT_PRIMARY = 0x2B24,
+ IPA_RC_SBP_OSA_NO_QDIO_QUEUES = 0x2BEB,
IPA_RC_DATA_MISMATCH = 0xe001,
IPA_RC_INVALID_MTU_SIZE = 0xe002,
IPA_RC_INVALID_LANTYPE = 0xe003,
@@ -187,12 +201,16 @@ enum qeth_ipa_return_codes {
#define IPA_RC_INVALID_SUBCMD IPA_RC_IP_TABLE_FULL
#define IPA_RC_HARDWARE_AUTH_ERROR IPA_RC_UNKNOWN_ERROR
+/* for SETBRIDGEPORT (double occupancies) */
+#define IPA_RC_SBP_IQD_OS_MISMATCH IPA_RC_DUP_IPV6_HOME
+#define IPA_RC_SBP_IQD_NOT_AUTHD_BY_ZMAN IPA_RC_INVALID_IP_VERSION
+
/* IPA function flags; each flag marks availability of respective function */
enum qeth_ipa_funcs {
IPA_ARP_PROCESSING = 0x00000001L,
IPA_INBOUND_CHECKSUM = 0x00000002L,
IPA_OUTBOUND_CHECKSUM = 0x00000004L,
- IPA_IP_FRAGMENTATION = 0x00000008L,
+ /* RESERVED = 0x00000008L,*/
IPA_FILTERING = 0x00000010L,
IPA_IPV6 = 0x00000020L,
IPA_MULTICASTING = 0x00000040L,
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index db6a285d41e0..6d255c22656d 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -413,7 +413,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
if (card->options.layer2 == newdis)
goto out;
- if (card->info.type == QETH_CARD_TYPE_OSM) {
+ if (card->info.layer_enforced) {
/* fixed layer, can't switch */
rc = -EOPNOTSUPP;
goto out;
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index bd2df62a5cdf..ad110abfdd47 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -21,6 +21,7 @@
#include <linux/hash.h>
#include <linux/hashtable.h>
#include <linux/string.h>
+#include <asm/setup.h>
#include "qeth_core.h"
#include "qeth_l2.h"
@@ -505,9 +506,19 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
int rc = 0;
char vendor_pre[] = {0x02, 0x00, 0x00};
- QETH_DBF_TEXT(SETUP, 2, "doL2init");
+ QETH_DBF_TEXT(SETUP, 2, "l2reqmac");
QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
+ if (MACHINE_IS_VM) {
+ rc = qeth_vm_request_mac(card);
+ if (!rc)
+ goto out;
+ QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n",
+ CARD_BUS_ID(card), rc);
+ QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc);
+ /* fall back to alternative mechanism: */
+ }
+
if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
rc = qeth_query_setadapterparms(card);
if (rc) {
@@ -528,11 +539,12 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
return rc;
}
- QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN);
} else {
eth_random_addr(card->dev->dev_addr);
memcpy(card->dev->dev_addr, vendor_pre, 3);
}
+out:
+ QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len);
return 0;
}
@@ -759,8 +771,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
sizeof(struct qeth_hdr));
if (!new_skb)
goto tx_drop;
- hdr = (struct qeth_hdr *)skb_push(new_skb,
- sizeof(struct qeth_hdr));
+ hdr = skb_push(new_skb, sizeof(struct qeth_hdr));
skb_set_mac_header(new_skb, sizeof(struct qeth_hdr));
qeth_l2_fill_header(card, hdr, new_skb, cast_type);
if (new_skb->ip_summed == CHECKSUM_PARTIAL)
@@ -1017,6 +1028,13 @@ static int qeth_l2_start_ipassists(struct qeth_card *card)
return 0;
}
+static void qeth_l2_trace_features(struct qeth_card *card)
+{
+ QETH_CARD_TEXT(card, 2, "l2featur");
+ QETH_CARD_HEX(card, 2, &card->options.sbp.supported_funcs,
+ sizeof(card->options.sbp.supported_funcs));
+}
+
static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
@@ -1040,6 +1058,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_info(&card->gdev->dev,
"The device represents a Bridge Capable Port\n");
qeth_trace_features(card);
+ qeth_l2_trace_features(card);
if (!card->dev && qeth_l2_setup_netdev(card)) {
rc = -ENODEV;
@@ -1643,27 +1662,27 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
(!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
switch (cbctl->cmd_rc) {
- case 0x0000:
+ case IPA_RC_SUCCESS:
rc = 0;
break;
- case 0x2B04:
- case 0x0004:
+ case IPA_RC_L2_UNSUPPORTED_CMD:
+ case IPA_RC_UNSUPPORTED_COMMAND:
rc = -EOPNOTSUPP;
break;
- case 0x2B0C:
- case 0x000C: /* Not configured as bridge Port */
+ case IPA_RC_SBP_OSA_NOT_CONFIGURED:
+ case IPA_RC_SBP_IQD_NOT_CONFIGURED:
rc = -ENODEV; /* maybe not the best code here? */
dev_err(&card->gdev->dev,
"The device is not configured as a Bridge Port\n");
break;
- case 0x2B10:
- case 0x0010: /* OS mismatch */
+ case IPA_RC_SBP_OSA_OS_MISMATCH:
+ case IPA_RC_SBP_IQD_OS_MISMATCH:
rc = -EPERM;
dev_err(&card->gdev->dev,
"A Bridge Port is already configured by a different operating system\n");
break;
- case 0x2B14:
- case 0x0014: /* Another device is Primary */
+ case IPA_RC_SBP_OSA_ANO_DEV_PRIMARY:
+ case IPA_RC_SBP_IQD_ANO_DEV_PRIMARY:
switch (setcmd) {
case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
rc = -EEXIST;
@@ -1679,26 +1698,26 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
rc = -EIO;
}
break;
- case 0x2B18:
- case 0x0018: /* This device is currently Secondary */
+ case IPA_RC_SBP_OSA_CURRENT_SECOND:
+ case IPA_RC_SBP_IQD_CURRENT_SECOND:
rc = -EBUSY;
dev_err(&card->gdev->dev,
"The device is already a secondary Bridge Port\n");
break;
- case 0x2B1C:
- case 0x001C: /* Limit for Secondary devices reached */
+ case IPA_RC_SBP_OSA_LIMIT_SECOND:
+ case IPA_RC_SBP_IQD_LIMIT_SECOND:
rc = -EEXIST;
dev_err(&card->gdev->dev,
"The LAN cannot have more secondary Bridge Ports\n");
break;
- case 0x2B24:
- case 0x0024: /* This device is currently Primary */
+ case IPA_RC_SBP_OSA_CURRENT_PRIMARY:
+ case IPA_RC_SBP_IQD_CURRENT_PRIMARY:
rc = -EBUSY;
dev_err(&card->gdev->dev,
"The device is already a primary Bridge Port\n");
break;
- case 0x2B20:
- case 0x0020: /* Not authorized by zManager */
+ case IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN:
+ case IPA_RC_SBP_IQD_NOT_AUTHD_BY_ZMAN:
rc = -EACCES;
dev_err(&card->gdev->dev,
"The device is not authorized to be a Bridge Port\n");
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h
index 26f79533e62e..9b5e439f18cf 100644
--- a/drivers/s390/net/qeth_l3.h
+++ b/drivers/s390/net/qeth_l3.h
@@ -65,6 +65,7 @@ struct qeth_ipato_entry {
int mask_bits;
};
+extern const struct attribute_group *qeth_l3_attr_groups[];
void qeth_l3_ipaddr_to_string(enum qeth_prot_versions, const __u8 *, char *);
int qeth_l3_string_to_ipaddr(const char *, enum qeth_prot_versions, __u8 *);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index d8df1e635163..3062cde33a3d 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -956,31 +956,6 @@ static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
return rc;
}
-static int qeth_l3_start_ipa_ip_fragmentation(struct qeth_card *card)
-{
- int rc;
-
- QETH_CARD_TEXT(card, 3, "ipaipfrg");
-
- if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
- dev_info(&card->gdev->dev,
- "Hardware IP fragmentation not supported on %s\n",
- QETH_CARD_IFNAME(card));
- return -EOPNOTSUPP;
- }
-
- rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
- IPA_CMD_ASS_START, 0);
- if (rc) {
- dev_warn(&card->gdev->dev,
- "Starting IP fragmentation support for %s failed\n",
- QETH_CARD_IFNAME(card));
- } else
- dev_info(&card->gdev->dev,
- "Hardware IP fragmentation enabled \n");
- return rc;
-}
-
static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
{
int rc;
@@ -1060,9 +1035,6 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
QETH_CARD_TEXT(card, 3, "softipv6");
- if (card->info.type == QETH_CARD_TYPE_IQD)
- goto out;
-
rc = qeth_query_ipassists(card, QETH_PROT_IPV6);
if (rc) {
dev_err(&card->gdev->dev,
@@ -1070,6 +1042,10 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
QETH_CARD_IFNAME(card));
return rc;
}
+
+ if (card->info.type == QETH_CARD_TYPE_IQD)
+ goto out;
+
rc = qeth_send_simple_setassparms(card, IPA_IPV6,
IPA_CMD_ASS_START, 3);
if (rc) {
@@ -1171,7 +1147,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
if (qeth_set_access_ctrl_online(card, 0))
return -EIO;
qeth_l3_start_ipa_arp_processing(card); /* go on*/
- qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/
qeth_l3_start_ipa_source_mac(card); /* go on*/
qeth_l3_start_ipa_vlan(card); /* go on*/
qeth_l3_start_ipa_multicast(card); /* go on*/
@@ -2702,8 +2677,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
use_tso = skb_is_gso(skb) &&
(qeth_get_ip_protocol(skb) == IPPROTO_TCP) && (ipv == 4);
- if ((card->info.type == QETH_CARD_TYPE_IQD) &&
- !skb_is_nonlinear(skb)) {
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
new_skb = skb;
data_offset = ETH_HLEN;
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
@@ -2716,12 +2690,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
+ VLAN_HLEN);
if (!new_skb)
goto tx_drop;
- }
- if (card->info.type == QETH_CARD_TYPE_IQD) {
- if (data_offset < 0)
- skb_pull(new_skb, ETH_HLEN);
- } else {
if (ipv == 4) {
skb_pull(new_skb, ETH_HLEN);
}
@@ -2760,16 +2729,14 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
}
if (use_tso) {
- hdr = (struct qeth_hdr *)skb_push(new_skb,
- sizeof(struct qeth_hdr_tso));
+ hdr = skb_push(new_skb, sizeof(struct qeth_hdr_tso));
memset(hdr, 0, sizeof(struct qeth_hdr_tso));
qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
qeth_tso_fill_header(card, hdr, new_skb);
hdr_elements++;
} else {
if (data_offset < 0) {
- hdr = (struct qeth_hdr *)skb_push(new_skb,
- sizeof(struct qeth_hdr));
+ hdr = skb_push(new_skb, sizeof(struct qeth_hdr));
qeth_l3_fill_header(card, hdr, new_skb, ipv,
cast_type);
} else {
@@ -3036,14 +3003,21 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
return register_netdev(card->dev);
}
+static const struct device_type qeth_l3_devtype = {
+ .name = "qeth_layer3",
+ .groups = qeth_l3_attr_groups,
+};
+
static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
{
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
int rc;
- rc = qeth_l3_create_device_attributes(&gdev->dev);
- if (rc)
- return rc;
+ if (gdev->dev.type == &qeth_generic_devtype) {
+ rc = qeth_l3_create_device_attributes(&gdev->dev);
+ if (rc)
+ return rc;
+ }
hash_init(card->ip_htable);
hash_init(card->ip_mc_htable);
card->options.layer2 = 0;
@@ -3055,7 +3029,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
{
struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
- qeth_l3_remove_device_attributes(&cgdev->dev);
+ if (cgdev->dev.type == &qeth_generic_devtype)
+ qeth_l3_remove_device_attributes(&cgdev->dev);
qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
@@ -3311,7 +3286,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
}
struct qeth_discipline qeth_l3_discipline = {
- .devtype = &qeth_generic_devtype,
+ .devtype = &qeth_l3_devtype,
.start_poll = qeth_qdio_start_poll,
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index ff29a4b416b4..f2f94f59e0fa 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -1049,3 +1049,14 @@ void qeth_l3_remove_device_attributes(struct device *dev)
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
}
+
+const struct attribute_group *qeth_l3_attr_groups[] = {
+ &qeth_device_attr_group,
+ &qeth_device_blkt_group,
+ /* l3 specific, see l3_{create,remove}_device_attributes(): */
+ &qeth_l3_device_attr_group,
+ &qeth_device_ipato_group,
+ &qeth_device_vipa_group,
+ &qeth_device_rxip_group,
+NULL,
+};