aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c149
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c51
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c75
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h1
-rw-r--r--drivers/s390/scsi/zfcp_def.h183
-rw-r--r--drivers/s390/scsi/zfcp_erp.c231
-rw-r--r--drivers/s390/scsi/zfcp_ext.h27
-rw-r--r--drivers/s390/scsi/zfcp_fc.c252
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c616
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h75
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c67
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c28
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c62
13 files changed, 840 insertions, 977 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 90abfd06ed5..3b56220fb90 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -88,11 +88,13 @@ static int __init zfcp_device_setup(char *devstr)
strncpy(zfcp_data.init_busid, token, BUS_ID_SIZE);
token = strsep(&str, ",");
- if (!token || strict_strtoull(token, 0, &zfcp_data.init_wwpn))
+ if (!token || strict_strtoull(token, 0,
+ (unsigned long long *) &zfcp_data.init_wwpn))
goto err_out;
token = strsep(&str, ",");
- if (!token || strict_strtoull(token, 0, &zfcp_data.init_fcp_lun))
+ if (!token || strict_strtoull(token, 0,
+ (unsigned long long *) &zfcp_data.init_fcp_lun))
goto err_out;
kfree(str);
@@ -100,24 +102,10 @@ static int __init zfcp_device_setup(char *devstr)
err_out:
kfree(str);
- pr_err("zfcp: Parse error for device parameter string %s, "
- "device not attached.\n", devstr);
+ pr_err("zfcp: %s is not a valid SCSI device\n", devstr);
return 0;
}
-static struct zfcp_adapter *zfcp_get_adapter_by_busid(char *bus_id)
-{
- struct zfcp_adapter *adapter;
-
- list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list)
- if ((strncmp(bus_id, adapter->ccw_device->dev.bus_id,
- BUS_ID_SIZE) == 0) &&
- !(atomic_read(&adapter->status) &
- ZFCP_STATUS_COMMON_REMOVE))
- return adapter;
- return NULL;
-}
-
static void __init zfcp_init_device_configure(void)
{
struct zfcp_adapter *adapter;
@@ -141,7 +129,12 @@ static void __init zfcp_init_device_configure(void)
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:
@@ -180,9 +173,9 @@ static int __init zfcp_module_init(void)
if (!zfcp_data.gid_pn_cache)
goto out_gid_cache;
- INIT_LIST_HEAD(&zfcp_data.adapter_list_head);
- INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh);
+ zfcp_data.work_queue = create_singlethread_workqueue("zfcp_wq");
+ INIT_LIST_HEAD(&zfcp_data.adapter_list_head);
sema_init(&zfcp_data.config_sema, 1);
rwlock_init(&zfcp_data.config_lock);
@@ -193,13 +186,14 @@ static int __init zfcp_module_init(void)
retval = misc_register(&zfcp_cfdc_misc);
if (retval) {
- pr_err("zfcp: registration of misc device zfcp_cfdc failed\n");
+ pr_err("zfcp: Registering the misc device zfcp_cfdc failed\n");
goto out_misc;
}
retval = zfcp_ccw_register();
if (retval) {
- pr_err("zfcp: Registration with common I/O layer failed.\n");
+ pr_err("zfcp: The zfcp device driver could not register with "
+ "the common I/O layer\n");
goto out_ccw_register;
}
@@ -231,8 +225,7 @@ module_init(zfcp_module_init);
*
* Returns: pointer to zfcp_unit or NULL
*/
-struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port,
- fcp_lun_t fcp_lun)
+struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
@@ -251,7 +244,7 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port,
* Returns: pointer to zfcp_port or NULL
*/
struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
- wwn_t wwpn)
+ u64 wwpn)
{
struct zfcp_port *port;
@@ -276,7 +269,7 @@ static void zfcp_sysfs_unit_release(struct device *dev)
*
* Sets up some unit internal structures and creates sysfs entry.
*/
-struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
+struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
{
struct zfcp_unit *unit;
@@ -290,7 +283,8 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
unit->port = port;
unit->fcp_lun = fcp_lun;
- snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx", fcp_lun);
+ dev_set_name(&unit->sysfs_device, "0x%016llx",
+ (unsigned long long) fcp_lun);
unit->sysfs_device.parent = &port->sysfs_device;
unit->sysfs_device.release = zfcp_sysfs_unit_release;
dev_set_drvdata(&unit->sysfs_device, unit);
@@ -323,7 +317,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
}
zfcp_unit_get(unit);
- unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun);
write_lock_irq(&zfcp_data.config_lock);
list_add_tail(&unit->list, &port->unit_list_head);
@@ -332,7 +325,6 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
write_unlock_irq(&zfcp_data.config_lock);
- port->units++;
zfcp_port_get(port);
return unit;
@@ -351,11 +343,10 @@ err_out_free:
*/
void zfcp_unit_dequeue(struct zfcp_unit *unit)
{
- zfcp_unit_wait(unit);
+ wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
write_lock_irq(&zfcp_data.config_lock);
list_del(&unit->list);
write_unlock_irq(&zfcp_data.config_lock);
- unit->port->units--;
zfcp_port_put(unit->port);
sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs);
device_unregister(&unit->sysfs_device);
@@ -416,11 +407,6 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
mempool_destroy(adapter->pool.data_gid_pn);
}
-static void zfcp_dummy_release(struct device *dev)
-{
- return;
-}
-
/**
* zfcp_status_read_refill - refill the long running status_read_requests
* @adapter: ptr to struct zfcp_adapter for which the buffers should be refilled
@@ -450,19 +436,6 @@ static void _zfcp_status_read_scheduler(struct work_struct *work)
stat_work));
}
-static int zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
-{
- struct zfcp_port *port;
-
- port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
- ZFCP_DID_DIRECTORY_SERVICE);
- if (IS_ERR(port))
- return PTR_ERR(port);
- zfcp_port_put(port);
-
- return 0;
-}
-
/**
* zfcp_adapter_enqueue - enqueue a new adapter to the list
* @ccw_device: pointer to the struct cc_device
@@ -508,7 +481,6 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
init_waitqueue_head(&adapter->erp_done_wqh);
INIT_LIST_HEAD(&adapter->port_list_head);
- INIT_LIST_HEAD(&adapter->port_remove_lh);
INIT_LIST_HEAD(&adapter->erp_ready_head);
INIT_LIST_HEAD(&adapter->erp_running_head);
@@ -518,7 +490,7 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
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);
+ spin_lock_init(&adapter->req_q_lock);
rwlock_init(&adapter->erp_lock);
rwlock_init(&adapter->abort_lock);
@@ -537,28 +509,15 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
&zfcp_sysfs_adapter_attrs))
goto sysfs_failed;
- adapter->generic_services.parent = &adapter->ccw_device->dev;
- adapter->generic_services.release = zfcp_dummy_release;
- snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE,
- "generic_services");
-
- if (device_register(&adapter->generic_services))
- goto generic_services_failed;
-
write_lock_irq(&zfcp_data.config_lock);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
list_add_tail(&adapter->list, &zfcp_data.adapter_list_head);
write_unlock_irq(&zfcp_data.config_lock);
- zfcp_data.adapters++;
-
- zfcp_nameserver_enqueue(adapter);
+ zfcp_fc_nameserver_init(adapter);
return 0;
-generic_services_failed:
- sysfs_remove_group(&ccw_device->dev.kobj,
- &zfcp_sysfs_adapter_attrs);
sysfs_failed:
zfcp_adapter_debug_unregister(adapter);
debug_register_failed:
@@ -585,7 +544,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
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);
@@ -603,9 +561,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
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);
@@ -633,21 +588,19 @@ static void zfcp_sysfs_port_release(struct device *dev)
* 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,
+struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 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);
+ INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);
port->adapter = adapter;
port->d_id = d_id;
@@ -657,34 +610,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
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;
- }
+ dev_set_name(&port->sysfs_device, "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);
@@ -700,12 +627,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
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);
+ retval = sysfs_create_group(&port->sysfs_device.kobj,
+ &zfcp_sysfs_port_attrs);
if (retval) {
device_unregister(&port->sysfs_device);
@@ -718,10 +641,6 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
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);
@@ -740,21 +659,15 @@ err_out:
*/
void zfcp_port_dequeue(struct zfcp_port *port)
{
- zfcp_port_wait(port);
+ wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
write_lock_irq(&zfcp_data.config_lock);
list_del(&port->list);
- port->adapter->ports--;
write_unlock_irq(&zfcp_data.config_lock);
if (port->rport)
fc_remote_port_delete(port->rport);
port->rport = NULL;
zfcp_adapter_put(port->adapter);
- if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)
- sysfs_remove_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_ns_port_attrs);
- else
- sysfs_remove_group(&port->sysfs_device.kobj,
- &zfcp_sysfs_port_attrs);
+ sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
device_unregister(&port->sysfs_device);
}
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 391dd29749f..b04038c7478 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -25,7 +25,8 @@ static int zfcp_ccw_probe(struct ccw_device *ccw_device)
down(&zfcp_data.config_sema);
if (zfcp_adapter_enqueue(ccw_device)) {
dev_err(&ccw_device->dev,
- "Setup of data structures failed.\n");
+ "Setting up data structures for the "
+ "FCP adapter failed\n");
retval = -EINVAL;
}
up(&zfcp_data.config_sema);
@@ -46,6 +47,8 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
struct zfcp_adapter *adapter;
struct zfcp_port *port, *p;
struct zfcp_unit *unit, *u;
+ LIST_HEAD(unit_remove_lh);
+ LIST_HEAD(port_remove_lh);
ccw_device_set_offline(ccw_device);
down(&zfcp_data.config_sema);
@@ -54,26 +57,26 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
write_lock_irq(&zfcp_data.config_lock);
list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
- list_move(&unit->list, &port->unit_remove_lh);
+ list_move(&unit->list, &unit_remove_lh);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
&unit->status);
}
- list_move(&port->list, &adapter->port_remove_lh);
+ list_move(&port->list, &port_remove_lh);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
}
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
write_unlock_irq(&zfcp_data.config_lock);
- list_for_each_entry_safe(port, p, &adapter->port_remove_lh, list) {
- list_for_each_entry_safe(unit, u, &port->unit_remove_lh, list) {
- if (atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED,
- &unit->status))
+ list_for_each_entry_safe(port, p, &port_remove_lh, list) {
+ list_for_each_entry_safe(unit, u, &unit_remove_lh, list) {
+ if (atomic_read(&unit->status) &
+ ZFCP_STATUS_UNIT_REGISTERED)
scsi_remove_device(unit->device);
zfcp_unit_dequeue(unit);
}
zfcp_port_dequeue(port);
}
- zfcp_adapter_wait(adapter);
+ wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
zfcp_adapter_dequeue(adapter);
up(&zfcp_data.config_sema);
@@ -152,21 +155,22 @@ static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
*/
static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
{
- struct zfcp_adapter *adapter;
+ struct zfcp_adapter *adapter = dev_get_drvdata(&ccw_device->dev);
- down(&zfcp_data.config_sema);
- adapter = dev_get_drvdata(&ccw_device->dev);
switch (event) {
case CIO_GONE:
- dev_warn(&adapter->ccw_device->dev, "device gone\n");
+ dev_warn(&adapter->ccw_device->dev,
+ "The FCP device has been detached\n");
zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
break;
case CIO_NO_PATH:
- dev_warn(&adapter->ccw_device->dev, "no path\n");
+ dev_warn(&adapter->ccw_device->dev,
+ "The CHPID for the FCP device is offline\n");
zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
break;
case CIO_OPER:
- dev_info(&adapter->ccw_device->dev, "operational again\n");
+ dev_info(&adapter->ccw_device->dev,
+ "The FCP device is operational again\n");
zfcp_erp_modify_adapter_status(adapter, 11, NULL,
ZFCP_STATUS_COMMON_RUNNING,
ZFCP_SET);
@@ -174,8 +178,6 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
89, NULL);
break;
}
- zfcp_erp_wait(adapter);
- up(&zfcp_data.config_sema);
return 1;
}
@@ -224,3 +226,20 @@ int __init zfcp_ccw_register(void)
{
return ccw_driver_register(&zfcp_ccw_driver);
}
+
+/**
+ * zfcp_get_adapter_by_busid - find zfcp_adapter struct
+ * @busid: bus id string of zfcp adapter to find
+ */
+struct zfcp_adapter *zfcp_get_adapter_by_busid(char *busid)
+{
+ struct ccw_device *ccw_device;
+ struct zfcp_adapter *adapter = NULL;
+
+ ccw_device = get_ccwdev_by_busid(&zfcp_ccw_driver, busid);
+ if (ccw_device) {
+ adapter = dev_get_drvdata(&ccw_device->dev);
+ put_device(&ccw_device->dev);
+ }
+ return adapter;
+}
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index fca48b88fc5..060f5f2352e 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -318,6 +318,26 @@ void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter,
spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
}
+/**
+ * zfcp_hba_dbf_event_berr - trace event for bit error threshold
+ * @adapter: adapter affected by this QDIO related event
+ * @req: fsf request
+ */
+void zfcp_hba_dbf_event_berr(struct zfcp_adapter *adapter,
+ struct zfcp_fsf_req *req)
+{
+ struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
+ struct fsf_status_read_buffer *sr_buf = req->data;
+ struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
+ memset(r, 0, sizeof(*r));
+ strncpy(r->tag, "berr", ZFCP_DBF_TAG_SIZE);
+ memcpy(&r->u.berr, err, sizeof(struct fsf_bit_error_payload));
+ debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
+ spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
+}
static void zfcp_hba_dbf_view_response(char **p,
struct zfcp_hba_dbf_record_response *r)
{
@@ -399,6 +419,30 @@ static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
}
+static void zfcp_hba_dbf_view_berr(char **p, struct fsf_bit_error_payload *r)
+{
+ zfcp_dbf_out(p, "link_failures", "%d", r->link_failure_error_count);
+ zfcp_dbf_out(p, "loss_of_sync_err", "%d", r->loss_of_sync_error_count);
+ zfcp_dbf_out(p, "loss_of_sig_err", "%d", r->loss_of_signal_error_count);
+ zfcp_dbf_out(p, "prim_seq_err", "%d",
+ r->primitive_sequence_error_count);
+ zfcp_dbf_out(p, "inval_trans_word_err", "%d",
+ r->invalid_transmission_word_error_count);
+ zfcp_dbf_out(p, "CRC_errors", "%d", r->crc_error_count);
+ zfcp_dbf_out(p, "prim_seq_event_to", "%d",
+ r->primitive_sequence_event_timeout_count);
+ zfcp_dbf_out(p, "elast_buf_overrun_err", "%d",
+ r->elastic_buffer_overrun_error_count);
+ zfcp_dbf_out(p, "adv_rec_buf2buf_cred", "%d",
+ r->advertised_receive_b2b_credit);
+ zfcp_dbf_out(p, "curr_rec_buf2buf_cred", "%d",
+ r->current_receive_b2b_credit);
+ zfcp_dbf_out(p, "adv_trans_buf2buf_cred", "%d",
+ r->advertised_transmit_b2b_credit);
+ zfcp_dbf_out(p, "curr_trans_buf2buf_cred", "%d",
+ r->current_transmit_b2b_credit);
+}
+
static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
@@ -418,6 +462,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view,
zfcp_hba_dbf_view_status(&p, &r->u.status);
else if (strncmp(r->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0)
zfcp_hba_dbf_view_qdio(&p, &r->u.qdio);
+ else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0)
+ zfcp_hba_dbf_view_berr(&p, &r->u.berr);
p += sprintf(p, "\n");
return p - out_buf;
@@ -519,14 +565,14 @@ static const char *zfcp_rec_dbf_ids[] = {
[75] = "physical port recovery escalation after failed port "
"recovery",
[76] = "port recovery escalation after failed unit recovery",
- [77] = "recovery opening nameserver port",
+ [77] = "",
[78] = "duplicate request id",
[79] = "link down",
[80] = "exclusive read-only unit access unsupported",
[81] = "shared read-write unit access unsupported",
[82] = "incoming rscn",
[83] = "incoming wwpn",
- [84] = "",
+ [84] = "wka port handle not valid close port",
[85] = "online",
[86] = "offline",
[87] = "ccw device gone",
@@ -570,7 +616,7 @@ static const char *zfcp_rec_dbf_ids[] = {
[125] = "need newer zfcp",
[126] = "need newer microcode",
[127] = "arbitrated loop not supported",
- [128] = "unknown topology",
+ [128] = "",
[129] = "qtcb size mismatch",
[130] = "unknown fsf status ecd",
[131] = "fcp request too big",
@@ -829,9 +875,9 @@ void zfcp_rec_dbf_event_action(u8 id2, struct zfcp_erp_action *erp_action)
void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
- struct zfcp_port *port = ct->port;
- struct zfcp_adapter *adapter = port->adapter;
- struct ct_hdr *hdr = zfcp_sg_to_address(ct->req);
+ struct zfcp_wka_port *wka_port = ct->wka_port;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct ct_hdr *hdr = sg_virt(ct->req);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req;
unsigned long flags;
@@ -842,7 +888,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
r->fsf_reqid = (unsigned long)fsf_req;
r->fsf_seqno = fsf_req->seq_no;
r->s_id = fc_host_port_id(adapter->scsi_host);
- r->d_id = port->d_id;
+ r->d_id = wka_port->d_id;
oct->cmd_req_code = hdr->cmd_rsp_code;
oct->revision = hdr->revision;
oct->gs_type = hdr->gs_type;
@@ -863,9 +909,9 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
- struct zfcp_port *port = ct->port;
- struct zfcp_adapter *adapter = port->adapter;
- struct ct_hdr *hdr = zfcp_sg_to_address(ct->resp);
+ struct zfcp_wka_port *wka_port = ct->wka_port;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct ct_hdr *hdr = sg_virt(ct->resp);
struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf;
struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp;
unsigned long flags;
@@ -875,7 +921,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
strncpy(r->tag, "rctc", ZFCP_DBF_TAG_SIZE);
r->fsf_reqid = (unsigned long)fsf_req;
r->fsf_seqno = fsf_req->seq_no;
- r->s_id = port->d_id;
+ r->s_id = wka_port->d_id;
r->d_id = fc_host_port_id(adapter->scsi_host);
rct->cmd_rsp_code = hdr->cmd_rsp_code;
rct->revision = hdr->revision;
@@ -922,8 +968,8 @@ void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
zfcp_san_dbf_event_els("oels", 2, fsf_req,
fc_host_port_id(els->adapter->scsi_host),
- els->d_id, *(u8 *) zfcp_sg_to_address(els->req),
- zfcp_sg_to_address(els->req), els->req->length);
+ els->d_id, *(u8 *) sg_virt(els->req),
+ sg_virt(els->req), els->req->length);
}
/**
@@ -936,8 +982,7 @@ void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
zfcp_san_dbf_event_els("rels", 2, fsf_req, els->d_id,
fc_host_port_id(els->adapter->scsi_host),
- *(u8 *)zfcp_sg_to_address(els->req),
- zfcp_sg_to_address(els->resp),
+ *(u8 *)sg_virt(els->req), sg_virt(els->resp),
els->resp->length);
}
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 0ddb18449d1..e8f450801fe 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -151,6 +151,7 @@ struct zfcp_hba_dbf_record {
struct zfcp_hba_dbf_record_response response;
struct zfcp_hba_dbf_record_status status;
struct zfcp_hba_dbf_record_qdio qdio;
+ struct fsf_bit_error_payload berr;
} u;
} __attribute__ ((packed));
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 67f45fc62f5..8a13071c444 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -39,29 +39,6 @@
/********************* GENERAL DEFINES *********************************/
-/**
- * zfcp_sg_to_address - determine kernel address from struct scatterlist
- * @list: struct scatterlist
- * Return: kernel address
- */
-static inline void *
-zfcp_sg_to_address(struct scatterlist *list)
-{
- return sg_virt(list);
-}
-
-/**
- * zfcp_address_to_sg - set up struct scatterlist from kernel address
- * @address: kernel address
- * @list: struct scatterlist
- * @size: buffer size
- */
-static inline void
-zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
-{
- sg_set_buf(list, address, size);
-}
-
#define REQUEST_LIST_SIZE 128
/********************* SCSI SPECIFIC DEFINES *********************************/
@@ -101,11 +78,6 @@ zfcp_address_to_sg(void *address, struct scatterlist *list, unsigned int size)
/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
-typedef unsigned long long wwn_t;
-typedef unsigned long long fcp_lun_t;
-/* data length field may be at variable position in FCP-2 FCP_CMND IU */
-typedef unsigned int fcp_dl_t;
-
/* timeout for name-server lookup (in seconds) */
#define ZFCP_NS_GID_PN_TIMEOUT 10
@@ -129,7 +101,7 @@ typedef unsigned int fcp_dl_t;
/* FCP(-2) FCP_CMND IU */
struct fcp_cmnd_iu {
- fcp_lun_t fcp_lun; /* FCP logical unit number */
+ u64 fcp_lun; /* FCP logical unit number */
u8 crn; /* command reference number */
u8 reserved0:5; /* reserved */
u8 task_attribute:3; /* task attribute */
@@ -204,7 +176,7 @@ struct fcp_rscn_element {
struct fcp_logo {
u32 command;
u32 nport_did;
- wwn_t nport_wwpn;
+ u64 nport_wwpn;
} __attribute__((packed));
/*
@@ -218,13 +190,6 @@ struct fcp_logo {
#define ZFCP_LS_RSCN 0x61
#define ZFCP_LS_RNID 0x78
-struct zfcp_ls_rjt_par {
- u8 action;
- u8 reason_code;
- u8 reason_expl;
- u8 vendor_unique;
-} __attribute__ ((packed));
-
struct zfcp_ls_adisc {
u8 code;
u8 field[3];
@@ -234,20 +199,6 @@ struct zfcp_ls_adisc {
u32 nport_id;
} __attribute__ ((packed));
-struct zfcp_ls_adisc_acc {
- u8 code;
- u8 field[3];
- u32 hard_nport_id;
- u64 wwpn;
- u64 wwnn;
- u32 nport_id;
-} __attribute__ ((packed));
-
-struct zfcp_rc_entry {
- u8 code;
- const char *description;
-};
-
/*
* FC-GS-2 stuff
*/
@@ -281,9 +232,7 @@ struct zfcp_rc_entry {
#define ZFCP_STATUS_COMMON_RUNNING 0x40000000
#define ZFCP_STATUS_COMMON_ERP_FAILED 0x20000000
#define ZFCP_STATUS_COMMON_UNBLOCKED 0x10000000
-#define ZFCP_STATUS_COMMON_OPENING 0x08000000
#define ZFCP_STATUS_COMMON_OPEN 0x04000000
-#define ZFCP_STATUS_COMMON_CLOSING 0x02000000
#define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000
#define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000
#define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000
@@ -291,16 +240,15 @@ struct zfcp_rc_entry {
/* adapter status */
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
-#define ZFCP_STATUS_ADAPTER_REGISTERED 0x00000004
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010
#define ZFCP_STATUS_ADAPTER_ERP_THREAD_UP 0x00000020
#define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080
#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
-#define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800
/* FC-PH/FC-GS well-known address identifiers for generic services */
+#define ZFCP_DID_WKA 0xFFFFF0
#define ZFCP_DID_MANAGEMENT_SERVICE 0xFFFFFA
#define ZFCP_DID_TIME_SERVICE 0xFFFFFB
#define ZFCP_DID_DIRECTORY_SERVICE 0xFFFFFC
@@ -312,29 +260,27 @@ struct zfcp_rc_entry {
#define ZFCP_STATUS_PORT_DID_DID 0x00000002
#define ZFCP_STATUS_PORT_PHYS_CLOSING 0x00000004
#define ZFCP_STATUS_PORT_NO_WWPN 0x00000008
-#define ZFCP_STATUS_PORT_NO_SCSI_ID 0x00000010
#define ZFCP_STATUS_PORT_INVALID_WWPN 0x00000020
-/* for ports with well known addresses */
-#define ZFCP_STATUS_PORT_WKA \
- (ZFCP_STATUS_PORT_NO_WWPN | \
- ZFCP_STATUS_PORT_NO_SCSI_ID)
+/* well known address (WKA) port status*/
+enum zfcp_wka_status {
+ ZFCP_WKA_PORT_OFFLINE,
+ ZFCP_WKA_PORT_CLOSING,
+ ZFCP_WKA_PORT_OPENING,
+ ZFCP_WKA_PORT_ONLINE,
+};
/* logical unit status */
-#define ZFCP_STATUS_UNIT_TEMPORARY 0x00000002
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
/* FSF request status (this does not have a common part) */
-#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
-#define ZFCP_STATUS_FSFREQ_POOL 0x00000001
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
#define ZFCP_STATUS_FSFREQ_COMPLETED 0x00000004
#define ZFCP_STATUS_FSFREQ_ERROR 0x00000008
#define ZFCP_STATUS_FSFREQ_CLEANUP 0x00000010
-#define ZFCP_STATUS_FSFREQ_ABORTING 0x00000020
#define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED 0x00000040
#define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED 0x00000080
#define ZFCP_STATUS_FSFREQ_ABORTED 0x00000100
@@ -379,7 +325,7 @@ struct ct_hdr {
* a port name is required */
struct ct_iu_gid_pn_req {
struct ct_hdr header;
- wwn_t wwpn;
+ u64 wwpn;
} __attribute__ ((packed));
/* FS_ACC IU and data unit for GID_PN nameserver request */
@@ -388,11 +334,9 @@ struct ct_iu_gid_pn_resp {
u32 d_id;
} __attribute__ ((packed));
-typedef void (*zfcp_send_ct_handler_t)(unsigned long);
-
/**
* struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
- * @port: port where the request is sent to
+ * @wka_port: port where the request is sent to
* @req: scatter-gather list for request
* @resp: scatter-gather list for response
* @req_count: number of elements in request scatter-gather list
@@ -404,12 +348,12 @@ typedef void (*zfcp_send_ct_handler_t)(unsigned long);
* @status: used to pass error status to calling function
*/
struct zfcp_send_ct {
- struct zfcp_port *port;
+ struct zfcp_wka_port *wka_port;
struct scatterlist *req;
struct scatterlist *resp;
unsigned int req_count;
unsigned int resp_count;
- zfcp_send_ct_handler_t handler;
+ void (*handler)(unsigned long);
unsigned long handler_data;
int timeout;
struct completion *completion;
@@ -426,8 +370,6 @@ struct zfcp_gid_pn_data {
struct zfcp_port *port;
};
-typedef void (*zfcp_send_els_handler_t)(unsigned long);
-
/**
* struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
* @adapter: adapter where request is sent from
@@ -451,22 +393,28 @@ struct zfcp_send_els {
struct scatterlist *resp;
unsigned int req_count;
unsigned int resp_count;
- zfcp_send_els_handler_t handler;
+ void (*handler)(unsigned long);
unsigned long handler_data;
struct completion *completion;
int ls_code;
int status;
};
+struct zfcp_wka_port {
+ struct zfcp_adapter *adapter;
+ wait_queue_head_t completion_wq;
+ enum zfcp_wka_status status;
+ atomic_t refcount;
+ u32 d_id;
+ u32 handle;
+ struct mutex mutex;
+ struct delayed_work work;
+};
+
struct zfcp_qdio_queue {
- struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */
- u8 first; /* index of next free bfr
- in queue (free_count>0) */
- atomic_t count; /* number of free buffers
- in queue */
- spinlock_t lock; /* lock for operations on queue */
- int pci_batch; /* SBALs since PCI indication
- was last set */
+ struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
+ u8 first; /* index of next free bfr in queue */
+ atomic_t count; /* number of free buffers in queue */
};
struct zfcp_erp_action {
@@ -475,7 +423,7 @@ struct zfcp_erp_action {
struct zfcp_adapter *adapter; /* device which should be recovered */
struct zfcp_port *port;
struct zfcp_unit *unit;
- volatile u32 status; /* recovery status */
+ u32 status; /* recovery status */
u32 step; /* active step of this erp action */
struct zfcp_fsf_req *fsf_req; /* fsf request currently pending
for this action */
@@ -506,8 +454,8 @@ struct zfcp_adapter {
atomic_t refcount; /* reference count */
wait_queue_head_t remove_wq; /* can be used to wait for
refcount drop to zero */
- wwn_t peer_wwnn; /* P2P peer WWNN */
- wwn_t peer_wwpn; /* P2P peer WWPN */
+ u64 peer_wwnn; /* P2P peer WWNN */
+ u64 peer_wwpn; /* P2P peer WWPN */
u32 peer_d_id; /* P2P peer D_ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u32 hydra_version; /* Hydra version */
@@ -518,13 +466,13 @@ struct zfcp_adapter {
u16 timer_ticks; /* time int for a tick */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
struct list_head port_list_head; /* remote port list */
- struct list_head port_remove_lh; /* head of ports to be
- removed */
- u32 ports; /* number of remote ports */
unsigned long req_no; /* unique FSF req number */
struct list_head *req_list; /* list of pending reqs */
spinlock_t req_list_lock; /* request list lock */
struct zfcp_qdio_queue req_q; /* request queue */
+ spinlock_t req_q_lock; /* for operations on queue */
+ int req_q_pci_batch; /* SBALs since PCI indication
+ was last set */
u32 fsf_req_seq_no; /* FSF cmnd seq number */
wait_queue_head_t request_wq; /* can be used to wait for
more avaliable SBALs */
@@ -548,7 +496,7 @@ struct zfcp_adapter {
actions */
u32 erp_low_mem_count; /* nr of erp actions waiting
for memory */
- struct zfcp_port *nameserver_port; /* adapter's nameserver */
+ struct zfcp_wka_port nsp; /* adapter's nameserver */
debug_info_t *rec_dbf;
debug_info_t *hba_dbf;
debug_info_t *san_dbf; /* debug feature areas */
@@ -563,11 +511,11 @@ struct zfcp_adapter {
struct zfcp_scsi_dbf_record scsi_dbf_buf;
struct zfcp_adapter_mempool pool; /* Adapter memory pools */
struct qdio_initialize qdio_init_data; /* for qdio_establish */
- struct device generic_services; /* directory for WKA ports */
struct fc_host_statistics *fc_stats;
struct fsf_qtcb_bottom_port *stats_reset_data;
unsigned long stats_reset;
struct work_struct scan_work;
+ atomic_t qdio_outb_full; /* queue full incidents */
};
struct zfcp_port {
@@ -579,18 +527,16 @@ struct zfcp_port {
refcount drop to zero */
struct zfcp_adapter *adapter; /* adapter used to access port */
struct list_head unit_list_head; /* head of logical unit list */
- struct list_head unit_remove_lh; /* head of luns to be removed
- list */
- u32 units; /* # of logical units in list */
atomic_t status; /* status of this remote port */
- wwn_t wwnn; /* WWNN if known */
- wwn_t wwpn; /* WWPN */
+ u64 wwnn; /* WWNN if known */
+ u64 wwpn; /* WWPN */
u32 d_id; /* D_ID */
u32 handle; /* handle assigned by FSF */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
u32 maxframe_size;
u32 supported_classes;
+ struct work_struct gid_pn_work;
};
struct zfcp_unit {
@@ -601,8 +547,7 @@ struct zfcp_unit {
refcount drop to zero */
struct zfcp_port *port; /* remote port of unit */
atomic_t status; /* status of this logical unit */
- unsigned int scsi_lun; /* own SCSI LUN */
- fcp_lun_t fcp_lun; /* own FCP_LUN */
+ u64 fcp_lun; /* own FCP_LUN */
u32 handle; /* handle assigned by FSF */
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
@@ -625,7 +570,7 @@ struct zfcp_fsf_req {
u8 sbal_response; /* SBAL used in interrupt */
wait_queue_head_t completion_wq; /* can be used by a routine
to wait for completion */
- volatile u32 status; /* status of this request */
+ u32 status; /* status of this request */
u32 fsf_command; /* FSF Command copy */
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
@@ -644,23 +589,20 @@ struct zfcp_fsf_req {
struct zfcp_data {
struct scsi_host_template scsi_host_template;
struct scsi_transport_template *scsi_transport_template;
- atomic_t status; /* Module status flags */
struct list_head adapter_list_head; /* head of adapter list */
- struct list_head adapter_remove_lh; /* head of adapters to be
- removed */
- u32 adapters; /* # of adapters in list */
rwlock_t config_lock; /* serialises changes
to adapter/port/unit
lists */
struct semaphore config_sema; /* serialises configuration
changes */
atomic_t loglevel; /* current loglevel */
- char init_busid[BUS_ID_SIZE];
- wwn_t init_wwpn;
- fcp_lun_t init_fcp_lun;
- struct kmem_cache *fsf_req_qtcb_cache;
- struct kmem_cache *sr_buffer_cache;
- struct kmem_cache *gid_pn_cache;
+ char init_busid[20];
+ u64 init_wwpn;
+ u64 init_fcp_lun;
+ struct kmem_cache *fsf_req_qtcb_cache;
+ struct kmem_cache *sr_buffer_cache;
+ struct kmem_cache *gid_pn_cache;
+ struct workqueue_struct *work_queue;
};
/* struct used by memory pools for fsf_requests */
@@ -677,14 +619,7 @@ struct zfcp_fsf_req_qtcb {
#define ZFCP_SET 0x00000100
#define ZFCP_CLEAR 0x00000200
-#ifndef atomic_test_mask
-#define atomic_test_mask(mask, target) \
- ((atomic_read(target) & mask) == mask)
-#endif
-
-#define zfcp_get_busid_by_adapter(adapter) (adapter->ccw_device->dev.bus_id)
-#define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter))
-#define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port))
+#define zfcp_get_busid_by_adapter(adapter) (dev_name(&adapter->ccw_device->dev))
/*
* Helper functions for request ID management.
@@ -745,12 +680,6 @@ zfcp_unit_put(struct zfcp_unit *unit)
}
static inline void
-zfcp_unit_wait(struct zfcp_unit *unit)
-{
- wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
-}
-
-static inline void
zfcp_port_get(struct zfcp_port *port)
{
atomic_inc(&port->refcount);
@@ -764,12 +693,6 @@ zfcp_port_put(struct zfcp_port *port)
}
static inline void
-zfcp_port_wait(struct zfcp_port *port)
-{
- wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
-}
-
-static inline void
zfcp_adapter_get(struct zfcp_adapter *adapter)
{
atomic_inc(&adapter->refcount);
@@ -782,10 +705,4 @@ zfcp_adapter_put(struct zfcp_adapter *adapter)
wake_up(&adapter->remove_wq);
}
-static inline void
-zfcp_adapter_wait(struct zfcp_adapter *adapter)
-{
- wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
-}
-
#endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 643ac4bba5b..9040f738ff3 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -23,7 +23,6 @@ enum zfcp_erp_steps {
ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
- ZFCP_ERP_STEP_NAMESERVER_OPEN = 0x0200,
ZFCP_ERP_STEP_NAMESERVER_LOOKUP = 0x0400,
ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
ZFCP_ERP_STEP_UNIT_CLOSING = 0x1000,
@@ -532,8 +531,7 @@ static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
struct zfcp_port *port;
list_for_each_entry(port, &adapter->port_list_head, list)
- if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA))
- _zfcp_erp_port_reopen(port, clear, id, ref);
+ _zfcp_erp_port_reopen(port, clear, id, ref);
}
static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear, u8 id,
@@ -669,8 +667,6 @@ static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *act)
int ret;
struct zfcp_adapter *adapter = act->adapter;
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
-
write_lock_irq(&adapter->erp_lock);
zfcp_erp_action_to_running(act);
write_unlock_irq(&adapter->erp_lock);
@@ -741,8 +737,7 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
failed_qdio:
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK |
- ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
- ZFCP_STATUS_ADAPTER_XPORT_OK,
+ ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&act->adapter->status);
return retval;
}
@@ -751,15 +746,11 @@ static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *act)
{
int retval;
- atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status);
zfcp_erp_adapter_strategy_generic(act, 1); /* close */
- atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &act->adapter->status);
if (act->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
return ZFCP_ERP_EXIT;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status);
retval = zfcp_erp_adapter_strategy_generic(act, 0); /* open */
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &act->adapter->status);
if (retval == ZFCP_ERP_FAILED)
ssleep(8);
@@ -783,10 +774,7 @@ static int zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *act)
static void zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
{
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
- ZFCP_STATUS_COMMON_CLOSING |
- ZFCP_STATUS_COMMON_ACCESS_DENIED |
- ZFCP_STATUS_PORT_DID_DID |
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_PORT_PHYS_CLOSING |
ZFCP_STATUS_PORT_INVALID_WWPN,
&port->status);
@@ -839,73 +827,12 @@ static int zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
return ZFCP_ERP_CONTINUES;
}
-static void zfcp_erp_port_strategy_open_ns_wake(struct zfcp_erp_action *ns_act)
-{
- unsigned long flags;
- struct zfcp_adapter *adapter = ns_act->adapter;
- struct zfcp_erp_action *act, *tmp;
- int status;
-
- read_lock_irqsave(&adapter->erp_lock, flags);
- list_for_each_entry_safe(act, tmp, &adapter->erp_running_head, list) {
- if (act->step == ZFCP_ERP_STEP_NAMESERVER_OPEN) {
- status = atomic_read(&adapter->nameserver_port->status);
- if (status & ZFCP_STATUS_COMMON_ERP_FAILED)
- zfcp_erp_port_failed(act->port, 27, NULL);
- zfcp_erp_action_ready(act);
- }
- }
- read_unlock_irqrestore(&adapter->erp_lock, flags);
-}
-
-static int zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *act)
-{
- int retval;
-
- switch (act->step) {
- case ZFCP_ERP_STEP_UNINITIALIZED:
- case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
- case ZFCP_ERP_STEP_PORT_CLOSING:
- return zfcp_erp_port_strategy_open_port(act);
-
- case ZFCP_ERP_STEP_PORT_OPENING:
- if (atomic_read(&act->port->status) & ZFCP_STATUS_COMMON_OPEN)
- retval = ZFCP_ERP_SUCCEEDED;
- else
- retval = ZFCP_ERP_FAILED;
- /* this is needed anyway */
- zfcp_erp_port_strategy_open_ns_wake(act);
- return retval;
-
- default:
- return ZFCP_ERP_FAILED;
- }
-}
-
-static int zfcp_erp_port_strategy_open_lookup(struct zfcp_erp_action *act)
-{
- int retval;
-
- retval = zfcp_fc_ns_gid_pn_request(act);
- if (retval == -ENOMEM)
- return ZFCP_ERP_NOMEM;
- act->step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
- if (retval)
- return ZFCP_ERP_FAILED;
- return ZFCP_ERP_CONTINUES;
-}
-
static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
{
struct zfcp_adapter *adapter = act->adapter;
struct zfcp_port *port = act->port;
if (port->wwpn != adapter->peer_wwpn) {
- dev_err(&adapter->ccw_device->dev,
- "Failed to open port 0x%016Lx, "
- "Peer WWPN 0x%016Lx does not "
- "match.\n", port->wwpn,
- adapter->peer_wwpn);
zfcp_erp_port_failed(port, 25, NULL);
return ZFCP_ERP_FAILED;
}
@@ -914,11 +841,25 @@ static int zfcp_erp_open_ptp_port(struct zfcp_erp_action *act)
return zfcp_erp_port_strategy_open_port(act);
}
+void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
+{
+ int retval;
+ struct zfcp_port *port = container_of(work, struct zfcp_port,
+ gid_pn_work);
+
+ retval = zfcp_fc_ns_gid_pn(&port->erp_action);
+ if (retval == -ENOMEM)
+ zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM);
+ port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
+ if (retval)
+ zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED);
+
+}
+
static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
{
struct zfcp_adapter *adapter = act->adapter;
struct zfcp_port *port = act->port;
- struct zfcp_port *ns_port = adapter->nameserver_port;
int p_status = atomic_read(&port->status);
switch (act->step) {
@@ -927,28 +868,10 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
case ZFCP_ERP_STEP_PORT_CLOSING:
if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
return zfcp_erp_open_ptp_port(act);
- if (!ns_port) {
- dev_err(&adapter->ccw_device->dev,
- "Nameserver port unavailable.\n");
- return ZFCP_ERP_FAILED;
- }
- if (!(atomic_read(&ns_port->status) &
- ZFCP_STATUS_COMMON_UNBLOCKED)) {
- /* nameserver port may live again */
- atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING,
- &ns_port->status);
- if (zfcp_erp_port_reopen(ns_port, 0, 77, act) >= 0) {
- act->step = ZFCP_ERP_STEP_NAMESERVER_OPEN;
- return ZFCP_ERP_CONTINUES;
- }
- return ZFCP_ERP_FAILED;
+ if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) {
+ queue_work(zfcp_data.work_queue, &port->gid_pn_work);
+ return ZFCP_ERP_CONTINUES;
}
- /* else nameserver port is already open, fall through */
- case ZFCP_ERP_STEP_NAMESERVER_OPEN:
- if (!(atomic_read(&ns_port->status) & ZFCP_STATUS_COMMON_OPEN))
- return ZFCP_ERP_FAILED;
- return zfcp_erp_port_strategy_open_lookup(act);
-
case ZFCP_ERP_STEP_NAMESERVER_LOOKUP:
if (!(p_status & ZFCP_STATUS_PORT_DID_DID)) {
if (p_status & (ZFCP_STATUS_PORT_INVALID_WWPN)) {
@@ -961,25 +884,26 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
case ZFCP_ERP_STEP_PORT_OPENING:
/* D_ID might have changed during open */
- if ((p_status & ZFCP_STATUS_COMMON_OPEN) &&
- (p_status & ZFCP_STATUS_PORT_DID_DID))
- return ZFCP_ERP_SUCCEEDED;
+ if (p_status & ZFCP_STATUS_COMMON_OPEN) {
+ if (p_status & ZFCP_STATUS_PORT_DID_DID)
+ return ZFCP_ERP_SUCCEEDED;
+ else {
+ act->step = ZFCP_ERP_STEP_PORT_CLOSING;
+ return ZFCP_ERP_CONTINUES;
+ }
/* fall through otherwise */
+ }
}
return ZFCP_ERP_FAILED;
}
-static int zfcp_erp_port_strategy_open(struct zfcp_erp_action *act)
-{
- if (atomic_read(&act->port->status) & (ZFCP_STATUS_PORT_WKA))
- return zfcp_erp_port_strategy_open_nameserver(act);
- return zfcp_erp_port_strategy_open_common(act);
-}
-
static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
{
struct zfcp_port *port = erp_action->port;
+ if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)
+ goto close_init_done;
+
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
zfcp_erp_port_strategy_clearstati(port);
@@ -992,19 +916,17 @@ static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
return ZFCP_ERP_FAILED;
break;
}
+
+close_init_done:
if (erp_action->status & ZFCP_STATUS_ERP_CLOSE_ONLY)
return ZFCP_ERP_EXIT;
- else
- return zfcp_erp_port_strategy_open(erp_action);
- return ZFCP_ERP_FAILED;
+ return zfcp_erp_port_strategy_open_common(erp_action);
}
static void zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
{
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING |
- ZFCP_STATUS_COMMON_CLOSING |
- ZFCP_STATUS_COMMON_ACCESS_DENIED |
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_UNIT_SHARED |
ZFCP_STATUS_UNIT_READONLY,
&unit->status);
@@ -1065,8 +987,14 @@ static int zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
break;
case ZFCP_ERP_FAILED :
atomic_inc(&unit->erp_counter);
- if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS)
+ if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&unit->port->adapter->ccw_device->dev,
+ "ERP failed for unit 0x%016Lx on "
+ "port 0x%016Lx\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 21, NULL);
+ }
break;
}
@@ -1091,8 +1019,12 @@ static int zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
result = ZFCP_ERP_EXIT;
}
atomic_inc(&port->erp_counter);
- if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
+ if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&port->adapter->ccw_device->dev,
+ "ERP failed for remote port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
zfcp_erp_port_failed(port, 22, NULL);
+ }
break;
}
@@ -1114,8 +1046,12 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter,
case ZFCP_ERP_FAILED :
atomic_inc(&adapter->erp_counter);
- if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS)
+ if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) {
+ dev_err(&adapter->ccw_device->dev,
+ "ERP cannot recover an error "
+ "on the FCP device\n");
zfcp_erp_adapter_failed(adapter, 23, NULL);
+ }
break;
}
@@ -1250,9 +1186,10 @@ static void zfcp_erp_scsi_scan(struct work_struct *work)
struct zfcp_unit *unit = p->unit;
struct fc_rport *rport = unit->port->rport;
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
- unit->scsi_lun, 0);
+ scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
zfcp_unit_put(unit);
+ wake_up(&unit->port->adapter->erp_done_wqh);
kfree(p);
}
@@ -1263,9 +1200,9 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p) {
dev_err(&unit->port->adapter->ccw_device->dev,
- "Out of resources. Could not register unit "
- "0x%016Lx on port 0x%016Lx with SCSI stack.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
return;
}
@@ -1273,7 +1210,7 @@ static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
INIT_WORK(&p->work, zfcp_erp_scsi_scan);
p->unit = unit;
- schedule_work(&p->work);
+ queue_work(zfcp_data.work_queue, &p->work);
}
static void zfcp_erp_rport_register(struct zfcp_port *port)
@@ -1286,8 +1223,8 @@ static void zfcp_erp_rport_register(struct zfcp_port *port)
port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
if (!port->rport) {
dev_err(&port->adapter->ccw_device->dev,
- "Failed registration of rport "
- "0x%016Lx.\n", port->wwpn);
+ "Registering port 0x%016Lx failed\n",
+ (unsigned long long)port->wwpn);
return;
}
@@ -1299,12 +1236,12 @@ static void zfcp_erp_rport_register(struct zfcp_port *port)
static void zfcp_erp_rports_del(struct zfcp_adapter *adapter)
{
struct zfcp_port *port;
- list_for_each_entry(port, &adapter->port_list_head, list)
- if (port->rport && !(atomic_read(&port->status) &
- ZFCP_STATUS_PORT_WKA)) {
- fc_remote_port_delete(port->rport);
- port->rport = NULL;
- }
+ list_for_each_entry(port, &adapter->port_list_head, list) {
+ if (!port->rport)
+ continue;
+ fc_remote_port_delete(port->rport);
+ port->rport = NULL;
+ }
}
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
@@ -1439,7 +1376,7 @@ static int zfcp_erp_thread(void *data)
struct zfcp_erp_action *act;
unsigned long flags;
- daemonize("zfcperp%s", adapter->ccw_device->dev.bus_id);
+ daemonize("zfcperp%s", dev_name(&adapter->ccw_device->dev));
/* Block all signals */
siginitsetinv(&current->blocked, 0);
atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
@@ -1459,9 +1396,9 @@ static int zfcp_erp_thread(void *data)
zfcp_erp_wakeup(adapter);
}
- zfcp_rec_dbf_event_thread(4, adapter);
+ zfcp_rec_dbf_event_thread_lock(4, adapter);
down_interruptible(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread(5, adapter);
+ zfcp_rec_dbf_event_thread_lock(5, adapter);
}
atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
@@ -1484,7 +1421,7 @@ int zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
if (retval < 0) {
dev_err(&adapter->ccw_device->dev,
- "Creation of ERP thread failed.\n");
+ "Creating an ERP thread for the FCP device failed.\n");
return retval;
}
wait_event(adapter->erp_thread_wqh,
@@ -1506,7 +1443,7 @@ void zfcp_erp_thread_kill(struct zfcp_adapter *adapter)
{
atomic_set_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL, &adapter->status);
up(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock(2, adapter);
+ zfcp_rec_dbf_event_thread_lock(3, adapter);
wait_event(adapter->erp_thread_wqh,
!(atomic_read(&adapter->status) &
@@ -1526,7 +1463,6 @@ void zfcp_erp_adapter_failed(struct zfcp_adapter *adapter, u8 id, void *ref)
{
zfcp_erp_modify_adapter_status(adapter, id, ref,
ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
- dev_err(&adapter->ccw_device->dev, "Adapter ERP failed.\n");
}
/**
@@ -1539,15 +1475,6 @@ void zfcp_erp_port_failed(struct zfcp_port *port, u8 id, void *ref)
{
zfcp_erp_modify_port_status(port, id, ref,
ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-
- if (atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA)
- dev_err(&port->adapter->ccw_device->dev,
- "Port ERP failed for WKA port d_id=0x%06x.\n",
- port->d_id);
- else
- dev_err(&port->adapter->ccw_device->dev,
- "Port ERP failed for port wwpn=0x%016Lx.\n",
- port->wwpn);
}
/**
@@ -1560,10 +1487,6 @@ void zfcp_erp_unit_failed(struct zfcp_unit *unit, u8 id, void *ref)
{
zfcp_erp_modify_unit_status(unit, id, ref,
ZFCP_STATUS_COMMON_ERP_FAILED, ZFCP_SET);
-
- dev_err(&unit->port->adapter->ccw_device->dev,
- "Unit ERP failed for unit 0x%016Lx on port 0x%016Lx.\n",
- unit->fcp_lun, unit->port->wwpn);
}
/**
@@ -1754,9 +1677,8 @@ static void zfcp_erp_port_access_changed(struct zfcp_port *port, u8 id,
if (!(status & (ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_COMMON_ACCESS_BOXED))) {
- if (!(status & ZFCP_STATUS_PORT_WKA))
- list_for_each_entry(unit, &port->unit_list_head, list)
- zfcp_erp_unit_access_changed(unit, id, ref);
+ list_for_each_entry(unit, &port->unit_list_head, list)
+ zfcp_erp_unit_access_changed(unit, id, ref);
return;
}
@@ -1779,10 +1701,7 @@ void zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter, u8 id,
return;
read_lock_irqsave(&zfcp_data.config_lock, flags);
- if (adapter->nameserver_port)
- zfcp_erp_port_access_changed(adapter->nameserver_port, id, ref);
list_for_each_entry(port, &adapter->port_list_head, list)
- if (port != adapter->nameserver_port)
- zfcp_erp_port_access_changed(port, id, ref);
+ zfcp_erp_port_access_changed(port, id, ref);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index edfdb21591f..b5adeda93e1 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -12,16 +12,14 @@
#include "zfcp_def.h"
/* zfcp_aux.c */
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *,
- fcp_lun_t);
-extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *,
- wwn_t);
+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 int zfcp_adapter_enqueue(struct ccw_device *);
extern void zfcp_adapter_dequeue(struct zfcp_adapter *);
-extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32,
+extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32,
u32);
extern void zfcp_port_dequeue(struct zfcp_port *);
-extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
+extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, u64);
extern void zfcp_unit_dequeue(struct zfcp_unit *);
extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
extern void zfcp_sg_free_table(struct scatterlist *, int);
@@ -29,6 +27,7 @@ extern int zfcp_sg_setup_table(struct scatterlist *, int);
/* zfcp_ccw.c */
extern int zfcp_ccw_register(void);
+extern struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
/* zfcp_cfdc.c */
extern struct miscdevice zfcp_cfdc_misc;
@@ -50,6 +49,8 @@ extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
struct fsf_status_read_buffer *);
extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int,
int);
+extern void zfcp_hba_dbf_event_berr(struct zfcp_adapter *,
+ struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *);
@@ -91,17 +92,21 @@ extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8, void *);
extern void zfcp_erp_unit_access_denied(struct zfcp_unit *, u8, void *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, u8, void *);
extern void zfcp_erp_timeout_handler(unsigned long);
+extern void zfcp_erp_port_strategy_open_lookup(struct work_struct *);
/* zfcp_fc.c */
extern int zfcp_scan_ports(struct zfcp_adapter *);
extern void _zfcp_scan_ports_later(struct work_struct *);
extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
-extern int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *);
+extern int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *);
extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
extern void zfcp_test_link(struct zfcp_port *);
+extern void zfcp_fc_nameserver_init(struct zfcp_adapter *);
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
+extern int zfcp_fsf_open_wka_port(struct zfcp_wka_port *);
+extern int zfcp_fsf_close_wka_port(struct zfcp_wka_port *);
extern int zfcp_fsf_close_port(struct zfcp_erp_action *);
extern int zfcp_fsf_close_physical_port(struct zfcp_erp_action *);
extern int zfcp_fsf_open_unit(struct zfcp_erp_action *);
@@ -135,10 +140,8 @@ extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long,
extern int zfcp_qdio_allocate(struct zfcp_adapter *);
extern void zfcp_qdio_free(struct zfcp_adapter *);
extern int zfcp_qdio_send(struct zfcp_fsf_req *);
-extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req(
- struct zfcp_fsf_req *);
-extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr(
- struct zfcp_fsf_req *);
+extern struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *);
+extern struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *);
extern int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *, unsigned long,
struct scatterlist *, int);
extern int zfcp_qdio_open(struct zfcp_adapter *);
@@ -148,14 +151,12 @@ extern void zfcp_qdio_close(struct zfcp_adapter *);
extern struct zfcp_data zfcp_data;
extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
-extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t);
extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
extern struct fc_function_template zfcp_transport_functions;
/* zfcp_sysfs.c */
extern struct attribute_group zfcp_sysfs_unit_attrs;
extern struct attribute_group zfcp_sysfs_adapter_attrs;
-extern struct attribute_group zfcp_sysfs_ns_port_attrs;
extern struct attribute_group zfcp_sysfs_port_attrs;
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index e984469bb98..1a7c80a77ff 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -39,16 +39,82 @@ struct zfcp_gpn_ft {
struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS];
};
-static struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *adapter,
- u32 d_id)
+struct zfcp_fc_ns_handler_data {
+ struct completion done;
+ void (*handler)(unsigned long);
+ unsigned long handler_data;
+};
+
+static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
{
- struct zfcp_port *port;
+ if (mutex_lock_interruptible(&wka_port->mutex))
+ return -ERESTARTSYS;
- list_for_each_entry(port, &adapter->port_list_head, list)
- if ((port->d_id == d_id) &&
- !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status))
- return port;
- return NULL;
+ if (wka_port->status != ZFCP_WKA_PORT_ONLINE) {
+ wka_port->status = ZFCP_WKA_PORT_OPENING;
+ if (zfcp_fsf_open_wka_port(wka_port))
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ }
+
+ mutex_unlock(&wka_port->mutex);
+
+ wait_event_timeout(
+ wka_port->completion_wq,
+ wka_port->status == ZFCP_WKA_PORT_ONLINE ||
+ wka_port->status == ZFCP_WKA_PORT_OFFLINE,
+ HZ >> 1);
+
+ if (wka_port->status == ZFCP_WKA_PORT_ONLINE) {
+ atomic_inc(&wka_port->refcount);
+ return 0;
+ }
+ return -EIO;
+}
+
+static void zfcp_wka_port_offline(struct work_struct *work)
+{
+ struct delayed_work *dw = container_of(work, struct delayed_work, work);
+ struct zfcp_wka_port *wka_port =
+ container_of(dw, struct zfcp_wka_port, work);
+
+ wait_event(wka_port->completion_wq,
+ atomic_read(&wka_port->refcount) == 0);
+
+ mutex_lock(&wka_port->mutex);
+ if ((atomic_read(&wka_port->refcount) != 0) ||
+ (wka_port->status != ZFCP_WKA_PORT_ONLINE))
+ goto out;
+
+ wka_port->status = ZFCP_WKA_PORT_CLOSING;
+ if (zfcp_fsf_close_wka_port(wka_port)) {
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ wake_up(&wka_port->completion_wq);
+ }
+out:
+ mutex_unlock(&wka_port->mutex);
+}
+
+static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port)
+{
+ if (atomic_dec_return(&wka_port->refcount) != 0)
+ return;
+ /* wait 10 miliseconds, other reqs might pop in */
+ schedule_delayed_work(&wka_port->work, HZ / 100);
+}
+
+void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter)
+{
+ struct zfcp_wka_port *wka_port = &adapter->nsp;
+
+ init_waitqueue_head(&wka_port->completion_wq);
+
+ wka_port->adapter = adapter;
+ wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE;
+
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ atomic_set(&wka_port->refcount, 0);
+ mutex_init(&wka_port->mutex);
+ INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
}
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
@@ -59,10 +125,8 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
read_lock_irqsave(&zfcp_data.config_lock, flags);
list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
- if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
- continue;
/* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */
- if (!atomic_test_mask(ZFCP_STATUS_PORT_DID_DID, &port->status))
+ if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID))
/* Try to connect to unused ports anyway. */
zfcp_erp_port_reopen(port,
ZFCP_STATUS_COMMON_ERP_FAILED,
@@ -114,7 +178,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
schedule_work(&fsf_req->adapter->scan_work);
}
-static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, wwn_t wwpn)
+static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
{
struct zfcp_adapter *adapter = req->adapter;
struct zfcp_port *port;
@@ -169,7 +233,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req)
zfcp_fc_incoming_rscn(fsf_req);
}
-static void zfcp_ns_gid_pn_handler(unsigned long data)
+static void zfcp_fc_ns_handler(unsigned long data)
+{
+ struct zfcp_fc_ns_handler_data *compl_rec =
+ (struct zfcp_fc_ns_handler_data *) data;
+
+ if (compl_rec->handler)
+ compl_rec->handler(compl_rec->handler_data);
+
+ complete(&compl_rec->done);
+}
+
+static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
{
struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data;
struct zfcp_send_ct *ct = &gid_pn->ct;
@@ -178,43 +253,31 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
struct zfcp_port *port = gid_pn->port;
if (ct->status)
- goto out;
+ return;
if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
- goto out;
+ return;
}
/* paranoia */
if (ct_iu_req->wwpn != port->wwpn)
- goto out;
+ return;
/* looks like a valid d_id */
port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
-out:
- mempool_free(gid_pn, port->adapter->pool.data_gid_pn);
}
-/**
- * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
- * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
- * return: -ENOMEM on error, 0 otherwise
- */
-int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
+int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
+ struct zfcp_gid_pn_data *gid_pn)
{
- int ret;
- struct zfcp_gid_pn_data *gid_pn;
struct zfcp_adapter *adapter = erp_action->adapter;
-
- gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
- if (!gid_pn)
- return -ENOMEM;
-
- memset(gid_pn, 0, sizeof(*gid_pn));
+ struct zfcp_fc_ns_handler_data compl_rec;
+ int ret;
/* setup parameters for send generic command */
gid_pn->port = erp_action->port;
- gid_pn->ct.port = adapter->nameserver_port;
- gid_pn->ct.handler = zfcp_ns_gid_pn_handler;
- gid_pn->ct.handler_data = (unsigned long) gid_pn;
+ gid_pn->ct.wka_port = &adapter->nsp;
+ gid_pn->ct.handler = zfcp_fc_ns_handler;
+ gid_pn->ct.handler_data = (unsigned long) &compl_rec;
gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
gid_pn->ct.req = &gid_pn->req;
gid_pn->ct.resp = &gid_pn->resp;
@@ -234,10 +297,42 @@ int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE;
gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
+ init_completion(&compl_rec.done);
+ compl_rec.handler = zfcp_fc_ns_gid_pn_eval;
+ compl_rec.handler_data = (unsigned long) gid_pn;
ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
erp_action);
+ if (!ret)
+ wait_for_completion(&compl_rec.done);
+ return ret;
+}
+
+/**
+ * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
+ * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
+ * return: -ENOMEM on error, 0 otherwise
+ */
+int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action)
+{
+ int ret;
+ struct zfcp_gid_pn_data *gid_pn;
+ struct zfcp_adapter *adapter = erp_action->adapter;
+
+ gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
+ if (!gid_pn)
+ return -ENOMEM;
+
+ memset(gid_pn, 0, sizeof(*gid_pn));
+
+ ret = zfcp_wka_port_get(&adapter->nsp);
if (ret)
- mempool_free(gid_pn, adapter->pool.data_gid_pn);
+ goto out;
+
+ ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn);
+
+ zfcp_wka_port_put(&adapter->nsp);
+out:
+ mempool_free(gid_pn, adapter->pool.data_gid_pn);
return ret;
}
@@ -267,14 +362,14 @@ struct zfcp_els_adisc {
struct scatterlist req;
struct scatterlist resp;
struct zfcp_ls_adisc ls_adisc;
- struct zfcp_ls_adisc_acc ls_adisc_acc;
+ struct zfcp_ls_adisc ls_adisc_acc;
};
static void zfcp_fc_adisc_handler(unsigned long data)
{
struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data;
struct zfcp_port *port = adisc->els.port;
- struct zfcp_ls_adisc_acc *ls_adisc = &adisc->ls_adisc_acc;
+ struct zfcp_ls_adisc *ls_adisc = &adisc->ls_adisc_acc;
if (adisc->els.status) {
/* request rejected or timed out */
@@ -307,7 +402,7 @@ static int zfcp_fc_adisc(struct zfcp_port *port)
sg_init_one(adisc->els.req, &adisc->ls_adisc,
sizeof(struct zfcp_ls_adisc));
sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc,
- sizeof(struct zfcp_ls_adisc_acc));
+ sizeof(struct zfcp_ls_adisc));
adisc->els.req_count = 1;
adisc->els.resp_count = 1;
@@ -341,37 +436,13 @@ void zfcp_test_link(struct zfcp_port *port)
zfcp_port_get(port);
retval = zfcp_fc_adisc(port);
- if (retval == 0 || retval == -EBUSY)
+ if (retval == 0)
return;
/* send of ADISC was not possible */
zfcp_port_put(port);
- zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
-}
-
-static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter)
-{
- int ret;
-
- if (!adapter->nameserver_port)
- return -EINTR;
-
- if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
- &adapter->nameserver_port->status)) {
- ret = zfcp_erp_port_reopen(adapter->nameserver_port, 0, 148,
- NULL);
- if (ret)
- return ret;
- zfcp_erp_wait(adapter);
- zfcp_port_put(adapter->nameserver_port);
- }
- return !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
- &adapter->nameserver_port->status);
-}
-
-static void zfcp_gpn_ft_handler(unsigned long _done)
-{
- complete((struct completion *)_done);
+ if (retval != -EBUSY)
+ zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
}
static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft)
@@ -415,7 +486,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
{
struct zfcp_send_ct *ct = &gpn_ft->ct;
struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
- struct completion done;
+ struct zfcp_fc_ns_handler_data compl_rec;
int ret;
/* prepare CT IU for GPN_FT */
@@ -432,19 +503,20 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
req->fc4_type = ZFCP_CT_SCSI_FCP;
/* prepare zfcp_send_ct */
- ct->port = adapter->nameserver_port;
- ct->handler = zfcp_gpn_ft_handler;
- ct->handler_data = (unsigned long)&done;
+ ct->wka_port = &adapter->nsp;
+ ct->handler = zfcp_fc_ns_handler;
+ ct->handler_data = (unsigned long)&compl_rec;
ct->timeout = 10;
ct->req = &gpn_ft->sg_req;
ct->resp = gpn_ft->sg_resp;
ct->req_count = 1;
ct->resp_count = ZFCP_GPN_FT_BUFFERS;
- init_completion(&done);
+ init_completion(&compl_rec.done);
+ compl_rec.handler = NULL;
ret = zfcp_fsf_send_ct(ct, NULL, NULL);
if (!ret)
- wait_for_completion(&done);
+ wait_for_completion(&compl_rec.done);
return ret;
}
@@ -454,9 +526,8 @@ static void zfcp_validate_port(struct zfcp_port *port)
atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
- if (port == adapter->nameserver_port)
- return;
- if ((port->supported_classes != 0) || (port->units != 0)) {
+ if ((port->supported_classes != 0) ||
+ !list_empty(&port->unit_list_head)) {
zfcp_port_put(port);
return;
}
@@ -472,10 +543,10 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
struct scatterlist *sg = gpn_ft->sg_resp;
struct ct_hdr *hdr = sg_virt(sg);
struct gpn_ft_resp_acc *acc = sg_virt(sg);
- struct zfcp_adapter *adapter = ct->port->adapter;
+ struct zfcp_adapter *adapter = ct->wka_port->adapter;
struct zfcp_port *port, *tmp;
u32 d_id;
- int ret = 0, x;
+ int ret = 0, x, last = 0;
if (ct->status)
return -EIO;
@@ -492,19 +563,27 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
down(&zfcp_data.config_sema);
/* first entry is the header */
- for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES; x++) {
+ for (x = 1; x < ZFCP_GPN_FT_MAX_ENTRIES && !last; x++) {
if (x % (ZFCP_GPN_FT_ENTRIES + 1))
acc++;
else
acc = sg_virt(++sg);
+ last = acc->control & 0x80;
d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 |
acc->port_id[2];
+ /* don't attach ports with a well known address */
+ if ((d_id & ZFCP_DID_WKA) == ZFCP_DID_WKA)
+ continue;
/* skip the adapter's port and known remote ports */
- if (acc->wwpn == fc_host_port_name(adapter->scsi_host) ||
- zfcp_get_port_by_did(adapter, d_id))
+ if (acc->wwpn == fc_host_port_name(adapter->scsi_host))
continue;
+ port = zfcp_get_port_by_wwpn(adapter, acc->wwpn);
+ if (port) {
+ zfcp_port_get(port);
+ continue;
+ }
port = zfcp_port_enqueue(adapter, acc->wwpn,
ZFCP_STATUS_PORT_DID_DID |
@@ -513,8 +592,6 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
ret = PTR_ERR(port);
else
zfcp_erp_port_reopen(port, 0, 149, NULL);
- if (acc->control & 0x80) /* last entry */
- break;
}
zfcp_erp_wait(adapter);
@@ -537,13 +614,15 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
return 0;
- ret = zfcp_scan_get_nameserver(adapter);
+ ret = zfcp_wka_port_get(&adapter->nsp);
if (ret)
return ret;
gpn_ft = zfcp_alloc_sg_env();
- if (!gpn_ft)
- return -ENOMEM;
+ if (!gpn_ft) {
+ ret = -ENOMEM;
+ goto out;
+ }
for (i = 0; i < 3; i++) {
ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter);
@@ -556,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
}
}
zfcp_free_sg_env(gpn_ft);
-
+out:
+ zfcp_wka_port_put(&adapter->nsp);
return ret;
}
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 19c1ca91387..739356a5c12 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -50,19 +50,16 @@ static u32 fsf_qtcb_type[] = {
[FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND
};
-static const char *zfcp_act_subtable_type[] = {
- "unknown", "OS", "WWPN", "DID", "LUN"
-};
-
static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table)
{
u16 subtable = table >> 16;
u16 rule = table & 0xffff;
+ const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" };
- if (subtable && subtable < ARRAY_SIZE(zfcp_act_subtable_type))
+ if (subtable && subtable < ARRAY_SIZE(act_type))
dev_warn(&adapter->ccw_device->dev,
- "Access denied in subtable %s, rule %d.\n",
- zfcp_act_subtable_type[subtable], rule);
+ "Access denied according to ACT rule type %s, "
+ "rule %d\n", act_type[subtable], rule);
}
static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
@@ -70,8 +67,8 @@ static void zfcp_fsf_access_denied_port(struct zfcp_fsf_req *req,
{
struct fsf_qtcb_header *header = &req->qtcb->header;
dev_warn(&req->adapter->ccw_device->dev,
- "Access denied, cannot send command to port 0x%016Lx.\n",
- port->wwpn);
+ "Access denied to port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
zfcp_erp_port_access_denied(port, 55, req);
@@ -83,8 +80,9 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
{
struct fsf_qtcb_header *header = &req->qtcb->header;
dev_warn(&req->adapter->ccw_device->dev,
- "Access denied for unit 0x%016Lx on port 0x%016Lx.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Access denied to unit 0x%016Lx on port 0x%016Lx\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[0]);
zfcp_act_eval_err(req->adapter, header->fsf_status_qual.halfword[1]);
zfcp_erp_unit_access_denied(unit, 59, req);
@@ -93,9 +91,8 @@ static void zfcp_fsf_access_denied_unit(struct zfcp_fsf_req *req,
static void zfcp_fsf_class_not_supp(struct zfcp_fsf_req *req)
{
- dev_err(&req->adapter->ccw_device->dev,
- "Required FC class not supported by adapter, "
- "shutting down adapter.\n");
+ dev_err(&req->adapter->ccw_device->dev, "FCP device not "
+ "operational because of an unsupported FC class\n");
zfcp_erp_adapter_shutdown(req->adapter, 0, 123, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
@@ -171,42 +168,6 @@ static void zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *req)
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
-static void zfcp_fsf_bit_error_threshold(struct zfcp_fsf_req *req)
-{
- struct zfcp_adapter *adapter = req->adapter;
- struct fsf_status_read_buffer *sr_buf = req->data;
- struct fsf_bit_error_payload *err = &sr_buf->payload.bit_error;
-
- dev_warn(&adapter->ccw_device->dev,
- "Warning: bit error threshold data "
- "received for the adapter: "
- "link failures = %i, loss of sync errors = %i, "
- "loss of signal errors = %i, "
- "primitive sequence errors = %i, "
- "invalid transmission word errors = %i, "
- "CRC errors = %i).\n",
- err->link_failure_error_count,
- err->loss_of_sync_error_count,
- err->loss_of_signal_error_count,
- err->primitive_sequence_error_count,
- err->invalid_transmission_word_error_count,
- err->crc_error_count);
- dev_warn(&adapter->ccw_device->dev,
- "Additional bit error threshold data of the adapter: "
- "primitive sequence event time-outs = %i, "
- "elastic buffer overrun errors = %i, "
- "advertised receive buffer-to-buffer credit = %i, "
- "current receice buffer-to-buffer credit = %i, "
- "advertised transmit buffer-to-buffer credit = %i, "
- "current transmit buffer-to-buffer credit = %i).\n",
- err->primitive_sequence_event_timeout_count,
- err->elastic_buffer_overrun_error_count,
- err->advertised_receive_b2b_credit,
- err->current_receive_b2b_credit,
- err->advertised_transmit_b2b_credit,
- err->current_transmit_b2b_credit);
-}
-
static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id,
struct fsf_link_down_info *link_down)
{
@@ -223,62 +184,66 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, u8 id,
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: no light detected.\n");
+ "There is no light signal from the local "
+ "fibre channel cable\n");
break;
case FSF_PSQ_LINK_WRAP_PLUG:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: wrap plug detected.\n");
+ "There is a wrap plug instead of a fibre "
+ "channel cable\n");
break;
case FSF_PSQ_LINK_NO_FCP:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "adjacent node on link does not support FCP.\n");
+ "The adjacent fibre channel node does not "
+ "support FCP\n");
break;
case FSF_PSQ_LINK_FIRMWARE_UPDATE:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "firmware update in progress.\n");
+ "The FCP device is suspended because of a "
+ "firmware update\n");
break;
case FSF_PSQ_LINK_INVALID_WWPN:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "duplicate or invalid WWPN detected.\n");
+ "The FCP device detected a WWPN that is "
+ "duplicate or not valid\n");
break;
case FSF_PSQ_LINK_NO_NPIV_SUPPORT:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "no support for NPIV by Fabric.\n");
+ "The fibre channel fabric does not support NPIV\n");
break;
case FSF_PSQ_LINK_NO_FCP_RESOURCES:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "out of resource in FCP daughtercard.\n");
+ "The FCP adapter cannot support more NPIV ports\n");
break;
case FSF_PSQ_LINK_NO_FABRIC_RESOURCES:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "out of resource in Fabric.\n");
+ "The adjacent switch cannot support "
+ "more NPIV ports\n");
break;
case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link is down: "
- "unable to login to Fabric.\n");
+ "The FCP adapter could not log in to the "
+ "fibre channel fabric\n");
break;
case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED:
dev_warn(&req->adapter->ccw_device->dev,
- "WWPN assignment file corrupted on adapter.\n");
+ "The WWPN assignment file on the FCP adapter "
+ "has been damaged\n");
break;
case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED:
dev_warn(&req->adapter->ccw_device->dev,
- "Mode table corrupted on adapter.\n");
+ "The mode table on the FCP adapter "
+ "has been damaged\n");
break;
case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT:
dev_warn(&req->adapter->ccw_device->dev,
- "No WWPN for assignment table on adapter.\n");
+ "All NPIV ports on the FCP adapter have "
+ "been assigned\n");
break;
default:
dev_warn(&req->adapter->ccw_device->dev,
- "The local link to adapter is down.\n");
+ "The link between the FCP adapter and "
+ "the FC fabric is down\n");
}
out:
zfcp_erp_adapter_failed(adapter, id, req);
@@ -286,27 +251,18 @@ out:
static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req)
{
- struct zfcp_adapter *adapter = req->adapter;
struct fsf_status_read_buffer *sr_buf = req->data;
struct fsf_link_down_info *ldi =
(struct fsf_link_down_info *) &sr_buf->payload;
switch (sr_buf->status_subtype) {
case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
- dev_warn(&adapter->ccw_device->dev,
- "Physical link is down.\n");
zfcp_fsf_link_down_info_eval(req, 38, ldi);
break;
case FSF_STATUS_READ_SUB_FDISC_FAILED:
- dev_warn(&adapter->ccw_device->dev,
- "Local link is down "
- "due to failed FDISC login.\n");
zfcp_fsf_link_down_info_eval(req, 39, ldi);
break;
case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
- dev_warn(&adapter->ccw_device->dev,
- "Local link is down "
- "due to firmware update on adapter.\n");
zfcp_fsf_link_down_info_eval(req, 40, NULL);
};
}
@@ -335,14 +291,17 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
case FSF_STATUS_READ_SENSE_DATA_AVAIL:
break;
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
- zfcp_fsf_bit_error_threshold(req);
+ dev_warn(&adapter->ccw_device->dev,
+ "The error threshold for checksum statistics "
+ "has been exceeded\n");
+ zfcp_hba_dbf_event_berr(adapter, req);
break;
case FSF_STATUS_READ_LINK_DOWN:
zfcp_fsf_status_read_link_down(req);
break;
case FSF_STATUS_READ_LINK_UP:
dev_info(&adapter->ccw_device->dev,
- "Local link was replugged.\n");
+ "The local link has been restored\n");
/* All ports should be marked as ready to run again */
zfcp_erp_modify_adapter_status(adapter, 30, NULL,
ZFCP_STATUS_COMMON_RUNNING,
@@ -370,7 +329,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
zfcp_fsf_req_free(req);
atomic_inc(&adapter->stat_miss);
- schedule_work(&adapter->stat_work);
+ queue_work(zfcp_data.work_queue, &adapter->stat_work);
}
static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
@@ -386,8 +345,8 @@ static void zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *req)
break;
case FSF_SQ_NO_RECOM:
dev_err(&req->adapter->ccw_device->dev,
- "No recommendation could be given for a "
- "problem on the adapter.\n");
+ "The FCP adapter reported a problem "
+ "that cannot be recovered\n");
zfcp_erp_adapter_shutdown(req->adapter, 0, 121, req);
break;
}
@@ -403,8 +362,7 @@ static void zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *req)
switch (req->qtcb->header.fsf_status) {
case FSF_UNKNOWN_COMMAND:
dev_err(&req->adapter->ccw_device->dev,
- "Command issued by the device driver (0x%x) is "
- "not known by the adapter.\n",
+ "The FCP adapter does not recognize the command 0x%x\n",
req->qtcb->header.fsf_command);
zfcp_erp_adapter_shutdown(req->adapter, 0, 120, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -435,11 +393,9 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
return;
case FSF_PROT_QTCB_VERSION_ERROR:
dev_err(&adapter->ccw_device->dev,
- "The QTCB version requested by zfcp (0x%x) is not "
- "supported by the FCP adapter (lowest supported "
- "0x%x, highest supported 0x%x).\n",
- FSF_QTCB_CURRENT_VERSION, psq->word[0],
- psq->word[1]);
+ "QTCB version 0x%x not supported by FCP adapter "
+ "(0x%x to 0x%x)\n", FSF_QTCB_CURRENT_VERSION,
+ psq->word[0], psq->word[1]);
zfcp_erp_adapter_shutdown(adapter, 0, 117, req);
break;
case FSF_PROT_ERROR_STATE:
@@ -449,8 +405,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
break;
case FSF_PROT_UNSUPP_QTCB_TYPE:
dev_err(&adapter->ccw_device->dev,
- "Packet header type used by the device driver is "
- "incompatible with that used on the adapter.\n");
+ "The QTCB type is not supported by the FCP adapter\n");
zfcp_erp_adapter_shutdown(adapter, 0, 118, req);
break;
case FSF_PROT_HOST_CONNECTION_INITIALIZING:
@@ -459,7 +414,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
break;
case FSF_PROT_DUPLICATE_REQUEST_ID:
dev_err(&adapter->ccw_device->dev,
- "The request identifier 0x%Lx is ambiguous.\n",
+ "0x%Lx is an ambiguous request identifier\n",
(unsigned long long)qtcb->bottom.support.req_handle);
zfcp_erp_adapter_shutdown(adapter, 0, 78, req);
break;
@@ -479,9 +434,7 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req)
break;
default:
dev_err(&adapter->ccw_device->dev,
- "Transfer protocol status information"
- "provided by the adapter (0x%x) "
- "is not compatible with the device driver.\n",
+ "0x%x is not a valid transfer protocol status\n",
qtcb->prefix.prot_status);
zfcp_erp_adapter_shutdown(adapter, 0, 119, req);
}
@@ -559,33 +512,17 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
adapter->peer_wwpn = bottom->plogi_payload.wwpn;
adapter->peer_wwnn = bottom->plogi_payload.wwnn;
fc_host_port_type(shost) = FC_PORTTYPE_PTP;
- if (req->erp_action)
- dev_info(&adapter->ccw_device->dev,
- "Point-to-Point fibrechannel "
- "configuration detected.\n");
break;
case FSF_TOPO_FABRIC:
fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
- if (req->erp_action)
- dev_info(&adapter->ccw_device->dev,
- "Switched fabric fibrechannel "
- "network detected.\n");
break;
case FSF_TOPO_AL:
fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
- dev_err(&adapter->ccw_device->dev,
- "Unsupported arbitrated loop fibrechannel "
- "topology detected, shutting down "
- "adapter.\n");
- zfcp_erp_adapter_shutdown(adapter, 0, 127, req);
- return -EIO;
default:
- fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
dev_err(&adapter->ccw_device->dev,
- "The fibrechannel topology reported by the"
- " adapter is not known by the zfcp driver,"
- " shutting down adapter.\n");
- zfcp_erp_adapter_shutdown(adapter, 0, 128, req);
+ "Unknown or unsupported arbitrated loop "
+ "fibre channel topology detected\n");
+ zfcp_erp_adapter_shutdown(adapter, 0, 127, req);
return -EIO;
}
@@ -616,11 +553,9 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) {
dev_err(&adapter->ccw_device->dev,
- "Maximum QTCB size (%d bytes) allowed by "
- "the adapter is lower than the minimum "
- "required by the driver (%ld bytes).\n",
- bottom->max_qtcb_size,
- sizeof(struct fsf_qtcb));
+ "FCP adapter maximum QTCB size (%d bytes) "
+ "is too small\n",
+ bottom->max_qtcb_size);
zfcp_erp_adapter_shutdown(adapter, 0, 129, req);
return;
}
@@ -656,15 +591,15 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
dev_err(&adapter->ccw_device->dev,
- "The adapter only supports newer control block "
- "versions, try updated device driver.\n");
+ "The FCP adapter only supports newer "
+ "control block versions\n");
zfcp_erp_adapter_shutdown(adapter, 0, 125, req);
return;
}
if (FSF_QTCB_CURRENT_VERSION > bottom->high_qtcb_version) {
dev_err(&adapter->ccw_device->dev,
- "The adapter only supports older control block "
- "versions, consider a microcode upgrade.\n");
+ "The FCP adapter only supports older "
+ "control block versions\n");
zfcp_erp_adapter_shutdown(adapter, 0, 126, req);
}
}
@@ -688,7 +623,6 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
{
- struct zfcp_adapter *adapter = req->adapter;
struct fsf_qtcb *qtcb = req->qtcb;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -697,38 +631,47 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
switch (qtcb->header.fsf_status) {
case FSF_GOOD:
zfcp_fsf_exchange_port_evaluate(req);
- atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
zfcp_fsf_exchange_port_evaluate(req);
- atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
zfcp_fsf_link_down_info_eval(req, 43,
&qtcb->header.fsf_status_qual.link_down_info);
break;
}
}
-static int zfcp_fsf_sbal_check(struct zfcp_qdio_queue *queue)
+static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter)
{
- spin_lock(&queue->lock);
- if (atomic_read(&queue->count))
+ struct zfcp_qdio_queue *req_q = &adapter->req_q;
+
+ spin_lock_bh(&adapter->req_q_lock);
+ if (atomic_read(&req_q->count))
return 1;
- spin_unlock(&queue->lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return 0;
}
+static int zfcp_fsf_sbal_available(struct zfcp_adapter *adapter)
+{
+ unsigned int count = atomic_read(&adapter->req_q.count);
+ if (!count)
+ atomic_inc(&adapter->qdio_outb_full);
+ return count > 0;
+}
+
static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
{
long ret;
- struct zfcp_qdio_queue *req_q = &adapter->req_q;
- spin_unlock(&req_q->lock);
+ spin_unlock_bh(&adapter->req_q_lock);
ret = wait_event_interruptible_timeout(adapter->request_wq,
- zfcp_fsf_sbal_check(req_q), 5 * HZ);
+ zfcp_fsf_sbal_check(adapter), 5 * HZ);
if (ret > 0)
return 0;
+ if (!ret)
+ atomic_inc(&adapter->qdio_outb_full);
- spin_lock(&req_q->lock);
+ spin_lock_bh(&adapter->req_q_lock);
return -EIO;
}
@@ -765,7 +708,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
u32 fsf_cmd, int req_flags,
mempool_t *pool)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
struct zfcp_qdio_queue *req_q = &adapter->req_q;
@@ -867,17 +810,17 @@ int zfcp_fsf_status_read(struct zfcp_adapter *adapter)
{
struct zfcp_fsf_req *req;
struct fsf_status_read_buffer *sr_buf;
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS,
ZFCP_REQ_NO_QTCB,
adapter->pool.fsf_req_status_read);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -910,7 +853,7 @@ failed_buf:
zfcp_fsf_req_free(req);
zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -980,15 +923,15 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
struct zfcp_unit *unit,
int req_flags)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND,
req_flags, adapter->pool.fsf_req_abort);
- if (unlikely(IS_ERR(req)))
+ if (IS_ERR(req))
goto out;
if (unlikely(!(atomic_read(&unit->status) &
@@ -1013,7 +956,7 @@ out_error_free:
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return req;
}
@@ -1021,7 +964,6 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
struct zfcp_send_ct *send_ct = req->data;
- struct zfcp_port *port = send_ct->port;
struct fsf_qtcb_header *header = &req->qtcb->header;
send_ct->status = -EINVAL;
@@ -1040,17 +982,14 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
case FSF_ADAPTER_STATUS_AVAILABLE:
switch (header->fsf_status_qual.word[0]){
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- zfcp_test_link(port);
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
break;
case FSF_ACCESS_DENIED:
- zfcp_fsf_access_denied_port(req, port);
break;
case FSF_PORT_BOXED:
- zfcp_erp_port_boxed(port, 49, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
break;
@@ -1101,18 +1040,18 @@ static int zfcp_fsf_setup_sbals(struct zfcp_fsf_req *req,
int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
struct zfcp_erp_action *erp_action)
{
- struct zfcp_port *port = ct->port;
- struct zfcp_adapter *adapter = port->adapter;
+ struct zfcp_wka_port *wka_port = ct->wka_port;
+ struct zfcp_adapter *adapter = wka_port->adapter;
struct zfcp_fsf_req *req;
int ret = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC,
ZFCP_REQ_AUTO_CLEANUP, pool);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
@@ -1123,7 +1062,7 @@ int zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
goto failed_send;
req->handler = zfcp_fsf_send_ct_handler;
- req->qtcb->header.port_handle = port->handle;
+ req->qtcb->header.port_handle = wka_port->handle;
req->qtcb->bottom.support.service_class = FSF_CLASS_3;
req->qtcb->bottom.support.timeout = ct->timeout;
req->data = ct;
@@ -1148,7 +1087,7 @@ failed_send:
if (erp_action)
erp_action->fsf_req = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return ret;
}
@@ -1218,18 +1157,18 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
ZFCP_STATUS_COMMON_UNBLOCKED)))
return -EBUSY;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS,
ZFCP_REQ_AUTO_CLEANUP, NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
- ret = zfcp_fsf_setup_sbals(req, els->req, els->resp,
- FSF_MAX_SBALS_PER_ELS_REQ);
+ ret = zfcp_fsf_setup_sbals(req, els->req, els->resp, 2);
+
if (ret)
goto failed_send;
@@ -1252,25 +1191,25 @@ int zfcp_fsf_send_els(struct zfcp_send_els *els)
failed_send:
zfcp_fsf_req_free(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return ret;
}
int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
struct zfcp_adapter *adapter = erp_action->adapter;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock_bh(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter,
FSF_QTCB_EXCHANGE_CONFIG_DATA,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1295,24 +1234,24 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
struct fsf_qtcb_bottom_config *data)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
0, NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1334,7 +1273,7 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
@@ -1351,7 +1290,7 @@ out:
*/
int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req;
struct zfcp_adapter *adapter = erp_action->adapter;
int retval = -EIO;
@@ -1359,13 +1298,13 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock_bh(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1385,7 +1324,7 @@ int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1398,20 +1337,20 @@ out:
int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
struct fsf_qtcb_bottom_port *data)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
int retval = -EIO;
if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT))
return -EOPNOTSUPP;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock_bh(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1427,7 +1366,7 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
@@ -1443,7 +1382,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
struct fsf_plogi *plogi;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
switch (header->fsf_status) {
case FSF_PORT_ALREADY_OPEN:
@@ -1453,9 +1392,9 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
break;
case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
dev_warn(&req->adapter->ccw_device->dev,
- "The adapter is out of resources. The remote port "
- "0x%016Lx could not be opened, disabling it.\n",
- port->wwpn);
+ "Not enough FCP adapter resources to open "
+ "remote port 0x%016Lx\n",
+ (unsigned long long)port->wwpn);
zfcp_erp_port_failed(port, 31, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -1467,8 +1406,8 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
break;
case FSF_SQ_NO_RETRY_POSSIBLE:
dev_warn(&req->adapter->ccw_device->dev,
- "The remote port 0x%016Lx could not be "
- "opened. Disabling it.\n", port->wwpn);
+ "Remote port 0x%016Lx could not be opened\n",
+ (unsigned long long)port->wwpn);
zfcp_erp_port_failed(port, 32, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -1496,9 +1435,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
* another GID_PN straight after a port has been opened.
* Alternately, an ADISC/PDISC ELS should suffice, as well.
*/
- if (atomic_read(&port->status) & ZFCP_STATUS_PORT_NO_WWPN)
- break;
-
plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
if (req->qtcb->bottom.support.els1_length >= sizeof(*plogi)) {
if (plogi->serv_param.wwpn != port->wwpn)
@@ -1514,9 +1450,6 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
}
-
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &port->status);
}
/**
@@ -1526,12 +1459,12 @@ skip_fsfstatus:
*/
int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
@@ -1539,7 +1472,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
FSF_QTCB_OPEN_PORT_WITH_DID,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1553,7 +1486,6 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
req->data = erp_action->port;
req->erp_action = erp_action;
erp_action->fsf_req = req;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
@@ -1562,7 +1494,7 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1571,7 +1503,7 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
struct zfcp_port *port = req->data;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
@@ -1586,9 +1518,6 @@ static void zfcp_fsf_close_port_handler(struct zfcp_fsf_req *req)
ZFCP_CLEAR);
break;
}
-
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &port->status);
}
/**
@@ -1598,19 +1527,19 @@ skip_fsfstatus:
*/
int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1624,7 +1553,6 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
req->erp_action = erp_action;
req->qtcb->header.port_handle = erp_action->port->handle;
erp_action->fsf_req = req;
- atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
@@ -1633,7 +1561,131 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
+ return retval;
+}
+
+static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
+{
+ struct zfcp_wka_port *wka_port = req->data;
+ struct fsf_qtcb_header *header = &req->qtcb->header;
+
+ if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ goto out;
+ }
+
+ switch (header->fsf_status) {
+ case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
+ dev_warn(&req->adapter->ccw_device->dev,
+ "Opening WKA port 0x%x failed\n", wka_port->d_id);
+ case FSF_ADAPTER_STATUS_AVAILABLE:
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ case FSF_ACCESS_DENIED:
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ break;
+ case FSF_PORT_ALREADY_OPEN:
+ case FSF_GOOD:
+ wka_port->handle = header->port_handle;
+ wka_port->status = ZFCP_WKA_PORT_ONLINE;
+ }
+out:
+ wake_up(&wka_port->completion_wq);
+}
+
+/**
+ * zfcp_fsf_open_wka_port - create and send open wka-port request
+ * @wka_port: pointer to struct zfcp_wka_port
+ * Returns: 0 on success, error otherwise
+ */
+int zfcp_fsf_open_wka_port(struct zfcp_wka_port *wka_port)
+{
+ struct qdio_buffer_element *sbale;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_fsf_req *req;
+ int retval = -EIO;
+
+ spin_lock_bh(&adapter->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(adapter))
+ goto out;
+
+ req = zfcp_fsf_req_create(adapter,
+ FSF_QTCB_OPEN_PORT_WITH_DID,
+ ZFCP_REQ_AUTO_CLEANUP,
+ adapter->pool.fsf_req_erp);
+ if (unlikely(IS_ERR(req))) {
+ retval = PTR_ERR(req);
+ goto out;
+ }
+
+ sbale = zfcp_qdio_sbale_req(req);
+ sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+ sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+ req->handler = zfcp_fsf_open_wka_port_handler;
+ req->qtcb->bottom.support.d_id = wka_port->d_id;
+ req->data = wka_port;
+
+ zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
+ retval = zfcp_fsf_req_send(req);
+ if (retval)
+ zfcp_fsf_req_free(req);
+out:
+ spin_unlock_bh(&adapter->req_q_lock);
+ return retval;
+}
+
+static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
+{
+ struct zfcp_wka_port *wka_port = req->data;
+
+ if (req->qtcb->header.fsf_status == FSF_PORT_HANDLE_NOT_VALID) {
+ req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ zfcp_erp_adapter_reopen(wka_port->adapter, 0, 84, req);
+ }
+
+ wka_port->status = ZFCP_WKA_PORT_OFFLINE;
+ wake_up(&wka_port->completion_wq);
+}
+
+/**
+ * zfcp_fsf_close_wka_port - create and send close wka port request
+ * @erp_action: pointer to struct zfcp_erp_action
+ * Returns: 0 on success, error otherwise
+ */
+int zfcp_fsf_close_wka_port(struct zfcp_wka_port *wka_port)
+{
+ struct qdio_buffer_element *sbale;
+ struct zfcp_adapter *adapter = wka_port->adapter;
+ struct zfcp_fsf_req *req;
+ int retval = -EIO;
+
+ spin_lock_bh(&adapter->req_q_lock);
+ if (zfcp_fsf_req_sbal_get(adapter))
+ goto out;
+
+ req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PORT,
+ ZFCP_REQ_AUTO_CLEANUP,
+ adapter->pool.fsf_req_erp);
+ if (unlikely(IS_ERR(req))) {
+ retval = PTR_ERR(req);
+ goto out;
+ }
+
+ sbale = zfcp_qdio_sbale_req(req);
+ sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+ sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+ req->handler = zfcp_fsf_close_wka_port_handler;
+ req->data = wka_port;
+ req->qtcb->header.port_handle = wka_port->handle;
+
+ zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
+ retval = zfcp_fsf_req_send(req);
+ if (retval)
+ zfcp_fsf_req_free(req);
+out:
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1695,19 +1747,19 @@ skip_fsfstatus:
*/
int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1731,7 +1783,7 @@ int zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1746,7 +1798,7 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
int exclusive, readwrite;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
ZFCP_STATUS_COMMON_ACCESS_BOXED |
@@ -1774,14 +1826,12 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
case FSF_LUN_SHARING_VIOLATION:
if (header->fsf_status_qual.word[0])
dev_warn(&adapter->ccw_device->dev,
- "FCP-LUN 0x%Lx at the remote port "
- "with WWPN 0x%Lx "
- "connected to the adapter "
- "is already in use in LPAR%d, CSS%d.\n",
- unit->fcp_lun,
- unit->port->wwpn,
- queue_designator->hla,
- queue_designator->cssid);
+ "LUN 0x%Lx on port 0x%Lx is already in "
+ "use by CSS%d, MIF Image ID %x\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn,
+ queue_designator->cssid,
+ queue_designator->hla);
else
zfcp_act_eval_err(adapter,
header->fsf_status_qual.word[2]);
@@ -1792,9 +1842,10 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
break;
case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
dev_warn(&adapter->ccw_device->dev,
- "The adapter ran out of resources. There is no "
- "handle available for unit 0x%016Lx on port 0x%016Lx.",
- unit->fcp_lun, unit->port->wwpn);
+ "No handle is available for LUN "
+ "0x%016Lx on port 0x%016Lx\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 34, req);
/* fall through */
case FSF_INVALID_COMMAND_OPTION:
@@ -1831,26 +1882,29 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
atomic_set_mask(ZFCP_STATUS_UNIT_READONLY,
&unit->status);
dev_info(&adapter->ccw_device->dev,
- "Read-only access for unit 0x%016Lx "
- "on port 0x%016Lx.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "SCSI device at LUN 0x%016Lx on port "
+ "0x%016Lx opened read-only\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
}
if (exclusive && !readwrite) {
dev_err(&adapter->ccw_device->dev,
- "Exclusive access of read-only unit "
- "0x%016Lx on port 0x%016Lx not "
- "supported, disabling unit.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Exclusive read-only access not "
+ "supported (unit 0x%016Lx, "
+ "port 0x%016Lx)\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 35, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
zfcp_erp_unit_shutdown(unit, 0, 80, req);
} else if (!exclusive && readwrite) {
dev_err(&adapter->ccw_device->dev,
- "Shared access of read-write unit "
- "0x%016Lx on port 0x%016Lx not "
- "supported, disabling unit.\n",
- unit->fcp_lun, unit->port->wwpn);
+ "Shared read-write access not "
+ "supported (unit 0x%016Lx, port "
+ "0x%016Lx\n)",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_failed(unit, 36, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
zfcp_erp_unit_shutdown(unit, 0, 81, req);
@@ -1858,9 +1912,6 @@ static void zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *req)
}
break;
}
-
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_OPENING, &unit->status);
}
/**
@@ -1870,19 +1921,19 @@ skip_fsfstatus:
*/
int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_OPEN_LUN,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1901,8 +1952,6 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE))
req->qtcb->bottom.support.option = FSF_OPEN_LUN_SUPPRESS_BOXING;
- atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
-
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
if (retval) {
@@ -1910,7 +1959,7 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -1919,7 +1968,7 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
struct zfcp_unit *unit = req->data;
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
- goto skip_fsfstatus;
+ return;
switch (req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
@@ -1949,8 +1998,6 @@ static void zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *req)
atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
break;
}
-skip_fsfstatus:
- atomic_clear_mask(ZFCP_STATUS_COMMON_CLOSING, &unit->status);
}
/**
@@ -1960,18 +2007,18 @@ skip_fsfstatus:
*/
int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_fsf_req *req;
int retval = -EIO;
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_CLOSE_LUN,
ZFCP_REQ_AUTO_CLEANUP,
adapter->pool.fsf_req_erp);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -1986,7 +2033,6 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
req->data = erp_action->unit;
req->erp_action = erp_action;
erp_action->fsf_req = req;
- atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status);
zfcp_fsf_start_erp_timer(req);
retval = zfcp_fsf_req_send(req);
@@ -1995,7 +2041,7 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
erp_action->fsf_req = NULL;
}
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
@@ -2156,21 +2202,21 @@ static void zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *req)
break;
case FSF_DIRECTION_INDICATOR_NOT_VALID:
dev_err(&req->adapter->ccw_device->dev,
- "Invalid data direction (%d) given for unit "
- "0x%016Lx on port 0x%016Lx, shutting down "
- "adapter.\n",
+ "Incorrect direction %d, unit 0x%016Lx on port "
+ "0x%016Lx closed\n",
req->qtcb->bottom.io.data_direction,
- unit->fcp_lun, unit->port->wwpn);
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 133, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_CMND_LENGTH_NOT_VALID:
dev_err(&req->adapter->ccw_device->dev,
- "An invalid control-data-block length field (%d) "
- "was found in a command for unit 0x%016Lx on port "
- "0x%016Lx. Shutting down adapter.\n",
+ "Incorrect CDB length %d, unit 0x%016Lx on "
+ "port 0x%016Lx closed\n",
req->qtcb->bottom.io.fcp_cmnd_length,
- unit->fcp_lun, unit->port->wwpn);
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_adapter_shutdown(unit->port->adapter, 0, 134, req);
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -2201,6 +2247,20 @@ skip_fsfstatus:
}
}
+static void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, u32 fcp_dl)
+{
+ u32 *fcp_dl_ptr;
+
+ /*
+ * fcp_dl_addr = start address of fcp_cmnd structure +
+ * size of fixed part + size of dynamically sized add_dcp_cdb field
+ * SEE FCP-2 documentation
+ */
+ fcp_dl_ptr = (u32 *) ((unsigned char *) &fcp_cmd[1] +
+ (fcp_cmd->add_fcp_cdb_length << 2));
+ *fcp_dl_ptr = fcp_dl;
+}
+
/**
* zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
* @adapter: adapter where scsi command is issued
@@ -2223,12 +2283,12 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
ZFCP_STATUS_COMMON_UNBLOCKED)))
return -EBUSY;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
adapter->pool.fsf_req_scsi);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = PTR_ERR(req);
goto out;
}
@@ -2286,7 +2346,7 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
memcpy(fcp_cmnd_iu->fcp_cdb, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
- fcp_cmnd_iu->add_fcp_cdb_length + sizeof(fcp_dl_t);
+ fcp_cmnd_iu->add_fcp_cdb_length + sizeof(u32);
real_bytes = zfcp_qdio_sbals_from_sg(req, sbtype,
scsi_sglist(scsi_cmnd),
@@ -2296,10 +2356,10 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
retval = -EIO;
else {
dev_err(&adapter->ccw_device->dev,
- "SCSI request too large. "
- "Shutting down unit 0x%016Lx on port "
- "0x%016Lx.\n", unit->fcp_lun,
- unit->port->wwpn);
+ "Oversize data package, unit 0x%016Lx "
+ "on port 0x%016Lx closed\n",
+ (unsigned long long)unit->fcp_lun,
+ (unsigned long long)unit->port->wwpn);
zfcp_erp_unit_shutdown(unit, 0, 131, req);
retval = -EINVAL;
}
@@ -2322,7 +2382,7 @@ failed_scsi_cmnd:
zfcp_fsf_req_free(req);
scsi_cmnd->host_scribble = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return retval;
}
@@ -2338,7 +2398,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
struct zfcp_unit *unit,
u8 tm_flags, int req_flags)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
struct fcp_cmnd_iu *fcp_cmnd_iu;
@@ -2346,12 +2406,12 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
ZFCP_STATUS_COMMON_UNBLOCKED)))
return NULL;
- spin_lock(&adapter->req_q.lock);
- if (!atomic_read(&adapter->req_q.count))
+ spin_lock(&adapter->req_q_lock);
+ if (!zfcp_fsf_sbal_available(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags,
adapter->pool.fsf_req_scsi);
- if (unlikely(IS_ERR(req)))
+ if (IS_ERR(req))
goto out;
req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
@@ -2362,7 +2422,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
req->qtcb->bottom.io.service_class = FSF_CLASS_3;
req->qtcb->bottom.io.fcp_cmnd_length = sizeof(struct fcp_cmnd_iu) +
- sizeof(fcp_dl_t);
+ sizeof(u32);
sbale = zfcp_qdio_sbale_req(req);
sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE;
@@ -2379,7 +2439,7 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter,
zfcp_fsf_req_free(req);
req = NULL;
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock(&adapter->req_q_lock);
return req;
}
@@ -2398,7 +2458,7 @@ static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_fsf_cfdc *fsf_cfdc)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *req = NULL;
struct fsf_qtcb_bottom_support *bottom;
int direction, retval = -EIO, bytes;
@@ -2417,12 +2477,12 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
return ERR_PTR(-EINVAL);
}
- spin_lock(&adapter->req_q.lock);
+ spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
goto out;
req = zfcp_fsf_req_create(adapter, fsf_cfdc->command, 0, NULL);
- if (unlikely(IS_ERR(req))) {
+ if (IS_ERR(req)) {
retval = -EPERM;
goto out;
}
@@ -2447,7 +2507,7 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
out:
- spin_unlock(&adapter->req_q.lock);
+ spin_unlock_bh(&adapter->req_q_lock);
if (!retval) {
wait_event(req->completion_wq,
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index bf94b4da076..fd3a88777ac 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -71,13 +71,6 @@
#define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED 0x00000041
#define FSF_ELS_COMMAND_REJECTED 0x00000050
#define FSF_GENERIC_COMMAND_REJECTED 0x00000051
-#define FSF_OPERATION_PARTIALLY_SUCCESSFUL 0x00000052
-#define FSF_AUTHORIZATION_FAILURE 0x00000053
-#define FSF_CFDC_ERROR_DETECTED 0x00000054
-#define FSF_CONTROL_FILE_UPDATE_ERROR 0x00000055
-#define FSF_CONTROL_FILE_TOO_LARGE 0x00000056
-#define FSF_ACCESS_CONFLICT_DETECTED 0x00000057
-#define FSF_CONFLICTS_OVERRULED 0x00000058
#define FSF_PORT_BOXED 0x00000059
#define FSF_LUN_BOXED 0x0000005A
#define FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE 0x0000005B
@@ -85,9 +78,7 @@
#define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061
#define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062
#define FSF_SBAL_MISMATCH 0x00000063
-#define FSF_OPEN_PORT_WITHOUT_PRLI 0x00000064
#define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD
-#define FSF_FCP_RSP_AVAILABLE 0x000000AF
#define FSF_UNKNOWN_COMMAND 0x000000E2
#define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3
#define FSF_INVALID_COMMAND_OPTION 0x000000E5
@@ -102,20 +93,9 @@
#define FSF_SQ_RETRY_IF_POSSIBLE 0x02
#define FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED 0x03
#define FSF_SQ_INVOKE_LINK_TEST_PROCEDURE 0x04
-#define FSF_SQ_ULP_PROGRAMMING_ERROR 0x05
#define FSF_SQ_COMMAND_ABORTED 0x06
#define FSF_SQ_NO_RETRY_POSSIBLE 0x07
-/* FSF status qualifier for CFDC commands */
-#define FSF_SQ_CFDC_HARDENED_ON_SE 0x00000000
-#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE 0x00000001
-#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2 0x00000002
-/* CFDC subtable codes */
-#define FSF_SQ_CFDC_SUBTABLE_OS 0x0001
-#define FSF_SQ_CFDC_SUBTABLE_PORT_WWPN 0x0002
-#define FSF_SQ_CFDC_SUBTABLE_PORT_DID 0x0003
-#define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004
-
/* FSF status qualifier (most significant 4 bytes), local link down */
#define FSF_PSQ_LINK_NO_LIGHT 0x00000004
#define FSF_PSQ_LINK_WRAP_PLUG 0x00000008
@@ -145,7 +125,6 @@
#define FSF_STATUS_READ_LINK_UP 0x00000006
#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009
#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
-#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C
/* status subtypes in status read buffer */
@@ -159,20 +138,9 @@
/* status subtypes for unsolicited status notification lost */
#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001
-#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002
-#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004
-#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008
-#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010
#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020
-#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040
-#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
-
-/* status subtypes for CFDC */
-#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
-#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
/* topologie that is detected by the adapter */
-#define FSF_TOPO_ERROR 0x00000000
#define FSF_TOPO_P2P 0x00000001
#define FSF_TOPO_FABRIC 0x00000002
#define FSF_TOPO_AL 0x00000003
@@ -180,17 +148,13 @@
/* data direction for FCP commands */
#define FSF_DATADIR_WRITE 0x00000001
#define FSF_DATADIR_READ 0x00000002
-#define FSF_DATADIR_READ_WRITE 0x00000003
#define FSF_DATADIR_CMND 0x00000004
/* fc service class */
-#define FSF_CLASS_1 0x00000001
-#define FSF_CLASS_2 0x00000002
#define FSF_CLASS_3 0x00000003
/* SBAL chaining */
#define FSF_MAX_SBALS_PER_REQ 36
-#define FSF_MAX_SBALS_PER_ELS_REQ 2
/* logging space behind QTCB */
#define FSF_QTCB_LOG_SIZE 1024
@@ -200,50 +164,16 @@
#define FSF_FEATURE_LUN_SHARING 0x00000004
#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
-#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
/* host connection features */
#define FSF_FEATURE_NPIV_MODE 0x00000001
-#define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002
/* option */
#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001
-#define FSF_OPEN_LUN_REPLICATE_SENSE 0x00000002
-
-/* adapter types */
-#define FSF_ADAPTER_TYPE_FICON 0x00000001
-#define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002
-
-/* port types */
-#define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001
-#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003
-#define FSF_HBA_PORTTYPE_NPORT 0x00000005
-#define FSF_HBA_PORTTYPE_PTP 0x00000021
-/* following are not defined and used by FSF Spec
- but are additionally defined by FC-HBA */
-#define FSF_HBA_PORTTYPE_OTHER 0x00000002
-#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003
-#define FSF_HBA_PORTTYPE_NLPORT 0x00000006
-#define FSF_HBA_PORTTYPE_FLPORT 0x00000007
-#define FSF_HBA_PORTTYPE_FPORT 0x00000008
-#define FSF_HBA_PORTTYPE_LPORT 0x00000020
-
-/* port states */
-#define FSF_HBA_PORTSTATE_UNKNOWN 0x00000001
-#define FSF_HBA_PORTSTATE_ONLINE 0x00000002
-#define FSF_HBA_PORTSTATE_OFFLINE 0x00000003
-#define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006
-#define FSF_HBA_PORTSTATE_ERROR 0x00000007
-
-/* IO states of adapter */
-#define FSF_IOSTAT_NPORT_RJT 0x00000004
-#define FSF_IOSTAT_FABRIC_RJT 0x00000005
-#define FSF_IOSTAT_LS_RJT 0x00000009
/* open LUN access flags*/
-#define FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED 0x01000000
#define FSF_UNIT_ACCESS_EXCLUSIVE 0x02000000
#define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER 0x10000000
@@ -265,11 +195,6 @@ struct fsf_queue_designator {
u32 res1;
} __attribute__ ((packed));
-struct fsf_port_closed_payload {
- struct fsf_queue_designator queue_designator;
- u32 port_handle;
-} __attribute__ ((packed));
-
struct fsf_bit_error_payload {
u32 res1;
u32 link_failure_error_count;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index d6dbd653fde..3e05080e62d 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -28,7 +28,7 @@ static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
return 0;
}
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
{
return &q->sbal[sbal_idx]->element[sbale_idx];
@@ -57,7 +57,7 @@ void zfcp_qdio_free(struct zfcp_adapter *adapter)
static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id)
{
- dev_warn(&adapter->ccw_device->dev, "QDIO problem occurred.\n");
+ dev_warn(&adapter->ccw_device->dev, "A QDIO problem occurred\n");
zfcp_erp_adapter_reopen(adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
@@ -145,7 +145,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
{
struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
struct zfcp_qdio_queue *queue = &adapter->resp_q;
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int sbal_idx, sbale_idx, sbal_no;
if (unlikely(qdio_err)) {
@@ -174,8 +174,8 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
dev_warn(&adapter->ccw_device->dev,
- "Protocol violation by adapter. "
- "Continuing operations.\n");
+ "A QDIO protocol error occurred, "
+ "operations continue\n");
}
/*
@@ -190,8 +190,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
* @fsf_req: pointer to struct fsf_req
* Returns: pointer to qdio_buffer_element (SBALE) structure
*/
-volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
{
return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0);
}
@@ -201,8 +200,7 @@ zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
* @fsf_req: pointer to struct fsf_req
* Returns: pointer to qdio_buffer_element (SBALE) structure
*/
-volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
+struct qdio_buffer_element *zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
{
return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last,
req->sbale_curr);
@@ -216,10 +214,10 @@ static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
% QDIO_MAX_BUFFERS_PER_Q;
}
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
/* set last entry flag in current SBALE of current SBAL */
sbale = zfcp_qdio_sbale_curr(fsf_req);
@@ -250,7 +248,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
return sbale;
}
-static volatile struct qdio_buffer_element *
+static struct qdio_buffer_element *
zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
{
if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
@@ -273,7 +271,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
unsigned int sbtype, void *start_addr,
unsigned int total_length)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
unsigned long remaining, length;
void *addr;
@@ -282,6 +280,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
addr += length, remaining -= length) {
sbale = zfcp_qdio_sbale_next(fsf_req, sbtype);
if (!sbale) {
+ atomic_inc(&fsf_req->adapter->qdio_outb_full);
zfcp_qdio_undo_sbals(fsf_req);
return -EINVAL;
}
@@ -307,7 +306,7 @@ static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
struct scatterlist *sg, int max_sbals)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int retval, bytes = 0;
/* figure out last allowed SBAL */
@@ -344,10 +343,10 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
int first = fsf_req->sbal_first;
int count = fsf_req->sbal_number;
int retval, pci, pci_batch;
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
/* acknowledgements for transferred buffers */
- pci_batch = req_q->pci_batch + count;
+ pci_batch = adapter->req_q_pci_batch + count;
if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) {
pci_batch %= ZFCP_QDIO_PCI_INTERVAL;
pci = first + count - (pci_batch + 1);
@@ -367,7 +366,7 @@ int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
atomic_sub(count, &req_q->count);
req_q->first += count;
req_q->first %= QDIO_MAX_BUFFERS_PER_Q;
- req_q->pci_batch = pci_batch;
+ adapter->req_q_pci_batch = pci_batch;
return 0;
}
@@ -418,14 +417,14 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
struct zfcp_qdio_queue *req_q;
int first, count;
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+ if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP))
return;
/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
req_q = &adapter->req_q;
- spin_lock(&req_q->lock);
+ spin_lock_bh(&adapter->req_q_lock);
atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
- spin_unlock(&req_q->lock);
+ spin_unlock_bh(&adapter->req_q_lock);
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
@@ -438,7 +437,7 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
}
req_q->first = 0;
atomic_set(&req_q->count, 0);
- req_q->pci_batch = 0;
+ adapter->req_q_pci_batch = 0;
adapter->resp_q.first = 0;
atomic_set(&adapter->resp_q.count, 0);
}
@@ -450,23 +449,17 @@ void zfcp_qdio_close(struct zfcp_adapter *adapter)
*/
int zfcp_qdio_open(struct zfcp_adapter *adapter)
{
- volatile struct qdio_buffer_element *sbale;
+ struct qdio_buffer_element *sbale;
int cc;
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+ if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)
return -EIO;
- if (qdio_establish(&adapter->qdio_init_data)) {
- dev_err(&adapter->ccw_device->dev,
- "Establish of QDIO queues failed.\n");
- return -EIO;
- }
+ if (qdio_establish(&adapter->qdio_init_data))
+ goto failed_establish;
- if (qdio_activate(adapter->ccw_device)) {
- dev_err(&adapter->ccw_device->dev,
- "Activate of QDIO queues failed.\n");
+ if (qdio_activate(adapter->ccw_device))
goto failed_qdio;
- }
for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
sbale = &(adapter->resp_q.sbal[cc]->element[0]);
@@ -476,20 +469,20 @@ int zfcp_qdio_open(struct zfcp_adapter *adapter)
}
if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0,
- QDIO_MAX_BUFFERS_PER_Q)) {
- dev_err(&adapter->ccw_device->dev,
- "Init of QDIO response queue failed.\n");
+ QDIO_MAX_BUFFERS_PER_Q))
goto failed_qdio;
- }
/* set index of first avalable SBALS / number of available SBALS */
adapter->req_q.first = 0;
atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
- adapter->req_q.pci_batch = 0;
+ adapter->req_q_pci_batch = 0;
return 0;
failed_qdio:
qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR);
+failed_establish:
+ dev_err(&adapter->ccw_device->dev,
+ "Setting up the QDIO connection to the FCP adapter failed\n");
return -EIO;
}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index aeae56b00b4..ca8f85f3dad 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -21,20 +21,6 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
return fcp_sns_info_ptr;
}
-void zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl)
-{
- fcp_dl_t *fcp_dl_ptr;
-
- /*
- * fcp_dl_addr = start address of fcp_cmnd structure +
- * size of fixed part + size of dynamically sized add_dcp_cdb field
- * SEE FCP-2 documentation
- */
- fcp_dl_ptr = (fcp_dl_t *) ((unsigned char *) &fcp_cmd[1] +
- (fcp_cmd->add_fcp_cdb_length << 2));
- *fcp_dl_ptr = fcp_dl;
-}
-
static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
{
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
@@ -119,13 +105,17 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter,
{
struct zfcp_port *port;
struct zfcp_unit *unit;
+ int scsi_lun;
list_for_each_entry(port, &adapter->port_list_head, list) {
if (!port->rport || (id != port->rport->scsi_target_id))
continue;
- list_for_each_entry(unit, &port->unit_list_head, list)
- if (lun == unit->scsi_lun)
+ list_for_each_entry(unit, &port->unit_list_head, list) {
+ scsi_lun = scsilun_to_int(
+ (struct scsi_lun *)&unit->fcp_lun);
+ if (lun == scsi_lun)
return unit;
+ }
}
return NULL;
@@ -183,7 +173,6 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
return retval;
}
fsf_req->data = NULL;
- fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
/* don't access old fsf_req after releasing the abort_lock */
write_unlock_irqrestore(&adapter->abort_lock, flags);
@@ -294,7 +283,8 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
sizeof (struct zfcp_adapter *));
if (!adapter->scsi_host) {
dev_err(&adapter->ccw_device->dev,
- "registration with SCSI stack failed.");
+ "Registering the FCP device with the "
+ "SCSI stack failed\n");
return -EIO;
}
@@ -312,7 +302,6 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
scsi_host_put(adapter->scsi_host);
return -EIO;
}
- atomic_set_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return 0;
}
@@ -336,7 +325,6 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
scsi_remove_host(shost);
scsi_host_put(shost);
adapter->scsi_host = NULL;
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
return;
}
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 2e85c6c49e7..ca9293ba176 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -26,9 +26,9 @@ static ZFCP_DEV_ATTR(_feat, _name, S_IRUGO, \
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, status, "0x%08x\n",
atomic_read(&adapter->status));
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwnn, "0x%016llx\n",
- adapter->peer_wwnn);
+ (unsigned long long) adapter->peer_wwnn);
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_wwpn, "0x%016llx\n",
- adapter->peer_wwpn);
+ (unsigned long long) adapter->peer_wwpn);
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, peer_d_id, "0x%06x\n",
adapter->peer_d_id);
ZFCP_DEFINE_ATTR(zfcp_adapter, adapter, card_version, "0x%04x\n",
@@ -135,8 +135,9 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
{
struct zfcp_adapter *adapter = dev_get_drvdata(dev);
struct zfcp_port *port;
- wwn_t wwpn;
+ u64 wwpn;
int retval = 0;
+ LIST_HEAD(port_remove_lh);
down(&zfcp_data.config_sema);
if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_REMOVE) {
@@ -144,7 +145,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
goto out;
}
- if (strict_strtoull(buf, 0, &wwpn)) {
+ if (strict_strtoull(buf, 0, (unsigned long long *) &wwpn)) {
retval = -EINVAL;
goto out;
}
@@ -154,7 +155,7 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
if (port && (atomic_read(&port->refcount) == 0)) {
zfcp_port_get(port);
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
- list_move(&port->list, &adapter->port_remove_lh);
+ list_move(&port->list, &port_remove_lh);
} else
port = NULL;
write_unlock_irq(&zfcp_data.config_lock);
@@ -200,7 +201,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
{
struct zfcp_port *port = dev_get_drvdata(dev);
struct zfcp_unit *unit;
- fcp_lun_t fcp_lun;
+ u64 fcp_lun;
int retval = -EINVAL;
down(&zfcp_data.config_sema);
@@ -209,7 +210,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
goto out;
}
- if (strict_strtoull(buf, 0, &fcp_lun))
+ if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
goto out;
unit = zfcp_unit_enqueue(port, fcp_lun);
@@ -233,8 +234,9 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
{
struct zfcp_port *port = dev_get_drvdata(dev);
struct zfcp_unit *unit;
- fcp_lun_t fcp_lun;
+ u64 fcp_lun;
int retval = 0;
+ LIST_HEAD(unit_remove_lh);
down(&zfcp_data.config_sema);
if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE) {
@@ -242,7 +244,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
goto out;
}
- if (strict_strtoull(buf, 0, &fcp_lun)) {
+ if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) {
retval = -EINVAL;
goto out;
}
@@ -252,7 +254,7 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev,
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);
+ list_move(&unit->list, &unit_remove_lh);
} else
unit = NULL;
@@ -273,22 +275,7 @@ out:
}
static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
-static struct attribute *zfcp_port_ns_attrs[] = {
- &dev_attr_port_failed.attr,
- &dev_attr_port_in_recovery.attr,
- &dev_attr_port_status.attr,
- &dev_attr_port_access_denied.attr,
- NULL
-};
-
-/**
- * zfcp_sysfs_ns_port_attrs - sysfs attributes for nameserver
- */
-struct attribute_group zfcp_sysfs_ns_port_attrs = {
- .attrs = zfcp_port_ns_attrs,
-};
-
-static struct attribute *zfcp_port_no_ns_attrs[] = {
+static struct attribute *zfcp_port_attrs[] = {
&dev_attr_unit_add.attr,
&dev_attr_unit_remove.attr,
&dev_attr_port_failed.attr,
@@ -302,7 +289,7 @@ static struct attribute *zfcp_port_no_ns_attrs[] = {
* zfcp_sysfs_port_attrs - sysfs attributes for all other ports
*/
struct attribute_group zfcp_sysfs_port_attrs = {
- .attrs = zfcp_port_no_ns_attrs,
+ .attrs = zfcp_port_attrs,
};
static struct attribute *zfcp_unit_attrs[] = {
@@ -394,9 +381,11 @@ static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);
ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n",
- unit->port->adapter->ccw_device->dev.bus_id);
-ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);
-ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);
+ dev_name(&unit->port->adapter->ccw_device->dev));
+ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n",
+ (unsigned long long) unit->port->wwpn);
+ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n",
+ (unsigned long long) unit->fcp_lun);
struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
&dev_attr_fcp_lun,
@@ -487,10 +476,23 @@ ZFCP_SHOST_ATTR(megabytes, "%llu %llu\n",
ZFCP_SHOST_ATTR(seconds_active, "%llu\n",
(unsigned long long) stat_info.seconds_act);
+static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *scsi_host = class_to_shost(dev);
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *) scsi_host->hostdata[0];
+
+ return sprintf(buf, "%d\n", atomic_read(&adapter->qdio_outb_full));
+}
+static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
+
struct device_attribute *zfcp_sysfs_shost_attrs[] = {
&dev_attr_utilization,
&dev_attr_requests,
&dev_attr_megabytes,
&dev_attr_seconds_active,
+ &dev_attr_queue_full,
NULL
};