Skip to content

Commit

Permalink
[SCSI] zfcp: Automatically attach remote ports
Browse files Browse the repository at this point in the history
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: Swen Schillig <[email protected]>
Signed-off-by: Christof Schmitt <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
  • Loading branch information
sswen authored and James Bottomley committed Jul 12, 2008
1 parent 85a8239 commit cc8c282
Show file tree
Hide file tree
Showing 8 changed files with 336 additions and 31 deletions.
36 changes: 20 additions & 16 deletions drivers/s390/scsi/zfcp_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand 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);
Expand All @@ -673,6 +687,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)

zfcp_data.adapters++;

zfcp_nameserver_enqueue(adapter);

goto out;

generic_services_failed:
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions drivers/s390/scsi/zfcp_dbf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions drivers/s390/scsi/zfcp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
};

/*
Expand Down
42 changes: 29 additions & 13 deletions drivers/s390/scsi/zfcp_erp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

/*
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1899,14 +1917,12 @@ 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) {
dev_err(&adapter->ccw_device->dev,
"Nameserver port unavailable.\n");
retval = ZFCP_ERP_FAILED;
break;
}

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)) {
Expand Down
4 changes: 2 additions & 2 deletions drivers/s390/scsi/zfcp_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 *);
Expand Down
Loading

0 comments on commit cc8c282

Please sign in to comment.