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

Commit dc543f9e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull FCoE fixes from Robert Love:
 "Critical patches to fix FCoE VN2VN mode with new interfaces targeting
  3.9-rc"

* tag 'for-3.9-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/rwlove/fcoe:
  libfcoe: Fix fcoe_sysfs VN2VN mode
  libfc, fcoe, bnx2fc: Split fc_disc_init into fc_disc_{init, config}
  libfc, fcoe, bnx2fc: Always use fcoe_disc_init for discovery layer initialization
  fcoe: Fix deadlock between create and destroy paths
  bnx2fc: Make the fcoe_cltr the SCSI host parent
parents 3658f360 0db0e377
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -940,6 +940,7 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
	fc_exch_init(lport);
	fc_exch_init(lport);
	fc_rport_init(lport);
	fc_rport_init(lport);
	fc_disc_init(lport);
	fc_disc_init(lport);
	fc_disc_config(lport, lport);
	return 0;
	return 0;
}
}


@@ -2133,6 +2134,7 @@ static int _bnx2fc_create(struct net_device *netdev,
	}
	}


	ctlr = bnx2fc_to_ctlr(interface);
	ctlr = bnx2fc_to_ctlr(interface);
	cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
	interface->vlan_id = vlan_id;
	interface->vlan_id = vlan_id;


	interface->timer_work_queue =
	interface->timer_work_queue =
@@ -2143,7 +2145,7 @@ static int _bnx2fc_create(struct net_device *netdev,
		goto ifput_err;
		goto ifput_err;
	}
	}


	lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
	lport = bnx2fc_if_create(interface, &cdev->dev, 0);
	if (!lport) {
	if (!lport) {
		printk(KERN_ERR PFX "Failed to create interface (%s)\n",
		printk(KERN_ERR PFX "Failed to create interface (%s)\n",
			netdev->name);
			netdev->name);
@@ -2159,8 +2161,6 @@ static int _bnx2fc_create(struct net_device *netdev,
	/* Make this master N_port */
	/* Make this master N_port */
	ctlr->lp = lport;
	ctlr->lp = lport;


	cdev = fcoe_ctlr_to_ctlr_dev(ctlr);

	if (link_state == BNX2FC_CREATE_LINK_UP)
	if (link_state == BNX2FC_CREATE_LINK_UP)
		cdev->enabled = FCOE_CTLR_ENABLED;
		cdev->enabled = FCOE_CTLR_ENABLED;
	else
	else
+11 −4
Original line number Original line Diff line number Diff line
@@ -490,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
{
	struct net_device *netdev = fcoe->netdev;
	struct net_device *netdev = fcoe->netdev;
	struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
	struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
	struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);


	rtnl_lock();
	rtnl_lock();
	if (!fcoe->removed)
	if (!fcoe->removed)
@@ -501,7 +500,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
	/* tear-down the FCoE controller */
	/* tear-down the FCoE controller */
	fcoe_ctlr_destroy(fip);
	fcoe_ctlr_destroy(fip);
	scsi_host_put(fip->lp->host);
	scsi_host_put(fip->lp->host);
	fcoe_ctlr_device_delete(ctlr_dev);
	dev_put(netdev);
	dev_put(netdev);
	module_put(THIS_MODULE);
	module_put(THIS_MODULE);
}
}
@@ -2194,6 +2192,8 @@ static int fcoe_destroy(struct net_device *netdev)
 */
 */
static void fcoe_destroy_work(struct work_struct *work)
static void fcoe_destroy_work(struct work_struct *work)
{
{
	struct fcoe_ctlr_device *cdev;
	struct fcoe_ctlr *ctlr;
	struct fcoe_port *port;
	struct fcoe_port *port;
	struct fcoe_interface *fcoe;
	struct fcoe_interface *fcoe;
	struct Scsi_Host *shost;
	struct Scsi_Host *shost;
@@ -2224,10 +2224,15 @@ static void fcoe_destroy_work(struct work_struct *work)
	mutex_lock(&fcoe_config_mutex);
	mutex_lock(&fcoe_config_mutex);


	fcoe = port->priv;
	fcoe = port->priv;
	ctlr = fcoe_to_ctlr(fcoe);
	cdev = fcoe_ctlr_to_ctlr_dev(ctlr);

	fcoe_if_destroy(port->lport);
	fcoe_if_destroy(port->lport);
	fcoe_interface_cleanup(fcoe);
	fcoe_interface_cleanup(fcoe);


	mutex_unlock(&fcoe_config_mutex);
	mutex_unlock(&fcoe_config_mutex);

	fcoe_ctlr_device_delete(cdev);
}
}


/**
/**
@@ -2335,7 +2340,9 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
		rc = -EIO;
		rc = -EIO;
		rtnl_unlock();
		rtnl_unlock();
		fcoe_interface_cleanup(fcoe);
		fcoe_interface_cleanup(fcoe);
		goto out_nortnl;
		mutex_unlock(&fcoe_config_mutex);
		fcoe_ctlr_device_delete(ctlr_dev);
		goto out;
	}
	}


	/* Make this the "master" N_Port */
	/* Make this the "master" N_Port */
@@ -2375,8 +2382,8 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,


out_nodev:
out_nodev:
	rtnl_unlock();
	rtnl_unlock();
out_nortnl:
	mutex_unlock(&fcoe_config_mutex);
	mutex_unlock(&fcoe_config_mutex);
out:
	return rc;
	return rc;
}
}


+46 −14
Original line number Original line Diff line number Diff line
@@ -2814,6 +2814,47 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
		fc_lport_set_local_id(fip->lp, new_port_id);
		fc_lport_set_local_id(fip->lp, new_port_id);
}
}


/**
 * fcoe_ctlr_mode_set() - Set or reset the ctlr's mode
 * @lport: The local port to be (re)configured
 * @fip:   The FCoE controller whose mode is changing
 * @fip_mode: The new fip mode
 *
 * Note that the we shouldn't be changing the libfc discovery settings
 * (fc_disc_config) while an lport is going through the libfc state
 * machine. The mode can only be changed when a fcoe_ctlr device is
 * disabled, so that should ensure that this routine is only called
 * when nothing is happening.
 */
void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip,
			enum fip_state fip_mode)
{
	void *priv;

	WARN_ON(lport->state != LPORT_ST_RESET &&
		lport->state != LPORT_ST_DISABLED);

	if (fip_mode == FIP_MODE_VN2VN) {
		lport->rport_priv_size = sizeof(struct fcoe_rport);
		lport->point_to_multipoint = 1;
		lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
		lport->tt.disc_start = fcoe_ctlr_disc_start;
		lport->tt.disc_stop = fcoe_ctlr_disc_stop;
		lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
		priv = fip;
	} else {
		lport->rport_priv_size = 0;
		lport->point_to_multipoint = 0;
		lport->tt.disc_recv_req = NULL;
		lport->tt.disc_start = NULL;
		lport->tt.disc_stop = NULL;
		lport->tt.disc_stop_final = NULL;
		priv = lport;
	}

	fc_disc_config(lport, priv);
}

/**
/**
 * fcoe_libfc_config() - Sets up libfc related properties for local port
 * fcoe_libfc_config() - Sets up libfc related properties for local port
 * @lport:    The local port to configure libfc for
 * @lport:    The local port to configure libfc for
@@ -2833,21 +2874,9 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
	fc_exch_init(lport);
	fc_exch_init(lport);
	fc_elsct_init(lport);
	fc_elsct_init(lport);
	fc_lport_init(lport);
	fc_lport_init(lport);
	if (fip->mode == FIP_MODE_VN2VN)
		lport->rport_priv_size = sizeof(struct fcoe_rport);
	fc_rport_init(lport);
	fc_rport_init(lport);
	if (fip->mode == FIP_MODE_VN2VN) {
		lport->point_to_multipoint = 1;
		lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
		lport->tt.disc_start = fcoe_ctlr_disc_start;
		lport->tt.disc_stop = fcoe_ctlr_disc_stop;
		lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
		mutex_init(&lport->disc.disc_mutex);
		INIT_LIST_HEAD(&lport->disc.rports);
		lport->disc.priv = fip;
	} else {
	fc_disc_init(lport);
	fc_disc_init(lport);
	}
	fcoe_ctlr_mode_set(lport, fip, fip->mode);
	return 0;
	return 0;
}
}
EXPORT_SYMBOL_GPL(fcoe_libfc_config);
EXPORT_SYMBOL_GPL(fcoe_libfc_config);
@@ -2875,6 +2904,7 @@ EXPORT_SYMBOL(fcoe_fcf_get_selected);
void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
{
{
	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
	struct fc_lport *lport = ctlr->lp;


	mutex_lock(&ctlr->ctlr_mutex);
	mutex_lock(&ctlr->ctlr_mutex);
	switch (ctlr_dev->mode) {
	switch (ctlr_dev->mode) {
@@ -2888,5 +2918,7 @@ void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
	}
	}


	mutex_unlock(&ctlr->ctlr_mutex);
	mutex_unlock(&ctlr->ctlr_mutex);

	fcoe_ctlr_mode_set(lport, ctlr, ctlr->mode);
}
}
EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
+18 −8
Original line number Original line Diff line number Diff line
@@ -712,12 +712,13 @@ static void fc_disc_stop_final(struct fc_lport *lport)
}
}


/**
/**
 * fc_disc_init() - Initialize the discovery layer for a local port
 * fc_disc_config() - Configure the discovery layer for a local port
 * @lport: The local port that needs the discovery layer to be initialized
 * @lport: The local port that needs the discovery layer to be configured
 * @priv: Private data structre for users of the discovery layer
 */
 */
int fc_disc_init(struct fc_lport *lport)
void fc_disc_config(struct fc_lport *lport, void *priv)
{
{
	struct fc_disc *disc;
	struct fc_disc *disc = &lport->disc;


	if (!lport->tt.disc_start)
	if (!lport->tt.disc_start)
		lport->tt.disc_start = fc_disc_start;
		lport->tt.disc_start = fc_disc_start;
@@ -732,12 +733,21 @@ int fc_disc_init(struct fc_lport *lport)
		lport->tt.disc_recv_req = fc_disc_recv_req;
		lport->tt.disc_recv_req = fc_disc_recv_req;


	disc = &lport->disc;
	disc = &lport->disc;

	disc->priv = priv;
}
EXPORT_SYMBOL(fc_disc_config);

/**
 * fc_disc_init() - Initialize the discovery layer for a local port
 * @lport: The local port that needs the discovery layer to be initialized
 */
void fc_disc_init(struct fc_lport *lport)
{
	struct fc_disc *disc = &lport->disc;

	INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
	INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
	mutex_init(&disc->disc_mutex);
	mutex_init(&disc->disc_mutex);
	INIT_LIST_HEAD(&disc->rports);
	INIT_LIST_HEAD(&disc->rports);

	disc->priv = lport;

	return 0;
}
}
EXPORT_SYMBOL(fc_disc_init);
EXPORT_SYMBOL(fc_disc_init);
+2 −1
Original line number Original line Diff line number Diff line
@@ -1074,7 +1074,8 @@ void fc_rport_terminate_io(struct fc_rport *);
/*
/*
 * DISCOVERY LAYER
 * DISCOVERY LAYER
 *****************************/
 *****************************/
int fc_disc_init(struct fc_lport *);
void fc_disc_init(struct fc_lport *);
void fc_disc_config(struct fc_lport *, void *);


static inline struct fc_lport *fc_disc_lport(struct fc_disc *disc)
static inline struct fc_lport *fc_disc_lport(struct fc_disc *disc)
{
{