aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c150
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c45
-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.h179
-rw-r--r--drivers/s390/scsi/zfcp_erp.c229
-rw-r--r--drivers/s390/scsi/zfcp_ext.h27
-rw-r--r--drivers/s390/scsi/zfcp_fc.c227
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c584
-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.c60
13 files changed, 812 insertions, 935 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 90abfd06ed5..24255e42dc3 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);
+ snprintf(unit->sysfs_device.bus_id, BUS_ID_SIZE, "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,9 @@ 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;
- }
+ snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "0x%016llx",
+ (unsigned long long) wwpn);
+ port->sysfs_device.parent = &adapter->ccw_device->dev;
port->sysfs_device.release = zfcp_sysfs_port_release;
dev_set_drvdata(&port->sysfs_device, port);
@@ -700,12 +628,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 +642,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 +660,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 51b6a05f4d1..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);
@@ -156,15 +159,18 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
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);
@@ -220,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..73eb41580f2 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 */
u