On Wed, 2010-07-07 at 18:29 -0700, Tom Chen wrote:
> Hello,
> 
> I am implementing Fault Management (FMA) for my kernel driver. I modified 
> bofi.conf to enable the FMA test. 
> 
> I noticed that, when allocating large dma memory, for example 8192 bytes on 
> Sun x4270 x86 server running Solaris10 u9, the ddi_dma_addr_bind_handle() 
> always fails and return DDI_DMA_TOOBIG.
> However, when freeing previously allocated dma handle and access handle, the 
> ddi_dma_free_handle function always crashes with "driver freeing bound 
> dma_handle". Does this mean that the dma handle is still being used? however, 
> if I call ddi_dma_unbind_handle, I got "driver unbinding unbound dma_handle" 
> panic which indicates that it is not bounded. 
> 
> I am very puzzled. Can someone help me?

If you have gotten any error back from ddi_dma_addr_bind_handle() other
than DDI_DMA_MAPPED or DDI_DMA_PARTIAL_MAP then the resource has not
been bound, and you can't rely on it.

However, 8k should probably never come back with DDI_DMA_TOOBIG.
(Unless perhaps you allocated the handle with attributes that would
prohibit such a mapping?)

Its an error to reuse a handle with a new mapping without first
unmapping the previous mapping.  Could that be involved here?

It sounds to me like you have some other serious issues, and that
perhaps the system is more seriously confused than you realize.  I'd try
to understand why you are getting DDI_DMA_TOOBIG... 

        - Garrett

> 
> Tom
>  
> WARNING: Could not bind dummy dma resource: fffffffd, size: 9632
> Jul  7 16:54:15 fourier unix: [ID 836849 kern.notice] 
> Jul  7 16:54:15 fourier ^Mpanic[cpu13]/thread=ffffffffa1c5a820: 
> Jul  7 16:54:15 fourier genunix: [ID 195494 kern.notice] driver freeing bound 
> dma_handle
> Jul  7 16:54:15 fourier unix: [ID 100000 kern.notice] 
> Jul  7 16:54:15 fourier genunix: [ID 655072 kern.notice] fffffe8001ef7610 
> bofi:bofi_error_chan+2f78a1e6 ()
> Jul  7 16:54:15 fourier genunix: [ID 655072 kern.notice] fffffe8001ef7640 
> genunix:ddi_dma_freehdl+42 ()
> Jul  7 16:54:15 fourier genunix: [ID 655072 kern.notice] fffffe8001ef7680 
> bofi:bofi_dma_freehdl+9c ()
> Jul  7 16:54:15 fourier genunix: [ID 655072 kern.notice] fffffe8001ef76b0 
> genunix:ddi_dma_freehdl+42 ()
> Jul  7 16:54:15 fourier genunix: [ID 655072 kern.notice] fffffe8001ef76c0 
> genunix:ddi_dma_free_handle+13 ()
> Jul  7 16:54:15 fourier genunix: [ID 655072 kern.notice] fffffe8001ef7750 
> qlcnic:alloc_dummy_dma+1b8 ()
> 
> Below is my sample code which is used to allocate 8k+ dma memory:
> 
> static ddi_dma_attr_t qlcnic_dma_attr_rxbuf = {
>       DMA_ATTR_V0,            /* dma_attr_version */
>       0,                      /* dma_attr_addr_lo */
>       0x7ffffffffULL,         /* dma_attr_addr_hi */
>       0xffffull,              /* dma_attr_count_max */
>       4096,                   /* dma_attr_align */
>       0xfff8ull,              /* dma_attr_burstsizes */
>       1,                      /* dma_attr_minxfer */
>       0xffffffffull,          /* dma_attr_maxxfer */
>       0xffffull,              /* dma_attr_seg */
>       1,                      /* dma_attr_sgllen */
>       1,                      /* dma_attr_granular */
>       0       /* dma_attr_flags */
> };
> 
> static struct ddi_device_acc_attr qlcnic_buf_acc_attr = {
>       DDI_DEVICE_ATTR_V0,
>       DDI_NEVERSWAP_ACC,
>       DDI_STRICTORDER_ACC,
> };
> 
> static int
> alloc_dummy_dma(qlcnic_t *adapter, size_t size)
> {
>       int ret;
>       size_t len;
>       uint_t cookie_num;
>       dev_info_t *devinfo;
>       ddi_dma_cookie_t cookie;
>       ddi_acc_handle_t acc_hdl = NULL;
>       ddi_dma_handle_t dma_hdl = NULL;
>       uint32_t ncookies = NULL;
>       uint64_t dma_addr = 0;
>       void *vaddr = NULL;
> 
>       devinfo = adapter->dip;
> 
>       /*
>        * Allocate a new DMA handle for the receive descriptor
>        * memory area.
>        */
>       ret = ddi_dma_alloc_handle(devinfo, 
> &qlcnic_dma_attr_rxbuf/*&ixgbe_desc_dma_attr*/,
>           DDI_DMA_DONTWAIT, NULL,
>           &dma_hdl);
> 
>       if (ret != DDI_SUCCESS) {
>               cmn_err(CE_WARN,
>                   "Could not allocate dummy dma handle: %x", ret);
>               dma_hdl = NULL;
>               return (DDI_FAILURE);
>       }
> 
>       /*
>        * Allocate memory to DMA data to and from the receive
>        * descriptors.
>        */
>       ret = ddi_dma_mem_alloc(dma_hdl,
>           size, &qlcnic_buf_acc_attr/* &ixgbe_desc_acc_attr*/, 
> DDI_DMA_CONSISTENT,
>           DDI_DMA_DONTWAIT, NULL,
>           (caddr_t *)&vaddr,
>           &len, &acc_hdl);
> 
>       if (ret != DDI_SUCCESS) {
>               cmn_err(CE_WARN,
>                   "Could not allocate dummy dma memory: %x", ret);
>               acc_hdl = NULL;
>               vaddr = NULL;
>               if (dma_hdl != NULL) {
>                       ddi_dma_free_handle(&dma_hdl);
>                       dma_hdl = NULL;
>               }
>               return (DDI_FAILURE);
>       }
> 
>       /*
>        * Initialize the entire transmit buffer descriptor area to zero
>        */
>       bzero(vaddr, len);
> 
>       /*
>        * Allocates DMA resources for the memory that was allocated by
>        * the ddi_dma_mem_alloc call.
>        */
>       ret = ddi_dma_addr_bind_handle(dma_hdl,
>           NULL, (caddr_t)vaddr,
>           len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
>           DDI_DMA_DONTWAIT, NULL, &cookie, &cookie_num);
> 
>       if (ret != DDI_DMA_MAPPED) {
>               cmn_err(CE_WARN,
>                   "Could not bind dummy dma resource: %x, size: %d", ret, 
> size);
>               dma_addr = NULL;
>               if (acc_hdl != NULL) {
>                       ddi_dma_mem_free(&acc_hdl);
>                       acc_hdl = NULL;
>                       vaddr = NULL;
>               }
>               if (dma_hdl != NULL) {
>                       /* ddi_dma_unbind_handle(dma_hdl); */
>                       ddi_dma_free_handle(&dma_hdl);
>                       dma_hdl = NULL;
>               }
>               return (DDI_FAILURE);
>       }
> 
>       ASSERT(cookie_num == 1);
> 
>       dma_addr = cookie.dmac_laddress;
>       
>       cmn_err(CE_NOTE, "alloc_dummy_dma done\n");
> 
>       return (DDI_SUCCESS);
> }


_______________________________________________
driver-discuss mailing list
[email protected]
http://mail.opensolaris.org/mailman/listinfo/driver-discuss

Reply via email to