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

Commit cc8c2829 authored by Swen Schillig's avatar Swen Schillig Committed by James Bottomley
Browse files

[SCSI] zfcp: Automatically attach remote ports



Automatically attach the remote ports in zfcp when the adapter is set
online. This is done by querying all available ports from the FC
namesever. The scan for remote ports is also triggered by RSCNs and
can be triggered manually with the sysfs attribute 'port_rescan'.

Signed-off-by: default avatarSwen Schillig <swen@vnet.ibm.com>
Signed-off-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 85a82392
Loading
Loading
Loading
Loading
+20 −16
Original line number Diff line number Diff line
@@ -568,6 +568,19 @@ 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 (!port)
		return -ENXIO;
	zfcp_port_put(port);

	return 0;
}

/*
 * Enqueues an adapter at the end of the adapter list in the driver data.
 * All adapter internal structures are set up.
@@ -648,6 +661,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
	/* initialize lock of associated request queue */
	rwlock_init(&adapter->req_q.lock);
	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
	INIT_WORK(&adapter->scan_work, _zfcp_scan_ports_later);

	/* mark adapter unusable as long as sysfs registration is not complete */
	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -673,6 +687,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)

	zfcp_data.adapters++;

	zfcp_nameserver_enqueue(adapter);

	goto out;

 generic_services_failed:
@@ -704,6 +720,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
	int retval = 0;
	unsigned long flags;

	cancel_work_sync(&adapter->scan_work);
	cancel_work_sync(&adapter->stat_work);
	zfcp_adapter_scsi_unregister(adapter);
	device_unregister(&adapter->generic_services);
@@ -816,13 +833,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
			kfree(port);
			return NULL;
		}
		port->d_id = d_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;
	}

	port->d_id = d_id;

	port->sysfs_device.release = zfcp_sysfs_port_release;
	dev_set_drvdata(&port->sysfs_device, port);

@@ -873,21 +892,6 @@ zfcp_port_dequeue(struct zfcp_port *port)
	device_unregister(&port->sysfs_device);
}

/* Enqueues a nameserver port */
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 (!port)
		return -ENXIO;
	zfcp_port_put(port);

	return 0;
}

void zfcp_sg_free_table(struct scatterlist *sg, int count)
{
	int i;
+4 −0
Original line number Diff line number Diff line
@@ -596,6 +596,10 @@ static const char *zfcp_rec_dbf_ids[] = {
	[145]	= "recovery action being processed",
	[146]	= "recovery action ready for next step",
	[147]	= "qdio error inbound",
	[148]   = "nameserver needed for port scan",
	[149]   = "port scan",
	[150]	= "ptp attach",
	[151]   = "port validation failed",
};

static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
+5 −0
Original line number Diff line number Diff line
@@ -282,7 +282,10 @@ struct zfcp_rc_entry {
#define ZFCP_CT_DIRECTORY_SERVICE	0xFC
#define ZFCP_CT_NAME_SERVER		0x02
#define ZFCP_CT_SYNCHRONOUS		0x00
#define ZFCP_CT_SCSI_FCP		0x08
#define ZFCP_CT_UNABLE_TO_PERFORM_CMD	0x09
#define ZFCP_CT_GID_PN			0x0121
#define ZFCP_CT_GPN_FT			0x0172
#define ZFCP_CT_MAX_SIZE		0x1020
#define ZFCP_CT_ACCEPT			0x8002
#define ZFCP_CT_REJECT			0x8001
@@ -311,6 +314,7 @@ struct zfcp_rc_entry {
#define ZFCP_STATUS_COMMON_ERP_INUSE		0x01000000
#define ZFCP_STATUS_COMMON_ACCESS_DENIED	0x00800000
#define ZFCP_STATUS_COMMON_ACCESS_BOXED		0x00400000
#define ZFCP_STATUS_COMMON_NOESC		0x00200000

/* adapter status */
#define ZFCP_STATUS_ADAPTER_QDIOUP		0x00000002
@@ -629,6 +633,7 @@ struct zfcp_adapter {
	struct fc_host_statistics *fc_stats;
	struct fsf_qtcb_bottom_port *stats_reset_data;
	unsigned long		stats_reset;
	struct work_struct	scan_work;
};

/*
+29 −13
Original line number Diff line number Diff line
@@ -1199,6 +1199,10 @@ zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
		zfcp_erp_port_unblock(port);
		break;
	case ZFCP_ERP_FAILED :
		if (atomic_test_mask(ZFCP_STATUS_COMMON_NOESC, &port->status)) {
			zfcp_erp_port_block(port, 0);
			result = ZFCP_ERP_EXIT;
		}
		atomic_inc(&port->erp_counter);
		if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS)
			zfcp_erp_port_failed(port, 22, NULL);
@@ -1607,6 +1611,7 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
		goto failed_openfcp;

	atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &erp_action->adapter->status);
	schedule_work(&erp_action->adapter->scan_work);
	goto out;

 close_only:
@@ -1665,10 +1670,19 @@ zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
	return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
}

static void zfcp_erp_open_ptp_port(struct zfcp_adapter *adapter)
{
	struct zfcp_port *port;
	port = zfcp_port_enqueue(adapter, adapter->peer_wwpn, 0,
				 adapter->peer_d_id);
	if (!port) /* error or port already attached */
		return;
	zfcp_erp_port_reopen_internal(port, 0, 150, NULL);
}

static int
zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
	int retval = ZFCP_ERP_SUCCEEDED;
	int retries;
	int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP;
	struct zfcp_adapter *adapter = erp_action->adapter;
@@ -1682,8 +1696,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
		zfcp_erp_action_to_running(erp_action);
		write_unlock_irq(&adapter->erp_lock);
		if (zfcp_fsf_exchange_config_data(erp_action)) {
			retval = ZFCP_ERP_FAILED;
			break;
			atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
					  &adapter->status);
			return ZFCP_ERP_FAILED;
		}

		/*
@@ -1719,9 +1734,12 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)

	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
			      &adapter->status))
		retval = ZFCP_ERP_FAILED;
		return ZFCP_ERP_FAILED;

	return retval;
	if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
		zfcp_erp_open_ptp_port(adapter);

	return ZFCP_ERP_SUCCEEDED;
}

static int
@@ -1899,15 +1917,13 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
			retval = zfcp_erp_port_strategy_open_port(erp_action);
			break;
		}
		if (!(adapter->nameserver_port)) {
			retval = zfcp_nameserver_enqueue(adapter);
			if (retval != 0) {

		if (!adapter->nameserver_port) {
			dev_err(&adapter->ccw_device->dev,
				"Nameserver port unavailable.\n");
			retval = ZFCP_ERP_FAILED;
			break;
		}
		}
		if (!atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED,
				      &adapter->nameserver_port->status)) {
			/* nameserver port may live again */
+2 −2
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t,
extern void   zfcp_port_dequeue(struct zfcp_port *);
extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
extern void   zfcp_unit_dequeue(struct zfcp_unit *);
extern int zfcp_scan_ports(struct zfcp_adapter *);
extern void _zfcp_scan_ports_later(struct work_struct *work);

/******************************* S/390 IO ************************************/
extern int  zfcp_ccw_register(void);
@@ -97,8 +99,6 @@ extern int zfcp_fc_ns_gid_pn_request(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 int  zfcp_nameserver_enqueue(struct zfcp_adapter *);

/******************************* SCSI ****************************************/
extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
Loading