From: Greg Kroah-Hartman Date: Mon, 8 Oct 2012 18:34:46 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.0.46~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=26fc090feb27d55cdaaa0b4b6b733a195301fe15;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: drm-savage-re-add-busmaster-enable-regression-fix.patch pci-check-p2p-bridge-for-invalid-secondary-subordinate-range.patch scsi-zfcp-adapt-to-new-fc_portspeed-semantics.patch scsi-zfcp-bounds-checking-for-deferred-error-trace.patch scsi-zfcp-do-not-wakeup-while-suspended.patch scsi-zfcp-make-trace-record-tags-unique.patch scsi-zfcp-only-access-zfcp_scsi_dev-for-valid-scsi_device.patch scsi-zfcp-remove-invalid-reference-to-list-iterator-variable.patch scsi-zfcp-restore-refcount-check-on-port_remove.patch --- diff --git a/queue-3.5/drm-savage-re-add-busmaster-enable-regression-fix.patch b/queue-3.5/drm-savage-re-add-busmaster-enable-regression-fix.patch new file mode 100644 index 00000000000..d7cde32d367 --- /dev/null +++ b/queue-3.5/drm-savage-re-add-busmaster-enable-regression-fix.patch @@ -0,0 +1,34 @@ +From df86b5765a48d5f557489577652bd6df145b0e1b Mon Sep 17 00:00:00 2001 +From: Florian Zumbiehl +Date: Tue, 2 Oct 2012 12:20:37 +0000 +Subject: drm/savage: re-add busmaster enable, regression fix + +From: Florian Zumbiehl + +commit df86b5765a48d5f557489577652bd6df145b0e1b upstream. + +466e69b8b03b8c1987367912782bc12988ad8794 dropped busmaster enable from the +global drm code and moved it to the individual drivers, but missed the savage +driver. So, this re-adds busmaster enable to the savage driver, fixing the +regression. + +Signed-off-by: Florian Zumbiehl +Reviewed-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/savage/savage_bci.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/gpu/drm/savage/savage_bci.c ++++ b/drivers/gpu/drm/savage/savage_bci.c +@@ -547,6 +547,8 @@ int savage_driver_load(struct drm_device + + dev_priv->chipset = (enum savage_family)chipset; + ++ pci_set_master(dev->pdev); ++ + return 0; + } + diff --git a/queue-3.5/pci-check-p2p-bridge-for-invalid-secondary-subordinate-range.patch b/queue-3.5/pci-check-p2p-bridge-for-invalid-secondary-subordinate-range.patch new file mode 100644 index 00000000000..6d26652c0d0 --- /dev/null +++ b/queue-3.5/pci-check-p2p-bridge-for-invalid-secondary-subordinate-range.patch @@ -0,0 +1,51 @@ +From 1965f66e7db08d1ebccd24a59043eba826cc1ce8 Mon Sep 17 00:00:00 2001 +From: Yinghai Lu +Date: Mon, 10 Sep 2012 17:19:33 -0700 +Subject: PCI: Check P2P bridge for invalid secondary/subordinate range + +From: Yinghai Lu + +commit 1965f66e7db08d1ebccd24a59043eba826cc1ce8 upstream. + +For bridges with "secondary > subordinate", i.e., invalid bus number +apertures, we don't enumerate anything behind the bridge unless the +user specified "pci=assign-busses". + +This patch makes us automatically try to reassign the downstream bus +numbers in this case (just for that bridge, not for all bridges as +"pci=assign-busses" does). + +We don't discover all the devices on the Intel DP43BF motherboard +without this change (or "pci=assign-busses") because its BIOS configures +a bridge as: + + pci 0000:00:1e.0: PCI bridge to [bus 20-08] (subtractive decode) + +[bhelgaas: changelog, change message to dev_info] +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=18412 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=625754 +Reported-by: Brian C. Huffman +Reported-by: VL +Tested-by: VL +Signed-off-by: Yinghai Lu +Signed-off-by: Bjorn Helgaas + +--- + drivers/pci/probe.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -684,8 +684,10 @@ int __devinit pci_scan_bridge(struct pci + + /* Check if setup is sensible at all */ + if (!pass && +- (primary != bus->number || secondary <= bus->number)) { +- dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); ++ (primary != bus->number || secondary <= bus->number || ++ secondary > subordinate)) { ++ dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n", ++ secondary, subordinate); + broken = 1; + } + diff --git a/queue-3.5/scsi-zfcp-adapt-to-new-fc_portspeed-semantics.patch b/queue-3.5/scsi-zfcp-adapt-to-new-fc_portspeed-semantics.patch new file mode 100644 index 00000000000..e92648456f8 --- /dev/null +++ b/queue-3.5/scsi-zfcp-adapt-to-new-fc_portspeed-semantics.patch @@ -0,0 +1,87 @@ +From d22019778cd9ea04c1dadf7bf453920d5288f8d9 Mon Sep 17 00:00:00 2001 +From: Steffen Maier +Date: Tue, 4 Sep 2012 15:23:29 +0200 +Subject: SCSI: zfcp: Adapt to new FC_PORTSPEED semantics + +From: Steffen Maier + +commit d22019778cd9ea04c1dadf7bf453920d5288f8d9 upstream. + +Commit a9277e7783651d4e0a849f7988340b1c1cf748a4 +"[SCSI] scsi_transport_fc: Getting FC Port Speed in sync with FC-GS" +changed the semantics of FC_PORTSPEED defines to +FDMI port attributes of FC-HBA/SM-HBA +which is different from the previous bit reversed +Report Port Speed Capabilities (RPSC) ELS of FC-GS/FC-LS. + +Zfcp showed "10 Gbit" instead of "4 Gbit" for supported_speeds. +It now uses explicit bit conversion as the other LLDs already +do, in order to be independent of the kernel bit semantics. +See also http://marc.info/?l=linux-scsi&m=134452926830730&w=2 + +Signed-off-by: Steffen Maier +Reviewed-by: Martin Peschke +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_fsf.c | 34 ++++++++++++++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) + +--- a/drivers/s390/scsi/zfcp_fsf.c ++++ b/drivers/s390/scsi/zfcp_fsf.c +@@ -437,6 +437,34 @@ void zfcp_fsf_req_dismiss_all(struct zfc + } + } + ++#define ZFCP_FSF_PORTSPEED_1GBIT (1 << 0) ++#define ZFCP_FSF_PORTSPEED_2GBIT (1 << 1) ++#define ZFCP_FSF_PORTSPEED_4GBIT (1 << 2) ++#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3) ++#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4) ++#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5) ++#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) ++ ++static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) ++{ ++ u32 fdmi_speed = 0; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT) ++ fdmi_speed |= FC_PORTSPEED_1GBIT; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT) ++ fdmi_speed |= FC_PORTSPEED_2GBIT; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT) ++ fdmi_speed |= FC_PORTSPEED_4GBIT; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT) ++ fdmi_speed |= FC_PORTSPEED_10GBIT; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT) ++ fdmi_speed |= FC_PORTSPEED_8GBIT; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT) ++ fdmi_speed |= FC_PORTSPEED_16GBIT; ++ if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED) ++ fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED; ++ return fdmi_speed; ++} ++ + static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) + { + struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; +@@ -456,7 +484,8 @@ static int zfcp_fsf_exchange_config_eval + fc_host_port_name(shost) = nsp->fl_wwpn; + fc_host_node_name(shost) = nsp->fl_wwnn; + fc_host_port_id(shost) = ntoh24(bottom->s_id); +- fc_host_speed(shost) = bottom->fc_link_speed; ++ fc_host_speed(shost) = ++ zfcp_fsf_convert_portspeed(bottom->fc_link_speed); + fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; + + adapter->hydra_version = bottom->adapter_type; +@@ -580,7 +609,8 @@ static void zfcp_fsf_exchange_port_evalu + } else + fc_host_permanent_port_name(shost) = fc_host_port_name(shost); + fc_host_maxframe_size(shost) = bottom->maximum_frame_size; +- fc_host_supported_speeds(shost) = bottom->supported_speed; ++ fc_host_supported_speeds(shost) = ++ zfcp_fsf_convert_portspeed(bottom->supported_speed); + memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, + FC_FC4_LIST_SIZE); + memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, diff --git a/queue-3.5/scsi-zfcp-bounds-checking-for-deferred-error-trace.patch b/queue-3.5/scsi-zfcp-bounds-checking-for-deferred-error-trace.patch new file mode 100644 index 00000000000..30ed56f1e5a --- /dev/null +++ b/queue-3.5/scsi-zfcp-bounds-checking-for-deferred-error-trace.patch @@ -0,0 +1,73 @@ +From 01e60527f0a49b3d7df603010bd6079bb4b6cf07 Mon Sep 17 00:00:00 2001 +From: Steffen Maier +Date: Tue, 4 Sep 2012 15:23:31 +0200 +Subject: SCSI: zfcp: Bounds checking for deferred error trace + +From: Steffen Maier + +commit 01e60527f0a49b3d7df603010bd6079bb4b6cf07 upstream. + +The pl vector has scount elements, i.e. pl[scount-1] is the last valid +element. For maximum sized requests, payload->counter == scount after +the last loop iteration. Therefore, do bounds checking first (with +boolean shortcut) to not access the invalid element pl[scount]. + +Do not trust the maximum sbale->scount value from the HBA +but ensure we won't access the pl vector out of our allocated bounds. +While at it, clean up scoping and prevent unnecessary memset. + +Minor fix for 86a9668a8d29ea711613e1cb37efa68e7c4db564 +"[SCSI] zfcp: support for hardware data router" + +Signed-off-by: Steffen Maier +Reviewed-by: Martin Peschke +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_dbf.c | 2 +- + drivers/s390/scsi/zfcp_qdio.c | 16 ++++++++++------ + 2 files changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/s390/scsi/zfcp_dbf.c ++++ b/drivers/s390/scsi/zfcp_dbf.c +@@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_ad + length = min((u16)sizeof(struct qdio_buffer), + (u16)ZFCP_DBF_PAY_MAX_REC); + +- while ((char *)pl[payload->counter] && payload->counter < scount) { ++ while (payload->counter < scount && (char *)pl[payload->counter]) { + memcpy(payload->data, (char *)pl[payload->counter], length); + debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); + payload->counter++; +--- a/drivers/s390/scsi/zfcp_qdio.c ++++ b/drivers/s390/scsi/zfcp_qdio.c +@@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct cc + { + struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; + struct zfcp_adapter *adapter = qdio->adapter; +- struct qdio_buffer_element *sbale; + int sbal_no, sbal_idx; +- void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; +- u64 req_id; +- u8 scount; + + if (unlikely(qdio_err)) { +- memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); + if (zfcp_adapter_multi_buffer_active(adapter)) { ++ void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; ++ struct qdio_buffer_element *sbale; ++ u64 req_id; ++ u8 scount; ++ ++ memset(pl, 0, ++ ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); + sbale = qdio->res_q[idx]->element; + req_id = (u64) sbale->addr; +- scount = sbale->scount + 1; /* incl. signaling SBAL */ ++ scount = min(sbale->scount + 1, ++ ZFCP_QDIO_MAX_SBALS_PER_REQ + 1); ++ /* incl. signaling SBAL */ + + for (sbal_no = 0; sbal_no < scount; sbal_no++) { + sbal_idx = (idx + sbal_no) % diff --git a/queue-3.5/scsi-zfcp-do-not-wakeup-while-suspended.patch b/queue-3.5/scsi-zfcp-do-not-wakeup-while-suspended.patch new file mode 100644 index 00000000000..62272b649a6 --- /dev/null +++ b/queue-3.5/scsi-zfcp-do-not-wakeup-while-suspended.patch @@ -0,0 +1,264 @@ +From cb45214960bc989af8b911ebd77da541c797717d Mon Sep 17 00:00:00 2001 +From: Steffen Maier +Date: Tue, 4 Sep 2012 15:23:32 +0200 +Subject: SCSI: zfcp: Do not wakeup while suspended + +From: Steffen Maier + +commit cb45214960bc989af8b911ebd77da541c797717d upstream. + +If the mapping of FCP device bus ID and corresponding subchannel +is modified while the Linux image is suspended, the resume of FCP +devices can fail. During resume, zfcp gets callbacks from cio regarding +the modified subchannels but they can be arbitrarily mixed with the +restore/resume callback. Since the cio callbacks would trigger +adapter recovery, zfcp could wakeup before the resume callback. +Therefore, ignore the cio callbacks regarding subchannels while +being suspended. We can safely do so, since zfcp does not deal itself +with subchannels. For problem determination purposes, we still trace the +ignored callback events. + +The following kernel messages could be seen on resume: + +kernel: : parent should not be sleeping + +As part of adapter reopen recovery, zfcp performs auto port scanning +which can erroneously try to register new remote ports with +scsi_transport_fc and the device core code complains about the parent +(adapter) still sleeping. + +kernel: zfcp.3dff9c: :\ + Setting up the QDIO connection to the FCP adapter failed + +kernel: zfcp.574d43: :\ + ERP cannot recover an error on the FCP device + +In such cases, the adapter gave up recovery and remained blocked along +with its child objects: remote ports and LUNs/scsi devices. Even the +adapter shutdown as part of giving up recovery failed because the ccw +device state remained disconnected. Later, the corresponding remote +ports ran into dev_loss_tmo. As a result, the LUNs were erroneously +not available again after resume. + +Even a manually triggered adapter recovery (e.g. sysfs attribute +failed, or device offline/online via sysfs) could not recover the +adapter due to the remaining disconnected state of the corresponding +ccw device. + +Signed-off-by: Steffen Maier +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_ccw.c | 73 +++++++++++++++++++++++++++++++++++++------ + drivers/s390/scsi/zfcp_dbf.c | 20 +++++++++++ + drivers/s390/scsi/zfcp_dbf.h | 1 + drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + 5 files changed, 86 insertions(+), 10 deletions(-) + +--- a/drivers/s390/scsi/zfcp_ccw.c ++++ b/drivers/s390/scsi/zfcp_ccw.c +@@ -39,17 +39,23 @@ void zfcp_ccw_adapter_put(struct zfcp_ad + spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); + } + +-static int zfcp_ccw_activate(struct ccw_device *cdev) +- ++/** ++ * zfcp_ccw_activate - activate adapter and wait for it to finish ++ * @cdev: pointer to belonging ccw device ++ * @clear: Status flags to clear. ++ * @tag: s390dbf trace record tag ++ */ ++static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag) + { + struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); + + if (!adapter) + return 0; + ++ zfcp_erp_clear_adapter_status(adapter, clear); + zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); + zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, +- "ccresu2"); ++ tag); + zfcp_erp_wait(adapter); + flush_work(&adapter->scan_work); + +@@ -164,26 +170,29 @@ static int zfcp_ccw_set_online(struct cc + BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); + adapter->req_no = 0; + +- zfcp_ccw_activate(cdev); ++ zfcp_ccw_activate(cdev, 0, "ccsonl1"); + zfcp_ccw_adapter_put(adapter); + return 0; + } + + /** +- * zfcp_ccw_set_offline - set_offline function of zfcp driver ++ * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish + * @cdev: pointer to belonging ccw device ++ * @set: Status flags to set. ++ * @tag: s390dbf trace record tag + * + * This function gets called by the common i/o layer and sets an adapter + * into state offline. + */ +-static int zfcp_ccw_set_offline(struct ccw_device *cdev) ++static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) + { + struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); + + if (!adapter) + return 0; + +- zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); ++ zfcp_erp_set_adapter_status(adapter, set); ++ zfcp_erp_adapter_shutdown(adapter, 0, tag); + zfcp_erp_wait(adapter); + + zfcp_ccw_adapter_put(adapter); +@@ -191,6 +200,18 @@ static int zfcp_ccw_set_offline(struct c + } + + /** ++ * zfcp_ccw_set_offline - set_offline function of zfcp driver ++ * @cdev: pointer to belonging ccw device ++ * ++ * This function gets called by the common i/o layer and sets an adapter ++ * into state offline. ++ */ ++static int zfcp_ccw_set_offline(struct ccw_device *cdev) ++{ ++ return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); ++} ++ ++/** + * zfcp_ccw_notify - ccw notify function + * @cdev: pointer to belonging ccw device + * @event: indicates if adapter was detached or attached +@@ -207,6 +228,11 @@ static int zfcp_ccw_notify(struct ccw_de + + switch (event) { + case CIO_GONE: ++ if (atomic_read(&adapter->status) & ++ ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ ++ zfcp_dbf_hba_basic("ccnigo1", adapter); ++ break; ++ } + dev_warn(&cdev->dev, "The FCP device has been detached\n"); + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); + break; +@@ -216,6 +242,11 @@ static int zfcp_ccw_notify(struct ccw_de + zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); + break; + case CIO_OPER: ++ if (atomic_read(&adapter->status) & ++ ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ ++ zfcp_dbf_hba_basic("ccniop1", adapter); ++ break; ++ } + dev_info(&cdev->dev, "The FCP device is operational again\n"); + zfcp_erp_set_adapter_status(adapter, + ZFCP_STATUS_COMMON_RUNNING); +@@ -251,6 +282,28 @@ static void zfcp_ccw_shutdown(struct ccw + zfcp_ccw_adapter_put(adapter); + } + ++static int zfcp_ccw_suspend(struct ccw_device *cdev) ++{ ++ zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); ++ return 0; ++} ++ ++static int zfcp_ccw_thaw(struct ccw_device *cdev) ++{ ++ /* trace records for thaw and final shutdown during suspend ++ can only be found in system dump until the end of suspend ++ but not after resume because it's based on the memory image ++ right after the very first suspend (freeze) callback */ ++ zfcp_ccw_activate(cdev, 0, "ccthaw1"); ++ return 0; ++} ++ ++static int zfcp_ccw_resume(struct ccw_device *cdev) ++{ ++ zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); ++ return 0; ++} ++ + struct ccw_driver zfcp_ccw_driver = { + .driver = { + .owner = THIS_MODULE, +@@ -263,7 +316,7 @@ struct ccw_driver zfcp_ccw_driver = { + .set_offline = zfcp_ccw_set_offline, + .notify = zfcp_ccw_notify, + .shutdown = zfcp_ccw_shutdown, +- .freeze = zfcp_ccw_set_offline, +- .thaw = zfcp_ccw_activate, +- .restore = zfcp_ccw_activate, ++ .freeze = zfcp_ccw_suspend, ++ .thaw = zfcp_ccw_thaw, ++ .restore = zfcp_ccw_resume, + }; +--- a/drivers/s390/scsi/zfcp_dbf.c ++++ b/drivers/s390/scsi/zfcp_dbf.c +@@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_ad + spin_unlock_irqrestore(&dbf->pay_lock, flags); + } + ++/** ++ * zfcp_dbf_hba_basic - trace event for basic adapter events ++ * @adapter: pointer to struct zfcp_adapter ++ */ ++void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) ++{ ++ struct zfcp_dbf *dbf = adapter->dbf; ++ struct zfcp_dbf_hba *rec = &dbf->hba_buf; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dbf->hba_lock, flags); ++ memset(rec, 0, sizeof(*rec)); ++ ++ memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); ++ rec->id = ZFCP_DBF_HBA_BASIC; ++ ++ debug_event(dbf->hba, 1, rec, sizeof(*rec)); ++ spin_unlock_irqrestore(&dbf->hba_lock, flags); ++} ++ + static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, + struct zfcp_adapter *adapter, + struct zfcp_port *port, +--- a/drivers/s390/scsi/zfcp_dbf.h ++++ b/drivers/s390/scsi/zfcp_dbf.h +@@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id { + ZFCP_DBF_HBA_RES = 1, + ZFCP_DBF_HBA_USS = 2, + ZFCP_DBF_HBA_BIT = 3, ++ ZFCP_DBF_HBA_BASIC = 4, + }; + + /** +--- a/drivers/s390/scsi/zfcp_def.h ++++ b/drivers/s390/scsi/zfcp_def.h +@@ -77,6 +77,7 @@ struct zfcp_reqlist; + #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 + #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 + #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 ++#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 + #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 + #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 + #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 +--- a/drivers/s390/scsi/zfcp_ext.h ++++ b/drivers/s390/scsi/zfcp_ext.h +@@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, + extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); + extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); + extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); ++extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); + extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); + extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); + extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); diff --git a/queue-3.5/scsi-zfcp-make-trace-record-tags-unique.patch b/queue-3.5/scsi-zfcp-make-trace-record-tags-unique.patch new file mode 100644 index 00000000000..c6ae3d54847 --- /dev/null +++ b/queue-3.5/scsi-zfcp-make-trace-record-tags-unique.patch @@ -0,0 +1,47 @@ +From 0100998dbfe6dfcd90a6e912ca7ed6f255d48f25 Mon Sep 17 00:00:00 2001 +From: Steffen Maier +Date: Tue, 4 Sep 2012 15:23:30 +0200 +Subject: SCSI: zfcp: Make trace record tags unique + +From: Steffen Maier + +commit 0100998dbfe6dfcd90a6e912ca7ed6f255d48f25 upstream. + +Duplicate fssrh_2 from a54ca0f62f953898b05549391ac2a8a4dad6482b +"[SCSI] zfcp: Redesign of the debug tracing for HBA records." +complicates distinction of generic status read response from +local link up. +Duplicate fsscth1 from 2c55b750a884b86dea8b4cc5f15e1484cc47a25c +"[SCSI] zfcp: Redesign of the debug tracing for SAN records." +complicates distinction of good common transport response from +invalid port handle. + +Signed-off-by: Steffen Maier +Reviewed-by: Martin Peschke +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_fsf.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/s390/scsi/zfcp_fsf.c ++++ b/drivers/s390/scsi/zfcp_fsf.c +@@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler + return; + } + +- zfcp_dbf_hba_fsf_uss("fssrh_2", req); ++ zfcp_dbf_hba_fsf_uss("fssrh_4", req); + + switch (sr_buf->status_type) { + case FSF_STATUS_READ_PORT_CLOSED: +@@ -915,7 +915,7 @@ static void zfcp_fsf_send_ct_handler(str + + switch (header->fsf_status) { + case FSF_GOOD: +- zfcp_dbf_san_res("fsscth1", req); ++ zfcp_dbf_san_res("fsscth2", req); + ct->status = 0; + break; + case FSF_SERVICE_CLASS_NOT_SUPPORTED: diff --git a/queue-3.5/scsi-zfcp-only-access-zfcp_scsi_dev-for-valid-scsi_device.patch b/queue-3.5/scsi-zfcp-only-access-zfcp_scsi_dev-for-valid-scsi_device.patch new file mode 100644 index 00000000000..a53f1d4a1ee --- /dev/null +++ b/queue-3.5/scsi-zfcp-only-access-zfcp_scsi_dev-for-valid-scsi_device.patch @@ -0,0 +1,123 @@ +From d436de8ce25f53a8a880a931886821f632247943 Mon Sep 17 00:00:00 2001 +From: Martin Peschke +Date: Tue, 4 Sep 2012 15:23:36 +0200 +Subject: SCSI: zfcp: only access zfcp_scsi_dev for valid scsi_device + +From: Martin Peschke + +commit d436de8ce25f53a8a880a931886821f632247943 upstream. + +__scsi_remove_device (e.g. due to dev_loss_tmo) calls +zfcp_scsi_slave_destroy which in turn sends a close LUN FSF request to +the adapter. After 30 seconds without response, +zfcp_erp_timeout_handler kicks the ERP thread failing the close LUN +ERP action. zfcp_erp_wait in zfcp_erp_lun_shutdown_wait and thus +zfcp_scsi_slave_destroy returns and then scsi_device is no longer +valid. Sometime later the response to the close LUN FSF request may +finally come in. However, commit +b62a8d9b45b971a67a0f8413338c230e3117dff5 +"[SCSI] zfcp: Use SCSI device data zfcp_scsi_dev instead of zfcp_unit" +introduced a number of attempts to unconditionally access struct +zfcp_scsi_dev through struct scsi_device causing a use-after-free. +This leads to an Oops due to kernel page fault in one of: +zfcp_fsf_abort_fcp_command_handler, zfcp_fsf_open_lun_handler, +zfcp_fsf_close_lun_handler, zfcp_fsf_req_trace, +zfcp_fsf_fcp_handler_common. +Move dereferencing of zfcp private data zfcp_scsi_dev allocated in +scsi_device via scsi_transport_reserve_device after the check for +potentially aborted FSF request and thus no longer valid scsi_device. +Only then assign sdev_to_zfcp(sdev) to the local auto variable struct +zfcp_scsi_dev *zfcp_sdev. + +Signed-off-by: Martin Peschke +Signed-off-by: Steffen Maier +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_fsf.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/drivers/s390/scsi/zfcp_fsf.c ++++ b/drivers/s390/scsi/zfcp_fsf.c +@@ -801,12 +801,14 @@ out: + static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) + { + struct scsi_device *sdev = req->data; +- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); ++ struct zfcp_scsi_dev *zfcp_sdev; + union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; + + if (req->status & ZFCP_STATUS_FSFREQ_ERROR) + return; + ++ zfcp_sdev = sdev_to_zfcp(sdev); ++ + switch (req->qtcb->header.fsf_status) { + case FSF_PORT_HANDLE_NOT_VALID: + if (fsq->word[0] == fsq->word[1]) { +@@ -1769,13 +1771,15 @@ static void zfcp_fsf_open_lun_handler(st + { + struct zfcp_adapter *adapter = req->adapter; + struct scsi_device *sdev = req->data; +- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); ++ struct zfcp_scsi_dev *zfcp_sdev; + struct fsf_qtcb_header *header = &req->qtcb->header; + struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; + + if (req->status & ZFCP_STATUS_FSFREQ_ERROR) + return; + ++ zfcp_sdev = sdev_to_zfcp(sdev); ++ + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | + ZFCP_STATUS_COMMON_ACCESS_BOXED | + ZFCP_STATUS_LUN_SHARED | +@@ -1886,11 +1890,13 @@ out: + static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) + { + struct scsi_device *sdev = req->data; +- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); ++ struct zfcp_scsi_dev *zfcp_sdev; + + if (req->status & ZFCP_STATUS_FSFREQ_ERROR) + return; + ++ zfcp_sdev = sdev_to_zfcp(sdev); ++ + switch (req->qtcb->header.fsf_status) { + case FSF_PORT_HANDLE_NOT_VALID: + zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); +@@ -1980,7 +1986,7 @@ static void zfcp_fsf_req_trace(struct zf + { + struct fsf_qual_latency_info *lat_in; + struct latency_cont *lat = NULL; +- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); ++ struct zfcp_scsi_dev *zfcp_sdev; + struct zfcp_blk_drv_data blktrc; + int ticks = req->adapter->timer_ticks; + +@@ -1995,6 +2001,7 @@ static void zfcp_fsf_req_trace(struct zf + + if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && + !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { ++ zfcp_sdev = sdev_to_zfcp(scsi->device); + blktrc.flags |= ZFCP_BLK_LAT_VALID; + blktrc.channel_lat = lat_in->channel_lat * ticks; + blktrc.fabric_lat = lat_in->fabric_lat * ticks; +@@ -2032,12 +2039,14 @@ static void zfcp_fsf_fcp_handler_common( + { + struct scsi_cmnd *scmnd = req->data; + struct scsi_device *sdev = scmnd->device; +- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); ++ struct zfcp_scsi_dev *zfcp_sdev; + struct fsf_qtcb_header *header = &req->qtcb->header; + + if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) + return; + ++ zfcp_sdev = sdev_to_zfcp(sdev); ++ + switch (header->fsf_status) { + case FSF_HANDLE_MISMATCH: + case FSF_PORT_HANDLE_NOT_VALID: diff --git a/queue-3.5/scsi-zfcp-remove-invalid-reference-to-list-iterator-variable.patch b/queue-3.5/scsi-zfcp-remove-invalid-reference-to-list-iterator-variable.patch new file mode 100644 index 00000000000..72ab43d927e --- /dev/null +++ b/queue-3.5/scsi-zfcp-remove-invalid-reference-to-list-iterator-variable.patch @@ -0,0 +1,43 @@ +From ca579c9f136af4274ccfd1bcaee7f38a29a0e2e9 Mon Sep 17 00:00:00 2001 +From: Julia Lawall +Date: Tue, 4 Sep 2012 15:23:33 +0200 +Subject: SCSI: zfcp: remove invalid reference to list iterator variable + +From: Julia Lawall + +commit ca579c9f136af4274ccfd1bcaee7f38a29a0e2e9 upstream. + +If list_for_each_entry, etc complete a traversal of the list, the iterator +variable ends up pointing to an address at an offset from the list head, +and not a meaningful structure. Thus this value should not be used after +the end of the iterator. Replace port->adapter->scsi_host by +adapter->scsi_host. + +This problem was found using Coccinelle (http://coccinelle.lip6.fr/). + +Oversight in upsteam commit of v2.6.37 +a1ca48319a9aa1c5b57ce142f538e76050bb8972 +"[SCSI] zfcp: Move ACL/CFDC code to zfcp_cfdc.c" +which merged the content of zfcp_erp_port_access_changed(). + +Signed-off-by: Julia Lawall +Signed-off-by: Steffen Maier +Reviewed-by: Martin Peschke +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_cfdc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/s390/scsi/zfcp_cfdc.c ++++ b/drivers/s390/scsi/zfcp_cfdc.c +@@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(st + } + read_unlock_irqrestore(&adapter->port_list_lock, flags); + +- shost_for_each_device(sdev, port->adapter->scsi_host) { ++ shost_for_each_device(sdev, adapter->scsi_host) { + zfcp_sdev = sdev_to_zfcp(sdev); + status = atomic_read(&zfcp_sdev->status); + if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || diff --git a/queue-3.5/scsi-zfcp-restore-refcount-check-on-port_remove.patch b/queue-3.5/scsi-zfcp-restore-refcount-check-on-port_remove.patch new file mode 100644 index 00000000000..4ac81b46d2a --- /dev/null +++ b/queue-3.5/scsi-zfcp-restore-refcount-check-on-port_remove.patch @@ -0,0 +1,191 @@ +From d99b601b63386f3395dc26a699ae703a273d9982 Mon Sep 17 00:00:00 2001 +From: Steffen Maier +Date: Tue, 4 Sep 2012 15:23:34 +0200 +Subject: SCSI: zfcp: restore refcount check on port_remove + +From: Steffen Maier + +commit d99b601b63386f3395dc26a699ae703a273d9982 upstream. + +Upstream commit f3450c7b917201bb49d67032e9f60d5125675d6a +"[SCSI] zfcp: Replace local reference counting with common kref" +accidentally dropped a reference count check before tearing down +zfcp_ports that are potentially in use by zfcp_units. +Even remote ports in use can be removed causing +unreachable garbage objects zfcp_ports with zfcp_units. +Thus units won't come back even after a manual port_rescan. +The kref of zfcp_port->dev.kobj is already used by the driver core. +We cannot re-use it to track the number of zfcp_units. +Re-introduce our own counter for units per port +and check on port_remove. + +Signed-off-by: Steffen Maier +Reviewed-by: Heiko Carstens +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/scsi/zfcp_aux.c | 1 + + drivers/s390/scsi/zfcp_def.h | 1 + + drivers/s390/scsi/zfcp_ext.h | 1 + + drivers/s390/scsi/zfcp_sysfs.c | 18 ++++++++++++++++-- + drivers/s390/scsi/zfcp_unit.c | 36 ++++++++++++++++++++++++++---------- + 5 files changed, 45 insertions(+), 12 deletions(-) + +--- a/drivers/s390/scsi/zfcp_aux.c ++++ b/drivers/s390/scsi/zfcp_aux.c +@@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(stru + + rwlock_init(&port->unit_list_lock); + INIT_LIST_HEAD(&port->unit_list); ++ atomic_set(&port->units, 0); + + INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); + INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); +--- a/drivers/s390/scsi/zfcp_def.h ++++ b/drivers/s390/scsi/zfcp_def.h +@@ -205,6 +205,7 @@ struct zfcp_port { + struct zfcp_adapter *adapter; /* adapter used to access port */ + struct list_head unit_list; /* head of logical unit list */ + rwlock_t unit_list_lock; /* unit list lock */ ++ atomic_t units; /* zfcp_unit count */ + atomic_t status; /* status of this remote port */ + u64 wwnn; /* WWNN if known */ + u64 wwpn; /* WWPN */ +--- a/drivers/s390/scsi/zfcp_ext.h ++++ b/drivers/s390/scsi/zfcp_ext.h +@@ -159,6 +159,7 @@ extern void zfcp_scsi_dif_sense_error(st + extern struct attribute_group zfcp_sysfs_unit_attrs; + extern struct attribute_group zfcp_sysfs_adapter_attrs; + extern struct attribute_group zfcp_sysfs_port_attrs; ++extern struct mutex zfcp_sysfs_port_units_mutex; + extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; + extern struct device_attribute *zfcp_sysfs_shost_attrs[]; + +--- a/drivers/s390/scsi/zfcp_sysfs.c ++++ b/drivers/s390/scsi/zfcp_sysfs.c +@@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_st + static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, + zfcp_sysfs_port_rescan_store); + ++DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); ++ + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +@@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_st + else + retval = 0; + ++ mutex_lock(&zfcp_sysfs_port_units_mutex); ++ if (atomic_read(&port->units) > 0) { ++ retval = -EBUSY; ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ goto out; ++ } ++ /* port is about to be removed, so no more unit_add */ ++ atomic_set(&port->units, -1); ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ + write_lock_irq(&adapter->port_list_lock); + list_del(&port->list); + write_unlock_irq(&adapter->port_list_lock); +@@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store + { + struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); + u64 fcp_lun; ++ int retval; + + if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) + return -EINVAL; + +- if (zfcp_unit_add(port, fcp_lun)) +- return -EINVAL; ++ retval = zfcp_unit_add(port, fcp_lun); ++ if (retval) ++ return retval; + + return count; + } +--- a/drivers/s390/scsi/zfcp_unit.c ++++ b/drivers/s390/scsi/zfcp_unit.c +@@ -104,7 +104,7 @@ static void zfcp_unit_release(struct dev + { + struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); + +- put_device(&unit->port->dev); ++ atomic_dec(&unit->port->units); + kfree(unit); + } + +@@ -119,16 +119,27 @@ static void zfcp_unit_release(struct dev + int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) + { + struct zfcp_unit *unit; ++ int retval = 0; ++ ++ mutex_lock(&zfcp_sysfs_port_units_mutex); ++ if (atomic_read(&port->units) == -1) { ++ /* port is already gone */ ++ retval = -ENODEV; ++ goto out; ++ } + + unit = zfcp_unit_find(port, fcp_lun); + if (unit) { + put_device(&unit->dev); +- return -EEXIST; ++ retval = -EEXIST; ++ goto out; + } + + unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); +- if (!unit) +- return -ENOMEM; ++ if (!unit) { ++ retval = -ENOMEM; ++ goto out; ++ } + + unit->port = port; + unit->fcp_lun = fcp_lun; +@@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port + if (dev_set_name(&unit->dev, "0x%016llx", + (unsigned long long) fcp_lun)) { + kfree(unit); +- return -ENOMEM; ++ retval = -ENOMEM; ++ goto out; + } + +- get_device(&port->dev); +- + if (device_register(&unit->dev)) { + put_device(&unit->dev); +- return -ENOMEM; ++ retval = -ENOMEM; ++ goto out; + } + + if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { + device_unregister(&unit->dev); +- return -EINVAL; ++ retval = -EINVAL; ++ goto out; + } + ++ atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ ++ + write_lock_irq(&port->unit_list_lock); + list_add_tail(&unit->list, &port->unit_list); + write_unlock_irq(&port->unit_list_lock); + + zfcp_unit_scsi_scan(unit); + +- return 0; ++out: ++ mutex_unlock(&zfcp_sysfs_port_units_mutex); ++ return retval; + } + + /** diff --git a/queue-3.5/series b/queue-3.5/series index ceea223a987..3d56e945cbb 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -56,3 +56,12 @@ l2tp-fix-a-typo-in-l2tp_eth_dev_recv.patch netrom-copy_datagram_iovec-can-fail.patch net-do-not-disable-sg-for-packets-requiring-no-checksum.patch aoe-assert-aoe-packets-marked-as-requiring-no-checksum.patch +drm-savage-re-add-busmaster-enable-regression-fix.patch +scsi-zfcp-adapt-to-new-fc_portspeed-semantics.patch +scsi-zfcp-make-trace-record-tags-unique.patch +scsi-zfcp-bounds-checking-for-deferred-error-trace.patch +scsi-zfcp-do-not-wakeup-while-suspended.patch +scsi-zfcp-remove-invalid-reference-to-list-iterator-variable.patch +scsi-zfcp-restore-refcount-check-on-port_remove.patch +scsi-zfcp-only-access-zfcp_scsi_dev-for-valid-scsi_device.patch +pci-check-p2p-bridge-for-invalid-secondary-subordinate-range.patch