static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
{
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
	struct zfcp_unit *unit = act->unit;

	switch (act->action) {
	case ZFCP_ERP_ACTION_REOPEN_UNIT:
		if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
			zfcp_unit_get(unit);
			if (scsi_queue_work(unit->port->adapter->scsi_host,
					    &unit->scsi_work) <= 0)
				zfcp_unit_put(unit);
		}
		zfcp_unit_put(unit);
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
	case ZFCP_ERP_ACTION_REOPEN_PORT:
		if (result == ZFCP_ERP_SUCCEEDED)
			zfcp_scsi_schedule_rport_register(port);
		zfcp_port_put(port);
		break;

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		if (result == ZFCP_ERP_SUCCEEDED) {
			register_service_level(&adapter->service_level);
			schedule_work(&adapter->scan_work);
		} else
			unregister_service_level(&adapter->service_level);
		zfcp_adapter_put(adapter);
		break;
	}
}
Beispiel #2
0
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
{
	struct zfcp_adapter *adapter = act->adapter;
	struct zfcp_port *port = act->port;
	struct zfcp_unit *unit = act->unit;

	switch (act->action) {
	case ZFCP_ERP_ACTION_REOPEN_UNIT:
		zfcp_unit_put(unit);
		break;

	case ZFCP_ERP_ACTION_REOPEN_PORT:
		if (result == ZFCP_ERP_SUCCEEDED)
			zfcp_scsi_schedule_rport_register(port);
		/* fall through */
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
		zfcp_port_put(port);
		break;

	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
		if (result == ZFCP_ERP_SUCCEEDED) {
			register_service_level(&adapter->service_level);
			queue_work(adapter->work_queue, &adapter->scan_work);
		} else
			unregister_service_level(&adapter->service_level);
		zfcp_adapter_put(adapter);
		break;
	}
}
Beispiel #3
0
static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
					 struct device_attribute *attr,
					 const char *buf, size_t count)
{
	struct zfcp_port *port = dev_get_drvdata(dev);
	struct zfcp_unit *unit;
	u64 fcp_lun;
	int retval = -EINVAL;

	mutex_lock(&zfcp_data.config_mutex);
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
		retval = -EBUSY;
		goto out;
	}

	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
		goto out;

	unit = zfcp_unit_enqueue(port, fcp_lun);
	if (IS_ERR(unit))
		goto out;

	retval = 0;

	zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
	zfcp_erp_wait(unit->port->adapter);
	flush_work(&unit->scsi_work);
	zfcp_unit_put(unit);
out:
	mutex_unlock(&zfcp_data.config_mutex);
	return retval ? retval : (ssize_t) count;
}
static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
					 struct device_attribute *attr,
					 const char *buf, size_t count)
{
	struct zfcp_port *port = dev_get_drvdata(dev);
	struct zfcp_unit *unit;
	fcp_lun_t fcp_lun;
	int retval = -EINVAL;

	down(&zfcp_data.config_sema);
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
		retval = -EBUSY;
		goto out;
	}

	if (strict_strtoull(buf, 0, &fcp_lun))
		goto out;

	unit = zfcp_unit_enqueue(port, fcp_lun);
	if (IS_ERR(unit))
		goto out;

	retval = 0;

	zfcp_erp_unit_reopen(unit, 0, 94, NULL);
	zfcp_erp_wait(unit->port->adapter);
	zfcp_unit_put(unit);
out:
	up(&zfcp_data.config_sema);
	return retval ? retval : (ssize_t) count;
}
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;
}
Beispiel #6
0
/**
 * zfcp_sysfs_unit_add_store - add a unit to sysfs tree
 * @dev: pointer to belonging device
 * @buf: pointer to input buffer
 * @count: number of bytes in buffer
 *
 * Store function of the "unit_add" attribute of a port.
 */
static ssize_t
zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	fcp_lun_t fcp_lun;
	char *endp;
	struct zfcp_port *port;
	struct zfcp_unit *unit;
	int retval = -EINVAL;

	down(&zfcp_data.config_sema);

	port = dev_get_drvdata(dev);
	if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) {
		retval = -EBUSY;
		goto out;
	}

	fcp_lun = simple_strtoull(buf, &endp, 0);
	if ((endp + 1) < (buf + count))
		goto out;

	unit = zfcp_unit_enqueue(port, fcp_lun);
	if (!unit)
		goto out;

	retval = 0;

	zfcp_erp_unit_reopen(unit, 0);
	zfcp_erp_wait(unit->port->adapter);
	zfcp_unit_put(unit);
 out:
	up(&zfcp_data.config_sema);
	return retval ? retval : (ssize_t) count;
}
Beispiel #7
0
static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
					    struct device_attribute *attr,
					    const char *buf, size_t count)
{
	struct zfcp_port *port = dev_get_drvdata(dev);
	struct zfcp_unit *unit;
	u64 fcp_lun;
	LIST_HEAD(unit_remove_lh);
	struct scsi_device *sdev;

	mutex_lock(&zfcp_data.config_mutex);
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
		mutex_unlock(&zfcp_data.config_mutex);
		return -EBUSY;
	}

	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
		mutex_unlock(&zfcp_data.config_mutex);
		return -EINVAL;
	}

	read_lock_irq(&zfcp_data.config_lock);
	unit = zfcp_get_unit_by_lun(port, fcp_lun);
	read_unlock_irq(&zfcp_data.config_lock);
	if (!unit) {
		mutex_unlock(&zfcp_data.config_mutex);
		return -ENXIO;
	}
	zfcp_unit_get(unit);
	mutex_unlock(&zfcp_data.config_mutex);

	sdev = scsi_device_lookup(port->adapter->scsi_host, 0,
				  port->starget_id,
				  scsilun_to_int((struct scsi_lun *)&fcp_lun));
	if (sdev) {
		scsi_remove_device(sdev);
		scsi_device_put(sdev);
	}

	mutex_lock(&zfcp_data.config_mutex);
	zfcp_unit_put(unit);
	if (atomic_read(&unit->refcount)) {
		mutex_unlock(&zfcp_data.config_mutex);
		return -ENXIO;
	}

	write_lock_irq(&zfcp_data.config_lock);
	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
	list_move(&unit->list, &unit_remove_lh);
	write_unlock_irq(&zfcp_data.config_lock);
	mutex_unlock(&zfcp_data.config_mutex);

	zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
	zfcp_erp_wait(unit->port->adapter);
	zfcp_unit_dequeue(unit);

	return (ssize_t)count;
}
Beispiel #8
0
static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
					    struct device_attribute *attr,
					    const char *buf, size_t count)
{
	struct zfcp_port *port = dev_get_drvdata(dev);
	struct zfcp_unit *unit;
	u64 fcp_lun;
	int retval = 0;
	LIST_HEAD(unit_remove_lh);

	mutex_lock(&zfcp_data.config_mutex);
	if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
		retval = -EBUSY;
		goto out;
	}

	if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
		retval = -EINVAL;
		goto out;
	}

	write_lock_irq(&zfcp_data.config_lock);
	unit = zfcp_get_unit_by_lun(port, fcp_lun);
	if (unit) {
		write_unlock_irq(&zfcp_data.config_lock);
		
		flush_work(&unit->scsi_work);
		write_lock_irq(&zfcp_data.config_lock);

		if (atomic_read(&unit->refcount) == 0) {
			zfcp_unit_get(unit);
			atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
					&unit->status);
			list_move(&unit->list, &unit_remove_lh);
		} else {
			unit = NULL;
		}
	}

	write_unlock_irq(&zfcp_data.config_lock);

	if (!unit) {
		retval = -ENXIO;
		goto out;
	}

	zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
	zfcp_erp_wait(unit->port->adapter);
	zfcp_unit_put(unit);
	zfcp_unit_dequeue(unit);
out:
	mutex_unlock(&zfcp_data.config_mutex);
	return retval ? retval : (ssize_t) count;
}
Beispiel #9
0
/**
 * zfcp_sysfs_unit_remove_store - remove a unit from sysfs tree
 * @dev: pointer to belonging device
 * @buf: pointer to input buffer
 * @count: number of bytes in buffer
 */
static ssize_t
zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	struct zfcp_port *port;
	struct zfcp_unit *unit;
	fcp_lun_t fcp_lun;
	char *endp;
	int retval = 0;

	down(&zfcp_data.config_sema);

	port = dev_get_drvdata(dev);
	if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status)) {
		retval = -EBUSY;
		goto out;
	}

	fcp_lun = simple_strtoull(buf, &endp, 0);
	if ((endp + 1) < (buf + count)) {
		retval = -EINVAL;
		goto out;
	}

	write_lock_irq(&zfcp_data.config_lock);
	unit = zfcp_get_unit_by_lun(port, fcp_lun);
	if (unit && (atomic_read(&unit->refcount) == 0)) {
		zfcp_unit_get(unit);
		atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
		list_move(&unit->list, &port->unit_remove_lh);
	}
	else {
		unit = NULL;
	}
	write_unlock_irq(&zfcp_data.config_lock);

	if (!unit) {
		retval = -ENXIO;
		goto out;
	}

	zfcp_erp_unit_shutdown(unit, 0);
	zfcp_erp_wait(unit->port->adapter);
	zfcp_unit_put(unit);
	zfcp_unit_dequeue(unit);
 out:
	up(&zfcp_data.config_sema);
	return retval ? retval : (ssize_t) count;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}