- patches.fixes/fcoe-fix-offload-feature-flag-change: fcoe:
fix offload feature flag change from netdev (bnc#650116).
- patches.fixes/fcoe-sync-with-upstream-patches: Fix kABI.
- patches.fixes/libfc-call-fc_remote_port_chkready-under-the-host-lock:
libfc: call fc_remote_port_chkready under the host lock
(bnc#650116).
- patches.fixes/libfc-do-not-return-error-from-fc_fcp_send_abort:
libfc: do not return error from fc_fcp_send_abort with null
seq_ptr (bnc#650113).
- patches.fixes/libfc-fix-NULL-pointer-dereference-bug: libfc: fix
NULL pointer dereference bug in fc_fcp_pkt_release (bnc#650113).
- patches.fixes/libfc-fix-setting-of-rport-dev-loss: libfc:
fix setting of rport dev loss (bnc#650116).
suse-commit: b666d35bc0d2b577a93bee153c69f76d52cc760a
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 3323822..23c1520 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -573,6 +573,50 @@
}
/**
+ * fcoe_netdev_features_change - Updates the lport's offload flags based
+ * on the LLD netdev's FCoE feature flags
+ */
+static void fcoe_netdev_features_change(struct fc_lport *lport,
+ struct net_device *netdev)
+{
+ mutex_lock(&lport->lp_mutex);
+
+ if (netdev->features & NETIF_F_SG)
+ lport->sg_supp = 1;
+ else
+ lport->sg_supp = 0;
+
+ if (netdev->features & NETIF_F_FCOE_CRC) {
+ lport->crc_offload = 1;
+ FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
+ } else {
+ lport->crc_offload = 0;
+ }
+
+ if (netdev->features & NETIF_F_FSO) {
+ lport->seq_offload = 1;
+ lport->lso_max = netdev->gso_max_size;
+ FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
+ lport->lso_max);
+ } else {
+ lport->seq_offload = 0;
+ lport->lso_max = 0;
+ }
+
+ if (netdev->fcoe_ddp_xid) {
+ lport->lro_enabled = 1;
+ lport->lro_xid = netdev->fcoe_ddp_xid;
+ FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
+ lport->lro_xid);
+ } else {
+ lport->lro_enabled = 0;
+ lport->lro_xid = 0;
+ }
+
+ mutex_unlock(&lport->lp_mutex);
+}
+
+/**
* fcoe_netdev_config() - Set up net devive for SW FCoE
* @lport: The local port that is associated with the net device
* @netdev: The associated net device
@@ -608,25 +652,8 @@
return -EINVAL;
/* offload features support */
- if (netdev->features & NETIF_F_SG)
- lport->sg_supp = 1;
+ fcoe_netdev_features_change(lport, netdev);
- if (netdev->features & NETIF_F_FCOE_CRC) {
- lport->crc_offload = 1;
- FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
- }
- if (netdev->features & NETIF_F_FSO) {
- lport->seq_offload = 1;
- lport->lso_max = netdev->gso_max_size;
- FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
- lport->lso_max);
- }
- if (netdev->fcoe_ddp_xid) {
- lport->lro_enabled = 1;
- lport->lro_xid = netdev->fcoe_ddp_xid;
- FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
- lport->lro_xid);
- }
skb_queue_head_init(&port->fcoe_pending_queue);
port->fcoe_pending_queue_active = 0;
setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport);
@@ -818,7 +845,6 @@
/* Cleanup the fc_lport */
fc_lport_destroy(lport);
- fc_fcp_destroy(lport);
/* Stop the transmit retry timer */
del_timer_sync(&port->timer);
@@ -840,6 +866,9 @@
fc_remove_host(lport->host);
scsi_remove_host(lport->host);
+ /* Destroy lport scsi_priv */
+ fc_fcp_destroy(lport);
+
/* There are no more rports or I/O, free the EM */
fc_exch_mgr_free(lport);
@@ -1845,6 +1874,9 @@
schedule_work(&port->destroy_work);
goto out;
break;
+ case NETDEV_FEAT_CHANGE:
+ fcoe_netdev_features_change(lport, netdev);
+ break;
default:
FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
"from netdev netlink\n", event);
@@ -2037,8 +2069,8 @@
rc = -ENODEV;
goto out_putdev;
}
- list_del(&fcoe->list);
fcoe_interface_cleanup(fcoe);
+ list_del(&fcoe->list);
/* RTNL mutex is dropped by fcoe_if_destroy */
fcoe_if_destroy(fcoe->ctlr.lp);
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 16c2bc7..1f05519 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -50,7 +50,7 @@
#define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */
static void fcoe_ctlr_timeout(unsigned long);
-static void fcoe_ctlr_timer_work(struct work_struct *);
+static void fcoe_ctlr_link_work(struct work_struct *);
static void fcoe_ctlr_recv_work(struct work_struct *);
static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
@@ -115,7 +115,7 @@
spin_lock_init(&fip->lock);
fip->flogi_oxid = FC_XID_UNKNOWN;
setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
- INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
+ INIT_WORK(&fip->link_work, fcoe_ctlr_link_work);
INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
skb_queue_head_init(&fip->fip_recv_list);
}
@@ -163,7 +163,7 @@
fcoe_ctlr_reset_fcfs(fip);
spin_unlock_bh(&fip->lock);
del_timer_sync(&fip->timer);
- cancel_work_sync(&fip->timer_work);
+ cancel_work_sync(&fip->link_work);
}
EXPORT_SYMBOL(fcoe_ctlr_destroy);
@@ -1275,7 +1275,7 @@
"Starting FCF discovery.\n",
fip->lp->host->host_no);
fip->reset_req = 1;
- schedule_work(&fip->timer_work);
+ schedule_work(&fip->link_work);
}
}
@@ -1301,25 +1301,25 @@
mod_timer(&fip->timer, next_timer);
}
if (fip->send_ctlr_ka || fip->send_port_ka)
- schedule_work(&fip->timer_work);
+ schedule_work(&fip->link_work);
spin_unlock_bh(&fip->lock);
}
/**
- * fcoe_ctlr_timer_work() - Worker thread function for timer work
+ * fcoe_ctlr_link_work() - Worker thread function for link changes
* @work: Handle to a FCoE controller
*
* Sends keep-alives and resets which must not
* be called from the timer directly, since they use a mutex.
*/
-static void fcoe_ctlr_timer_work(struct work_struct *work)
+static void fcoe_ctlr_link_work(struct work_struct *work)
{
struct fcoe_ctlr *fip;
struct fc_lport *vport;
u8 *mac;
int reset;
- fip = container_of(work, struct fcoe_ctlr, timer_work);
+ fip = container_of(work, struct fcoe_ctlr, link_work);
spin_lock_bh(&fip->lock);
reset = fip->reset_req;
fip->reset_req = 0;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index f8d56cb..e29e25c 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -262,7 +262,7 @@
static int fc_fcp_send_abort(struct fc_fcp_pkt *fsp)
{
if (!fsp->seq_ptr)
- return -EINVAL;
+ return 0;
fsp->state |= FC_SRB_ABORT_PENDING;
return fsp->lp->tt.seq_exch_abort(fsp->seq_ptr, 0);
@@ -1800,14 +1800,14 @@
struct fcoe_dev_stats *stats;
lport = shost_priv(sc_cmd->device->host);
- spin_unlock_irq(lport->host->host_lock);
rval = fc_remote_port_chkready(rport);
if (rval) {
sc_cmd->result = rval;
done(sc_cmd);
- goto out;
+ return 0;
}
+ spin_unlock_irq(lport->host->host_lock);
if (!*(struct fc_remote_port **)rport->dd_data) {
/*
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 4632d71..974b07e 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -243,6 +243,17 @@
}
/**
+ * fc_get_host_port_type() - Return the port type of the given Scsi_Host
+ * @shost: The SCSI host whose port type is to be determined
+ */
+void fc_get_host_port_type(struct Scsi_Host *shost)
+{
+ /* TODO - currently just NPORT */
+ fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+}
+EXPORT_SYMBOL(fc_get_host_port_type);
+
+/**
* fc_get_host_port_state() - Return the port state of the given Scsi_Host
* @shost: The SCSI host whose port state is to be determined
*/
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index fd3b17d..c420d81 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -198,9 +198,9 @@
void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
{
if (timeout)
- rport->dev_loss_tmo = timeout + 5;
+ rport->dev_loss_tmo = timeout;
else
- rport->dev_loss_tmo = 30;
+ rport->dev_loss_tmo = 1;
}
EXPORT_SYMBOL(fc_set_rport_loss_tmo);
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 962fa0a..d0959ec 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -834,7 +834,9 @@
u8 retry_count;
/* Fabric information */
+#ifndef __GENKSYMS__
u32 port_id;
+#endif
u64 wwpn;
u64 wwnn;
unsigned int service_params;
@@ -1058,6 +1060,7 @@
* Functions for fc_functions_template
*/
void fc_get_host_speed(struct Scsi_Host *);
+void fc_get_host_port_type(struct Scsi_Host *);
void fc_get_host_port_state(struct Scsi_Host *);
void fc_set_rport_loss_tmo(struct fc_rport *, u32 timeout);
struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *);
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index 86ef554..98b1f21 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -67,7 +67,7 @@
* @port_ka_time: time of next port keep-alive.
* @ctlr_ka_time: time of next controller keep-alive.
* @timer: timer struct used for all delayed events.
- * @timer_work: &work_struct for doing keep-alives and resets.
+ * @link_work: &work_struct for doing FCF selection.
* @recv_work: &work_struct for receiving FIP frames.
* @fip_recv_list: list of received FIP frames.
* @user_mfs: configured maximum FC frame size, including FC header.
@@ -100,12 +100,16 @@
unsigned long port_ka_time;
unsigned long ctlr_ka_time;
struct timer_list timer;
- struct work_struct timer_work;
+ struct work_struct link_work;
struct work_struct recv_work;
struct sk_buff_head fip_recv_list;
u16 user_mfs;
u16 flogi_oxid;
u8 flogi_count;
+#ifdef __GENKSYMS__
+ u8 link;
+ u8 last_link;
+#endif
u8 reset_req;
u8 map_dest;
u8 spma;