I have noticed that the signature of [`pci_unmap_sg`](http://lxr.free-electrons.com/source/include/asm-generic/dma-mapping-common.h#L59)(I show `dma_unmap_sg_attrs`, which is called by `pci_unmap_sg` through two macros and has clear parameter naming) includes the direction and attributes.

```
static inline void dma_unmap_sg_attrs(
   struct device *dev,
   struct scatterlist *sg, 
   int nents,
   enum dma_data_direction dir, 
   struct dma_attrs *attrs)

```

I wonder why it is necessary to know about the direction and attributes for unmapping. Initially i thought mapping was a bit like `malloc` and `free`. But seeing this I wonder if something like the following is legal:

```
dma_map_sg_attrs(..., dir=DMA_BIDIRECTIONAL,...);
...
dma_unmap_sg_attrs(..., dir=DMA_FROM_DEVICE ,...);
//continue use in TO_DEVICE direction

```

or

```
dma_map_sg_attrs(..., dir=DMA_TO_DEVICE,...);
...
dma_map_sg_attrs(..., dir=DMA_FROM_DEVICE ,...);
//start bidirectional use

```

Also can I do this (stream data via DMA from one device to the other if they cant directly dma each other):

```
dma_map_sg_attrs(dev1, ..., dir=DMA_FROM_DEVICE ,...);
dma_map_sg_attrs(dev2, ..., dir=DMA_TO_DEVICE ,...);

```

I tried digging into the function, but ended at `get_dma_ops` which gets function pointers from a global. But how to follow this code further is another [question](https://stackoverflow.com/questions/28006154/knowing-where-op-structs-are-filled)

---

Update
------

I find the synchronization api even more confusing: 

```
pci_dma_sync_sg_for_cpu(
  struct pci_dev *hwdev,
  struct scatterlist *sg,
  int nelems,
  int direction
)

```

What is the reason for this api to know the direction? Is there no way for the api to remember the original mapping direction and is it thus to eleminate `sync_for_cpu` if we mapped as `DMA_TO_DEVICE` only?