summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h3
-rw-r--r--drivers/net/ethernet/sfc/tx.c7
-rw-r--r--net/ieee802154/6lowpan.c32
-rw-r--r--net/mac802154/wpan.c2
4 files changed, 21 insertions, 23 deletions
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index aac22a1e85b8..b14a717ac3e8 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -141,6 +141,8 @@ struct efx_special_buffer {
* @len: Length of this fragment.
* This field is zero when the queue slot is empty.
* @unmap_len: Length of this fragment to unmap
+ * @dma_offset: Offset of @dma_addr from the address of the backing DMA mapping.
+ * Only valid if @unmap_len != 0.
*/
struct efx_tx_buffer {
union {
@@ -154,6 +156,7 @@ struct efx_tx_buffer {
unsigned short flags;
unsigned short len;
unsigned short unmap_len;
+ unsigned short dma_offset;
};
#define EFX_TX_BUF_CONT 1 /* not last descriptor of packet */
#define EFX_TX_BUF_SKB 2 /* buffer is last part of skb */
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 282692c48e6b..c49d1fb16965 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -65,8 +65,7 @@ static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
{
if (buffer->unmap_len) {
struct device *dma_dev = &tx_queue->efx->pci_dev->dev;
- dma_addr_t unmap_addr = (buffer->dma_addr + buffer->len -
- buffer->unmap_len);
+ dma_addr_t unmap_addr = buffer->dma_addr - buffer->dma_offset;
if (buffer->flags & EFX_TX_BUF_MAP_SINGLE)
dma_unmap_single(dma_dev, unmap_addr, buffer->unmap_len,
DMA_TO_DEVICE);
@@ -414,6 +413,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
/* Transfer ownership of the unmapping to the final buffer */
buffer->flags = EFX_TX_BUF_CONT | dma_flags;
buffer->unmap_len = unmap_len;
+ buffer->dma_offset = buffer->dma_addr - unmap_addr;
unmap_len = 0;
/* Get address and size of next fragment */
@@ -980,6 +980,7 @@ static int efx_tso_put_header(struct efx_tx_queue *tx_queue,
return -ENOMEM;
}
buffer->unmap_len = buffer->len;
+ buffer->dma_offset = 0;
buffer->flags |= EFX_TX_BUF_MAP_SINGLE;
}
@@ -1121,6 +1122,7 @@ static void tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue,
if (st->in_len == 0) {
/* Transfer ownership of the DMA mapping */
buffer->unmap_len = st->unmap_len;
+ buffer->dma_offset = buffer->unmap_len - buffer->len;
buffer->flags |= st->dma_flags;
st->unmap_len = 0;
}
@@ -1219,6 +1221,7 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
if (is_last) {
buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_MAP_SINGLE;
buffer->unmap_len = st->header_unmap_len;
+ buffer->dma_offset = 0;
/* Ensure we only unmap them once in case of a
* later DMA mapping error and rollback
*/
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index fde90e63027d..9497c6f3276b 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -654,7 +654,9 @@ static int lowpan_header_create(struct sk_buff *skb,
head[1] = iphc1;
skb_pull(skb, sizeof(struct ipv6hdr));
+ skb_reset_transport_header(skb);
memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
+ skb_reset_network_header(skb);
lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
skb->len);
@@ -737,7 +739,6 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
return -ENOMEM;
skb_push(new, sizeof(struct ipv6hdr));
- skb_reset_network_header(new);
skb_copy_to_linear_data(new, hdr, sizeof(struct ipv6hdr));
new->protocol = htons(ETH_P_IPV6);
@@ -1059,7 +1060,6 @@ lowpan_process_data(struct sk_buff *skb)
skb = new;
skb_push(skb, sizeof(struct udphdr));
- skb_reset_transport_header(skb);
skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
lowpan_raw_dump_table(__func__, "raw UDP header dump",
@@ -1102,17 +1102,6 @@ static int lowpan_set_address(struct net_device *dev, void *p)
return 0;
}
-static int lowpan_get_mac_header_length(struct sk_buff *skb)
-{
- /*
- * Currently long addressing mode is supported only, so the overall
- * header size is 21:
- * FC SeqNum DPAN DA SA Sec
- * 2 + 1 + 2 + 8 + 8 + 0 = 21
- */
- return 21;
-}
-
static int
lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
int mlen, int plen, int offset, int type)
@@ -1133,12 +1122,15 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
frag->priority = skb->priority;
/* copy header, MFR and payload */
- memcpy(skb_put(frag, mlen), skb->data, mlen);
- memcpy(skb_put(frag, hlen), head, hlen);
+ skb_put(frag, mlen);
+ skb_copy_to_linear_data(frag, skb_mac_header(skb), mlen);
+
+ skb_put(frag, hlen);
+ skb_copy_to_linear_data_offset(frag, mlen, head, hlen);
- if (plen)
- skb_copy_from_linear_data_offset(skb, offset + mlen,
- skb_put(frag, plen), plen);
+ skb_put(frag, plen);
+ skb_copy_to_linear_data_offset(frag, mlen + hlen,
+ skb_network_header(skb) + offset, plen);
lowpan_raw_dump_table(__func__, " raw fragment dump", frag->data,
frag->len);
@@ -1152,7 +1144,7 @@ lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev)
int err, header_length, payload_length, tag, offset = 0;
u8 head[5];
- header_length = lowpan_get_mac_header_length(skb);
+ header_length = skb->mac_len;
payload_length = skb->len - header_length;
tag = lowpan_dev_info(dev)->fragment_tag++;
@@ -1323,8 +1315,6 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
/* Pull off the 1-byte of 6lowpan header. */
skb_pull(local_skb, 1);
- skb_reset_network_header(local_skb);
- skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
lowpan_give_skb_to_devices(local_skb);
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
index 2ca2f4dceab7..e24bcf977296 100644
--- a/net/mac802154/wpan.c
+++ b/net/mac802154/wpan.c
@@ -208,6 +208,8 @@ static int mac802154_header_create(struct sk_buff *skb,
head[1] = fc >> 8;
memcpy(skb_push(skb, pos), head, pos);
+ skb_reset_mac_header(skb);
+ skb->mac_len = pos;
return pos;
}