s390/qeth: remove qeth_hdr_chk_and_bounce()
Restructure the OSN xmit path to handle misaligned HW headers properly, without shifting the packet data around. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
356156b60a
commit
69d7ce80df
@ -1021,7 +1021,6 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
|
||||
int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
|
||||
struct ethtool_link_ksettings *cmd);
|
||||
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_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
|
||||
void qeth_trace_features(struct qeth_card *);
|
||||
|
@ -3823,27 +3823,6 @@ unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_count_elements);
|
||||
|
||||
int qeth_hdr_chk_and_bounce(struct sk_buff *skb, struct qeth_hdr **hdr, int len)
|
||||
{
|
||||
int hroom, inpage, rest;
|
||||
|
||||
if (((unsigned long)skb->data & PAGE_MASK) !=
|
||||
(((unsigned long)skb->data + len - 1) & PAGE_MASK)) {
|
||||
hroom = skb_headroom(skb);
|
||||
inpage = PAGE_SIZE - ((unsigned long) skb->data % PAGE_SIZE);
|
||||
rest = len - inpage;
|
||||
if (rest > hroom)
|
||||
return 1;
|
||||
memmove(skb->data - rest, skb->data, skb_headlen(skb));
|
||||
skb->data -= rest;
|
||||
skb->tail -= rest;
|
||||
*hdr = (struct qeth_hdr *)skb->data;
|
||||
QETH_DBF_MESSAGE(2, "skb bounce len: %d rest: %d\n", len, rest);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_hdr_chk_and_bounce);
|
||||
|
||||
#define QETH_HDR_CACHE_OBJ_SIZE (sizeof(struct qeth_hdr_tso) + \
|
||||
MAX_TCP_HEADER)
|
||||
|
||||
|
@ -650,19 +650,38 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
|
||||
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;
|
||||
struct qeth_hdr *hdr = (struct qeth_hdr *)skb->data;
|
||||
addr_t end = (addr_t)(skb->data + sizeof(*hdr));
|
||||
addr_t start = (addr_t)skb->data;
|
||||
unsigned int elements = 0;
|
||||
unsigned int hd_len = 0;
|
||||
int rc;
|
||||
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
hdr = (struct qeth_hdr *)skb->data;
|
||||
elements = qeth_count_elements(skb, 0);
|
||||
if (elements > QETH_MAX_BUFFER_ELEMENTS(card))
|
||||
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);
|
||||
if (qeth_get_elements_for_range(start, end) > 1) {
|
||||
/* Misaligned HW header, move it to its own buffer element. */
|
||||
hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
|
||||
if (!hdr)
|
||||
return -ENOMEM;
|
||||
hd_len = sizeof(*hdr);
|
||||
skb_copy_from_linear_data(skb, (char *)hdr, hd_len);
|
||||
elements++;
|
||||
}
|
||||
|
||||
elements += qeth_count_elements(skb, hd_len);
|
||||
if (elements > QETH_MAX_BUFFER_ELEMENTS(card)) {
|
||||
rc = -E2BIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = qeth_do_send_packet(card, queue, skb, hdr, hd_len, hd_len,
|
||||
elements);
|
||||
out:
|
||||
if (rc && hd_len)
|
||||
kmem_cache_free(qeth_core_header_cache, hdr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
||||
|
Loading…
Reference in New Issue
Block a user