/* * fnic_trace_buf_init - Initialize fnic trace buffer logging facility * * Description: * Initialize trace buffer data structure by allocating required memory and * setting page_offset information for every trace entry by adding trace entry * length to previous page_offset value. */ int fnic_trace_buf_init(void) { unsigned long fnic_buf_head; int i; int err = 0; trace_max_pages = fnic_trace_max_pages; fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/ FNIC_ENTRY_SIZE_BYTES; fnic_trace_buf_p = (unsigned long)vmalloc((trace_max_pages * PAGE_SIZE)); if (!fnic_trace_buf_p) { printk(KERN_ERR PFX "Failed to allocate memory " "for fnic_trace_buf_p\n"); err = -ENOMEM; goto err_fnic_trace_buf_init; } memset((void *)fnic_trace_buf_p, 0, (trace_max_pages * PAGE_SIZE)); fnic_trace_entries.page_offset = vmalloc(fnic_max_trace_entries * sizeof(unsigned long)); if (!fnic_trace_entries.page_offset) { printk(KERN_ERR PFX "Failed to allocate memory for" " page_offset\n"); if (fnic_trace_buf_p) { vfree((void *)fnic_trace_buf_p); fnic_trace_buf_p = 0; } err = -ENOMEM; goto err_fnic_trace_buf_init; } memset((void *)fnic_trace_entries.page_offset, 0, (fnic_max_trace_entries * sizeof(unsigned long))); fnic_trace_entries.wr_idx = fnic_trace_entries.rd_idx = 0; fnic_buf_head = fnic_trace_buf_p; /* * Set page_offset field of fnic_trace_entries struct by * calculating memory location for every trace entry using * length of each trace entry */ for (i = 0; i < fnic_max_trace_entries; i++) { fnic_trace_entries.page_offset[i] = fnic_buf_head; fnic_buf_head += FNIC_ENTRY_SIZE_BYTES; } err = fnic_trace_debugfs_init(); if (err < 0) { pr_err("fnic: Failed to initialize debugfs for tracing\n"); goto err_fnic_trace_debugfs_init; } pr_info("fnic: Successfully Initialized Trace Buffer\n"); return err; err_fnic_trace_debugfs_init: fnic_trace_free(); err_fnic_trace_buf_init: return err; }
static void __exit fnic_cleanup_module(void) { pci_unregister_driver(&fnic_driver); destroy_workqueue(fnic_event_queue); if (fnic_fip_queue) { flush_workqueue(fnic_fip_queue); destroy_workqueue(fnic_fip_queue); } kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]); kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); kmem_cache_destroy(fnic_io_req_cache); fc_release_transport(fnic_fc_transport); fnic_trace_free(); }
static int __init fnic_init_module(void) { size_t len; int err = 0; printk(KERN_INFO PFX "%s, ver %s\n", DRV_DESCRIPTION, DRV_VERSION); /* Create debugfs entries for fnic */ err = fnic_debugfs_init(); if (err < 0) { printk(KERN_ERR PFX "Failed to create fnic directory " "for tracing and stats logging\n"); fnic_debugfs_terminate(); } /* Allocate memory for trace buffer */ err = fnic_trace_buf_init(); if (err < 0) { printk(KERN_ERR PFX "Trace buffer initialization Failed " "Fnic Tracing utility is disabled\n"); fnic_trace_free(); } /* Create a cache for allocation of default size sgls */ len = sizeof(struct fnic_dflt_sgl_list); fnic_sgl_cache[FNIC_SGL_CACHE_DFLT] = kmem_cache_create ("fnic_sgl_dflt", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN, SLAB_HWCACHE_ALIGN, NULL); if (!fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]) { printk(KERN_ERR PFX "failed to create fnic dflt sgl slab\n"); err = -ENOMEM; goto err_create_fnic_sgl_slab_dflt; } /* Create a cache for allocation of max size sgls*/ len = sizeof(struct fnic_sgl_list); fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create ("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN, SLAB_HWCACHE_ALIGN, NULL); if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) { printk(KERN_ERR PFX "failed to create fnic max sgl slab\n"); err = -ENOMEM; goto err_create_fnic_sgl_slab_max; } /* Create a cache of io_req structs for use via mempool */ fnic_io_req_cache = kmem_cache_create("fnic_io_req", sizeof(struct fnic_io_req), 0, SLAB_HWCACHE_ALIGN, NULL); if (!fnic_io_req_cache) { printk(KERN_ERR PFX "failed to create fnic io_req slab\n"); err = -ENOMEM; goto err_create_fnic_ioreq_slab; } fnic_event_queue = create_singlethread_workqueue("fnic_event_wq"); if (!fnic_event_queue) { printk(KERN_ERR PFX "fnic work queue create failed\n"); err = -ENOMEM; goto err_create_fnic_workq; } spin_lock_init(&fnic_list_lock); INIT_LIST_HEAD(&fnic_list); fnic_fip_queue = create_singlethread_workqueue("fnic_fip_q"); if (!fnic_fip_queue) { printk(KERN_ERR PFX "fnic FIP work queue create failed\n"); err = -ENOMEM; goto err_create_fip_workq; } fnic_fc_transport = fc_attach_transport(&fnic_fc_functions); if (!fnic_fc_transport) { printk(KERN_ERR PFX "fc_attach_transport error\n"); err = -ENOMEM; goto err_fc_transport; } /* register the driver with PCI system */ err = pci_register_driver(&fnic_driver); if (err < 0) { printk(KERN_ERR PFX "pci register error\n"); goto err_pci_register; } return err; err_pci_register: fc_release_transport(fnic_fc_transport); err_fc_transport: destroy_workqueue(fnic_fip_queue); err_create_fip_workq: destroy_workqueue(fnic_event_queue); err_create_fnic_workq: kmem_cache_destroy(fnic_io_req_cache); err_create_fnic_ioreq_slab: kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]); err_create_fnic_sgl_slab_max: kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); err_create_fnic_sgl_slab_dflt: fnic_trace_free(); fnic_debugfs_terminate(); return err; }