/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to driver/kmem.c

  • Committer: Suren A. Chilingaryan
  • Date: 2011-10-23 00:43:20 UTC
  • Revision ID: csa@dside.dyndns.org-20111023004320-523yoab3y82nketc
Properly perform synchronization of DMA buffers

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
                    kmem_handle->align = kmem_entry->align;
47
47
                } else {
48
48
                    if (kmem_handle->type != kmem_entry->type) {
49
 
                        mod_info("Invalid type of reusable kmem_entry\n");
 
49
                        mod_info("Invalid type of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->type, kmem_handle->type);
50
50
                        return -EINVAL;
51
51
                    }
52
52
 
53
 
                    if (kmem_handle->type == PCILIB_KMEM_TYPE_PAGE) {
 
53
                    if ((kmem_handle->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_PAGE) {
54
54
                            kmem_handle->size = kmem_entry->size;
55
55
                    } else if (kmem_handle->size != kmem_entry->size) {
56
 
                        mod_info("Invalid size of reusable kmem_entry\n");
 
56
                        mod_info("Invalid size of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->size, kmem_handle->size);
57
57
                        return -EINVAL;
58
58
                    }
59
59
                    
60
60
                    if (kmem_handle->align != kmem_entry->align) {
61
 
                        mod_info("Invalid alignment of reusable kmem_entry\n");
 
61
                        mod_info("Invalid alignment of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->align, kmem_handle->align);
62
62
                        return -EINVAL;
63
63
                    }
64
64
 
112
112
        kmem_entry->item = kmem_handle->item;
113
113
        kmem_entry->type = kmem_handle->type;
114
114
        kmem_entry->align = kmem_handle->align;
 
115
        kmem_entry->direction = PCI_DMA_NONE;
115
116
 
116
117
        /* Initialize sysfs if possible */
117
118
        if (pcidriver_sysfs_initialize_kmem(privdata, kmem_entry->id, &(kmem_entry->sysfs_attr)) != 0)
124
125
         * CPU address is used for the mmap (internal to the driver), and
125
126
         * PCI address is the address passed to the DMA Controller in the device.
126
127
         */
127
 
        switch (kmem_entry->type) {
 
128
        switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) {
128
129
         case PCILIB_KMEM_TYPE_CONSISTENT:
129
130
            retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) );
130
131
            break;
132
133
            retptr = (void*)__get_free_pages(GFP_KERNEL, get_order(PAGE_SIZE));
133
134
            kmem_entry->dma_handle = 0;
134
135
            kmem_handle->size = PAGE_SIZE;
135
 
 
136
 
//          kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, PAGE_SIZE,  PCI_DMA_FROMDEVICE);
137
 
//          printk("%llx %lx\n", kmem_entry->dma_handle, retptr);
 
136
            
 
137
            if (retptr) {
 
138
                if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {
 
139
                    kmem_entry->direction = PCI_DMA_TODEVICE;
 
140
                    kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, PAGE_SIZE, PCI_DMA_TODEVICE);
 
141
                    if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) {
 
142
                        free_page((unsigned long)retptr);
 
143
                        goto kmem_alloc_mem_fail;
 
144
                    }
 
145
                } else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) {
 
146
                    kmem_entry->direction = PCI_DMA_FROMDEVICE;
 
147
                    kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, PAGE_SIZE, PCI_DMA_FROMDEVICE);
 
148
                    if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) {
 
149
                        free_page((unsigned long)retptr);
 
150
                        goto kmem_alloc_mem_fail;
 
151
                    
 
152
                    }
 
153
                }
 
154
            }
 
155
            
138
156
            break;
139
157
         default:
140
158
            goto kmem_alloc_mem_fail;
141
159
        }
 
160
        
 
161
        
142
162
        if (retptr == NULL)
143
163
                goto kmem_alloc_mem_fail;
144
164
 
316
336
        if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL)
317
337
                return -EINVAL;                                 /* kmem_handle is not valid */
318
338
 
319
 
 
320
 
        if (!kmem_entry->dma_handle) {
321
 
            mod_info_dbg("Instead of synchronization, we are mapping kmem_entry with id: %d\n", kmem_entry->id);
322
 
            if (kmem_sync->dir == PCIDRIVER_DMA_TODEVICE) 
323
 
                kmem_entry->dma_handle = pci_map_single(privdata->pdev, (void*)kmem_entry->cpua, kmem_entry->size,  PCI_DMA_TODEVICE);
324
 
            else
325
 
                kmem_entry->dma_handle = pci_map_single(privdata->pdev, (void*)kmem_entry->cpua, kmem_entry->size,  PCI_DMA_FROMDEVICE);
326
 
 
327
 
            kmem_sync->handle.pa = kmem_entry->dma_handle;
328
 
        }
329
 
        
 
339
        if (kmem_entry->direction == PCI_DMA_NONE)
 
340
                return -EINVAL;
 
341
 
330
342
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
331
343
        switch (kmem_sync->dir) {
332
 
                case PCIDRIVER_DMA_TODEVICE:
333
 
                        pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE );
334
 
                        break;
335
 
                case PCIDRIVER_DMA_FROMDEVICE:
336
 
                        pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE );
337
 
                        break;
338
 
                case PCIDRIVER_DMA_BIDIRECTIONAL:
339
 
                        pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_BIDIRECTIONAL );
340
 
                        pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_BIDIRECTIONAL );
 
344
                case PCILIB_KMEM_SYNC_TODEVICE:
 
345
                        pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
 
346
                        break;
 
347
                case PCILIB_KMEM_SYNC_FROMDEVICE:
 
348
                        pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
 
349
                        break;
 
350
                case PCILIB_KMEM_SYNC_BIDIRECTIONAL:
 
351
                        pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
 
352
                        pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
341
353
                        break;
342
354
                default:
343
355
                        return -EINVAL;                         /* wrong direction parameter */
344
356
        }
345
357
#else
346
358
        switch (kmem_sync->dir) {
347
 
                case PCIDRIVER_DMA_TODEVICE:
348
 
                        pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE );
349
 
                        break;
350
 
                case PCIDRIVER_DMA_FROMDEVICE:
351
 
                        pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE );
352
 
                        break;
353
 
                case PCIDRIVER_DMA_BIDIRECTIONAL:
354
 
                        pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_BIDIRECTIONAL );
 
359
                case PCILIB_KMEM_SYNC_TODEVICE:
 
360
                        pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
 
361
                        break;
 
362
                case PCILIB_KMEM_SYNC_FROMDEVICE:
 
363
                        pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
 
364
                        break;
 
365
                case PCILIB_KMEM_SYNC_BIDIRECTIONAL:
 
366
                        pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction );
355
367
                        break;
356
368
                default:
357
369
                        return -EINVAL;                         /* wrong direction parameter */
400
412
#endif
401
413
 
402
414
        /* Release DMA memory */
403
 
        switch (kmem_entry->type) {
 
415
        switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) {
404
416
         case PCILIB_KMEM_TYPE_CONSISTENT:
405
417
            pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle );
406
418
            break;
407
419
         case PCILIB_KMEM_TYPE_PAGE:
408
 
            if (kmem_entry->dma_handle) pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE);
 
420
            if (kmem_entry->dma_handle) {
 
421
                if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) {
 
422
                    pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE);
 
423
                } else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) {
 
424
                    pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE);
 
425
                }
 
426
            }
409
427
            free_page((unsigned long)kmem_entry->cpua);
410
428
            break;
411
429
        }