Commit dc543f9e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-3.9-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/rwlove/fcoe

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
...@@ -940,6 +940,7 @@ static int bnx2fc_libfc_config(struct fc_lport *lport) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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
......
...@@ -490,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
...@@ -2814,6 +2814,47 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) ...@@ -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, ...@@ -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); ...@@ -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) ...@@ -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);
...@@ -712,12 +712,13 @@ static void fc_disc_stop_final(struct fc_lport *lport) ...@@ -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) ...@@ -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);
...@@ -1074,7 +1074,8 @@ void fc_rport_terminate_io(struct fc_rport *); ...@@ -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)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment