/** * dcdbas_exit: perform driver cleanup */ static void __exit dcdbas_exit(void) { /* * make sure functions that use dcdbas_pdev are called * before platform_device_unregister */ unregister_reboot_notifier(&dcdbas_reboot_nb); smi_data_buf_free(); platform_device_unregister(dcdbas_pdev); platform_driver_unregister(&dcdbas_driver); /* * We have to free the buffer here instead of dcdbas_remove * because only in module exit function we can be sure that * all sysfs attributes belonging to this module have been * released. */ smi_data_buf_free(); }
/** * smi_data_buf_realloc: grow SMI data buffer if needed */ static int smi_data_buf_realloc(unsigned long size) { void *buf; dma_addr_t handle; if (smi_data_buf_size >= size) return 0; if (size > MAX_SMI_DATA_BUF_SIZE) return -EINVAL; /* new buffer is needed */ buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL); if (!buf) { dev_dbg(&dcdbas_pdev->dev, "%s: failed to allocate memory size %lu\n", __func__, size); return -ENOMEM; } /* memory zeroed by dma_alloc_coherent */ if (smi_data_buf) memcpy(buf, smi_data_buf, smi_data_buf_size); /* free any existing buffer */ smi_data_buf_free(); /* set up new buffer for use */ smi_data_buf = buf; smi_data_buf_handle = handle; smi_data_buf_phys_addr = (u32) virt_to_phys(buf); smi_data_buf_size = size; dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n", __func__, smi_data_buf_phys_addr, smi_data_buf_size); return 0; }