static void __init zfcp_init_device_configure(void) { struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; down(&zfcp_data.config_sema); read_lock_irq(&zfcp_data.config_lock); adapter = zfcp_get_adapter_by_busid(zfcp_data.init_busid); if (adapter) zfcp_adapter_get(adapter); read_unlock_irq(&zfcp_data.config_lock); if (!adapter) goto out_adapter; port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0, 0); if (IS_ERR(port)) goto out_port; unit = zfcp_unit_enqueue(port, zfcp_data.init_fcp_lun); if (IS_ERR(unit)) goto out_unit; up(&zfcp_data.config_sema); ccw_device_set_online(adapter->ccw_device); zfcp_erp_wait(adapter); down(&zfcp_data.config_sema); zfcp_unit_put(unit); out_unit: zfcp_port_put(port); out_port: zfcp_adapter_put(adapter); out_adapter: up(&zfcp_data.config_sema); return; }
static struct zfcp_erp_action *zfcp_erp_setup_act(int need, struct zfcp_adapter *adapter, struct zfcp_port *port, struct zfcp_unit *unit) { struct zfcp_erp_action *erp_action; u32 status = 0; switch (need) { case ZFCP_ERP_ACTION_REOPEN_UNIT: zfcp_unit_get(unit); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status); erp_action = &unit->erp_action; if (!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_RUNNING)) status = ZFCP_STATUS_ERP_CLOSE_ONLY; break; case ZFCP_ERP_ACTION_REOPEN_PORT: case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: zfcp_port_get(port); zfcp_erp_action_dismiss_port(port); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); erp_action = &port->erp_action; if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) status = ZFCP_STATUS_ERP_CLOSE_ONLY; break; case ZFCP_ERP_ACTION_REOPEN_ADAPTER: zfcp_adapter_get(adapter); zfcp_erp_action_dismiss_adapter(adapter); atomic_set_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); erp_action = &adapter->erp_action; if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) status = ZFCP_STATUS_ERP_CLOSE_ONLY; break; default: return NULL; } memset(erp_action, 0, sizeof(struct zfcp_erp_action)); erp_action->adapter = adapter; erp_action->port = port; erp_action->unit = unit; erp_action->action = need; erp_action->status = status; return erp_action; }
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) { struct ccw_device *ccwdev; struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); if (!ccwdev) return; if (ccw_device_set_online(ccwdev)) goto out_ccwdev; mutex_lock(&zfcp_data.config_mutex); adapter = dev_get_drvdata(&ccwdev->dev); if (!adapter) goto out_unlock; zfcp_adapter_get(adapter); port = zfcp_get_port_by_wwpn(adapter, wwpn); if (!port) goto out_port; zfcp_port_get(port); unit = zfcp_unit_enqueue(port, lun); if (IS_ERR(unit)) goto out_unit; mutex_unlock(&zfcp_data.config_mutex); zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); zfcp_erp_wait(adapter); flush_work(&unit->scsi_work); mutex_lock(&zfcp_data.config_mutex); zfcp_unit_put(unit); out_unit: zfcp_port_put(port); out_port: zfcp_adapter_put(adapter); out_unlock: mutex_unlock(&zfcp_data.config_mutex); out_ccwdev: put_device(&ccwdev->dev); return; }
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) { struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; down(&zfcp_data.config_sema); read_lock_irq(&zfcp_data.config_lock); adapter = zfcp_get_adapter_by_busid(busid); if (adapter) zfcp_adapter_get(adapter); read_unlock_irq(&zfcp_data.config_lock); if (!adapter) goto out_adapter; port = zfcp_port_enqueue(adapter, wwpn, 0, 0); if (IS_ERR(port)) goto out_port; unit = zfcp_unit_enqueue(port, lun); if (IS_ERR(unit)) goto out_unit; up(&zfcp_data.config_sema); ccw_device_set_online(adapter->ccw_device); zfcp_erp_wait(adapter); wait_event(adapter->erp_done_wqh, !(atomic_read(&unit->status) & ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)); down(&zfcp_data.config_sema); zfcp_unit_put(unit); out_unit: zfcp_port_put(port); out_port: zfcp_adapter_put(adapter); out_adapter: up(&zfcp_data.config_sema); return; }
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) { struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; mutex_lock(&zfcp_data.config_mutex); read_lock_irq(&zfcp_data.config_lock); adapter = zfcp_get_adapter_by_busid(busid); if (adapter) zfcp_adapter_get(adapter); read_unlock_irq(&zfcp_data.config_lock); if (!adapter) goto out_adapter; port = zfcp_port_enqueue(adapter, wwpn, 0, 0); if (IS_ERR(port)) goto out_port; unit = zfcp_unit_enqueue(port, lun); if (IS_ERR(unit)) goto out_unit; mutex_unlock(&zfcp_data.config_mutex); ccw_device_set_online(adapter->ccw_device); zfcp_erp_wait(adapter); flush_work(&unit->scsi_work); mutex_lock(&zfcp_data.config_mutex); zfcp_unit_put(unit); out_unit: zfcp_port_put(port); out_port: zfcp_adapter_put(adapter); out_adapter: mutex_unlock(&zfcp_data.config_mutex); return; }
/** * zfcp_port_enqueue - enqueue port to port list of adapter * @adapter: adapter where remote port is added * @wwpn: WWPN of the remote port to be enqueued * @status: initial status for the port * @d_id: destination id of the remote port to be enqueued * Returns: pointer to enqueued port on success, ERR_PTR on error * Locks: config_sema must be held to serialize changes to the port list * * All port internal structures are set up and the sysfs entry is generated. * d_id is used to enqueue ports with a well known address like the Directory * Service for nameserver lookup. */ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, u32 status, u32 d_id) { struct zfcp_port *port; int retval; port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); if (!port) return ERR_PTR(-ENOMEM); init_waitqueue_head(&port->remove_wq); INIT_LIST_HEAD(&port->unit_list_head); INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup); port->adapter = adapter; port->d_id = d_id; port->wwpn = wwpn; /* mark port unusable as long as sysfs registration is not complete */ atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set(&port->refcount, 0); dev_set_name(&port->sysfs_device, "0x%016llx", (unsigned long long)wwpn); port->sysfs_device.parent = &adapter->ccw_device->dev; port->sysfs_device.release = zfcp_sysfs_port_release; dev_set_drvdata(&port->sysfs_device, port); read_lock_irq(&zfcp_data.config_lock); if (!(status & ZFCP_STATUS_PORT_NO_WWPN)) if (zfcp_get_port_by_wwpn(adapter, wwpn)) { read_unlock_irq(&zfcp_data.config_lock); goto err_out_free; } read_unlock_irq(&zfcp_data.config_lock); if (device_register(&port->sysfs_device)) goto err_out_free; retval = sysfs_create_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); if (retval) { device_unregister(&port->sysfs_device); goto err_out; } zfcp_port_get(port); write_lock_irq(&zfcp_data.config_lock); list_add_tail(&port->list, &adapter->port_list_head); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); write_unlock_irq(&zfcp_data.config_lock); zfcp_adapter_get(adapter); return port; err_out_free: kfree(port); err_out: return ERR_PTR(-EINVAL); }
/** * zfcp_port_enqueue - enqueue port to port list of adapter * @adapter: adapter where remote port is added * @wwpn: WWPN of the remote port to be enqueued * @status: initial status for the port * @d_id: destination id of the remote port to be enqueued * Returns: pointer to enqueued port on success, ERR_PTR on error * Locks: config_sema must be held to serialize changes to the port list * * All port internal structures are set up and the sysfs entry is generated. * d_id is used to enqueue ports with a well known address like the Directory * Service for nameserver lookup. */ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status, u32 d_id) { struct zfcp_port *port; int retval; char *bus_id; port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); if (!port) return ERR_PTR(-ENOMEM); init_waitqueue_head(&port->remove_wq); INIT_LIST_HEAD(&port->unit_list_head); INIT_LIST_HEAD(&port->unit_remove_lh); port->adapter = adapter; port->d_id = d_id; port->wwpn = wwpn; /* mark port unusable as long as sysfs registration is not complete */ atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set(&port->refcount, 0); if (status & ZFCP_STATUS_PORT_WKA) { switch (d_id) { case ZFCP_DID_DIRECTORY_SERVICE: bus_id = "directory"; break; case ZFCP_DID_MANAGEMENT_SERVICE: bus_id = "management"; break; case ZFCP_DID_KEY_DISTRIBUTION_SERVICE: bus_id = "key_distribution"; break; case ZFCP_DID_ALIAS_SERVICE: bus_id = "alias"; break; case ZFCP_DID_TIME_SERVICE: bus_id = "time"; break; default: kfree(port); return ERR_PTR(-EINVAL); } snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "%s", bus_id); port->sysfs_device.parent = &adapter->generic_services; } else { snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", wwpn); port->sysfs_device.parent = &adapter->ccw_device->dev; } port->sysfs_device.release = zfcp_sysfs_port_release; dev_set_drvdata(&port->sysfs_device, port); read_lock_irq(&zfcp_data.config_lock); if (!(status & ZFCP_STATUS_PORT_NO_WWPN)) if (zfcp_get_port_by_wwpn(adapter, wwpn)) { read_unlock_irq(&zfcp_data.config_lock); goto err_out_free; } read_unlock_irq(&zfcp_data.config_lock); if (device_register(&port->sysfs_device)) goto err_out_free; if (status & ZFCP_STATUS_PORT_WKA) retval = sysfs_create_group(&port->sysfs_device.kobj, &zfcp_sysfs_ns_port_attrs); else retval = sysfs_create_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); if (retval) { device_unregister(&port->sysfs_device); goto err_out; } zfcp_port_get(port); write_lock_irq(&zfcp_data.config_lock); list_add_tail(&port->list, &adapter->port_list_head); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); if (d_id == ZFCP_DID_DIRECTORY_SERVICE) if (!adapter->nameserver_port) adapter->nameserver_port = port; adapter->ports++; write_unlock_irq(&zfcp_data.config_lock); zfcp_adapter_get(adapter); return port; err_out_free: kfree(port); err_out: return ERR_PTR(-EINVAL); }