Commit 998f6dfb authored by Mark Einon's avatar Mark Einon Committed by Greg Kroah-Hartman

staging: et131x: Fix 64bit tx dma address handling

The driver checks that the device can handle 64bit DMA addressing in
et131x_pci_setup(), but then assumes that the top dword of a tx dma
address is always zero when creating a dma mapping in nic_send_packet().
Fix the mapping to use the higher dword of the dma_addr_t returned by
dma_map_single() and skb_frag_dma_map().

Also remove incorrect comments stating that dma_map_single() only returns
a 32 bit address.
Signed-off-by: default avatarMark Einon <mark.einon@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f1b540b9
...@@ -3285,6 +3285,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) ...@@ -3285,6 +3285,7 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
struct skb_frag_struct *frags = &skb_shinfo(skb)->frags[0]; struct skb_frag_struct *frags = &skb_shinfo(skb)->frags[0];
unsigned long flags; unsigned long flags;
struct phy_device *phydev = adapter->phydev; struct phy_device *phydev = adapter->phydev;
dma_addr_t dma_addr;
/* Part of the optimizations of this send routine restrict us to /* Part of the optimizations of this send routine restrict us to
* sending 24 fragments at a pass. In practice we should never see * sending 24 fragments at a pass. In practice we should never see
...@@ -3314,77 +3315,46 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb) ...@@ -3314,77 +3315,46 @@ static int nic_send_packet(struct et131x_adapter *adapter, struct tcb *tcb)
* doesn't seem to like large fragments. * doesn't seem to like large fragments.
*/ */
if (skb_headlen(skb) <= 1514) { if (skb_headlen(skb) <= 1514) {
desc[frag].addr_hi = 0;
/* Low 16bits are length, high is vlan and /* Low 16bits are length, high is vlan and
unused currently so zero */ unused currently so zero */
desc[frag].len_vlan = skb_headlen(skb); desc[frag].len_vlan = skb_headlen(skb);
dma_addr = dma_map_single(&adapter->pdev->dev,
/* NOTE: Here, the dma_addr_t returned from skb->data,
* dma_map_single() is implicitly cast as a skb_headlen(skb),
* u32. Although dma_addr_t can be DMA_TO_DEVICE);
* 64-bit, the address returned by desc[frag].addr_lo = lower_32_bits(dma_addr);
* dma_map_single() is always 32-bit desc[frag].addr_hi = upper_32_bits(dma_addr);
* addressable (as defined by the pci/dma frag++;
* subsystem)
*/
desc[frag++].addr_lo =
dma_map_single(&adapter->pdev->dev,
skb->data,
skb_headlen(skb),
DMA_TO_DEVICE);
} else { } else {
desc[frag].addr_hi = 0;
desc[frag].len_vlan = skb_headlen(skb) / 2; desc[frag].len_vlan = skb_headlen(skb) / 2;
dma_addr = dma_map_single(&adapter->pdev->dev,
/* NOTE: Here, the dma_addr_t returned from skb->data,
* dma_map_single() is implicitly cast as a (skb_headlen(skb) / 2),
* u32. Although dma_addr_t can be DMA_TO_DEVICE);
* 64-bit, the address returned by desc[frag].addr_lo = lower_32_bits(dma_addr);
* dma_map_single() is always 32-bit desc[frag].addr_hi = upper_32_bits(dma_addr);
* addressable (as defined by the pci/dma frag++;
* subsystem)
*/
desc[frag++].addr_lo =
dma_map_single(&adapter->pdev->dev,
skb->data,
(skb_headlen(skb) / 2),
DMA_TO_DEVICE);
desc[frag].addr_hi = 0;
desc[frag].len_vlan = skb_headlen(skb) / 2; desc[frag].len_vlan = skb_headlen(skb) / 2;
dma_addr = dma_map_single(&adapter->pdev->dev,
/* NOTE: Here, the dma_addr_t returned from skb->data +
* dma_map_single() is implicitly cast as a (skb_headlen(skb) / 2),
* u32. Although dma_addr_t can be (skb_headlen(skb) / 2),
* 64-bit, the address returned by DMA_TO_DEVICE);
* dma_map_single() is always 32-bit desc[frag].addr_lo = lower_32_bits(dma_addr);
* addressable (as defined by the pci/dma desc[frag].addr_hi = upper_32_bits(dma_addr);
* subsystem) frag++;
*/
desc[frag++].addr_lo =
dma_map_single(&adapter->pdev->dev,
skb->data +
(skb_headlen(skb) / 2),
(skb_headlen(skb) / 2),
DMA_TO_DEVICE);
} }
} else { } else {
desc[frag].addr_hi = 0; desc[frag].len_vlan = frags[i - 1].size;
desc[frag].len_vlan = dma_addr = skb_frag_dma_map(&adapter->pdev->dev,
frags[i - 1].size; &frags[i - 1],
0,
/* NOTE: Here, the dma_addr_t returned from frags[i - 1].size,
* dma_map_page() is implicitly cast as a u32. DMA_TO_DEVICE);
* Although dma_addr_t can be 64-bit, the address desc[frag].addr_lo = lower_32_bits(dma_addr);
* returned by dma_map_page() is always 32-bit desc[frag].addr_hi = upper_32_bits(dma_addr);
* addressable (as defined by the pci/dma subsystem) frag++;
*/
desc[frag++].addr_lo = skb_frag_dma_map(
&adapter->pdev->dev,
&frags[i - 1],
0,
frags[i - 1].size,
DMA_TO_DEVICE);
} }
} }
...@@ -3611,6 +3581,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter, ...@@ -3611,6 +3581,7 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
unsigned long flags; unsigned long flags;
struct tx_desc *desc = NULL; struct tx_desc *desc = NULL;
struct net_device_stats *stats = &adapter->net_stats; struct net_device_stats *stats = &adapter->net_stats;
dma_addr_t dma_addr;
if (tcb->flags & fMP_DEST_BROAD) if (tcb->flags & fMP_DEST_BROAD)
atomic_inc(&adapter->stats.broadcast_pkts_xmtd); atomic_inc(&adapter->stats.broadcast_pkts_xmtd);
...@@ -3631,8 +3602,13 @@ static inline void free_send_packet(struct et131x_adapter *adapter, ...@@ -3631,8 +3602,13 @@ static inline void free_send_packet(struct et131x_adapter *adapter,
(adapter->tx_ring.tx_desc_ring + (adapter->tx_ring.tx_desc_ring +
INDEX10(tcb->index_start)); INDEX10(tcb->index_start));
dma_addr = desc->addr_lo;
if (sizeof(dma_addr_t) == sizeof(u64))
dma_addr |= ((dma_addr_t)desc->addr_hi) << 32;
dma_unmap_single(&adapter->pdev->dev, dma_unmap_single(&adapter->pdev->dev,
desc->addr_lo, dma_addr,
desc->len_vlan, DMA_TO_DEVICE); desc->len_vlan, DMA_TO_DEVICE);
add_10bit(&tcb->index_start, 1); add_10bit(&tcb->index_start, 1);
......
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