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

Commit 3859f6a2 authored by Andreas Herrmann's avatar Andreas Herrmann Committed by Linus Torvalds
Browse files

[PATCH] zfcp: add rports to enable scsi_add_device to work again



This patch fixes a severe problem with 2.6.13-rc7.

Due to recent SCSI changes it is not possible to add any LUNs to the zfcp
device driver anymore.  With registration of remote ports this is fixed.

Signed-off-by: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Acked-by: default avatarJames Bottomley <jejb@steeleye.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 729d70f5
Loading
Loading
Loading
Loading
+7 −22
Original line number Diff line number Diff line
@@ -1299,13 +1299,10 @@ struct zfcp_port *
zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
		  u32 d_id)
{
	struct zfcp_port *port, *tmp_port;
	struct zfcp_port *port;
	int check_wwpn;
	scsi_id_t scsi_id;
	int found;

	check_wwpn = !(status & ZFCP_STATUS_PORT_NO_WWPN);

	/*
	 * check that there is no port with this WWPN already in list
	 */
@@ -1388,23 +1385,7 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,

	zfcp_port_get(port);

	scsi_id = 1;
	found = 0;
	write_lock_irq(&zfcp_data.config_lock);
	list_for_each_entry(tmp_port, &adapter->port_list_head, list) {
		if (atomic_test_mask(ZFCP_STATUS_PORT_NO_SCSI_ID,
				     &tmp_port->status))
			continue;
		if (tmp_port->scsi_id != scsi_id) {
			found = 1;
			break;
		}
		scsi_id++;
	}
	port->scsi_id = scsi_id;
	if (found)
		list_add_tail(&port->list, &tmp_port->list);
	else
	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);
@@ -1422,11 +1403,15 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
void
zfcp_port_dequeue(struct zfcp_port *port)
{
	struct fc_port *rport;

	zfcp_port_wait(port);
	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(rport);
	zfcp_adapter_put(port->adapter);
	zfcp_sysfs_port_remove_files(&port->sysfs_device,
				     atomic_read(&port->status));
+10 −0
Original line number Diff line number Diff line
@@ -202,9 +202,19 @@ static int
zfcp_ccw_set_offline(struct ccw_device *ccw_device)
{
	struct zfcp_adapter *adapter;
	struct zfcp_port *port;
	struct fc_port *rport;

	down(&zfcp_data.config_sema);
	adapter = dev_get_drvdata(&ccw_device->dev);
	/* might be racy, but we cannot take config_lock due to the fact that
	   fc_remote_port_delete might sleep */
	list_for_each_entry(port, &adapter->port_list_head, list)
		if (port->rport) {
			rport = port->rport;
			port->rport = NULL;
			fc_remote_port_delete(rport);
		}
	zfcp_erp_adapter_shutdown(adapter, 0);
	zfcp_erp_wait(adapter);
	zfcp_adapter_scsi_unregister(adapter);
+1 −1
Original line number Diff line number Diff line
@@ -906,6 +906,7 @@ struct zfcp_adapter {
 */
struct zfcp_port {
	struct device          sysfs_device;   /* sysfs device */
	struct fc_rport        *rport;         /* rport of fc transport class */
	struct list_head       list;	       /* list of remote ports */
	atomic_t               refcount;       /* reference count */
	wait_queue_head_t      remove_wq;      /* can be used to wait for
@@ -916,7 +917,6 @@ struct zfcp_port {
						  list */
	u32		       units;	       /* # of logical units in list */
	atomic_t	       status;	       /* status of this remote port */
	scsi_id_t	       scsi_id;	       /* own SCSI ID */
	wwn_t		       wwnn;	       /* WWNN if known */
	wwn_t		       wwpn;	       /* WWPN */
	fc_id_t		       d_id;	       /* D_ID */
+22 −3
Original line number Diff line number Diff line
@@ -3360,13 +3360,32 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
		if ((result == ZFCP_ERP_SUCCEEDED)
		    && (!atomic_test_mask(ZFCP_STATUS_UNIT_TEMPORARY,
					  &unit->status))
		    && (!unit->device))
 			scsi_add_device(unit->port->adapter->scsi_host, 0,
 					unit->port->scsi_id, unit->scsi_lun);
		    && !unit->device
		    && port->rport)
 			scsi_add_device(port->adapter->scsi_host, 0,
 					port->rport->scsi_target_id,
					unit->scsi_lun);
		zfcp_unit_put(unit);
		break;
	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
	case ZFCP_ERP_ACTION_REOPEN_PORT:
		if ((result == ZFCP_ERP_SUCCEEDED)
		    && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
					 &port->status)
		    && !port->rport) {
			struct fc_rport_identifiers ids;
			ids.node_name = port->wwnn;
			ids.port_name = port->wwpn;
			ids.port_id = port->d_id;
			ids.roles = FC_RPORT_ROLE_FCP_TARGET;
			port->rport =
				fc_remote_port_add(adapter->scsi_host, 0, &ids);
			if (!port->rport)
				ZFCP_LOG_NORMAL("failed registration of rport"
						"(adapter %s, wwpn=0x%016Lx)\n",
						zfcp_get_busid_by_port(port),
						port->wwpn);
		}
		zfcp_port_put(port);
		break;
	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
				   struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
				  struct timer_list *);
extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions;

Loading