--- /dev/null
+From: Chris Leech <christopher.leech@intel.com>
+Subject: [FcOE] make fc_disc inline with the fc_lport structure
+References: bnc #459142
+
+The extra memory allocation we're not being checked for failure. Rather than
+further complicating things, just make the discovery code required fields be
+part of the lport structure.
+
+Signed-off-by: Chris Leech <christopher.leech@intel.com>
+Acked-by: Bernhard Walle <bwalle@suse.de>
+---
+
+ drivers/scsi/libfc/fc_disc.c | 80 +++++++-----------------------------------
+ drivers/scsi/libfc/fc_lport.c | 2 -
+ include/scsi/libfc.h | 22 ++++++++++-
+ 3 files changed, 35 insertions(+), 69 deletions(-)
+
+
+--- a/drivers/scsi/libfc/fc_disc.c
++++ b/drivers/scsi/libfc/fc_disc.c
+@@ -45,26 +45,6 @@ static int fc_disc_debug;
+ FC_DBG(fmt); \
+ } while (0)
+
+-struct fc_disc {
+- unsigned char retry_count;
+- unsigned char delay;
+- unsigned char pending;
+- unsigned char requested;
+- unsigned short seq_count;
+- unsigned char buf_len;
+- enum fc_disc_event event;
+-
+- void (*disc_callback)(struct fc_lport *,
+- enum fc_disc_event);
+-
+- struct list_head rports;
+- struct fc_lport *lport;
+- struct mutex disc_mutex;
+- struct fc_gpn_ft_resp partial_buf; /* partial name buffer */
+- struct delayed_work disc_work;
+-
+-};
+-
+ static void fc_disc_gpn_ft_req(struct fc_disc *);
+ static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *);
+ static int fc_disc_new_target(struct fc_disc *, struct fc_rport *,
+@@ -83,14 +63,11 @@ static void fc_disc_restart(struct fc_di
+ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport,
+ u32 port_id)
+ {
+- struct fc_disc *disc = lport->disc;
++ const struct fc_disc *disc = &lport->disc;
+ struct fc_rport *rport, *found = NULL;
+ struct fc_rport_libfc_priv *rdata;
+ int disc_found = 0;
+
+- if (!disc)
+- return NULL;
+-
+ list_for_each_entry(rdata, &disc->rports, peers) {
+ rport = PRIV_TO_RPORT(rdata);
+ if (rport->port_id == port_id) {
+@@ -108,27 +85,6 @@ struct fc_rport *fc_disc_lookup_rport(co
+ }
+
+ /**
+- * fc_disc_alloc - Allocate a discovery work object
+- * @lport: The FC lport associated with the discovery job
+- */
+-static inline struct fc_disc *fc_disc_alloc(struct fc_lport *lport)
+-{
+- struct fc_disc *disc;
+-
+- disc = kzalloc(sizeof(struct fc_disc), GFP_KERNEL);
+- INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
+- mutex_init(&disc->disc_mutex);
+- INIT_LIST_HEAD(&disc->rports);
+-
+- disc->lport = lport;
+- lport->disc = disc;
+- disc->delay = FC_DISC_DELAY;
+- disc->event = DISC_EV_NONE;
+-
+- return disc;
+-}
+-
+-/**
+ * fc_disc_stop_rports - delete all the remote ports associated with the lport
+ * @disc: The discovery job to stop rports on
+ *
+@@ -167,7 +123,7 @@ static void fc_disc_rport_callback(struc
+ enum fc_rport_event event)
+ {
+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
+- struct fc_disc *disc = lport->disc;
++ struct fc_disc *disc = &lport->disc;
+ int found = 0;
+
+ FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event,
+@@ -304,13 +260,7 @@ static void fc_disc_recv_req(struct fc_s
+ struct fc_lport *lport)
+ {
+ u8 op;
+- struct fc_disc *disc = lport->disc;
+-
+- if (!disc) {
+- FC_DBG("Received a request for an lport not managed "
+- "by the discovery engine\n");
+- return;
+- }
++ struct fc_disc *disc = &lport->disc;
+
+ op = fc_frame_payload_op(fp);
+ switch (op) {
+@@ -365,17 +315,7 @@ static void fc_disc_start(void (*disc_ca
+ {
+ struct fc_rport *rport;
+ struct fc_rport_identifiers ids;
+- struct fc_disc *disc = lport->disc;
+-
+- if (!disc) {
+- FC_DEBUG_DISC("No existing discovery job, "
+- "creating one for lport (%6x)\n",
+- fc_host_port_id(lport->host));
+- disc = fc_disc_alloc(lport);
+- } else
+- FC_DEBUG_DISC("Found an existing discovery job "
+- "for lport (%6x)\n",
+- fc_host_port_id(lport->host));
++ struct fc_disc *disc = &lport->disc;
+
+ /*
+ * At this point we may have a new disc job or an existing
+@@ -831,7 +771,7 @@ out:
+ */
+ void fc_disc_stop(struct fc_lport *lport)
+ {
+- struct fc_disc *disc = lport->disc;
++ struct fc_disc *disc = &lport->disc;
+
+ if (disc) {
+ cancel_delayed_work_sync(&disc->disc_work);
+@@ -858,6 +798,7 @@ void fc_disc_stop_final(struct fc_lport
+ */
+ int fc_disc_init(struct fc_lport *lport)
+ {
++ struct fc_disc *disc;
+
+ if (!lport->tt.disc_start)
+ lport->tt.disc_start = fc_disc_start;
+@@ -874,6 +815,15 @@ int fc_disc_init(struct fc_lport *lport)
+ if (!lport->tt.rport_lookup)
+ lport->tt.rport_lookup = fc_disc_lookup_rport;
+
++ disc = &lport->disc;
++ INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
++ mutex_init(&disc->disc_mutex);
++ INIT_LIST_HEAD(&disc->rports);
++
++ disc->lport = lport;
++ disc->delay = FC_DISC_DELAY;
++ disc->event = DISC_EV_NONE;
++
+ return 0;
+ }
+ EXPORT_SYMBOL(fc_disc_init);
+--- a/drivers/scsi/libfc/fc_lport.c
++++ b/drivers/scsi/libfc/fc_lport.c
+@@ -627,8 +627,6 @@ int fc_fabric_logoff(struct fc_lport *lp
+ {
+ lport->tt.disc_stop_final(lport);
+ mutex_lock(&lport->lp_mutex);
+- kfree(lport->disc);
+- lport->disc = NULL;
+ fc_lport_enter_logo(lport);
+ mutex_unlock(&lport->lp_mutex);
+ return 0;
+--- a/include/scsi/libfc.h
++++ b/include/scsi/libfc.h
+@@ -572,7 +572,25 @@ struct libfc_function_template {
+ void (*disc_stop_final) (struct fc_lport *);
+ };
+
+-struct fc_disc;
++/* information used by the discovery layer */
++struct fc_disc {
++ unsigned char retry_count;
++ unsigned char delay;
++ unsigned char pending;
++ unsigned char requested;
++ unsigned short seq_count;
++ unsigned char buf_len;
++ enum fc_disc_event event;
++
++ void (*disc_callback)(struct fc_lport *,
++ enum fc_disc_event);
++
++ struct list_head rports;
++ struct fc_lport *lport;
++ struct mutex disc_mutex;
++ struct fc_gpn_ft_resp partial_buf; /* partial name buffer */
++ struct delayed_work disc_work;
++};
+
+ struct fc_lport {
+ struct list_head list;
+@@ -582,8 +600,8 @@ struct fc_lport {
+ struct fc_exch_mgr *emp;
+ struct fc_rport *dns_rp;
+ struct fc_rport *ptp_rp;
+- struct fc_disc *disc;
+ void *scsi_priv;
++ struct fc_disc disc;
+
+ /* Operational Information */
+ struct libfc_function_template tt;