/** * zfcp_adapter_dequeue - remove the adapter from the resource list * @adapter: pointer to struct zfcp_adapter which should be removed * locks: adapter list write lock is assumed to be held by caller */ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) { int retval = 0; unsigned long flags; cancel_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); zfcp_adapter_scsi_unregister(adapter); sysfs_remove_group(&adapter->ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs); dev_set_drvdata(&adapter->ccw_device->dev, NULL); /* sanity check: no pending FSF requests */ spin_lock_irqsave(&adapter->req_list_lock, flags); retval = zfcp_reqlist_isempty(adapter); spin_unlock_irqrestore(&adapter->req_list_lock, flags); if (!retval) return; zfcp_adapter_debug_unregister(adapter); zfcp_qdio_free(adapter); zfcp_free_low_mem_buffers(adapter); kfree(adapter->req_list); kfree(adapter->fc_stats); kfree(adapter->stats_reset_data); kfree(adapter); }
/** * zfcp_adapter_debug_register - registers debug feature for an adapter * @adapter: pointer to adapter for which debug features should be registered * return: -ENOMEM on error, 0 otherwise */ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) { char dbf_name[DEBUG_MAX_NAME_LEN]; /* debug feature area which records recovery activity */ sprintf(dbf_name, "zfcp_%s_rec", dev_name(&adapter->ccw_device->dev)); adapter->rec_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_rec_dbf_record)); if (!adapter->rec_dbf) goto failed; debug_register_view(adapter->rec_dbf, &debug_hex_ascii_view); debug_register_view(adapter->rec_dbf, &zfcp_rec_dbf_view); debug_set_level(adapter->rec_dbf, 3); /* debug feature area which records HBA (FSF and QDIO) conditions */ sprintf(dbf_name, "zfcp_%s_hba", dev_name(&adapter->ccw_device->dev)); adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_hba_dbf_record)); if (!adapter->hba_dbf) goto failed; debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view); debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view); debug_set_level(adapter->hba_dbf, 3); /* debug feature area which records SAN command failures and recovery */ sprintf(dbf_name, "zfcp_%s_san", dev_name(&adapter->ccw_device->dev)); adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_san_dbf_record)); if (!adapter->san_dbf) goto failed; debug_register_view(adapter->san_dbf, &debug_hex_ascii_view); debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view); debug_set_level(adapter->san_dbf, 6); /* debug feature area which records SCSI command failures and recovery */ sprintf(dbf_name, "zfcp_%s_scsi", dev_name(&adapter->ccw_device->dev)); adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, sizeof(struct zfcp_scsi_dbf_record)); if (!adapter->scsi_dbf) goto failed; debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view); debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view); debug_set_level(adapter->scsi_dbf, 3); return 0; failed: zfcp_adapter_debug_unregister(adapter); return -ENOMEM; }
/** * zfcp_adapter_dequeue - remove the adapter from the resource list * @adapter: pointer to struct zfcp_adapter which should be removed * locks: adapter list write lock is assumed to be held by caller */ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) { int retval = 0; unsigned long flags; cancel_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); zfcp_adapter_scsi_unregister(adapter); device_unregister(&adapter->generic_services); sysfs_remove_group(&adapter->ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs); dev_set_drvdata(&adapter->ccw_device->dev, NULL); /* sanity check: no pending FSF requests */ spin_lock_irqsave(&adapter->req_list_lock, flags); retval = zfcp_reqlist_isempty(adapter); spin_unlock_irqrestore(&adapter->req_list_lock, flags); if (!retval) return; zfcp_adapter_debug_unregister(adapter); /* remove specified adapter data structure from list */ write_lock_irq(&zfcp_data.config_lock); list_del(&adapter->list); write_unlock_irq(&zfcp_data.config_lock); /* decrease number of adapters in list */ zfcp_data.adapters--; zfcp_qdio_free(adapter); zfcp_free_low_mem_buffers(adapter); kfree(adapter->req_list); kfree(adapter->fc_stats); kfree(adapter->stats_reset_data); kfree(adapter); }
/** * zfcp_adapter_enqueue - enqueue a new adapter to the list * @ccw_device: pointer to the struct cc_device * * Returns: 0 if a new adapter was successfully enqueued * -ENOMEM if alloc failed * Enqueues an adapter at the end of the adapter list in the driver data. * All adapter internal structures are set up. * Proc-fs entries are also created. * locks: config_sema must be held to serialise changes to the adapter list */ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) { struct zfcp_adapter *adapter; /* * Note: It is safe to release the list_lock, as any list changes * are protected by the config_sema, which must be held to get here */ adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL); if (!adapter) return -ENOMEM; ccw_device->handler = NULL; adapter->ccw_device = ccw_device; atomic_set(&adapter->refcount, 0); if (zfcp_qdio_allocate(adapter)) goto qdio_allocate_failed; if (zfcp_allocate_low_mem_buffers(adapter)) goto failed_low_mem_buffers; if (zfcp_reqlist_alloc(adapter)) goto failed_low_mem_buffers; if (zfcp_adapter_debug_register(adapter)) goto debug_register_failed; init_waitqueue_head(&adapter->remove_wq); init_waitqueue_head(&adapter->erp_thread_wqh); init_waitqueue_head(&adapter->erp_done_wqh); INIT_LIST_HEAD(&adapter->port_list_head); INIT_LIST_HEAD(&adapter->erp_ready_head); INIT_LIST_HEAD(&adapter->erp_running_head); spin_lock_init(&adapter->req_list_lock); spin_lock_init(&adapter->hba_dbf_lock); spin_lock_init(&adapter->san_dbf_lock); spin_lock_init(&adapter->scsi_dbf_lock); spin_lock_init(&adapter->rec_dbf_lock); spin_lock_init(&adapter->req_q_lock); rwlock_init(&adapter->erp_lock); rwlock_init(&adapter->abort_lock); sema_init(&adapter->erp_ready_sem, 0); INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); INIT_WORK(&adapter->scan_work, _zfcp_scan_ports_later); adapter->service_level.seq_print = zfcp_print_sl; /* mark adapter unusable as long as sysfs registration is not complete */ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); dev_set_drvdata(&ccw_device->dev, adapter); if (sysfs_create_group(&ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs)) goto sysfs_failed; atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); zfcp_fc_nameserver_init(adapter); if (!zfcp_adapter_scsi_register(adapter)) return 0; sysfs_failed: zfcp_adapter_debug_unregister(adapter); debug_register_failed: dev_set_drvdata(&ccw_device->dev, NULL); kfree(adapter->req_list); failed_low_mem_buffers: zfcp_free_low_mem_buffers(adapter); qdio_allocate_failed: zfcp_qdio_free(adapter); kfree(adapter); return -ENOMEM; }