Yurong Sun
|
getting mbuf physical address
|
Yurong Sun
01/17/2012 11:13 AM
post90959
|
getting mbuf physical address
Hi,
I have a problem regarding getting mbuf physical address. In transmission, for example, when got a network packet, I
added some additional packet descriptor info into the M_LEADINGSPACE, between m->pkt_dat and m->m_data. I then need to
get the physical address starting from the packet descriptor in order for DMA operation. My assumption is that the mbuf
as a whole is in a contiguous buffer, or at least the buffer between m->pkt_data to the end of m->m_data is. Am I
correct?
Based on my assumption, I used mem_offset64 to get the physical address of the starting point, i.e., m->pkt_data +
alignment offset. It seems not getting the correct one. I noticed that there is mbuf_phys, but that seems, from the code
, only get the m->m_data physical address, not the one that I need.
I have a workaround to copy the mbuf into a contiguous buffer. But I fear for the performance impact.
Any suggestions?
Thanks,
Yurong
|
|
|
Sean Boudreau(deleted)
|
Re: getting mbuf physical address
|
Sean Boudreau(deleted)
01/17/2012 11:18 AM
post90960
|
Re: getting mbuf physical address
Use M_PREPEND which checks M_LEADINGSPACE and updates m->m_data,
m->m_len and m_pkthdr.len. You can then use mbuf_phys() correctly.
-seanb
On Tue, Jan 17, 2012 at 11:13:35AM -0500, Yurong Sun wrote:
> Hi,
>
> I have a problem regarding getting mbuf physical address. In transmission, for example, when got a network packet, I
added some additional packet descriptor info into the M_LEADINGSPACE, between m->pkt_dat and m->m_data. I then need to
get the physical address starting from the packet descriptor in order for DMA operation. My assumption is that the mbuf
as a whole is in a contiguous buffer, or at least the buffer between m->pkt_data to the end of m->m_data is. Am I
correct?
>
> Based on my assumption, I used mem_offset64 to get the physical address of the starting point, i.e., m->pkt_data +
alignment offset. It seems not getting the correct one. I noticed that there is mbuf_phys, but that seems, from the code
, only get the m->m_data physical address, not the one that I need.
>
> I have a workaround to copy the mbuf into a contiguous buffer. But I fear for the performance impact.
>
> Any suggestions?
>
> Thanks,
>
> Yurong
>
>
>
> _______________________________________________
>
> Networking Drivers
> http://community.qnx.com/sf/go/post90959
>
|
|
|
Yurong Sun
|
Re: getting mbuf physical address
|
Yurong Sun
01/17/2012 3:46 PM
post90964
|
Re: getting mbuf physical address
Hi Sean
I still see problem with M_PREPEND + mbuf_phys. I did a very simple experiment to prove that the problem is just related
with the mbuf physical address. See the code snippet below.
What it does is that I copied m->m_data into another contiguous buffer and use the physical address of the contiguous
buffer I created works, but not directly from the physical address of mbuf retrieved from mbuf_phys. I even dumped the m
->m_data content and verified that the content is correct. So if I copy the m->m_data into another buffer, and DMA the
other buffer works, it means the content of mbuf is correct. The only issue is that the address of mbuf for DMA is not
right.
The function below is on a thread that created by nw_pthread_create, not the io-pkt thread, could this be a problem?
int send_packet(struct mbuf* m)
{
int headsize = 22;
off64_t buf_phy1, buf_phy2;
M_PREPEND(m, headsize, M_DONTWAIT);
// initialization of head
...
buf_phy1 = mbuf_phys(m);
//1. directly dma m_buf physical address
DMA(buf_phy1, m->m_len); // not working
//2. workaround to copy mbuf into a contigous buffer
uint8_t* buffer = mmap(NULL, m->m_len, PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_ANON, NOFD, 0);
memcpy(buffer, m->m_data, m->m_len);
mem_offset64((void*)buffer, NOFD, 1, &buf_phy2, NULL);
DMA(buf_phy2, m->m_len); //Works!!
}
Thanks,
Yurong
|
|
|
Yurong Sun
|
Re: getting mbuf physical address
|
Yurong Sun
01/17/2012 3:50 PM
post90965
|
Re: getting mbuf physical address
I logged the logical and physical address of mbuf:
m->m_data 0x2c2dc0, buf_phy1 0x35a30dc0 //not working using buf_phy1
//the contiguous buffer created seperately
buffer 0x2e9040, buf_phy2 0x3f359040 //working using buf_phy2
The address all meet the alignment requirement for DMA.
|
|
|
Yurong Sun
|
Re: getting mbuf physical address
|
Yurong Sun
01/17/2012 5:49 PM
post90971
|
Re: getting mbuf physical address
Sean,
Many thanks. It solved my problem!
Yurong
|
|
|
Sean Boudreau(deleted)
|
Re: getting mbuf physical address
|
Sean Boudreau(deleted)
01/17/2012 4:08 PM
post90966
|
Re: getting mbuf physical address
Mbufs are cached. You may need to flush before and invalidate after dma depending on platform.
-seanb
----- Original Message -----
From: Yurong Sun [mailto:community-noreply@qnx.com]
Sent: Tuesday, January 17, 2012 03:46 PM
To: drivers-networking <post90964@community.qnx.com>
Subject: Re: getting mbuf physical address
Hi Sean
I still see problem with M_PREPEND + mbuf_phys. I did a very simple experiment to prove that the problem is just related
with the mbuf physical address. See the code snippet below.
What it does is that I copied m->m_data into another contiguous buffer and use the physical address of the contiguous
buffer I created works, but not directly from the physical address of mbuf retrieved from mbuf_phys. I even dumped the m
->m_data content and verified that the content is correct. So if I copy the m->m_data into another buffer, and DMA the
other buffer works, it means the content of mbuf is correct. The only issue is that the address of mbuf for DMA is not
right.
The function below is on a thread that created by nw_pthread_create, not the io-pkt thread, could this be a problem?
int send_packet(struct mbuf* m)
{
int headsize = 22;
off64_t buf_phy1, buf_phy2;
M_PREPEND(m, headsize, M_DONTWAIT);
// initialization of head
...
buf_phy1 = mbuf_phys(m);
//1. directly dma m_buf physical address
DMA(buf_phy1, m->m_len); // not working
//2. workaround to copy mbuf into a contigous buffer
uint8_t* buffer = mmap(NULL, m->m_len, PROT_READ|PROT_WRITE|PROT_NOCACHE,
MAP_PHYS|MAP_ANON, NOFD, 0);
memcpy(buffer, m->m_data, m->m_len);
mem_offset64((void*)buffer, NOFD, 1, &buf_phy2, NULL);
DMA(buf_phy2, m->m_len); //Works!!
}
Thanks,
Yurong
_______________________________________________
Networking Drivers
http://community.qnx.com/sf/go/post90964
|
|
|
|