static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); struct zfcp_port *port; u64 wwpn; int retval = -EINVAL; if (!adapter) return -ENODEV; if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) goto out; port = zfcp_get_port_by_wwpn(adapter, wwpn); if (!port) goto out; else retval = 0; write_lock_irq(&adapter->port_list_lock); list_del(&port->list); write_unlock_irq(&adapter->port_list_lock); put_device(&port->dev); zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL); zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); out: zfcp_ccw_adapter_put(adapter); return retval ? retval : (ssize_t) count; }
static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); unsigned long val; int retval = 0; if (!adapter) return -ENODEV; if (strict_strtoul(buf, 0, &val) || val != 0) { retval = -EINVAL; goto out; } zfcp_erp_modify_adapter_status(adapter, "syafai1", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, "syafai2", NULL); zfcp_erp_wait(adapter); out: zfcp_ccw_adapter_put(adapter); return retval ? retval : (ssize_t) count; }
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) { struct ccw_device *cdev; struct zfcp_adapter *adapter; struct zfcp_port *port; cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); if (!cdev) return; if (ccw_device_set_online(cdev)) goto out_ccw_device; adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) goto out_ccw_device; port = zfcp_get_port_by_wwpn(adapter, wwpn); if (!port) goto out_port; flush_work(&port->rport_work); zfcp_unit_add(port, lun); put_device(&port->dev); out_port: zfcp_ccw_adapter_put(adapter); out_ccw_device: put_device(&cdev->dev); return; }
static void zfcp_port_release(struct device *dev) { struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); zfcp_ccw_adapter_put(port->adapter); kfree(port); }
/** * 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 * * 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 = -ENOMEM; kref_get(&adapter->ref); port = zfcp_get_port_by_wwpn(adapter, wwpn); if (port) { put_device(&port->dev); retval = -EEXIST; goto err_out; } port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); if (!port) goto err_out; rwlock_init(&port->unit_list_lock); INIT_LIST_HEAD(&port->unit_list); atomic_set(&port->units, 0); INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); INIT_WORK(&port->rport_work, zfcp_scsi_rport_work); port->adapter = adapter; port->d_id = d_id; port->wwpn = wwpn; port->rport_task = RPORT_NONE; port->dev.parent = &adapter->ccw_device->dev; port->dev.groups = zfcp_port_attr_groups; port->dev.release = zfcp_port_release; if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { kfree(port); goto err_out; } retval = -EINVAL; if (device_register(&port->dev)) { put_device(&port->dev); goto err_out; } write_lock_irq(&adapter->port_list_lock); list_add_tail(&port->list, &adapter->port_list); write_unlock_irq(&adapter->port_list_lock); atomic_or(status | ZFCP_STATUS_COMMON_RUNNING, &port->status); return port; err_out: zfcp_ccw_adapter_put(adapter); return ERR_PTR(retval); }
static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return -ENODEV; /* sync the user-space- with the kernel-invocation of scan_work */ queue_work(adapter->work_queue, &adapter->scan_work); flush_work(&adapter->scan_work); zfcp_ccw_adapter_put(adapter); return (ssize_t) count; }
void zfcp_adapter_unregister(struct zfcp_adapter *adapter) { struct ccw_device *cdev = adapter->ccw_device; cancel_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); zfcp_destroy_adapter_work_queue(adapter); zfcp_fc_wka_ports_force_offline(adapter->gs); zfcp_adapter_scsi_unregister(adapter); sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs); zfcp_erp_thread_kill(adapter); zfcp_dbf_adapter_unregister(adapter->dbf); zfcp_qdio_destroy(adapter->qdio); zfcp_ccw_adapter_put(adapter); /* final put to release */ }
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); struct zfcp_port *port; u64 wwpn; int retval = -EINVAL; if (!adapter) return -ENODEV; if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) goto out; port = zfcp_get_port_by_wwpn(adapter, wwpn); if (!port) goto out; else retval = 0; mutex_lock(&zfcp_sysfs_port_units_mutex); if (atomic_read(&port->units) > 0) { retval = -EBUSY; mutex_unlock(&zfcp_sysfs_port_units_mutex); goto out; } /* port is about to be removed, so no more unit_add */ atomic_set(&port->units, -1); mutex_unlock(&zfcp_sysfs_port_units_mutex); write_lock_irq(&adapter->port_list_lock); list_del(&port->list); write_unlock_irq(&adapter->port_list_lock); put_device(&port->dev); zfcp_erp_port_shutdown(port, 0, "syprs_1"); zfcp_device_unregister(&port->dev, &zfcp_sysfs_port_attrs); out: zfcp_ccw_adapter_put(adapter); return retval ? retval : (ssize_t) count; }
static ssize_t zfcp_sysfs_adapter_failed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ccw_device *cdev = to_ccwdev(dev); struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); int i; if (!adapter) return -ENODEV; if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) i = sprintf(buf, "1\n"); else i = sprintf(buf, "0\n"); zfcp_ccw_adapter_put(adapter); return i; }
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) { struct ccw_device *cdev; struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid); if (!cdev) return; if (ccw_device_set_online(cdev)) goto out_ccw_device; adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) goto out_ccw_device; port = zfcp_get_port_by_wwpn(adapter, wwpn); if (!port) goto out_port; unit = zfcp_unit_enqueue(port, lun); if (IS_ERR(unit)) goto out_unit; zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL); zfcp_erp_wait(adapter); flush_work(&unit->scsi_work); out_unit: put_device(&port->dev); out_port: zfcp_ccw_adapter_put(adapter); out_ccw_device: put_device(&cdev->dev); return; }
static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, unsigned long arg) { struct zfcp_cfdc_data *data; struct zfcp_cfdc_data __user *data_user; struct zfcp_adapter *adapter; struct zfcp_fsf_req *req; struct zfcp_fsf_cfdc *fsf_cfdc; int retval; if (command != ZFCP_CFDC_IOC) return -ENOTTY; if (is_compat_task()) data_user = compat_ptr(arg); else data_user = (void __user *)arg; if (!data_user) return -EINVAL; fsf_cfdc = kmalloc(sizeof(struct zfcp_fsf_cfdc), GFP_KERNEL); if (!fsf_cfdc) return -ENOMEM; data = kmalloc(sizeof(struct zfcp_cfdc_data), GFP_KERNEL); if (!data) { retval = -ENOMEM; goto no_mem_sense; } retval = copy_from_user(data, data_user, sizeof(*data)); if (retval) { retval = -EFAULT; goto free_buffer; } if (data->signature != 0xCFDCACDF) { retval = -EINVAL; goto free_buffer; } retval = zfcp_cfdc_set_fsf(fsf_cfdc, data->command); adapter = zfcp_cfdc_get_adapter(data->devno); if (!adapter) { retval = -ENXIO; goto free_buffer; } retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg, data_user->control_file); if (retval) goto adapter_put; req = zfcp_fsf_control_file(adapter, fsf_cfdc); if (IS_ERR(req)) { retval = PTR_ERR(req); goto free_sg; } if (req->status & ZFCP_STATUS_FSFREQ_ERROR) { retval = -ENXIO; goto free_fsf; } zfcp_cfdc_req_to_sense(data, req); retval = copy_to_user(data_user, data, sizeof(*data_user)); if (retval) { retval = -EFAULT; goto free_fsf; } if (data->command & ZFCP_CFDC_UPLOAD) retval = zfcp_cfdc_copy_to_user(&data_user->control_file, fsf_cfdc->sg); free_fsf: zfcp_fsf_req_free(req); free_sg: zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES); adapter_put: zfcp_ccw_adapter_put(adapter); free_buffer: kfree(data); no_mem_sense: kfree(fsf_cfdc); return retval; }