Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef5bef35 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (37 commits)
  [SCSI] zfcp: fix double dbf id usage
  [SCSI] zfcp: wait on SCSI work to be finished before proceeding with init dev
  [SCSI] zfcp: fix erp list usage without using locks
  [SCSI] zfcp: prevent fc_remote_port_delete calls for unregistered rport
  [SCSI] zfcp: fix deadlock caused by shared work queue tasks
  [SCSI] zfcp: put threshold data in hba trace
  [SCSI] zfcp: Simplify zfcp data structures
  [SCSI] zfcp: Simplify get_adapter_by_busid
  [SCSI] zfcp: remove all typedefs and replace them with standards
  [SCSI] zfcp: attach and release SAN nameserver port on demand
  [SCSI] zfcp: remove unused references, declarations and flags
  [SCSI] zfcp: Update message with input from review
  [SCSI] zfcp: add queue_full sysfs attribute
  [SCSI] scsi_dh: suppress comparison warning
  [SCSI] scsi_dh: add Dell product information into rdac device handler
  [SCSI] qla2xxx: remove the unused SCSI_QLOGIC_FC_FIRMWARE option
  [SCSI] qla2xxx: fix printk format warnings
  [SCSI] qla2xxx: Update version number to 8.02.01-k8.
  [SCSI] qla2xxx: Ignore payload reserved-bits during RSCN processing.
  [SCSI] qla2xxx: Additional residual-count corrections during UNDERRUN handling.
  ...
parents e26feff6 41bfcf90
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -436,6 +436,42 @@ Other:
    was updated to remove all vports for the fc_host as well.


Transport supplied functions
----------------------------

The following functions are supplied by the FC-transport for use by LLDs.

   fc_vport_create - create a vport
   fc_vport_terminate - detach and remove a vport

Details:

/**
 * fc_vport_create - Admin App or LLDD requests creation of a vport
 * @shost:     scsi host the virtual port is connected to.
 * @ids:       The world wide names, FC4 port roles, etc for
 *              the virtual port.
 *
 * Notes:
 *     This routine assumes no locks are held on entry.
 */
struct fc_vport *
fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids)

/**
 * fc_vport_terminate - Admin App or LLDD requests termination of a vport
 * @vport:      fc_vport to be terminated
 *
 * Calls the LLDD vport_delete() function, then deallocates and removes
 * the vport from the shost and object tree.
 *
 * Notes:
 *      This routine assumes no locks are held on entry.
 */
int
fc_vport_terminate(struct fc_vport *vport)


Credits
=======
The following people have contributed to this document:
+7 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <linux/string_helpers.h>

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -532,6 +533,8 @@ static int mmc_blk_probe(struct mmc_card *card)
	struct mmc_blk_data *md;
	int err;

	char cap_str[10];

	/*
	 * Check that the card supports the command class(es) we need.
	 */
@@ -546,10 +549,11 @@ static int mmc_blk_probe(struct mmc_card *card)
	if (err)
		goto out;

	printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
	string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
			cap_str, sizeof(cap_str));
	printk(KERN_INFO "%s: %s %s %s %s\n",
		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
		(unsigned long long)(get_capacity(md->disk) >> 1),
		md->read_only ? "(ro)" : "");
		cap_str, md->read_only ? "(ro)" : "");

	mmc_set_drvdata(card, md);
	add_disk(md->disk);
+32 −118
Original line number Diff line number Diff line
@@ -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 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
 */
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);
	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,10 +628,6 @@ 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);

@@ -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 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn,
 */
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);
}

+34 −11
Original line number Diff line number Diff line
@@ -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;
}
+60 −15
Original line number Diff line number Diff line
@@ -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);
}

Loading