2008-09-11 04:51:14 -07:00
/* skb_dma_map.c: DMA mapping helpers for socket buffers.
*
* Copyright ( C ) David S . Miller < davem @ davemloft . net >
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/dma-mapping.h>
# include <linux/skbuff.h>
int skb_dma_map ( struct device * dev , struct sk_buff * skb ,
enum dma_data_direction dir )
{
struct skb_shared_info * sp = skb_shinfo ( skb ) ;
dma_addr_t map ;
int i ;
map = dma_map_single ( dev , skb - > data ,
skb_headlen ( skb ) , dir ) ;
if ( dma_mapping_error ( dev , map ) )
goto out_err ;
2009-06-05 04:04:16 +00:00
sp - > dma_head = map ;
2008-09-11 04:51:14 -07:00
for ( i = 0 ; i < sp - > nr_frags ; i + + ) {
skb_frag_t * fp = & sp - > frags [ i ] ;
map = dma_map_page ( dev , fp - > page , fp - > page_offset ,
fp - > size , dir ) ;
if ( dma_mapping_error ( dev , map ) )
goto unwind ;
2009-06-05 04:04:16 +00:00
sp - > dma_maps [ i ] = map ;
2008-09-11 04:51:14 -07:00
}
return 0 ;
unwind :
2008-10-12 21:07:34 -07:00
while ( - - i > = 0 ) {
2008-09-11 04:51:14 -07:00
skb_frag_t * fp = & sp - > frags [ i ] ;
2009-06-05 04:04:16 +00:00
dma_unmap_page ( dev , sp - > dma_maps [ i ] ,
2008-09-11 04:51:14 -07:00
fp - > size , dir ) ;
}
2009-06-05 04:04:16 +00:00
dma_unmap_single ( dev , sp - > dma_head ,
2008-09-11 04:51:14 -07:00
skb_headlen ( skb ) , dir ) ;
out_err :
return - ENOMEM ;
}
EXPORT_SYMBOL ( skb_dma_map ) ;
void skb_dma_unmap ( struct device * dev , struct sk_buff * skb ,
enum dma_data_direction dir )
{
struct skb_shared_info * sp = skb_shinfo ( skb ) ;
int i ;
2009-06-05 04:04:16 +00:00
dma_unmap_single ( dev , sp - > dma_head ,
2008-09-11 04:51:14 -07:00
skb_headlen ( skb ) , dir ) ;
for ( i = 0 ; i < sp - > nr_frags ; i + + ) {
skb_frag_t * fp = & sp - > frags [ i ] ;
2009-06-05 04:04:16 +00:00
dma_unmap_page ( dev , sp - > dma_maps [ i ] ,
2008-09-11 04:51:14 -07:00
fp - > size , dir ) ;
}
}
EXPORT_SYMBOL ( skb_dma_unmap ) ;