Critical patches to fix FCoE VN2VN mode with new interfaces targeting 3.9-rc
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRUNwyAAoJEEajxTw9cn4H/u8P/RfsrptbQ2buaWmdEaq1NfG6 +UFyFQknsEsNlk/mxBCwwsNcSi6Jj6RuKLo+mTWNmcx4BYudjlD2/bFkaqwqXKGi g5ukpx+0a9jwNDsN6LV55vKqgBRabfIucISil1RFzGS9+vmxudbrk4CWDknDiCRw XGZeuWw6ei0OhZcxzyithwVJvjAqT1MrTpJk9Szo8ufjfkbs1EmSorFHKU92sFsp tGChzoYVUIdAAvrMjnOJtlgtI+c1sq/dIYBq7kDYYsRpqa5YJUo5ZZfPpM0aCCVs hEIq9454d/Ze3QlxlXfDsY/EWCI0HziXV15OmPCDzZ7DtuIvUGgHRAEBuZH8tMBb K09Fh1f5ybFhnnMNEC7f8FKItIZs5AK71+e6S8ots6k5b6RrGFZHkkeL9qwatgIu Jz1CnQYHM4TgOq0WrGLV/CkdG/I7IJIGSFZv4vbHSLhMAugtA2buL4pOvQw5w/jt Bj5ZY/CuKOOD5OcedhwZMRUc0gcSUwQFhp34pOQ6vi9/QVCpkddtM7YwwfT2DTWf YAEMFNPHF0vAm/XD5raaCcYgoCRzh8SsBhqsw9F9xd+SsjxDIvVJZ+d4juOX9Bmk ZaKbAWviNzGzfqUOpXy3t3k8zZRHYLWEt7r4i9AzJ94lQydrAEXTHEb/apm3KWp1 oiyJ/iVx6T4UDhW8jLa0 =3kzY -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
dc543f9e2d
5 changed files with 80 additions and 30 deletions
|
@ -940,6 +940,7 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
|
|||
fc_exch_init(lport);
|
||||
fc_rport_init(lport);
|
||||
fc_disc_init(lport);
|
||||
fc_disc_config(lport, lport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2133,6 +2134,7 @@ static int _bnx2fc_create(struct net_device *netdev,
|
|||
}
|
||||
|
||||
ctlr = bnx2fc_to_ctlr(interface);
|
||||
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
interface->vlan_id = vlan_id;
|
||||
|
||||
interface->timer_work_queue =
|
||||
|
@ -2143,7 +2145,7 @@ static int _bnx2fc_create(struct net_device *netdev,
|
|||
goto ifput_err;
|
||||
}
|
||||
|
||||
lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
|
||||
lport = bnx2fc_if_create(interface, &cdev->dev, 0);
|
||||
if (!lport) {
|
||||
printk(KERN_ERR PFX "Failed to create interface (%s)\n",
|
||||
netdev->name);
|
||||
|
@ -2159,8 +2161,6 @@ static int _bnx2fc_create(struct net_device *netdev,
|
|||
/* Make this master N_port */
|
||||
ctlr->lp = lport;
|
||||
|
||||
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
|
||||
if (link_state == BNX2FC_CREATE_LINK_UP)
|
||||
cdev->enabled = FCOE_CTLR_ENABLED;
|
||||
else
|
||||
|
|
|
@ -490,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
|
|||
{
|
||||
struct net_device *netdev = fcoe->netdev;
|
||||
struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
|
||||
struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
|
||||
|
||||
rtnl_lock();
|
||||
if (!fcoe->removed)
|
||||
|
@ -501,7 +500,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
|
|||
/* tear-down the FCoE controller */
|
||||
fcoe_ctlr_destroy(fip);
|
||||
scsi_host_put(fip->lp->host);
|
||||
fcoe_ctlr_device_delete(ctlr_dev);
|
||||
dev_put(netdev);
|
||||
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)
|
||||
{
|
||||
struct fcoe_ctlr_device *cdev;
|
||||
struct fcoe_ctlr *ctlr;
|
||||
struct fcoe_port *port;
|
||||
struct fcoe_interface *fcoe;
|
||||
struct Scsi_Host *shost;
|
||||
|
@ -2224,10 +2224,15 @@ static void fcoe_destroy_work(struct work_struct *work)
|
|||
mutex_lock(&fcoe_config_mutex);
|
||||
|
||||
fcoe = port->priv;
|
||||
ctlr = fcoe_to_ctlr(fcoe);
|
||||
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
|
||||
fcoe_if_destroy(port->lport);
|
||||
fcoe_interface_cleanup(fcoe);
|
||||
|
||||
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;
|
||||
rtnl_unlock();
|
||||
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 */
|
||||
|
@ -2375,8 +2382,8 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
|
|||
|
||||
out_nodev:
|
||||
rtnl_unlock();
|
||||
out_nortnl:
|
||||
mutex_unlock(&fcoe_config_mutex);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -2814,6 +2814,47 @@ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
|
|||
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
|
||||
* @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_elsct_init(lport);
|
||||
fc_lport_init(lport);
|
||||
if (fip->mode == FIP_MODE_VN2VN)
|
||||
lport->rport_priv_size = sizeof(struct fcoe_rport);
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
|
||||
struct fc_lport *lport = ctlr->lp;
|
||||
|
||||
mutex_lock(&ctlr->ctlr_mutex);
|
||||
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);
|
||||
|
||||
fcoe_ctlr_mode_set(lport, ctlr, ctlr->mode);
|
||||
}
|
||||
EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
|
||||
|
|
|
@ -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
|
||||
* @lport: The local port that needs the discovery layer to be initialized
|
||||
* fc_disc_config() - Configure the discovery layer for a local port
|
||||
* @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)
|
||||
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;
|
||||
|
||||
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);
|
||||
mutex_init(&disc->disc_mutex);
|
||||
INIT_LIST_HEAD(&disc->rports);
|
||||
|
||||
disc->priv = lport;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(fc_disc_init);
|
||||
|
|
|
@ -1074,7 +1074,8 @@ void fc_rport_terminate_io(struct fc_rport *);
|
|||
/*
|
||||
* 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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue