[SCSI] zfcp: Remove global config_mutex
The global config_mutex was required for the serialization of a configuration change within the zfcp driver. This global locking is now obsolete and can be removed. The requirement of serializing the access to a zfcp_adapter reference via a ccw_device is realized wth a static spinlock. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
committed by
James Bottomley
parent
f3450c7b91
commit
de3dc57214
@@ -80,23 +80,21 @@ int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
|
|||||||
|
|
||||||
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
||||||
{
|
{
|
||||||
struct ccw_device *ccwdev;
|
struct ccw_device *cdev;
|
||||||
struct zfcp_adapter *adapter;
|
struct zfcp_adapter *adapter;
|
||||||
struct zfcp_port *port;
|
struct zfcp_port *port;
|
||||||
struct zfcp_unit *unit;
|
struct zfcp_unit *unit;
|
||||||
|
|
||||||
ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
||||||
if (!ccwdev)
|
if (!cdev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ccw_device_set_online(ccwdev))
|
if (ccw_device_set_online(cdev))
|
||||||
goto out_ccwdev;
|
goto out_ccw_device;
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
adapter = dev_get_drvdata(&ccwdev->dev);
|
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
goto out_unlock;
|
goto out_ccw_device;
|
||||||
kref_get(&adapter->ref);
|
|
||||||
|
|
||||||
port = zfcp_get_port_by_wwpn(adapter, wwpn);
|
port = zfcp_get_port_by_wwpn(adapter, wwpn);
|
||||||
if (!port)
|
if (!port)
|
||||||
@@ -105,21 +103,17 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
|
|||||||
unit = zfcp_unit_enqueue(port, lun);
|
unit = zfcp_unit_enqueue(port, lun);
|
||||||
if (IS_ERR(unit))
|
if (IS_ERR(unit))
|
||||||
goto out_unit;
|
goto out_unit;
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
|
zfcp_erp_unit_reopen(unit, 0, "auidc_1", NULL);
|
||||||
zfcp_erp_wait(adapter);
|
zfcp_erp_wait(adapter);
|
||||||
flush_work(&unit->scsi_work);
|
flush_work(&unit->scsi_work);
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
out_unit:
|
out_unit:
|
||||||
put_device(&port->sysfs_device);
|
put_device(&port->sysfs_device);
|
||||||
out_port:
|
out_port:
|
||||||
kref_put(&adapter->ref, zfcp_adapter_release);
|
zfcp_ccw_adapter_put(adapter);
|
||||||
out_unlock:
|
out_ccw_device:
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
put_device(&cdev->dev);
|
||||||
out_ccwdev:
|
|
||||||
put_device(&ccwdev->dev);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,8 +178,6 @@ static int __init zfcp_module_init(void)
|
|||||||
if (!zfcp_data.gid_pn_cache)
|
if (!zfcp_data.gid_pn_cache)
|
||||||
goto out_gid_cache;
|
goto out_gid_cache;
|
||||||
|
|
||||||
mutex_init(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
zfcp_data.scsi_transport_template =
|
zfcp_data.scsi_transport_template =
|
||||||
fc_attach_transport(&zfcp_transport_functions);
|
fc_attach_transport(&zfcp_transport_functions);
|
||||||
if (!zfcp_data.scsi_transport_template)
|
if (!zfcp_data.scsi_transport_template)
|
||||||
@@ -296,7 +288,6 @@ static void zfcp_unit_release(struct device *dev)
|
|||||||
* @port: pointer to port where unit is added
|
* @port: pointer to port where unit is added
|
||||||
* @fcp_lun: FCP LUN of unit to be enqueued
|
* @fcp_lun: FCP LUN of unit to be enqueued
|
||||||
* Returns: pointer to enqueued unit on success, ERR_PTR on error
|
* Returns: pointer to enqueued unit on success, ERR_PTR on error
|
||||||
* Locks: config_mutex must be held to serialize changes to the unit list
|
|
||||||
*
|
*
|
||||||
* Sets up some unit internal structures and creates sysfs entry.
|
* Sets up some unit internal structures and creates sysfs entry.
|
||||||
*/
|
*/
|
||||||
@@ -371,7 +362,6 @@ err_out:
|
|||||||
|
|
||||||
static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
|
static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
|
||||||
{
|
{
|
||||||
/* must only be called with zfcp_data.config_mutex taken */
|
|
||||||
adapter->pool.erp_req =
|
adapter->pool.erp_req =
|
||||||
mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
|
mempool_create_kmalloc_pool(1, sizeof(struct zfcp_fsf_req));
|
||||||
if (!adapter->pool.erp_req)
|
if (!adapter->pool.erp_req)
|
||||||
@@ -419,7 +409,6 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
|
|||||||
|
|
||||||
static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
|
static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
|
||||||
{
|
{
|
||||||
/* zfcp_data.config_mutex must be held */
|
|
||||||
if (adapter->pool.erp_req)
|
if (adapter->pool.erp_req)
|
||||||
mempool_destroy(adapter->pool.erp_req);
|
mempool_destroy(adapter->pool.erp_req);
|
||||||
if (adapter->pool.scsi_req)
|
if (adapter->pool.scsi_req)
|
||||||
@@ -501,24 +490,22 @@ static void zfcp_destroy_adapter_work_queue(struct zfcp_adapter *adapter)
|
|||||||
* zfcp_adapter_enqueue - enqueue a new adapter to the list
|
* zfcp_adapter_enqueue - enqueue a new adapter to the list
|
||||||
* @ccw_device: pointer to the struct cc_device
|
* @ccw_device: pointer to the struct cc_device
|
||||||
*
|
*
|
||||||
* Returns: 0 if a new adapter was successfully enqueued
|
* Returns: struct zfcp_adapter*
|
||||||
* -ENOMEM if alloc failed
|
|
||||||
* Enqueues an adapter at the end of the adapter list in the driver data.
|
* Enqueues an adapter at the end of the adapter list in the driver data.
|
||||||
* All adapter internal structures are set up.
|
* All adapter internal structures are set up.
|
||||||
* Proc-fs entries are also created.
|
* Proc-fs entries are also created.
|
||||||
* locks: config_mutex must be held to serialize changes to the adapter list
|
|
||||||
*/
|
*/
|
||||||
int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter;
|
struct zfcp_adapter *adapter;
|
||||||
|
|
||||||
if (!get_device(&ccw_device->dev))
|
if (!get_device(&ccw_device->dev))
|
||||||
return -ENODEV;
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
|
adapter = kzalloc(sizeof(struct zfcp_adapter), GFP_KERNEL);
|
||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
put_device(&ccw_device->dev);
|
put_device(&ccw_device->dev);
|
||||||
return -ENOMEM;
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
kref_init(&adapter->ref);
|
kref_init(&adapter->ref);
|
||||||
@@ -578,11 +565,30 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
|||||||
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
|
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
|
||||||
|
|
||||||
if (!zfcp_adapter_scsi_register(adapter))
|
if (!zfcp_adapter_scsi_register(adapter))
|
||||||
return 0;
|
return adapter;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
kref_put(&adapter->ref, zfcp_adapter_release);
|
zfcp_adapter_unregister(adapter);
|
||||||
return -ENOMEM;
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -594,27 +600,16 @@ void zfcp_adapter_release(struct kref *ref)
|
|||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter,
|
struct zfcp_adapter *adapter = container_of(ref, struct zfcp_adapter,
|
||||||
ref);
|
ref);
|
||||||
struct ccw_device *ccw_device = adapter->ccw_device;
|
struct ccw_device *cdev = adapter->ccw_device;
|
||||||
|
|
||||||
cancel_work_sync(&adapter->stat_work);
|
|
||||||
|
|
||||||
zfcp_fc_wka_ports_force_offline(adapter->gs);
|
|
||||||
sysfs_remove_group(&ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs);
|
|
||||||
|
|
||||||
dev_set_drvdata(&ccw_device->dev, NULL);
|
|
||||||
|
|
||||||
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
|
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
|
||||||
zfcp_fc_gs_destroy(adapter);
|
zfcp_fc_gs_destroy(adapter);
|
||||||
zfcp_erp_thread_kill(adapter);
|
|
||||||
zfcp_destroy_adapter_work_queue(adapter);
|
|
||||||
zfcp_dbf_adapter_unregister(adapter->dbf);
|
|
||||||
zfcp_free_low_mem_buffers(adapter);
|
zfcp_free_low_mem_buffers(adapter);
|
||||||
zfcp_qdio_destroy(adapter->qdio);
|
|
||||||
kfree(adapter->req_list);
|
kfree(adapter->req_list);
|
||||||
kfree(adapter->fc_stats);
|
kfree(adapter->fc_stats);
|
||||||
kfree(adapter->stats_reset_data);
|
kfree(adapter->stats_reset_data);
|
||||||
kfree(adapter);
|
kfree(adapter);
|
||||||
put_device(&ccw_device->dev);
|
put_device(&cdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -636,7 +631,7 @@ static void zfcp_port_release(struct device *dev)
|
|||||||
struct zfcp_port *port = container_of(dev, struct zfcp_port,
|
struct zfcp_port *port = container_of(dev, struct zfcp_port,
|
||||||
sysfs_device);
|
sysfs_device);
|
||||||
|
|
||||||
kref_put(&port->adapter->ref, zfcp_adapter_release);
|
zfcp_ccw_adapter_put(port->adapter);
|
||||||
kfree(port);
|
kfree(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,7 +642,6 @@ static void zfcp_port_release(struct device *dev)
|
|||||||
* @status: initial status for the port
|
* @status: initial status for the port
|
||||||
* @d_id: destination id of the remote port to be enqueued
|
* @d_id: destination id of the remote port to be enqueued
|
||||||
* Returns: pointer to enqueued port on success, ERR_PTR on error
|
* Returns: pointer to enqueued port on success, ERR_PTR on error
|
||||||
* Locks: config_mutex must be held to serialize changes to the port list
|
|
||||||
*
|
*
|
||||||
* All port internal structures are set up and the sysfs entry is generated.
|
* 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
|
* d_id is used to enqueue ports with a well known address like the Directory
|
||||||
@@ -718,7 +712,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
|||||||
err_out_put:
|
err_out_put:
|
||||||
device_unregister(&port->sysfs_device);
|
device_unregister(&port->sysfs_device);
|
||||||
err_out:
|
err_out:
|
||||||
kref_put(&adapter->ref, zfcp_adapter_release);
|
zfcp_ccw_adapter_put(adapter);
|
||||||
return ERR_PTR(retval);
|
return ERR_PTR(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,20 +13,42 @@
|
|||||||
|
|
||||||
#define ZFCP_MODEL_PRIV 0x4
|
#define ZFCP_MODEL_PRIV 0x4
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(zfcp_ccw_adapter_ref_lock);
|
||||||
|
|
||||||
|
struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *cdev)
|
||||||
|
{
|
||||||
|
struct zfcp_adapter *adapter;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
|
||||||
|
adapter = dev_get_drvdata(&cdev->dev);
|
||||||
|
if (adapter)
|
||||||
|
kref_get(&adapter->ref);
|
||||||
|
spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&zfcp_ccw_adapter_ref_lock, flags);
|
||||||
|
kref_put(&adapter->ref, zfcp_adapter_release);
|
||||||
|
spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int zfcp_ccw_suspend(struct ccw_device *cdev)
|
static int zfcp_ccw_suspend(struct ccw_device *cdev)
|
||||||
|
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
|
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccsusp1", NULL);
|
||||||
zfcp_erp_wait(adapter);
|
zfcp_erp_wait(adapter);
|
||||||
|
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
zfcp_ccw_adapter_put(adapter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -34,7 +56,7 @@ static int zfcp_ccw_suspend(struct ccw_device *cdev)
|
|||||||
static int zfcp_ccw_activate(struct ccw_device *cdev)
|
static int zfcp_ccw_activate(struct ccw_device *cdev)
|
||||||
|
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = dev_get_drvdata(&cdev->dev);
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
|
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -46,6 +68,8 @@ static int zfcp_ccw_activate(struct ccw_device *cdev)
|
|||||||
zfcp_erp_wait(adapter);
|
zfcp_erp_wait(adapter);
|
||||||
flush_work(&adapter->scan_work);
|
flush_work(&adapter->scan_work);
|
||||||
|
|
||||||
|
zfcp_ccw_adapter_put(adapter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,28 +91,28 @@ int zfcp_ccw_priv_sch(struct zfcp_adapter *adapter)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* zfcp_ccw_probe - probe function of zfcp driver
|
* zfcp_ccw_probe - probe function of zfcp driver
|
||||||
* @ccw_device: pointer to belonging ccw device
|
* @cdev: pointer to belonging ccw device
|
||||||
*
|
*
|
||||||
* This function gets called by the common i/o layer for each FCP
|
* This function gets called by the common i/o layer for each FCP
|
||||||
* device found on the current system. This is only a stub to make cio
|
* device found on the current system. This is only a stub to make cio
|
||||||
* work: To only allocate adapter resources for devices actually used,
|
* work: To only allocate adapter resources for devices actually used,
|
||||||
* the allocation is deferred to the first call to ccw_set_online.
|
* the allocation is deferred to the first call to ccw_set_online.
|
||||||
*/
|
*/
|
||||||
static int zfcp_ccw_probe(struct ccw_device *ccw_device)
|
static int zfcp_ccw_probe(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zfcp_ccw_remove - remove function of zfcp driver
|
* zfcp_ccw_remove - remove function of zfcp driver
|
||||||
* @ccw_device: pointer to belonging ccw device
|
* @cdev: pointer to belonging ccw device
|
||||||
*
|
*
|
||||||
* This function gets called by the common i/o layer and removes an adapter
|
* This function gets called by the common i/o layer and removes an adapter
|
||||||
* from the system. Task of this function is to get rid of all units and
|
* from the system. Task of this function is to get rid of all units and
|
||||||
* ports that belong to this adapter. And in addition all resources of this
|
* ports that belong to this adapter. And in addition all resources of this
|
||||||
* adapter will be freed too.
|
* adapter will be freed too.
|
||||||
*/
|
*/
|
||||||
static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
static void zfcp_ccw_remove(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter;
|
struct zfcp_adapter *adapter;
|
||||||
struct zfcp_port *port, *p;
|
struct zfcp_port *port, *p;
|
||||||
@@ -96,22 +120,12 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
|||||||
LIST_HEAD(unit_remove_lh);
|
LIST_HEAD(unit_remove_lh);
|
||||||
LIST_HEAD(port_remove_lh);
|
LIST_HEAD(port_remove_lh);
|
||||||
|
|
||||||
ccw_device_set_offline(ccw_device);
|
ccw_device_set_offline(cdev);
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
|
adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cancel_work_sync(&adapter->scan_work);
|
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
/* this also removes the scsi devices, so call it first */
|
|
||||||
zfcp_adapter_scsi_unregister(adapter);
|
|
||||||
|
|
||||||
write_lock_irq(&adapter->port_list_lock);
|
write_lock_irq(&adapter->port_list_lock);
|
||||||
list_for_each_entry_safe(port, p, &adapter->port_list, list) {
|
list_for_each_entry_safe(port, p, &adapter->port_list, list) {
|
||||||
write_lock(&port->unit_list_lock);
|
write_lock(&port->unit_list_lock);
|
||||||
@@ -126,7 +140,7 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
|||||||
}
|
}
|
||||||
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
|
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
|
||||||
write_unlock_irq(&adapter->port_list_lock);
|
write_unlock_irq(&adapter->port_list_lock);
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
zfcp_ccw_adapter_put(adapter); /* put from zfcp_ccw_adapter_by_cdev */
|
||||||
|
|
||||||
list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
|
list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
|
||||||
zfcp_device_unregister(&unit->sysfs_device,
|
zfcp_device_unregister(&unit->sysfs_device,
|
||||||
@@ -136,12 +150,12 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
|||||||
zfcp_device_unregister(&port->sysfs_device,
|
zfcp_device_unregister(&port->sysfs_device,
|
||||||
&zfcp_sysfs_port_attrs);
|
&zfcp_sysfs_port_attrs);
|
||||||
|
|
||||||
kref_put(&adapter->ref, zfcp_adapter_release);
|
zfcp_adapter_unregister(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zfcp_ccw_set_online - set_online function of zfcp driver
|
* zfcp_ccw_set_online - set_online function of zfcp driver
|
||||||
* @ccw_device: pointer to belonging ccw device
|
* @cdev: pointer to belonging ccw device
|
||||||
*
|
*
|
||||||
* This function gets called by the common i/o layer and sets an
|
* This function gets called by the common i/o layer and sets an
|
||||||
* adapter into state online. The first call will allocate all
|
* adapter into state online. The first call will allocate all
|
||||||
@@ -152,23 +166,20 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
|
|||||||
* the SCSI stack, that the QDIO queues will be set up and that the
|
* the SCSI stack, that the QDIO queues will be set up and that the
|
||||||
* adapter will be opened.
|
* adapter will be opened.
|
||||||
*/
|
*/
|
||||||
static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
|
static int zfcp_ccw_set_online(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter;
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
|
||||||
|
|
||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
ret = zfcp_adapter_enqueue(ccw_device);
|
adapter = zfcp_adapter_enqueue(cdev);
|
||||||
if (ret) {
|
|
||||||
dev_err(&ccw_device->dev,
|
if (IS_ERR(adapter)) {
|
||||||
|
dev_err(&cdev->dev,
|
||||||
"Setting up data structures for the "
|
"Setting up data structures for the "
|
||||||
"FCP adapter failed\n");
|
"FCP adapter failed\n");
|
||||||
goto out;
|
return PTR_ERR(adapter);
|
||||||
}
|
}
|
||||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
kref_get(&adapter->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize request counter */
|
/* initialize request counter */
|
||||||
@@ -180,58 +191,61 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
|
|||||||
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
|
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
|
||||||
"ccsonl2", NULL);
|
"ccsonl2", NULL);
|
||||||
zfcp_erp_wait(adapter);
|
zfcp_erp_wait(adapter);
|
||||||
out:
|
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
if (!ret)
|
|
||||||
flush_work(&adapter->scan_work);
|
flush_work(&adapter->scan_work);
|
||||||
return ret;
|
|
||||||
|
zfcp_ccw_adapter_put(adapter);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zfcp_ccw_set_offline - set_offline function of zfcp driver
|
* zfcp_ccw_set_offline - set_offline function of zfcp driver
|
||||||
* @ccw_device: pointer to belonging ccw device
|
* @cdev: pointer to belonging ccw device
|
||||||
*
|
*
|
||||||
* This function gets called by the common i/o layer and sets an adapter
|
* This function gets called by the common i/o layer and sets an adapter
|
||||||
* into state offline.
|
* into state offline.
|
||||||
*/
|
*/
|
||||||
static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
|
static int zfcp_ccw_set_offline(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter;
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
|
|
||||||
|
if (!adapter)
|
||||||
|
return 0;
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
adapter = dev_get_drvdata(&ccw_device->dev);
|
|
||||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1", NULL);
|
||||||
zfcp_erp_wait(adapter);
|
zfcp_erp_wait(adapter);
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
|
zfcp_ccw_adapter_put(adapter);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zfcp_ccw_notify - ccw notify function
|
* zfcp_ccw_notify - ccw notify function
|
||||||
* @ccw_device: pointer to belonging ccw device
|
* @cdev: pointer to belonging ccw device
|
||||||
* @event: indicates if adapter was detached or attached
|
* @event: indicates if adapter was detached or attached
|
||||||
*
|
*
|
||||||
* This function gets called by the common i/o layer if an adapter has gone
|
* This function gets called by the common i/o layer if an adapter has gone
|
||||||
* or reappeared.
|
* or reappeared.
|
||||||
*/
|
*/
|
||||||
static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
|
static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
|
|
||||||
|
if (!adapter)
|
||||||
|
return 1;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case CIO_GONE:
|
case CIO_GONE:
|
||||||
dev_warn(&adapter->ccw_device->dev,
|
dev_warn(&cdev->dev, "The FCP device has been detached\n");
|
||||||
"The FCP device has been detached\n");
|
|
||||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL);
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1", NULL);
|
||||||
break;
|
break;
|
||||||
case CIO_NO_PATH:
|
case CIO_NO_PATH:
|
||||||
dev_warn(&adapter->ccw_device->dev,
|
dev_warn(&cdev->dev,
|
||||||
"The CHPID for the FCP device is offline\n");
|
"The CHPID for the FCP device is offline\n");
|
||||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL);
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2", NULL);
|
||||||
break;
|
break;
|
||||||
case CIO_OPER:
|
case CIO_OPER:
|
||||||
dev_info(&adapter->ccw_device->dev,
|
dev_info(&cdev->dev, "The FCP device is operational again\n");
|
||||||
"The FCP device is operational again\n");
|
|
||||||
zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
|
zfcp_erp_modify_adapter_status(adapter, "ccnoti3", NULL,
|
||||||
ZFCP_STATUS_COMMON_RUNNING,
|
ZFCP_STATUS_COMMON_RUNNING,
|
||||||
ZFCP_SET);
|
ZFCP_SET);
|
||||||
@@ -239,11 +253,13 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
|
|||||||
"ccnoti4", NULL);
|
"ccnoti4", NULL);
|
||||||
break;
|
break;
|
||||||
case CIO_BOXED:
|
case CIO_BOXED:
|
||||||
dev_warn(&adapter->ccw_device->dev, "The FCP device "
|
dev_warn(&cdev->dev, "The FCP device did not respond within "
|
||||||
"did not respond within the specified time\n");
|
"the specified time\n");
|
||||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zfcp_ccw_adapter_put(adapter);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,18 +269,16 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
|
|||||||
*/
|
*/
|
||||||
static void zfcp_ccw_shutdown(struct ccw_device *cdev)
|
static void zfcp_ccw_shutdown(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter;
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
adapter = dev_get_drvdata(&cdev->dev);
|
|
||||||
if (!adapter)
|
if (!adapter)
|
||||||
goto out;
|
return;
|
||||||
|
|
||||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
|
zfcp_erp_adapter_shutdown(adapter, 0, "ccshut1", NULL);
|
||||||
zfcp_erp_wait(adapter);
|
zfcp_erp_wait(adapter);
|
||||||
zfcp_erp_thread_kill(adapter);
|
zfcp_erp_thread_kill(adapter);
|
||||||
out:
|
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
zfcp_ccw_adapter_put(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ccw_driver zfcp_ccw_driver = {
|
struct ccw_driver zfcp_ccw_driver = {
|
||||||
|
@@ -86,22 +86,17 @@ static int zfcp_cfdc_copy_to_user(void __user *user_buffer,
|
|||||||
static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno)
|
static struct zfcp_adapter *zfcp_cfdc_get_adapter(u32 devno)
|
||||||
{
|
{
|
||||||
char busid[9];
|
char busid[9];
|
||||||
struct ccw_device *ccwdev;
|
struct ccw_device *cdev;
|
||||||
struct zfcp_adapter *adapter = NULL;
|
struct zfcp_adapter *adapter;
|
||||||
|
|
||||||
snprintf(busid, sizeof(busid), "0.0.%04x", devno);
|
snprintf(busid, sizeof(busid), "0.0.%04x", devno);
|
||||||
ccwdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
cdev = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
|
||||||
if (!ccwdev)
|
if (!cdev)
|
||||||
goto out;
|
return NULL;
|
||||||
|
|
||||||
adapter = dev_get_drvdata(&ccwdev->dev);
|
adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
if (!adapter)
|
|
||||||
goto out_put;
|
|
||||||
|
|
||||||
kref_get(&adapter->ref);
|
put_device(&cdev->dev);
|
||||||
out_put:
|
|
||||||
put_device(&ccwdev->dev);
|
|
||||||
out:
|
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +239,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
|
|||||||
free_sg:
|
free_sg:
|
||||||
zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES);
|
zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES);
|
||||||
adapter_put:
|
adapter_put:
|
||||||
kref_put(&adapter->ref, zfcp_adapter_release);
|
zfcp_ccw_adapter_put(adapter);
|
||||||
free_buffer:
|
free_buffer:
|
||||||
kfree(data);
|
kfree(data);
|
||||||
no_mem_sense:
|
no_mem_sense:
|
||||||
|
@@ -595,7 +595,6 @@ struct zfcp_fsf_req {
|
|||||||
struct zfcp_data {
|
struct zfcp_data {
|
||||||
struct scsi_host_template scsi_host_template;
|
struct scsi_host_template scsi_host_template;
|
||||||
struct scsi_transport_template *scsi_transport_template;
|
struct scsi_transport_template *scsi_transport_template;
|
||||||
struct mutex config_mutex;
|
|
||||||
struct kmem_cache *gpn_ft_cache;
|
struct kmem_cache *gpn_ft_cache;
|
||||||
struct kmem_cache *qtcb_cache;
|
struct kmem_cache *qtcb_cache;
|
||||||
struct kmem_cache *sr_buffer_cache;
|
struct kmem_cache *sr_buffer_cache;
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
/* zfcp_aux.c */
|
/* zfcp_aux.c */
|
||||||
extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
|
extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, u64);
|
||||||
extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
|
extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64);
|
||||||
extern int zfcp_adapter_enqueue(struct ccw_device *);
|
extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
|
||||||
extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
|
extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
|
||||||
u32);
|
u32);
|
||||||
extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
|
extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
|
||||||
@@ -24,11 +24,14 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int);
|
|||||||
extern void zfcp_device_unregister(struct device *,
|
extern void zfcp_device_unregister(struct device *,
|
||||||
const struct attribute_group *);
|
const struct attribute_group *);
|
||||||
extern void zfcp_adapter_release(struct kref *);
|
extern void zfcp_adapter_release(struct kref *);
|
||||||
|
extern void zfcp_adapter_unregister(struct zfcp_adapter *);
|
||||||
|
|
||||||
/* zfcp_ccw.c */
|
/* zfcp_ccw.c */
|
||||||
extern int zfcp_ccw_register(void);
|
extern int zfcp_ccw_register(void);
|
||||||
extern int zfcp_ccw_priv_sch(struct zfcp_adapter *);
|
extern int zfcp_ccw_priv_sch(struct zfcp_adapter *);
|
||||||
extern struct ccw_driver zfcp_ccw_driver;
|
extern struct ccw_driver zfcp_ccw_driver;
|
||||||
|
extern struct zfcp_adapter *zfcp_ccw_adapter_by_cdev(struct ccw_device *);
|
||||||
|
extern void zfcp_ccw_adapter_put(struct zfcp_adapter *);
|
||||||
|
|
||||||
/* zfcp_cfdc.c */
|
/* zfcp_cfdc.c */
|
||||||
extern struct miscdevice zfcp_cfdc_misc;
|
extern struct miscdevice zfcp_cfdc_misc;
|
||||||
|
@@ -622,8 +622,6 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
|
|||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
/* first entry is the header */
|
/* first entry is the header */
|
||||||
for (x = 1; x < max_entries && !last; x++) {
|
for (x = 1; x < max_entries && !last; x++) {
|
||||||
if (x % (ZFCP_GPN_FT_ENTRIES + 1))
|
if (x % (ZFCP_GPN_FT_ENTRIES + 1))
|
||||||
@@ -655,7 +653,6 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
|
|||||||
list_for_each_entry_safe(port, tmp, &adapter->port_list, list)
|
list_for_each_entry_safe(port, tmp, &adapter->port_list, list)
|
||||||
zfcp_fc_validate_port(port, &remove_lh);
|
zfcp_fc_validate_port(port, &remove_lh);
|
||||||
write_unlock_irqrestore(&adapter->port_list_lock, flags);
|
write_unlock_irqrestore(&adapter->port_list_lock, flags);
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
|
|
||||||
list_for_each_entry_safe(port, tmp, &remove_lh, list) {
|
list_for_each_entry_safe(port, tmp, &remove_lh, list) {
|
||||||
zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL);
|
zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL);
|
||||||
|
@@ -26,22 +26,35 @@ static ssize_t zfcp_sysfs_##_feat##_##_name##_show(struct device *dev, \
|
|||||||
static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
|
static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
|
||||||
zfcp_sysfs_##_feat##_##_name##_show, NULL);
|
zfcp_sysfs_##_feat##_##_name##_show, NULL);
|
||||||
|
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n",
|
#define ZFCP_DEFINE_A_ATTR(_name, _format, _value) \
|
||||||
atomic_read(&adapter->status));
|
static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n",
|
struct device_attribute *at,\
|
||||||
|
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; \
|
||||||
|
\
|
||||||
|
i = sprintf(buf, _format, _value); \
|
||||||
|
zfcp_ccw_adapter_put(adapter); \
|
||||||
|
return i; \
|
||||||
|
} \
|
||||||
|
static ZFCP_DEV_ATTR(adapter, _name, S_IRUGO, \
|
||||||
|
zfcp_sysfs_adapter_##_name##_show, NULL);
|
||||||
|
|
||||||
|
ZFCP_DEFINE_A_ATTR(status, "0x%08x\n", atomic_read(&adapter->status));
|
||||||
|
ZFCP_DEFINE_A_ATTR(peer_wwnn, "0x%016llx\n",
|
||||||
(unsigned long long) adapter->peer_wwnn);
|
(unsigned long long) adapter->peer_wwnn);
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n",
|
ZFCP_DEFINE_A_ATTR(peer_wwpn, "0x%016llx\n",
|
||||||
(unsigned long long) adapter->peer_wwpn);
|
(unsigned long long) adapter->peer_wwpn);
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n",
|
ZFCP_DEFINE_A_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id);
|
||||||
adapter->peer_d_id);
|
ZFCP_DEFINE_A_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n",
|
ZFCP_DEFINE_A_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
|
||||||
adapter->hydra_version);
|
ZFCP_DEFINE_A_ATTR(hardware_version, "0x%08x\n", adapter->hardware_version);
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, lic_version, "0x%08x\n",
|
ZFCP_DEFINE_A_ATTR(in_recovery, "%d\n", (atomic_read(&adapter->status) &
|
||||||
adapter->fsf_lic_version);
|
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, hardware_version, "0x%08x\n",
|
|
||||||
adapter->hardware_version);
|
|
||||||
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, in_recovery, "%d\n",
|
|
||||||
(atomic_read(&adapter->status) &
|
|
||||||
ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
|
ZFCP_STATUS_COMMON_ERP_INUSE) != 0);
|
||||||
|
|
||||||
ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
|
ZFCP_DEFINE_ATTR(zfcp_port, port, status, "0x%08x\n",
|
||||||
@@ -88,7 +101,6 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
|
|||||||
unsigned long val; \
|
unsigned long val; \
|
||||||
int retval = 0; \
|
int retval = 0; \
|
||||||
\
|
\
|
||||||
mutex_lock(&zfcp_data.config_mutex); \
|
|
||||||
if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \
|
if (atomic_read(&_feat->status) & ZFCP_STATUS_COMMON_REMOVE) { \
|
||||||
retval = -EBUSY; \
|
retval = -EBUSY; \
|
||||||
goto out; \
|
goto out; \
|
||||||
@@ -105,28 +117,89 @@ static ssize_t zfcp_sysfs_##_feat##_failed_store(struct device *dev, \
|
|||||||
_reopen_id, NULL); \
|
_reopen_id, NULL); \
|
||||||
zfcp_erp_wait(_adapter); \
|
zfcp_erp_wait(_adapter); \
|
||||||
out: \
|
out: \
|
||||||
mutex_unlock(&zfcp_data.config_mutex); \
|
|
||||||
return retval ? retval : (ssize_t) count; \
|
return retval ? retval : (ssize_t) count; \
|
||||||
} \
|
} \
|
||||||
static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
|
static ZFCP_DEV_ATTR(_feat, failed, S_IWUSR | S_IRUGO, \
|
||||||
zfcp_sysfs_##_feat##_failed_show, \
|
zfcp_sysfs_##_feat##_failed_show, \
|
||||||
zfcp_sysfs_##_feat##_failed_store);
|
zfcp_sysfs_##_feat##_failed_store);
|
||||||
|
|
||||||
ZFCP_SYSFS_FAILED(zfcp_adapter, adapter, adapter, "syafai1", "syafai2");
|
|
||||||
ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
|
ZFCP_SYSFS_FAILED(zfcp_port, port, port->adapter, "sypfai1", "sypfai2");
|
||||||
ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
|
ZFCP_SYSFS_FAILED(zfcp_unit, unit, unit->port->adapter, "syufai1", "syufai2");
|
||||||
|
|
||||||
|
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 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 (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
||||||
|
retval = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ZFCP_DEV_ATTR(adapter, failed, S_IWUSR | S_IRUGO,
|
||||||
|
zfcp_sysfs_adapter_failed_show,
|
||||||
|
zfcp_sysfs_adapter_failed_store);
|
||||||
|
|
||||||
static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
|
static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = dev_get_drvdata(dev);
|
struct ccw_device *cdev = to_ccwdev(dev);
|
||||||
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE)
|
if (!adapter)
|
||||||
return -EBUSY;
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = zfcp_fc_scan_ports(adapter);
|
ret = zfcp_fc_scan_ports(adapter);
|
||||||
|
out:
|
||||||
|
zfcp_ccw_adapter_put(adapter);
|
||||||
return ret ? ret : (ssize_t) count;
|
return ret ? ret : (ssize_t) count;
|
||||||
}
|
}
|
||||||
static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
|
static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
|
||||||
@@ -136,12 +209,15 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
|||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct zfcp_adapter *adapter = dev_get_drvdata(dev);
|
struct ccw_device *cdev = to_ccwdev(dev);
|
||||||
|
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||||
struct zfcp_port *port;
|
struct zfcp_port *port;
|
||||||
u64 wwpn;
|
u64 wwpn;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
if (!adapter)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -169,7 +245,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
|||||||
zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
|
zfcp_erp_port_shutdown(port, 0, "syprs_1", NULL);
|
||||||
zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs);
|
zfcp_device_unregister(&port->sysfs_device, &zfcp_sysfs_port_attrs);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
zfcp_ccw_adapter_put(adapter);
|
||||||
return retval ? retval : (ssize_t) count;
|
return retval ? retval : (ssize_t) count;
|
||||||
}
|
}
|
||||||
static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
|
static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
|
||||||
@@ -203,7 +279,6 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
|
|||||||
u64 fcp_lun;
|
u64 fcp_lun;
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -222,7 +297,6 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
|
|||||||
zfcp_erp_wait(unit->port->adapter);
|
zfcp_erp_wait(unit->port->adapter);
|
||||||
flush_work(&unit->scsi_work);
|
flush_work(&unit->scsi_work);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
return retval ? retval : (ssize_t) count;
|
return retval ? retval : (ssize_t) count;
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
|
static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
|
||||||
@@ -236,7 +310,6 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
|
|||||||
u64 fcp_lun;
|
u64 fcp_lun;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
mutex_lock(&zfcp_data.config_mutex);
|
|
||||||
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -267,7 +340,6 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
|
|||||||
zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
|
zfcp_erp_unit_shutdown(unit, 0, "syurs_1", NULL);
|
||||||
zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs);
|
zfcp_device_unregister(&unit->sysfs_device, &zfcp_sysfs_unit_attrs);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&zfcp_data.config_mutex);
|
|
||||||
return retval ? retval : (ssize_t) count;
|
return retval ? retval : (ssize_t) count;
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
|
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
|
||||||
|
Reference in New Issue
Block a user