]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 21 Sep 2011 22:57:24 +0000 (15:57 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 21 Sep 2011 22:57:24 +0000 (15:57 -0700)
20 files changed:
queue-3.0/asix-add-ax88772b-usb-id.patch [new file with mode: 0644]
queue-3.0/cdc_ncm-fix-endianness-problem.patch [new file with mode: 0644]
queue-3.0/ehci-add-pci-quirk-for-ordissimo-and-rm-slate-100-too.patch [new file with mode: 0644]
queue-3.0/ehci-refactor-pci-quirk-to-use-standard-dmi_check_system-method.patch [new file with mode: 0644]
queue-3.0/fcoe-unable-to-select-the-exchangeid-from-offload-pool-for-storage-targets.patch [new file with mode: 0644]
queue-3.0/ipc-mqueue.c-fix-mq_open-return-value.patch [new file with mode: 0644]
queue-3.0/ipc-mqueue.c-refactor-failure-handling.patch [new file with mode: 0644]
queue-3.0/iscsi_tcp-fix-locking-around-iscsi-sk-user-data.patch [new file with mode: 0644]
queue-3.0/libfc-enhancement-to-rport-state-machine-applicable-only-for-vn2vn-mode.patch [new file with mode: 0644]
queue-3.0/mpt2sas-added-did_no_connect-return-when-driver-remove-and-avoid-shutdown-call.patch [new file with mode: 0644]
queue-3.0/mpt2sas-adding-support-for-customer-specific-branding.patch [new file with mode: 0644]
queue-3.0/perf-x86-add-model-45-sandybridge-support.patch [new file with mode: 0644]
queue-3.0/qdio-clear-shared-dsci-before-scheduling-the-queue-handler.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/tg3-add-5719-and-5720-to-eee_cap-list.patch [new file with mode: 0644]
queue-3.0/tg3-fix-int-selftest-for-recent-devices.patch [new file with mode: 0644]
queue-3.0/tg3-fix-io-failures-after-chip-reset.patch [new file with mode: 0644]
queue-3.0/usb-pl2303-correctly-handle-baudrates-above-115200.patch [new file with mode: 0644]
queue-3.0/writeback-introduce-.tagged_writepages-for-the-wb_sync_none-sync-stage.patch [new file with mode: 0644]
queue-3.0/writeback-update-dirtied_when-for-synced-inode-to-prevent-livelock.patch [new file with mode: 0644]

diff --git a/queue-3.0/asix-add-ax88772b-usb-id.patch b/queue-3.0/asix-add-ax88772b-usb-id.patch
new file mode 100644 (file)
index 0000000..90122a1
--- /dev/null
@@ -0,0 +1,32 @@
+From 308859097831831a979f2e82cbeef0a94f438080 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marek.vasut@gmail.com>
+Date: Wed, 20 Jul 2011 05:57:04 +0000
+Subject: ASIX: Add AX88772B USB ID
+
+From: Marek Vasut <marek.vasut@gmail.com>
+
+commit 308859097831831a979f2e82cbeef0a94f438080 upstream.
+
+This device can be found in Acer Iconia TAB W500 tablet dock.
+
+Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/usb/asix.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/usb/asix.c
++++ b/drivers/net/usb/asix.c
+@@ -1502,6 +1502,10 @@ static const struct usb_device_id       produc
+       USB_DEVICE (0x04f1, 0x3008),
+       .driver_info = (unsigned long) &ax8817x_info,
+ }, {
++      // ASIX AX88772B 10/100
++      USB_DEVICE (0x0b95, 0x772b),
++      .driver_info = (unsigned long) &ax88772_info,
++}, {
+       // ASIX AX88772 10/100
+       USB_DEVICE (0x0b95, 0x7720),
+       .driver_info = (unsigned long) &ax88772_info,
diff --git a/queue-3.0/cdc_ncm-fix-endianness-problem.patch b/queue-3.0/cdc_ncm-fix-endianness-problem.patch
new file mode 100644 (file)
index 0000000..79678c7
--- /dev/null
@@ -0,0 +1,268 @@
+From 36c35416a94f5632c3addad05217ff02c39b3b61 Mon Sep 17 00:00:00 2001
+From: Giuseppe Scrivano <giuseppe@southpole.se>
+Date: Wed, 3 Aug 2011 22:10:29 +0000
+Subject: cdc_ncm: fix endianness problem.
+
+From: Giuseppe Scrivano <giuseppe@southpole.se>
+
+commit 36c35416a94f5632c3addad05217ff02c39b3b61 upstream.
+
+Fix a misusage of the struct usb_cdc_notification to pass arguments to the
+usb_control_msg function.  The usb_control_msg function expects host endian
+arguments but usb_cdc_notification stores these values as little endian.
+
+Now usb_control_msg is directly invoked with host endian values.
+
+Signed-off-by: Giuseppe Scrivano <giuseppe@southpole.se>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/usb/cdc_ncm.c |  156 ++++++++++++++++------------------------------
+ 1 file changed, 56 insertions(+), 100 deletions(-)
+
+--- a/drivers/net/usb/cdc_ncm.c
++++ b/drivers/net/usb/cdc_ncm.c
+@@ -54,7 +54,7 @@
+ #include <linux/usb/usbnet.h>
+ #include <linux/usb/cdc.h>
+-#define       DRIVER_VERSION                          "01-June-2011"
++#define       DRIVER_VERSION                          "04-Aug-2011"
+ /* CDC NCM subclass 3.2.1 */
+ #define USB_CDC_NCM_NDP16_LENGTH_MIN          0x10
+@@ -164,35 +164,8 @@ cdc_ncm_get_drvinfo(struct net_device *n
+       usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
+ }
+-static int
+-cdc_ncm_do_request(struct cdc_ncm_ctx *ctx, struct usb_cdc_notification *req,
+-                 void *data, u16 flags, u16 *actlen, u16 timeout)
+-{
+-      int err;
+-
+-      err = usb_control_msg(ctx->udev, (req->bmRequestType & USB_DIR_IN) ?
+-                              usb_rcvctrlpipe(ctx->udev, 0) :
+-                              usb_sndctrlpipe(ctx->udev, 0),
+-                              req->bNotificationType, req->bmRequestType,
+-                              req->wValue,
+-                              req->wIndex, data,
+-                              req->wLength, timeout);
+-
+-      if (err < 0) {
+-              if (actlen)
+-                      *actlen = 0;
+-              return err;
+-      }
+-
+-      if (actlen)
+-              *actlen = err;
+-
+-      return 0;
+-}
+-
+ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
+ {
+-      struct usb_cdc_notification req;
+       u32 val;
+       u8 flags;
+       u8 iface_no;
+@@ -201,14 +174,14 @@ static u8 cdc_ncm_setup(struct cdc_ncm_c
+       iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
+-      req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE;
+-      req.bNotificationType = USB_CDC_GET_NTB_PARAMETERS;
+-      req.wValue = 0;
+-      req.wIndex = cpu_to_le16(iface_no);
+-      req.wLength = cpu_to_le16(sizeof(ctx->ncm_parm));
+-
+-      err = cdc_ncm_do_request(ctx, &req, &ctx->ncm_parm, 0, NULL, 1000);
+-      if (err) {
++      err = usb_control_msg(ctx->udev,
++                              usb_rcvctrlpipe(ctx->udev, 0),
++                              USB_CDC_GET_NTB_PARAMETERS,
++                              USB_TYPE_CLASS | USB_DIR_IN
++                               | USB_RECIP_INTERFACE,
++                              0, iface_no, &ctx->ncm_parm,
++                              sizeof(ctx->ncm_parm), 10000);
++      if (err < 0) {
+               pr_debug("failed GET_NTB_PARAMETERS\n");
+               return 1;
+       }
+@@ -254,31 +227,26 @@ static u8 cdc_ncm_setup(struct cdc_ncm_c
+       /* inform device about NTB input size changes */
+       if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
+-              req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+-                                                      USB_RECIP_INTERFACE;
+-              req.bNotificationType = USB_CDC_SET_NTB_INPUT_SIZE;
+-              req.wValue = 0;
+-              req.wIndex = cpu_to_le16(iface_no);
+               if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
+                       struct usb_cdc_ncm_ndp_input_size ndp_in_sz;
+-
+-                      req.wLength = 8;
+-                      ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+-                      ndp_in_sz.wNtbInMaxDatagrams =
+-                                      cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX);
+-                      ndp_in_sz.wReserved = 0;
+-                      err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL,
+-                                                                      1000);
++                      err = usb_control_msg(ctx->udev,
++                                      usb_sndctrlpipe(ctx->udev, 0),
++                                      USB_CDC_SET_NTB_INPUT_SIZE,
++                                      USB_TYPE_CLASS | USB_DIR_OUT
++                                       | USB_RECIP_INTERFACE,
++                                      0, iface_no, &ndp_in_sz, 8, 1000);
+               } else {
+                       __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
+-
+-                      req.wLength = 4;
+-                      err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0,
+-                                                              NULL, 1000);
++                      err = usb_control_msg(ctx->udev,
++                                      usb_sndctrlpipe(ctx->udev, 0),
++                                      USB_CDC_SET_NTB_INPUT_SIZE,
++                                      USB_TYPE_CLASS | USB_DIR_OUT
++                                       | USB_RECIP_INTERFACE,
++                                      0, iface_no, &dwNtbInMaxSize, 4, 1000);
+               }
+-              if (err)
++              if (err < 0)
+                       pr_debug("Setting NTB Input Size failed\n");
+       }
+@@ -333,29 +301,24 @@ static u8 cdc_ncm_setup(struct cdc_ncm_c
+       /* set CRC Mode */
+       if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
+-              req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+-                                                      USB_RECIP_INTERFACE;
+-              req.bNotificationType = USB_CDC_SET_CRC_MODE;
+-              req.wValue = cpu_to_le16(USB_CDC_NCM_CRC_NOT_APPENDED);
+-              req.wIndex = cpu_to_le16(iface_no);
+-              req.wLength = 0;
+-
+-              err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000);
+-              if (err)
++              err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
++                              USB_CDC_SET_CRC_MODE,
++                              USB_TYPE_CLASS | USB_DIR_OUT
++                               | USB_RECIP_INTERFACE,
++                              USB_CDC_NCM_CRC_NOT_APPENDED,
++                              iface_no, NULL, 0, 1000);
++              if (err < 0)
+                       pr_debug("Setting CRC mode off failed\n");
+       }
+       /* set NTB format, if both formats are supported */
+       if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
+-              req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+-                                                      USB_RECIP_INTERFACE;
+-              req.bNotificationType = USB_CDC_SET_NTB_FORMAT;
+-              req.wValue = cpu_to_le16(USB_CDC_NCM_NTB16_FORMAT);
+-              req.wIndex = cpu_to_le16(iface_no);
+-              req.wLength = 0;
+-
+-              err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000);
+-              if (err)
++              err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
++                              USB_CDC_SET_NTB_FORMAT, USB_TYPE_CLASS
++                               | USB_DIR_OUT | USB_RECIP_INTERFACE,
++                              USB_CDC_NCM_NTB16_FORMAT,
++                              iface_no, NULL, 0, 1000);
++              if (err < 0)
+                       pr_debug("Setting NTB format to 16-bit failed\n");
+       }
+@@ -365,17 +328,13 @@ static u8 cdc_ncm_setup(struct cdc_ncm_c
+       if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
+               __le16 max_datagram_size;
+               u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+-
+-              req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN |
+-                                                      USB_RECIP_INTERFACE;
+-              req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE;
+-              req.wValue = 0;
+-              req.wIndex = cpu_to_le16(iface_no);
+-              req.wLength = cpu_to_le16(2);
+-
+-              err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL,
+-                                                                      1000);
+-              if (err) {
++              err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0),
++                              USB_CDC_GET_MAX_DATAGRAM_SIZE,
++                              USB_TYPE_CLASS | USB_DIR_IN
++                               | USB_RECIP_INTERFACE,
++                              0, iface_no, &max_datagram_size,
++                              2, 1000);
++              if (err < 0) {
+                       pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
+                                               CDC_NCM_MIN_DATAGRAM_SIZE);
+               } else {
+@@ -396,17 +355,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_c
+                                       CDC_NCM_MIN_DATAGRAM_SIZE;
+                       /* if value changed, update device */
+-                      req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT |
+-                                                      USB_RECIP_INTERFACE;
+-                      req.bNotificationType = USB_CDC_SET_MAX_DATAGRAM_SIZE;
+-                      req.wValue = 0;
+-                      req.wIndex = cpu_to_le16(iface_no);
+-                      req.wLength = 2;
+-                      max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
+-
+-                      err = cdc_ncm_do_request(ctx, &req, &max_datagram_size,
+-                                                              0, NULL, 1000);
+-                      if (err)
++                      err = usb_control_msg(ctx->udev,
++                                              usb_sndctrlpipe(ctx->udev, 0),
++                                              USB_CDC_SET_MAX_DATAGRAM_SIZE,
++                                              USB_TYPE_CLASS | USB_DIR_OUT
++                                               | USB_RECIP_INTERFACE,
++                                              0,
++                                              iface_no, &max_datagram_size,
++                                              2, 1000);
++                      if (err < 0)
+                               pr_debug("SET_MAX_DATAGRAM_SIZE failed\n");
+               }
+@@ -672,7 +629,7 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx
+       u32 rem;
+       u32 offset;
+       u32 last_offset;
+-      u16 n = 0;
++      u16 n = 0, index;
+       u8 ready2send = 0;
+       /* if there is a remaining skb, it gets priority */
+@@ -860,8 +817,8 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx
+                                       cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
+       ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
+       ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
+-      ctx->tx_ncm.nth16.wNdpIndex = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
+-                                                      ctx->tx_ndp_modulus);
++      index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus);
++      ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index);
+       memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
+       ctx->tx_seq++;
+@@ -874,12 +831,11 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx
+       ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
+       ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
+-      memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex,
++      memcpy(((u8 *)skb_out->data) + index,
+                                               &(ctx->tx_ncm.ndp16),
+                                               sizeof(ctx->tx_ncm.ndp16));
+-      memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex +
+-                                      sizeof(ctx->tx_ncm.ndp16),
++      memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16),
+                                       &(ctx->tx_ncm.dpe16),
+                                       (ctx->tx_curr_frame_num + 1) *
+                                       sizeof(struct usb_cdc_ncm_dpe16));
diff --git a/queue-3.0/ehci-add-pci-quirk-for-ordissimo-and-rm-slate-100-too.patch b/queue-3.0/ehci-add-pci-quirk-for-ordissimo-and-rm-slate-100-too.patch
new file mode 100644 (file)
index 0000000..552c666
--- /dev/null
@@ -0,0 +1,36 @@
+From 0c42a4e84502533ec40544324debe2a62836ae11 Mon Sep 17 00:00:00 2001
+From: Anisse Astier <anisse@astier.eu>
+Date: Tue, 5 Jul 2011 16:38:46 +0200
+Subject: ehci: add pci quirk for Ordissimo and RM Slate 100 too
+
+From: Anisse Astier <anisse@astier.eu>
+
+commit 0c42a4e84502533ec40544324debe2a62836ae11 upstream.
+
+Add another variant of the Pegatron tablet used by Ordissimo, and
+apparently RM Slate 100, to the list of models that should skip the
+negociation for the handoff of the EHCI controller.
+
+Signed-off-by: Anisse Astier <anisse@astier.eu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/pci-quirks.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -543,6 +543,13 @@ static const struct dmi_system_id __init
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"),
+               },
+       },
++      {
++              /*  Pegatron Lucid (Ordissimo AIRIS) */
++              .matches = {
++                      DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
++                      DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
++              },
++      },
+       { }
+ };
diff --git a/queue-3.0/ehci-refactor-pci-quirk-to-use-standard-dmi_check_system-method.patch b/queue-3.0/ehci-refactor-pci-quirk-to-use-standard-dmi_check_system-method.patch
new file mode 100644 (file)
index 0000000..1e85ce6
--- /dev/null
@@ -0,0 +1,59 @@
+From 03c75362181b0b1d6a330e7cf8def10ba988dfbe Mon Sep 17 00:00:00 2001
+From: Anisse Astier <anisse@astier.eu>
+Date: Tue, 5 Jul 2011 16:38:45 +0200
+Subject: ehci: refactor pci quirk to use standard dmi_check_system method
+
+From: Anisse Astier <anisse@astier.eu>
+
+commit 03c75362181b0b1d6a330e7cf8def10ba988dfbe upstream.
+
+In commit 3610ea5397b80822e417aaa0e706fd803fb05680 (ehci: workaround for pci
+quirk timeout on ExoPC), a workaround was added to skip the negociation for
+the handoff of the EHCI controller.
+
+Refactor the DMI detection code to use standard dmi_check_system function.
+
+Signed-off-by: Anisse Astier <anisse@astier.eu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/pci-quirks.c |   21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -535,20 +535,27 @@ static void __devinit quirk_usb_handoff_
+       iounmap(base);
+ }
++static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = {
++      {
++              /*  Pegatron Lucid (ExoPC) */
++              .matches = {
++                      DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"),
++                      DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"),
++              },
++      },
++      { }
++};
++
+ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
+                                       void __iomem *op_reg_base,
+                                       u32 cap, u8 offset)
+ {
+       int try_handoff = 1, tried_handoff = 0;
+-      /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90
+-       * seconds trying the handoff on its unused controller.  Skip
+-       * it. */
++      /* The Pegatron Lucid tablet sporadically waits for 98 seconds trying
++       * the handoff on its unused controller.  Skip it. */
+       if (pdev->vendor == 0x8086 && pdev->device == 0x283a) {
+-              const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME);
+-              const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION);
+-              if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") &&
+-                  dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133"))
++              if (dmi_check_system(ehci_dmi_nohandoff_table))
+                       try_handoff = 0;
+       }
diff --git a/queue-3.0/fcoe-unable-to-select-the-exchangeid-from-offload-pool-for-storage-targets.patch b/queue-3.0/fcoe-unable-to-select-the-exchangeid-from-offload-pool-for-storage-targets.patch
new file mode 100644 (file)
index 0000000..b521c25
--- /dev/null
@@ -0,0 +1,62 @@
+From 1ff9918b625457ce20d450d00f9ed0a12ba191b7 Mon Sep 17 00:00:00 2001
+From: Kiran Patil <kiran.patil@intel.com>
+Date: Mon, 20 Jun 2011 16:59:15 -0700
+Subject: [SCSI] fcoe: Unable to select the exchangeID from offload pool for storage targets
+
+From: Kiran Patil <kiran.patil@intel.com>
+
+commit 1ff9918b625457ce20d450d00f9ed0a12ba191b7 upstream.
+
+Problem: When initiator sends write command to target, target tries to
+assign new sequence. It allocates new exchangeID (RX_ID)
+always from non-offloaded pool (Non-offload EMA)
+
+Fix: Enhanced fcoe_oem_match routine to look at F_CTL flags and if it
+is exchange responder and command type is WRITEDATA, then function
+returns TRUE instead of FALSE. This function is used to determine
+which pool to use (offload pool of exchange is used only if this
+function returns TRUE).
+
+Technical Notes: N/A
+
+Signed-off-by: Kiran Patil <kiran.patil@intel.com>
+Signed-off-by: Robert Love <robert.w.love@intel.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/fcoe/fcoe.c |   19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/fcoe/fcoe.c
++++ b/drivers/scsi/fcoe/fcoe.c
+@@ -749,12 +749,27 @@ static int fcoe_shost_config(struct fc_l
+  * The offload EM that this routine is associated with will handle any
+  * packets that are for SCSI read requests.
+  *
++ * This has been enhanced to work when FCoE stack is operating in target
++ * mode.
++ *
+  * Returns: True for read types I/O, otherwise returns false.
+  */
+ bool fcoe_oem_match(struct fc_frame *fp)
+ {
+-      return fc_fcp_is_read(fr_fsp(fp)) &&
+-              (fr_fsp(fp)->data_len > fcoe_ddp_min);
++      struct fc_frame_header *fh = fc_frame_header_get(fp);
++      struct fcp_cmnd *fcp;
++
++      if (fc_fcp_is_read(fr_fsp(fp)) &&
++          (fr_fsp(fp)->data_len > fcoe_ddp_min))
++              return true;
++      else if (!(ntoh24(fh->fh_f_ctl) & FC_FC_EX_CTX)) {
++              fcp = fc_frame_payload_get(fp, sizeof(*fcp));
++              if (ntohs(fh->fh_rx_id) == FC_XID_UNKNOWN &&
++                  fcp && (ntohl(fcp->fc_dl) > fcoe_ddp_min) &&
++                  (fcp->fc_flags & FCP_CFL_WRDATA))
++                      return true;
++      }
++      return false;
+ }
+ /**
diff --git a/queue-3.0/ipc-mqueue.c-fix-mq_open-return-value.patch b/queue-3.0/ipc-mqueue.c-fix-mq_open-return-value.patch
new file mode 100644 (file)
index 0000000..5d72874
--- /dev/null
@@ -0,0 +1,83 @@
+From d40dcdb0172a1ba853464983a059fb45e0aaf61a Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Tue, 26 Jul 2011 16:08:47 -0700
+Subject: ipc/mqueue.c: fix mq_open() return value
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit d40dcdb0172a1ba853464983a059fb45e0aaf61a upstream.
+
+We return ENOMEM from mqueue_get_inode even when we have enough memory.
+Namely in case the system rlimit of mqueue was reached.  This error
+propagates to mq_queue and user sees the error unexpectedly.  So fix
+this up to properly return EMFILE as described in the manpage:
+
+       EMFILE The process already has the maximum number of files and
+              message queues open.
+
+instead of:
+
+       ENOMEM Insufficient memory.
+
+With the previous patch we just switch to ERR_PTR/PTR_ERR/IS_ERR error
+handling here.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ ipc/mqueue.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/ipc/mqueue.c
++++ b/ipc/mqueue.c
+@@ -113,6 +113,7 @@ static struct inode *mqueue_get_inode(st
+ {
+       struct user_struct *u = current_user();
+       struct inode *inode;
++      int ret = -ENOMEM;
+       inode = new_inode(sb);
+       if (!inode)
+@@ -160,6 +161,7 @@ static struct inode *mqueue_get_inode(st
+                   u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
+                       spin_unlock(&mq_lock);
+                       /* mqueue_evict_inode() releases info->messages */
++                      ret = -EMFILE;
+                       goto out_inode;
+               }
+               u->mq_bytes += mq_bytes;
+@@ -179,7 +181,7 @@ static struct inode *mqueue_get_inode(st
+ out_inode:
+       iput(inode);
+ err:
+-      return NULL;
++      return ERR_PTR(ret);
+ }
+ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
+@@ -195,8 +197,8 @@ static int mqueue_fill_super(struct supe
+       inode = mqueue_get_inode(sb, ns, S_IFDIR | S_ISVTX | S_IRWXUGO,
+                               NULL);
+-      if (!inode) {
+-              error = -ENOMEM;
++      if (IS_ERR(inode)) {
++              error = PTR_ERR(inode);
+               goto out;
+       }
+@@ -316,8 +318,8 @@ static int mqueue_create(struct inode *d
+       spin_unlock(&mq_lock);
+       inode = mqueue_get_inode(dir->i_sb, ipc_ns, mode, attr);
+-      if (!inode) {
+-              error = -ENOMEM;
++      if (IS_ERR(inode)) {
++              error = PTR_ERR(inode);
+               spin_lock(&mq_lock);
+               ipc_ns->mq_queues_count--;
+               goto out_unlock;
diff --git a/queue-3.0/ipc-mqueue.c-refactor-failure-handling.patch b/queue-3.0/ipc-mqueue.c-refactor-failure-handling.patch
new file mode 100644 (file)
index 0000000..9784fb6
--- /dev/null
@@ -0,0 +1,157 @@
+From 04715206c0c2fd4ec5ca77fa51e3a5b41ce71492 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Tue, 26 Jul 2011 16:08:46 -0700
+Subject: ipc/mqueue.c: refactor failure handling
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 04715206c0c2fd4ec5ca77fa51e3a5b41ce71492 upstream.
+
+If new_inode fails to allocate an inode we need only to return with
+NULL.  But now we test the opposite and have all the work in a nested
+block.  So do the opposite to save one indentation level (and remove
+unnecessary line breaks).
+
+This is only a preparation/cleanup for the next patch where we fix up
+return values from mqueue_get_inode.
+
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ ipc/mqueue.c |  115 +++++++++++++++++++++++++++++------------------------------
+ 1 file changed, 58 insertions(+), 57 deletions(-)
+
+--- a/ipc/mqueue.c
++++ b/ipc/mqueue.c
+@@ -115,69 +115,70 @@ static struct inode *mqueue_get_inode(st
+       struct inode *inode;
+       inode = new_inode(sb);
+-      if (inode) {
+-              inode->i_ino = get_next_ino();
+-              inode->i_mode = mode;
+-              inode->i_uid = current_fsuid();
+-              inode->i_gid = current_fsgid();
+-              inode->i_mtime = inode->i_ctime = inode->i_atime =
+-                              CURRENT_TIME;
+-
+-              if (S_ISREG(mode)) {
+-                      struct mqueue_inode_info *info;
+-                      struct task_struct *p = current;
+-                      unsigned long mq_bytes, mq_msg_tblsz;
+-
+-                      inode->i_fop = &mqueue_file_operations;
+-                      inode->i_size = FILENT_SIZE;
+-                      /* mqueue specific info */
+-                      info = MQUEUE_I(inode);
+-                      spin_lock_init(&info->lock);
+-                      init_waitqueue_head(&info->wait_q);
+-                      INIT_LIST_HEAD(&info->e_wait_q[0].list);
+-                      INIT_LIST_HEAD(&info->e_wait_q[1].list);
+-                      info->notify_owner = NULL;
+-                      info->qsize = 0;
+-                      info->user = NULL;      /* set when all is ok */
+-                      memset(&info->attr, 0, sizeof(info->attr));
+-                      info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
+-                      info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
+-                      if (attr) {
+-                              info->attr.mq_maxmsg = attr->mq_maxmsg;
+-                              info->attr.mq_msgsize = attr->mq_msgsize;
+-                      }
+-                      mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
+-                      info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
+-                      if (!info->messages)
+-                              goto out_inode;
+-
+-                      mq_bytes = (mq_msg_tblsz +
+-                              (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+-
+-                      spin_lock(&mq_lock);
+-                      if (u->mq_bytes + mq_bytes < u->mq_bytes ||
+-                          u->mq_bytes + mq_bytes >
+-                          task_rlimit(p, RLIMIT_MSGQUEUE)) {
+-                              spin_unlock(&mq_lock);
+-                              /* mqueue_evict_inode() releases info->messages */
+-                              goto out_inode;
+-                      }
+-                      u->mq_bytes += mq_bytes;
+-                      spin_unlock(&mq_lock);
++      if (!inode)
++              goto err;
+-                      /* all is ok */
+-                      info->user = get_uid(u);
+-              } else if (S_ISDIR(mode)) {
+-                      inc_nlink(inode);
+-                      /* Some things misbehave if size == 0 on a directory */
+-                      inode->i_size = 2 * DIRENT_SIZE;
+-                      inode->i_op = &mqueue_dir_inode_operations;
+-                      inode->i_fop = &simple_dir_operations;
++      inode->i_ino = get_next_ino();
++      inode->i_mode = mode;
++      inode->i_uid = current_fsuid();
++      inode->i_gid = current_fsgid();
++      inode->i_mtime = inode->i_ctime = inode->i_atime = CURRENT_TIME;
++
++      if (S_ISREG(mode)) {
++              struct mqueue_inode_info *info;
++              struct task_struct *p = current;
++              unsigned long mq_bytes, mq_msg_tblsz;
++
++              inode->i_fop = &mqueue_file_operations;
++              inode->i_size = FILENT_SIZE;
++              /* mqueue specific info */
++              info = MQUEUE_I(inode);
++              spin_lock_init(&info->lock);
++              init_waitqueue_head(&info->wait_q);
++              INIT_LIST_HEAD(&info->e_wait_q[0].list);
++              INIT_LIST_HEAD(&info->e_wait_q[1].list);
++              info->notify_owner = NULL;
++              info->qsize = 0;
++              info->user = NULL;      /* set when all is ok */
++              memset(&info->attr, 0, sizeof(info->attr));
++              info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
++              info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
++              if (attr) {
++                      info->attr.mq_maxmsg = attr->mq_maxmsg;
++                      info->attr.mq_msgsize = attr->mq_msgsize;
++              }
++              mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
++              info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
++              if (!info->messages)
++                      goto out_inode;
++
++              mq_bytes = (mq_msg_tblsz +
++                      (info->attr.mq_maxmsg * info->attr.mq_msgsize));
++
++              spin_lock(&mq_lock);
++              if (u->mq_bytes + mq_bytes < u->mq_bytes ||
++                  u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
++                      spin_unlock(&mq_lock);
++                      /* mqueue_evict_inode() releases info->messages */
++                      goto out_inode;
+               }
++              u->mq_bytes += mq_bytes;
++              spin_unlock(&mq_lock);
++
++              /* all is ok */
++              info->user = get_uid(u);
++      } else if (S_ISDIR(mode)) {
++              inc_nlink(inode);
++              /* Some things misbehave if size == 0 on a directory */
++              inode->i_size = 2 * DIRENT_SIZE;
++              inode->i_op = &mqueue_dir_inode_operations;
++              inode->i_fop = &simple_dir_operations;
+       }
++
+       return inode;
+ out_inode:
+       iput(inode);
++err:
+       return NULL;
+ }
diff --git a/queue-3.0/iscsi_tcp-fix-locking-around-iscsi-sk-user-data.patch b/queue-3.0/iscsi_tcp-fix-locking-around-iscsi-sk-user-data.patch
new file mode 100644 (file)
index 0000000..b748782
--- /dev/null
@@ -0,0 +1,145 @@
+From 03adb5f91280b433c3685d0ee86b2e1424af3d88 Mon Sep 17 00:00:00 2001
+From: Mike Christie <michaelc@cs.wisc.edu>
+Date: Fri, 24 Jun 2011 15:11:54 -0500
+Subject: [SCSI] iscsi_tcp: fix locking around iscsi sk user data
+
+From: Mike Christie <michaelc@cs.wisc.edu>
+
+commit 03adb5f91280b433c3685d0ee86b2e1424af3d88 upstream.
+
+iscsi_sw_tcp_conn_restore_callbacks could have set
+the sk_user_data field to NULL then iscsi_sw_tcp_data_ready
+could read that and try to access the NULL pointer. This
+adds some checks for NULL sk_user_data in the sk
+callback functions and it uses the sk_callback_lock to
+set/get that sk_user_data field.
+
+Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/iscsi_tcp.c |   61 +++++++++++++++++++++++++++++++----------------
+ 1 file changed, 41 insertions(+), 20 deletions(-)
+
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -107,10 +107,12 @@ static int iscsi_sw_tcp_recv(read_descri
+  * If the socket is in CLOSE or CLOSE_WAIT we should
+  * not close the connection if there is still some
+  * data pending.
++ *
++ * Must be called with sk_callback_lock.
+  */
+ static inline int iscsi_sw_sk_state_check(struct sock *sk)
+ {
+-      struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
++      struct iscsi_conn *conn = sk->sk_user_data;
+       if ((sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) &&
+           !atomic_read(&sk->sk_rmem_alloc)) {
+@@ -123,11 +125,17 @@ static inline int iscsi_sw_sk_state_chec
+ static void iscsi_sw_tcp_data_ready(struct sock *sk, int flag)
+ {
+-      struct iscsi_conn *conn = sk->sk_user_data;
+-      struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
++      struct iscsi_conn *conn;
++      struct iscsi_tcp_conn *tcp_conn;
+       read_descriptor_t rd_desc;
+       read_lock(&sk->sk_callback_lock);
++      conn = sk->sk_user_data;
++      if (!conn) {
++              read_unlock(&sk->sk_callback_lock);
++              return;
++      }
++      tcp_conn = conn->dd_data;
+       /*
+        * Use rd_desc to pass 'conn' to iscsi_tcp_recv.
+@@ -141,11 +149,10 @@ static void iscsi_sw_tcp_data_ready(stru
+       iscsi_sw_sk_state_check(sk);
+-      read_unlock(&sk->sk_callback_lock);
+-
+       /* If we had to (atomically) map a highmem page,
+        * unmap it now. */
+       iscsi_tcp_segment_unmap(&tcp_conn->in.segment);
++      read_unlock(&sk->sk_callback_lock);
+ }
+ static void iscsi_sw_tcp_state_change(struct sock *sk)
+@@ -157,8 +164,11 @@ static void iscsi_sw_tcp_state_change(st
+       void (*old_state_change)(struct sock *);
+       read_lock(&sk->sk_callback_lock);
+-
+-      conn = (struct iscsi_conn*)sk->sk_user_data;
++      conn = sk->sk_user_data;
++      if (!conn) {
++              read_unlock(&sk->sk_callback_lock);
++              return;
++      }
+       session = conn->session;
+       iscsi_sw_sk_state_check(sk);
+@@ -178,11 +188,25 @@ static void iscsi_sw_tcp_state_change(st
+  **/
+ static void iscsi_sw_tcp_write_space(struct sock *sk)
+ {
+-      struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
+-      struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-      struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
++      struct iscsi_conn *conn;
++      struct iscsi_tcp_conn *tcp_conn;
++      struct iscsi_sw_tcp_conn *tcp_sw_conn;
++      void (*old_write_space)(struct sock *);
++
++      read_lock_bh(&sk->sk_callback_lock);
++      conn = sk->sk_user_data;
++      if (!conn) {
++              read_unlock_bh(&sk->sk_callback_lock);
++              return;
++      }
++
++      tcp_conn = conn->dd_data;
++      tcp_sw_conn = tcp_conn->dd_data;
++      old_write_space = tcp_sw_conn->old_write_space;
++      read_unlock_bh(&sk->sk_callback_lock);
++
++      old_write_space(sk);
+-      tcp_sw_conn->old_write_space(sk);
+       ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
+       iscsi_conn_queue_work(conn);
+ }
+@@ -592,20 +616,17 @@ static void iscsi_sw_tcp_conn_stop(struc
+       /* userspace may have goofed up and not bound us */
+       if (!sock)
+               return;
+-      /*
+-       * Make sure our recv side is stopped.
+-       * Older tools called conn stop before ep_disconnect
+-       * so IO could still be coming in.
+-       */
+-      write_lock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+-      set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+-      write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock);
+       sock->sk->sk_err = EIO;
+       wake_up_interruptible(sk_sleep(sock->sk));
+-      iscsi_conn_stop(cls_conn, flag);
++      /* stop xmit side */
++      iscsi_suspend_tx(conn);
++
++      /* stop recv side and release socket */
+       iscsi_sw_tcp_release_conn(conn);
++
++      iscsi_conn_stop(cls_conn, flag);
+ }
+ static int
diff --git a/queue-3.0/libfc-enhancement-to-rport-state-machine-applicable-only-for-vn2vn-mode.patch b/queue-3.0/libfc-enhancement-to-rport-state-machine-applicable-only-for-vn2vn-mode.patch
new file mode 100644 (file)
index 0000000..b33b12c
--- /dev/null
@@ -0,0 +1,72 @@
+From 480584818a4bb3655d8d0d875ed60b427fc61cc5 Mon Sep 17 00:00:00 2001
+From: Kiran Patil <kiran.patil@intel.com>
+Date: Mon, 20 Jun 2011 16:58:59 -0700
+Subject: [SCSI] libfc: Enhancement to RPORT state machine applicable only for VN2VN mode
+
+From: Kiran Patil <kiran.patil@intel.com>
+
+commit 480584818a4bb3655d8d0d875ed60b427fc61cc5 upstream.
+
+Problem: Existing RPORT state machine continues witg FLOGI/PLOGI
+process only after it receices beacon from other end. Once claiming
+stage is over (either clain notify or clain repose), beacon is sent
+and state machine enters into operational mode where it initiates the
+rlogin process (FLOGI/PLOGI) to the peer but before this rlogin is
+initiated, exitsing implementation checks if it received beacon from
+other end, it beacon is not received yet, rlogin process is not
+initiated. Other end initiates FLOGI but peer end keeps on rejecting
+FLOGI, hence after 3 retries other end deletes associated rport, then
+sends a beacon. Once the beacon is received, peer end now initiates
+rlogin to the peer end but since associated rport is deleted FLOGI is
+neither accepted nor the reject response send out because rport is
+deleted. Hence unable to proceed withg FLOGI/PLOGI process and fails
+to establish VN2VN connection.
+
+Fix: VN2VN spec is not standard yet but based on exitsing collateral
+on T11, it appears that, both end shall send beacon and enter into
+'operational mode' without explictly waiting for beacon from other
+end. Fix is to allow the RPORT login process as long as respective
+RPORT is created (as part of claim notification / claim response) even
+though state of RPORT is INIT. Means don't wait for beacon from peer
+end, if peer end initiates FLOGI (means peer end exist and
+responding).
+
+Notes: This patch is preparing the FCoE stack for target wrt
+offload. This is generic patch and harmless even if applied on storage
+initiator because 'else if' condition of function 'fcoe_oem_found'
+shall evaluate to TRUE only for targets.
+
+Dependencies: None
+
+Signed-off-by: Kiran Patil <kiran.patil@intel.com>
+Signed-off-by: Robert Love <robert.w.love@intel.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/libfc/fc_rport.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/scsi/libfc/fc_rport.c
++++ b/drivers/scsi/libfc/fc_rport.c
+@@ -801,6 +801,20 @@ static void fc_rport_recv_flogi_req(stru
+       switch (rdata->rp_state) {
+       case RPORT_ST_INIT:
++              /*
++               * If received the FLOGI request on RPORT which is INIT state
++               * (means not transition to FLOGI either fc_rport timeout
++               * function didn;t trigger or this end hasn;t received
++               * beacon yet from other end. In that case only, allow RPORT
++               * state machine to continue, otherwise fall through which
++               * causes the code to send reject response.
++               * NOTE; Not checking for FIP->state such as VNMP_UP or
++               * VNMP_CLAIM because if FIP state is not one of those,
++               * RPORT wouldn;t have created and 'rport_lookup' would have
++               * failed anyway in that case.
++               */
++              if (lport->point_to_multipoint)
++                      break;
+       case RPORT_ST_DELETE:
+               mutex_unlock(&rdata->rp_mutex);
+               rjt_data.reason = ELS_RJT_FIP;
diff --git a/queue-3.0/mpt2sas-added-did_no_connect-return-when-driver-remove-and-avoid-shutdown-call.patch b/queue-3.0/mpt2sas-added-did_no_connect-return-when-driver-remove-and-avoid-shutdown-call.patch
new file mode 100644 (file)
index 0000000..2218003
--- /dev/null
@@ -0,0 +1,40 @@
+From 7821578caa8cb831868989041112ab808029ca65 Mon Sep 17 00:00:00 2001
+From: "Kashyap, Desai" <kashyap.desai@lsi.com>
+Date: Tue, 14 Jun 2011 10:57:08 +0530
+Subject: [SCSI] mpt2sas: Added DID_NO_CONNECT return when driver remove and avoid shutdown call
+
+From: "Kashyap, Desai" <kashyap.desai@lsi.com>
+
+commit 7821578caa8cb831868989041112ab808029ca65 upstream.
+
+Driver should not call shutdown call from _scsih_remove otherwise,
+The scsi midlayer can be deadlocked when devices are removed from the driver
+pci_driver->shutdown handler.
+
+Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -3698,7 +3698,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd,
+               return 0;
+       }
+-      if (ioc->pci_error_recovery) {
++      if (ioc->pci_error_recovery || ioc->remove_host) {
+               scmd->result = DID_NO_CONNECT << 16;
+               scmd->scsi_done(scmd);
+               return 0;
+@@ -7211,7 +7211,6 @@ _scsih_remove(struct pci_dev *pdev)
+       }
+       sas_remove_host(shost);
+-      _scsih_shutdown(pdev);
+       list_del(&ioc->list);
+       scsi_remove_host(shost);
+       scsi_host_put(shost);
diff --git a/queue-3.0/mpt2sas-adding-support-for-customer-specific-branding.patch b/queue-3.0/mpt2sas-adding-support-for-customer-specific-branding.patch
new file mode 100644 (file)
index 0000000..cfa0859
--- /dev/null
@@ -0,0 +1,73 @@
+From ab3e5f60d1fc8fe725d02510ff820ff207a8dbef Mon Sep 17 00:00:00 2001
+From: "Kashyap, Desai" <kashyap.desai@lsi.com>
+Date: Tue, 14 Jun 2011 10:57:31 +0530
+Subject: [SCSI] mpt2sas: Adding support for customer specific branding
+
+From: "Kashyap, Desai" <kashyap.desai@lsi.com>
+
+commit ab3e5f60d1fc8fe725d02510ff820ff207a8dbef upstream.
+
+Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.c |   19 +++++++++++++++++--
+ drivers/scsi/mpt2sas/mpt2sas_base.h |    3 +++
+ 2 files changed, 20 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
+@@ -1740,9 +1740,11 @@ _base_display_dell_branding(struct MPT2S
+ static void
+ _base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
+ {
+-      if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_INTEL &&
+-          ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008) {
++      if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL)
++              return;
++      switch (ioc->pdev->device) {
++      case MPI2_MFGPAGE_DEVID_SAS2008:
+               switch (ioc->pdev->subsystem_device) {
+               case MPT2SAS_INTEL_RMS2LL080_SSDID:
+                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+@@ -1752,7 +1754,20 @@ _base_display_intel_branding(struct MPT2
+                       printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+                           MPT2SAS_INTEL_RMS2LL040_BRANDING);
+                       break;
++              default:
++                      break;
++              }
++      case MPI2_MFGPAGE_DEVID_SAS2308_2:
++              switch (ioc->pdev->subsystem_device) {
++              case MPT2SAS_INTEL_RS25GB008_SSDID:
++                      printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
++                          MPT2SAS_INTEL_RS25GB008_BRANDING);
++                      break;
++              default:
++                      break;
+               }
++      default:
++              break;
+       }
+ }
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -161,12 +161,15 @@
+                               "Intel Integrated RAID Module RMS2LL080"
+ #define MPT2SAS_INTEL_RMS2LL040_BRANDING      \
+                               "Intel Integrated RAID Module RMS2LL040"
++#define MPT2SAS_INTEL_RS25GB008_BRANDING       \
++                              "Intel(R) RAID Controller RS25GB008"
+ /*
+  * Intel HBA SSDIDs
+  */
+ #define MPT2SAS_INTEL_RMS2LL080_SSDID          0x350E
+ #define MPT2SAS_INTEL_RMS2LL040_SSDID          0x350F
++#define MPT2SAS_INTEL_RS25GB008_SSDID          0x3000
+ /*
diff --git a/queue-3.0/perf-x86-add-model-45-sandybridge-support.patch b/queue-3.0/perf-x86-add-model-45-sandybridge-support.patch
new file mode 100644 (file)
index 0000000..0187703
--- /dev/null
@@ -0,0 +1,33 @@
+From a34668f6beb4ab01e07683276d6a24bab6c175e0 Mon Sep 17 00:00:00 2001
+From: Youquan Song <youquan.song@intel.com>
+Date: Tue, 2 Aug 2011 14:01:35 +0800
+Subject: perf, x86: Add model 45 SandyBridge support
+
+From: Youquan Song <youquan.song@intel.com>
+
+commit a34668f6beb4ab01e07683276d6a24bab6c175e0 upstream.
+
+Add support to Romely-EP SandyBridge.
+
+Signed-off-by: Youquan Song <youquan.song@intel.com>
+Signed-off-by: Anhua Xu <anhua.xu@intel.com>
+Signed-off-by: Lin Ming <ming.m.lin@intel.com>
+Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Link: http://lkml.kernel.org/r/1312264895-2010-1-git-send-email-youquan.song@intel.com
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/cpu/perf_event_intel.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/x86/kernel/cpu/perf_event_intel.c
++++ b/arch/x86/kernel/cpu/perf_event_intel.c
+@@ -1495,6 +1495,7 @@ static __init int intel_pmu_init(void)
+               break;
+       case 42: /* SandyBridge */
++      case 45: /* SandyBridge, "Romely-EP" */
+               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
diff --git a/queue-3.0/qdio-clear-shared-dsci-before-scheduling-the-queue-handler.patch b/queue-3.0/qdio-clear-shared-dsci-before-scheduling-the-queue-handler.patch
new file mode 100644 (file)
index 0000000..0dbb462
--- /dev/null
@@ -0,0 +1,93 @@
+From b02f0c2ea25781e0f94b4fc8f6f85582057857b3 Mon Sep 17 00:00:00 2001
+From: Jan Glauber <jang@linux.vnet.ibm.com>
+Date: Sun, 24 Jul 2011 10:48:00 +0200
+Subject: [S390] qdio: clear shared DSCI before scheduling the queue handler
+
+From: Jan Glauber <jang@linux.vnet.ibm.com>
+
+commit b02f0c2ea25781e0f94b4fc8f6f85582057857b3 upstream.
+
+The following race can occur with qdio devices that use the shared device
+state change indicator:
+
+Device (Shared DSCI)    CPU0                            CPU1
+===============================================================================
+
+1. DSCI 0 => 1,
+   INT pending
+                        2. Thinint handler
+                        * si_used = 1
+                        * Inbound tasklet_schedule
+                        * DSCI 1 => 0
+
+3. DSCI 0 => 1,
+   INT pending
+
+                                                        4. Thinint handler
+                                                        * si_used = 1
+                                                        * Inbound tasklet_schedu
+le
+                                                           => NOP
+
+                        5. Inbound tasklet run
+
+6. DSCI = 1,
+   INT surpressed
+
+                                                        7. DSCI 1 => 0
+
+The race would lead to a stall where new data in the input queue is
+not recognized so the device stops working in case of no further traffic.
+
+Fix the race by resetting the DSCI before scheduling the inbound tasklet
+so the device generates an interrupt if new data arrives in the above
+scenario in step 6.
+
+Reviewed-by: Ursula Braun <ursula.braun@de.ibm.com>
+Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/s390/cio/qdio_thinint.c |   15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/s390/cio/qdio_thinint.c
++++ b/drivers/s390/cio/qdio_thinint.c
+@@ -95,9 +95,11 @@ void tiqdio_remove_input_queues(struct q
+       }
+ }
+-static inline u32 shared_ind_set(void)
++static inline u32 clear_shared_ind(void)
+ {
+-      return q_indicators[TIQDIO_SHARED_IND].ind;
++      if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count))
++              return 0;
++      return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
+ }
+ /**
+@@ -107,7 +109,7 @@ static inline u32 shared_ind_set(void)
+  */
+ static void tiqdio_thinint_handler(void *alsi, void *data)
+ {
+-      u32 si_used = shared_ind_set();
++      u32 si_used = clear_shared_ind();
+       struct qdio_q *q;
+       last_ai_time = S390_lowcore.int_clock;
+@@ -150,13 +152,6 @@ static void tiqdio_thinint_handler(void
+               qperf_inc(q, adapter_int);
+       }
+       rcu_read_unlock();
+-
+-      /*
+-       * If the shared indicator was used clear it now after all queues
+-       * were processed.
+-       */
+-      if (si_used && shared_ind_set())
+-              xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
+ }
+ static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
index aa120adeea7f78f0752339ef16f47be604e21e93..9ebe3bab1684df35a47b2cb011ee2d095816ba25 100644 (file)
@@ -154,3 +154,22 @@ wireless-reset-beacon_found-while-updating-regulatory.patch
 rtl2800usb-fix-incorrect-storage-of-mac-address-on.patch
 iwlagn-workaround-bug-crashing-some-aps.patch
 blk-cgroup-be-able-to-remove-the-record-of-unplugged-device.patch
+iscsi_tcp-fix-locking-around-iscsi-sk-user-data.patch
+tg3-fix-io-failures-after-chip-reset.patch
+ipc-mqueue.c-refactor-failure-handling.patch
+ipc-mqueue.c-fix-mq_open-return-value.patch
+writeback-introduce-.tagged_writepages-for-the-wb_sync_none-sync-stage.patch
+writeback-update-dirtied_when-for-synced-inode-to-prevent-livelock.patch
+qdio-clear-shared-dsci-before-scheduling-the-queue-handler.patch
+tg3-add-5719-and-5720-to-eee_cap-list.patch
+tg3-fix-int-selftest-for-recent-devices.patch
+ehci-refactor-pci-quirk-to-use-standard-dmi_check_system-method.patch
+ehci-add-pci-quirk-for-ordissimo-and-rm-slate-100-too.patch
+usb-pl2303-correctly-handle-baudrates-above-115200.patch
+asix-add-ax88772b-usb-id.patch
+cdc_ncm-fix-endianness-problem.patch
+libfc-enhancement-to-rport-state-machine-applicable-only-for-vn2vn-mode.patch
+fcoe-unable-to-select-the-exchangeid-from-offload-pool-for-storage-targets.patch
+mpt2sas-added-did_no_connect-return-when-driver-remove-and-avoid-shutdown-call.patch
+mpt2sas-adding-support-for-customer-specific-branding.patch
+perf-x86-add-model-45-sandybridge-support.patch
diff --git a/queue-3.0/tg3-add-5719-and-5720-to-eee_cap-list.patch b/queue-3.0/tg3-add-5719-and-5720-to-eee_cap-list.patch
new file mode 100644 (file)
index 0000000..8bcf3b4
--- /dev/null
@@ -0,0 +1,34 @@
+From 5baa5e9aa28baccd2a1227095c25bb3e999f250d Mon Sep 17 00:00:00 2001
+From: Matt Carlson <mcarlson@broadcom.com>
+Date: Wed, 20 Jul 2011 10:20:53 +0000
+Subject: tg3: Add 5719 and 5720 to EEE_CAP list
+
+From: Matt Carlson <mcarlson@broadcom.com>
+
+commit 5baa5e9aa28baccd2a1227095c25bb3e999f250d upstream.
+
+This patch adds the 5719 and the 5720 to the list of devices that are
+EEE capable.
+
+Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
+Reviewed-by: Michael Chan <mchan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/tg3.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -12941,7 +12941,9 @@ static int __devinit tg3_phy_probe(struc
+       }
+       if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
+-          ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
++          (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
++           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720 ||
++           (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
+             tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
+            (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+             tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
diff --git a/queue-3.0/tg3-fix-int-selftest-for-recent-devices.patch b/queue-3.0/tg3-fix-int-selftest-for-recent-devices.patch
new file mode 100644 (file)
index 0000000..4eb4a4b
--- /dev/null
@@ -0,0 +1,53 @@
+From 3aa1cdf87c0b3f2345e75c474acc32ebbf0a4724 Mon Sep 17 00:00:00 2001
+From: Matt Carlson <mcarlson@broadcom.com>
+Date: Wed, 20 Jul 2011 10:20:55 +0000
+Subject: tg3: Fix int selftest for recent devices.
+
+From: Matt Carlson <mcarlson@broadcom.com>
+
+commit 3aa1cdf87c0b3f2345e75c474acc32ebbf0a4724 upstream.
+
+This patch fixes interrupt selftest failures for recent devices (57765,
+5717, 5718. 5719, 5720) by disabling MSI one-shot mode and applying the
+status tag workaround to the selftest code.
+
+Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
+Reviewed-by: Michael Chan <mchan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/tg3.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -8982,7 +8982,7 @@ static int tg3_test_interrupt(struct tg3
+        * Turn off MSI one shot mode.  Otherwise this test has no
+        * observable way to know whether the interrupt was delivered.
+        */
+-      if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
++      if (tg3_flag(tp, 57765_PLUS)) {
+               val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE;
+               tw32(MSGINT_MODE, val);
+       }
+@@ -9010,6 +9010,10 @@ static int tg3_test_interrupt(struct tg3
+                       break;
+               }
++              if (tg3_flag(tp, 57765_PLUS) &&
++                  tnapi->hw_status->status_tag != tnapi->last_tag)
++                      tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
++
+               msleep(10);
+       }
+@@ -9024,7 +9028,7 @@ static int tg3_test_interrupt(struct tg3
+       if (intr_ok) {
+               /* Reenable MSI one shot mode. */
+-              if (tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
++              if (tg3_flag(tp, 57765_PLUS)) {
+                       val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
+                       tw32(MSGINT_MODE, val);
+               }
diff --git a/queue-3.0/tg3-fix-io-failures-after-chip-reset.patch b/queue-3.0/tg3-fix-io-failures-after-chip-reset.patch
new file mode 100644 (file)
index 0000000..a1389f3
--- /dev/null
@@ -0,0 +1,63 @@
+From 9e975cc291d80d5e4562d6bed15ec171e896d69b Mon Sep 17 00:00:00 2001
+From: Matt Carlson <mcarlson@broadcom.com>
+Date: Wed, 20 Jul 2011 10:20:50 +0000
+Subject: tg3: Fix io failures after chip reset
+
+From: Matt Carlson <mcarlson@broadcom.com>
+
+commit 9e975cc291d80d5e4562d6bed15ec171e896d69b upstream.
+
+Commit f2096f94b514d88593355995d5dd276961e88af1, entitled
+"tg3: Add 5720 H2BMC support", needed to add code to preserve some bits
+set by firmware.  Unfortunately the new code causes throughput to stop
+after a chip reset because it enables state machines before they are
+ready.  This patch undoes the problematic code.  The bits will be
+restored later in the init sequence.
+
+Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
+Reviewed-by: Michael Chan <mchan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/tg3.c |   18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/tg3.c
++++ b/drivers/net/tg3.c
+@@ -7267,16 +7267,11 @@ static int tg3_chip_reset(struct tg3 *tp
+               tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
+       }
+-      if (tg3_flag(tp, ENABLE_APE))
+-              tp->mac_mode = MAC_MODE_APE_TX_EN |
+-                             MAC_MODE_APE_RX_EN |
+-                             MAC_MODE_TDE_ENABLE;
+-
+       if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
+-              tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
++              tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
+               val = tp->mac_mode;
+       } else if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) {
+-              tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
++              tp->mac_mode = MAC_MODE_PORT_MODE_GMII;
+               val = tp->mac_mode;
+       } else
+               val = 0;
+@@ -8408,12 +8403,11 @@ static int tg3_reset_hw(struct tg3 *tp,
+               udelay(10);
+       }
+-      if (tg3_flag(tp, ENABLE_APE))
+-              tp->mac_mode = MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+-      else
+-              tp->mac_mode = 0;
+       tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
+-              MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
++                      MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE |
++                      MAC_MODE_FHDE_ENABLE;
++      if (tg3_flag(tp, ENABLE_APE))
++              tp->mac_mode |= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN;
+       if (!tg3_flag(tp, 5705_PLUS) &&
+           !(tp->phy_flags & TG3_PHYFLG_PHY_SERDES) &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
diff --git a/queue-3.0/usb-pl2303-correctly-handle-baudrates-above-115200.patch b/queue-3.0/usb-pl2303-correctly-handle-baudrates-above-115200.patch
new file mode 100644 (file)
index 0000000..4db6fb8
--- /dev/null
@@ -0,0 +1,53 @@
+From 8d48fdf689fed2c73c493e5146d1463689246442 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micha=C5=82=20Sroczy=C5=84ski?= <msroczyn@gmail.com>
+Date: Tue, 5 Jul 2011 21:53:35 +0200
+Subject: USB: PL2303: correctly handle baudrates above 115200
+
+From: Michal Sroczynski <msroczyn@gmail.com>
+
+commit 8d48fdf689fed2c73c493e5146d1463689246442 upstream.
+
+PL2303: correctly handle baudrates above 115200
+
+Signed-off-by: Michal Sroczynski <msroczyn@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/pl2303.c |   26 ++++++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -343,10 +343,28 @@ static void pl2303_set_termios(struct tt
+                               baud = 6000000;
+               }
+               dbg("%s - baud set = %d", __func__, baud);
+-              buf[0] = baud & 0xff;
+-              buf[1] = (baud >> 8) & 0xff;
+-              buf[2] = (baud >> 16) & 0xff;
+-              buf[3] = (baud >> 24) & 0xff;
++              if (baud <= 115200) {
++                      buf[0] = baud & 0xff;
++                      buf[1] = (baud >> 8) & 0xff;
++                      buf[2] = (baud >> 16) & 0xff;
++                      buf[3] = (baud >> 24) & 0xff;
++              } else {
++                      /* apparently the formula for higher speeds is:
++                       * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
++                       */
++                      unsigned tmp = 12*1000*1000*32 / baud;
++                      buf[3] = 0x80;
++                      buf[2] = 0;
++                      buf[1] = (tmp >= 256);
++                      while (tmp >= 256) {
++                              tmp >>= 2;
++                              buf[1] <<= 1;
++                      }
++                      if (tmp > 256) {
++                              tmp %= 256;
++                      }
++                      buf[0] = tmp;
++              }
+       }
+       /* For reference buf[4]=0 is 1 stop bits */
diff --git a/queue-3.0/writeback-introduce-.tagged_writepages-for-the-wb_sync_none-sync-stage.patch b/queue-3.0/writeback-introduce-.tagged_writepages-for-the-wb_sync_none-sync-stage.patch
new file mode 100644 (file)
index 0000000..3001a4f
--- /dev/null
@@ -0,0 +1,141 @@
+From 6e6938b6d3130305a5960c86b1a9b21e58cf6144 Mon Sep 17 00:00:00 2001
+From: Wu Fengguang <fengguang.wu@intel.com>
+Date: Sun, 6 Jun 2010 10:38:15 -0600
+Subject: writeback: introduce .tagged_writepages for the WB_SYNC_NONE sync stage
+
+From: Wu Fengguang <fengguang.wu@intel.com>
+
+commit 6e6938b6d3130305a5960c86b1a9b21e58cf6144 upstream.
+
+sync(2) is performed in two stages: the WB_SYNC_NONE sync and the
+WB_SYNC_ALL sync. Identify the first stage with .tagged_writepages and
+do livelock prevention for it, too.
+
+Jan's commit f446daaea9 ("mm: implement writeback livelock avoidance
+using page tagging") is a partial fix in that it only fixed the
+WB_SYNC_ALL phase livelock.
+
+Although ext4 is tested to no longer livelock with commit f446daaea9,
+it may due to some "redirty_tail() after pages_skipped" effect which
+is by no means a guarantee for _all_ the file systems.
+
+Note that writeback_inodes_sb() is called by not only sync(), they are
+treated the same because the other callers also need livelock prevention.
+
+Impact:  It changes the order in which pages/inodes are synced to disk.
+Now in the WB_SYNC_NONE stage, it won't proceed to write the next inode
+until finished with the current inode.
+
+Acked-by: Jan Kara <jack@suse.cz>
+CC: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext4/inode.c           |    4 ++--
+ fs/fs-writeback.c         |   17 +++++++++--------
+ include/linux/writeback.h |    1 +
+ mm/page-writeback.c       |    4 ++--
+ 4 files changed, 14 insertions(+), 12 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2756,7 +2756,7 @@ static int write_cache_pages_da(struct a
+       index = wbc->range_start >> PAGE_CACHE_SHIFT;
+       end = wbc->range_end >> PAGE_CACHE_SHIFT;
+-      if (wbc->sync_mode == WB_SYNC_ALL)
++      if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+               tag = PAGECACHE_TAG_TOWRITE;
+       else
+               tag = PAGECACHE_TAG_DIRTY;
+@@ -2988,7 +2988,7 @@ static int ext4_da_writepages(struct add
+       }
+ retry:
+-      if (wbc->sync_mode == WB_SYNC_ALL)
++      if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+               tag_pages_for_writeback(mapping, index, end);
+       while (!ret && wbc->nr_to_write > 0) {
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -36,6 +36,7 @@ struct wb_writeback_work {
+       long nr_pages;
+       struct super_block *sb;
+       enum writeback_sync_modes sync_mode;
++      unsigned int tagged_writepages:1;
+       unsigned int for_kupdate:1;
+       unsigned int range_cyclic:1;
+       unsigned int for_background:1;
+@@ -650,6 +651,7 @@ static long wb_writeback(struct bdi_writ
+ {
+       struct writeback_control wbc = {
+               .sync_mode              = work->sync_mode,
++              .tagged_writepages      = work->tagged_writepages,
+               .older_than_this        = NULL,
+               .for_kupdate            = work->for_kupdate,
+               .for_background         = work->for_background,
+@@ -657,7 +659,7 @@ static long wb_writeback(struct bdi_writ
+       };
+       unsigned long oldest_jif;
+       long wrote = 0;
+-      long write_chunk;
++      long write_chunk = MAX_WRITEBACK_PAGES;
+       struct inode *inode;
+       if (wbc.for_kupdate) {
+@@ -683,9 +685,7 @@ static long wb_writeback(struct bdi_writ
+        *                   (quickly) tag currently dirty pages
+        *                   (maybe slowly) sync all tagged pages
+        */
+-      if (wbc.sync_mode == WB_SYNC_NONE)
+-              write_chunk = MAX_WRITEBACK_PAGES;
+-      else
++      if (wbc.sync_mode == WB_SYNC_ALL || wbc.tagged_writepages)
+               write_chunk = LONG_MAX;
+       wbc.wb_start = jiffies; /* livelock avoidance */
+@@ -1188,10 +1188,11 @@ void writeback_inodes_sb_nr(struct super
+ {
+       DECLARE_COMPLETION_ONSTACK(done);
+       struct wb_writeback_work work = {
+-              .sb             = sb,
+-              .sync_mode      = WB_SYNC_NONE,
+-              .done           = &done,
+-              .nr_pages       = nr,
++              .sb                     = sb,
++              .sync_mode              = WB_SYNC_NONE,
++              .tagged_writepages      = 1,
++              .done                   = &done,
++              .nr_pages               = nr,
+       };
+       WARN_ON(!rwsem_is_locked(&sb->s_umount));
+--- a/include/linux/writeback.h
++++ b/include/linux/writeback.h
+@@ -47,6 +47,7 @@ struct writeback_control {
+       unsigned encountered_congestion:1; /* An output: a queue is full */
+       unsigned for_kupdate:1;         /* A kupdate writeback */
+       unsigned for_background:1;      /* A background writeback */
++      unsigned tagged_writepages:1;   /* tag-and-write to avoid livelock */
+       unsigned for_reclaim:1;         /* Invoked from the page allocator */
+       unsigned range_cyclic:1;        /* range_start is cyclic */
+       unsigned more_io:1;             /* more io to be dispatched */
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -892,12 +892,12 @@ int write_cache_pages(struct address_spa
+                       range_whole = 1;
+               cycled = 1; /* ignore range_cyclic tests */
+       }
+-      if (wbc->sync_mode == WB_SYNC_ALL)
++      if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+               tag = PAGECACHE_TAG_TOWRITE;
+       else
+               tag = PAGECACHE_TAG_DIRTY;
+ retry:
+-      if (wbc->sync_mode == WB_SYNC_ALL)
++      if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages)
+               tag_pages_for_writeback(mapping, index, end);
+       done_index = index;
+       while (!done && (index <= end)) {
diff --git a/queue-3.0/writeback-update-dirtied_when-for-synced-inode-to-prevent-livelock.patch b/queue-3.0/writeback-update-dirtied_when-for-synced-inode-to-prevent-livelock.patch
new file mode 100644 (file)
index 0000000..cb574cd
--- /dev/null
@@ -0,0 +1,60 @@
+From 94c3dcbb0b0cdfd82cedd21705424d8044edc42c Mon Sep 17 00:00:00 2001
+From: Wu Fengguang <fengguang.wu@intel.com>
+Date: Wed, 27 Apr 2011 19:05:21 -0600
+Subject: writeback: update dirtied_when for synced inode to prevent livelock
+
+From: Wu Fengguang <fengguang.wu@intel.com>
+
+commit 94c3dcbb0b0cdfd82cedd21705424d8044edc42c upstream.
+
+Explicitly update .dirtied_when on synced inodes, so that they are no
+longer considered for writeback in the next round.
+
+It can prevent both of the following livelock schemes:
+
+- while true; do echo data >> f; done
+- while true; do touch f;        done (in theory)
+
+The exact livelock condition is, during sync(1):
+
+(1) no new inodes are dirtied
+(2) an inode being actively dirtied
+
+On (2), the inode will be tagged and synced with .nr_to_write=LONG_MAX.
+When finished, it will be redirty_tail()ed because it's still dirty
+and (.nr_to_write > 0). redirty_tail() won't update its ->dirtied_when
+on condition (1). The sync work will then revisit it on the next
+queue_io() and find it eligible again because its old ->dirtied_when
+predates the sync work start time.
+
+We'll do more aggressive "keep writeback as long as we wrote something"
+logic in wb_writeback(). The "use LONG_MAX .nr_to_write" trick in commit
+b9543dac5bbc ("writeback: avoid livelocking WB_SYNC_ALL writeback") will
+no longer be enough to stop sync livelock.
+
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/fs-writeback.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -419,6 +419,15 @@ writeback_single_inode(struct inode *ino
+       spin_lock(&inode->i_lock);
+       inode->i_state &= ~I_SYNC;
+       if (!(inode->i_state & I_FREEING)) {
++              /*
++               * Sync livelock prevention. Each inode is tagged and synced in
++               * one shot. If still dirty, it will be redirty_tail()'ed below.
++               * Update the dirty time to prevent enqueue and sync it again.
++               */
++              if ((inode->i_state & I_DIRTY) &&
++                  (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages))
++                      inode->dirtied_when = jiffies;
++
+               if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
+                       /*
+                        * We didn't write back all the pages.  nfs_writepages()