[driver-discuss] ddi_dma_attr_t, dma_attr_maxxfer quesiton.

Carlos Cumming tcc_sun29 at thinkthink.com
Tue Dec 4 16:31:20 PST 2007


Mark Johnson wrote:
> What is MEMTYPE set to.  It looks like you have set
> DDI_DMA_PARTIAL which is correct. 
...I think I intended to have DDI_DMA_PARTIAL off. But you say, "is 
correct".  Is there a problem with turning it off if I want the whole 
kit'n kaboodle?
> e.g. if a dma engine has a 16 bit size for the DMA engine,  the max 
> size it can DMA is 64K - 1 byte. (0xffff). A few DMA
> engines will use 0 to signify the 0x10000 value, but that means adding 
> another bit to the counter or adding some more
> complicated logic.
[the above] is how I understood it.... But if you want to get optimal 
performance out of your hw, then you'd want to do a full 64k DMA 
(somehow). Xfering 65535 (64k - 1) bytes is a really oddball value. 
Specially if you have a block (512 byte) device like I have.

In my case I'm actually, "logically" limited. I.e., the firmware in the 
device is limiting me to 128k, the actual counter goes to 2^32 - 1 (to 
use your parlance). So I take it in my case using a full value of 128k 
(i.e., 0x20000) in dma_attr_maxxfer is correct.

Thanks!!!

Carlos
>
>
> Carlos Cumming wrote:
>> I'm writing a SCSI driver. The board I'm talking to can do a max 128k 
>> (256 blocks) DMA. I am using the following two dma_attr_t's:
>>
>> static ddi_dma_attr_t hba_dma_attr = {
>>     DMA_ATTR_V0,                        // dma_attr_version     
>> Version of this structure
>>     (u64)0,                             // dma_attr_addr_lo     
>> Lowest usable address
>>     (u64)0xffffffffffffffff,            // dma_attr_addr_hi     
>> Highest usable address
>>     (u64)(256 * 512) - 1,               // dma_attr_count_max   
>> Maximum DMAable byte count (1 sge * maxxfer)
>>     512,                                // dma_attr_align       
>> Minimum alignment (This value correct?)
>>     0x7f,                               // dma_attr_burstsizes  Burst 
>> sizes (??? big values don't work)
>>     (u64)4,                             // dma_attr_minxfer     
>> Minimum transfer
>>     (u64)(256 * 512) - 1,               // dma_attr_maxxfer     
>> Maximum transfer count for entire I/O.
>>     (u64)0xffffffffffffffff,            // dma_attr_seg         
>> Maximum segment (boundry DMA engine cannot cross).
>>     512,                                // dma_attr_sgllen      
>> Maximum scatter gather list entries
>>     512,                                // dma_attr_granular    
>> Granularity
>>     0,                                  // dma_attr_flags       Flags 
>> (reserved)
>> };
>>
>> static ddi_dma_attr_t cmd_dma_attr = {
>>     DMA_ATTR_V0,                        // dma_attr_version     
>> Version of this structure
>>     (u64)0,                             // dma_attr_addr_lo     
>> Lowest usable address
>>     (u64)0xffffffffffffffff,            // dma_attr_addr_hi     
>> Highest usable address
>>     (u64)(256 * 512) - 1,               // dma_attr_count_max   
>> Maximum DMAable byte count (1 sge * maxxfer)
>>     512,                                // dma_attr_align       
>> Minimum alignment (This value correct?)
>>     0x7f,                               // dma_attr_burstsizes  Burst 
>> sizes (??? big values don't work)
>>     (u64)512,                           // dma_attr_minxfer     
>> Minimum transfer
>>     (u64)(256 * 512) - 1,               // dma_attr_maxxfer     
>> Maximum transfer count for entire I/O.
>>     (u64)0xffffffffffffffff,            // dma_attr_seg         
>> Maximum segment (boundry DMA engine cannot cross).
>>     512,                                // dma_attr_sgllen      
>> Maximum scatter gather list entries
>>     512,                                // dma_attr_granular    
>> Granularity
>>     0,                                  // dma_attr_flags       Flags 
>> (reserved)
>> };
>>
>>
>>
>> Some time later, I use the first one:
>>
>> if (scsi_hba_attach_setup(dev, &hba_dma_attr, softs->tran, 0) != 
>> DDI_SUCCESS) ..
>>
>>
>>
>> Then even later (but still within attach if that matters) I use 
>> cmd_dma_attr...
>>
>>     if (ddi_dma_alloc_handle(softs->dev, &cmd_dma_attr, 
>> DDI_DMA_SLEEP, NULL, &softs->dma_hndl) != DDI_SUCCESS) {
>>         cmn_err(CE_WARN, "tw%d: tw_create_reqs: Cannot alloc dma 
>> handle for command blocks.", inst);
>>         return(1);
>>     }
>>
>> #define MEMSIZE (256 * 512)
>>
>>     if (ddi_dma_mem_alloc(softs->dma_hndl, MEMSIZE, &accattr, 
>> MEMTYPE, DDI_DMA_SLEEP, NULL, &mem, &rlen, &softs->acc_hndl)
>>       != DDI_SUCCESS) {
>>         cmn_err(CE_WARN, "tw%d: tw_create_reqs: Cannot alloc dma 
>> memory for command blocks.", inst);
>>         goto free_hndl;
>>     }
>>
>> {
>>     int a;
>>
>>     if ((a = ddi_dma_addr_bind_handle(softs->dma_hndl, NULL, mem, 
>> rlen, MEMTYPE, DDI_DMA_SLEEP, NULL, &dmacookie, &num_dmacookies)) != 
>> DDI_DMA_MAPPED) {
>>         cmn_err(CE_WARN, "tw%d: tw_create_reqs: Cannot bind dma 
>> memory to handle for command blocks. %d", inst, a);
>>         goto free_mem;
>>     }
>> }
>>
>>
>> The above ddi_dma_addr_bind_handle(.. ) _FAILS. It prints "Cannot 
>> bind dma memory to handle for command blocks. 1". The trailing ,"1" 
>> is DDI_ENOMEM if I understand it correctly.
>
> What is MEMTYPE set to.  It looks like you have set
> DDI_DMA_PARTIAL which is correct.
>
> You are not getting a failure returned.  You are getting
> DDI_DMA_PARTIAL_MAP which means you have multiple DMA
> windows.
>
> #define DDI_DMA_PARTIAL_MAP     1
>
>
>
>
>
>> Now, here's where I get lost. If you look at 
>> cmd_dma_attr.dma_attr_maxxfer above, it's set to (256 * 512) - 1. I'm 
>> trying to get 256 * 512 of memory. So, it makes sense that it fails 
>> ENOMEM, because I'm requesting one more byte than dma_attr_maxxfer.
>>
>> Or does it make sense...
>>
>> _Every_ example that I look at shows dma_attr_maxxfer set to a power 
>> of 2 - 1. I.e., the way everyone else uses dma_attr_maxxfer is as if 
>> it's the max value of a dma counter, just like dma_attr_count_max.
>>
>> So I'm feeling just a bit squeamish using a nice even power of two 
>> value for dma_attr_maxxfer when nobody else is using it that way. I 
>> figure they know something I don't.
>>
>> Can someone give me a clue???
>
> The reason folks use power of 2's - 1 for things like maxxfer, seg,
> dma count is because counters are usually powers of two :-)
>
> e.g. if a dma engine has a 16 bit size for the DMA engine,
> the max size it can DMA is 64K - 1 byte. (0xffff). A few DMA
> engines will use 0 to signify the 0x10000 value, but that
> means adding another bit to the counter or adding some more
> complicated logic.
>
>
> MRJ
>
>



More information about the driver-discuss mailing list