Commit ce5b127b authored by David S. Miller's avatar David S. Miller

Merge branch 's390-qeth-next'

Julian Wiedmann says:

====================
s390/qeth: updates 2018-09-17

please apply the following patchset to net-next. This brings more restructuring
of qeth's transmit code (eliminating its last usage of skb_realloc_headroom()),
and the usual mix of minor improvements & cleanups.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 75b2c206 500abbf0
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/if_inet6.h> #include <net/if_inet6.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/tcp.h>
#include <asm/debug.h> #include <asm/debug.h>
#include <asm/qdio.h> #include <asm/qdio.h>
...@@ -638,7 +639,6 @@ struct qeth_reply { ...@@ -638,7 +639,6 @@ struct qeth_reply {
atomic_t received; atomic_t received;
int rc; int rc;
void *param; void *param;
struct qeth_card *card;
refcount_t refcnt; refcount_t refcnt;
}; };
...@@ -892,11 +892,6 @@ static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags, int ipv) ...@@ -892,11 +892,6 @@ static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags, int ipv)
if ((ipv == 4 && ip_hdr(skb)->protocol == IPPROTO_UDP) || if ((ipv == 4 && ip_hdr(skb)->protocol == IPPROTO_UDP) ||
(ipv == 6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP)) (ipv == 6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP))
*flags |= QETH_HDR_EXT_UDP; *flags |= QETH_HDR_EXT_UDP;
if (ipv == 4) {
/* some HW requires combined L3+L4 csum offload: */
*flags |= QETH_HDR_EXT_CSUM_HDR_REQ;
ip_hdr(skb)->check = 0;
}
} }
static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,
...@@ -1007,9 +1002,7 @@ int qeth_query_switch_attributes(struct qeth_card *card, ...@@ -1007,9 +1002,7 @@ int qeth_query_switch_attributes(struct qeth_card *card,
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
void *reply_param); void *reply_param);
int qeth_get_elements_no(struct qeth_card *card, struct sk_buff *skb, unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset);
int extra_elems, int data_offset);
int qeth_get_elements_for_frags(struct sk_buff *);
int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb, int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, struct sk_buff *skb,
struct qeth_hdr *hdr, unsigned int offset, struct qeth_hdr *hdr, unsigned int offset,
unsigned int hd_len); unsigned int hd_len);
...@@ -1027,7 +1020,6 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); ...@@ -1027,7 +1020,6 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd); struct ethtool_link_ksettings *cmd);
int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback); int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback);
int qeth_hdr_chk_and_bounce(struct sk_buff *, struct qeth_hdr **, int);
int qeth_configure_cq(struct qeth_card *, enum qeth_cq); int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
void qeth_trace_features(struct qeth_card *); void qeth_trace_features(struct qeth_card *);
...@@ -1052,6 +1044,11 @@ int qeth_vm_request_mac(struct qeth_card *card); ...@@ -1052,6 +1044,11 @@ int qeth_vm_request_mac(struct qeth_card *card);
int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb, int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr **hdr, unsigned int hdr_len, struct qeth_hdr **hdr, unsigned int hdr_len,
unsigned int proto_len, unsigned int *elements); unsigned int proto_len, unsigned int *elements);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type,
void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type,
unsigned int data_len));
/* exports for OSN */ /* exports for OSN */
int qeth_osn_assist(struct net_device *, void *, int); int qeth_osn_assist(struct net_device *, void *, int);
......
This diff is collapsed.
...@@ -193,15 +193,21 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb) ...@@ -193,15 +193,21 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
return RTN_UNICAST; return RTN_UNICAST;
} }
static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb, static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
int cast_type, unsigned int data_len) struct sk_buff *skb, int ipv, int cast_type,
unsigned int data_len)
{ {
struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
memset(hdr, 0, sizeof(struct qeth_hdr));
hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2; hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
hdr->hdr.l2.pkt_length = data_len; hdr->hdr.l2.pkt_length = data_len;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv);
if (card->options.performance_stats)
card->perf_stats.tx_csum++;
}
/* set byte byte 3 to casting flags */ /* set byte byte 3 to casting flags */
if (cast_type == RTN_MULTICAST) if (cast_type == RTN_MULTICAST)
hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST; hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
...@@ -641,84 +647,43 @@ static void qeth_l2_set_rx_mode(struct net_device *dev) ...@@ -641,84 +647,43 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
qeth_promisc_to_bridge(card); qeth_promisc_to_bridge(card);
} }
static int qeth_l2_xmit(struct qeth_card *card, struct sk_buff *skb, static int qeth_l2_xmit_osn(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int cast_type, int ipv) struct qeth_qdio_out_q *queue)
{ {
const unsigned int proto_len = IS_IQD(card) ? ETH_HLEN : 0; struct qeth_hdr *hdr = (struct qeth_hdr *)skb->data;
const unsigned int hw_hdr_len = sizeof(struct qeth_hdr); addr_t end = (addr_t)(skb->data + sizeof(*hdr));
unsigned int frame_len = skb->len; addr_t start = (addr_t)skb->data;
unsigned int data_offset = 0; unsigned int elements = 0;
struct qeth_hdr *hdr = NULL;
unsigned int hd_len = 0; unsigned int hd_len = 0;
unsigned int elements; int rc;
int push_len, rc;
bool is_sg;
rc = skb_cow_head(skb, hw_hdr_len); if (skb->protocol == htons(ETH_P_IPV6))
if (rc) return -EPROTONOSUPPORT;
return rc;
push_len = qeth_add_hw_header(card, skb, &hdr, hw_hdr_len, proto_len, if (qeth_get_elements_for_range(start, end) > 1) {
&elements); /* Misaligned HW header, move it to its own buffer element. */
if (push_len < 0) hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
return push_len; if (!hdr)
if (!push_len) { return -ENOMEM;
/* HW header needs its own buffer element. */ hd_len = sizeof(*hdr);
hd_len = hw_hdr_len + proto_len; skb_copy_from_linear_data(skb, (char *)hdr, hd_len);
data_offset = proto_len; elements++;
}
qeth_l2_fill_header(hdr, skb, cast_type, frame_len);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv);
if (card->options.performance_stats)
card->perf_stats.tx_csum++;
} }
is_sg = skb_is_nonlinear(skb); elements += qeth_count_elements(skb, hd_len);
if (IS_IQD(card)) { if (elements > QETH_MAX_BUFFER_ELEMENTS(card)) {
rc = qeth_do_send_packet_fast(queue, skb, hdr, data_offset, rc = -E2BIG;
hd_len); goto out;
} else {
/* TODO: drop skb_orphan() once TX completion is fast enough */
skb_orphan(skb);
rc = qeth_do_send_packet(card, queue, skb, hdr, data_offset,
hd_len, elements);
} }
if (!rc) { rc = qeth_do_send_packet(card, queue, skb, hdr, hd_len, hd_len,
if (card->options.performance_stats) { elements);
card->perf_stats.buf_elements_sent += elements; out:
if (is_sg) if (rc && hd_len)
card->perf_stats.sg_skbs_sent++;
}
} else {
if (!push_len)
kmem_cache_free(qeth_core_header_cache, hdr); kmem_cache_free(qeth_core_header_cache, hdr);
if (rc == -EBUSY)
/* roll back to ETH header */
skb_pull(skb, push_len);
}
return rc; return rc;
} }
static int qeth_l2_xmit_osn(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue)
{
unsigned int elements;
struct qeth_hdr *hdr;
if (skb->protocol == htons(ETH_P_IPV6))
return -EPROTONOSUPPORT;
hdr = (struct qeth_hdr *)skb->data;
elements = qeth_get_elements_no(card, skb, 0, 0);
if (!elements)
return -E2BIG;
if (qeth_hdr_chk_and_bounce(skb, &hdr, sizeof(*hdr)))
return -EINVAL;
return qeth_do_send_packet(card, queue, skb, hdr, 0, 0, elements);
}
static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
...@@ -745,7 +710,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, ...@@ -745,7 +710,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
if (IS_OSN(card)) if (IS_OSN(card))
rc = qeth_l2_xmit_osn(card, skb, queue); rc = qeth_l2_xmit_osn(card, skb, queue);
else else
rc = qeth_l2_xmit(card, skb, queue, cast_type, ipv); rc = qeth_xmit(card, skb, queue, ipv, cast_type,
qeth_l2_fill_header);
if (!rc) { if (!rc) {
card->stats.tx_packets++; card->stats.tx_packets++;
...@@ -789,7 +755,10 @@ static int __qeth_l2_open(struct net_device *dev) ...@@ -789,7 +755,10 @@ static int __qeth_l2_open(struct net_device *dev)
if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
napi_enable(&card->napi); napi_enable(&card->napi);
local_bh_disable();
napi_schedule(&card->napi); napi_schedule(&card->napi);
/* kick-start the NAPI softirq: */
local_bh_enable();
} else } else
rc = -EIO; rc = -EIO;
return rc; return rc;
...@@ -1240,7 +1209,6 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len, ...@@ -1240,7 +1209,6 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
struct qeth_cmd_buffer *iob) struct qeth_cmd_buffer *iob)
{ {
struct qeth_channel *channel = iob->channel; struct qeth_channel *channel = iob->channel;
unsigned long flags;
int rc = 0; int rc = 0;
QETH_CARD_TEXT(card, 5, "osndctrd"); QETH_CARD_TEXT(card, 5, "osndctrd");
...@@ -1249,10 +1217,10 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len, ...@@ -1249,10 +1217,10 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len,
atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0); atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
qeth_prepare_control_data(card, len, iob); qeth_prepare_control_data(card, len, iob);
QETH_CARD_TEXT(card, 6, "osnoirqp"); QETH_CARD_TEXT(card, 6, "osnoirqp");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw, rc = ccw_device_start_timeout(channel->ccwdev, channel->ccw,
(addr_t) iob, 0, 0, QETH_IPA_TIMEOUT); (addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
if (rc) { if (rc) {
QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: " QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
"ccw_device_start rc = %i\n", rc); "ccw_device_start rc = %i\n", rc);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment