diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-09-21 15:57:24 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-09-21 15:57:24 -0700 |
commit | f09b31fa971e99069f8dc68a87c7db2cf5ac77a7 (patch) | |
tree | f6f44300c816250db54c3339a1494eeaf1cef5a2 | |
parent | 614915851e064c8d4a127bcf669e468aa2ec4eb3 (diff) | |
download | stable-queue-f09b31fa971e99069f8dc68a87c7db2cf5ac77a7.tar.gz |
3.0 patches
20 files changed, 1576 insertions, 0 deletions
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 index 0000000000..90122a1bb7 --- /dev/null +++ b/queue-3.0/asix-add-ax88772b-usb-id.patch @@ -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 index 0000000000..79678c700d --- /dev/null +++ b/queue-3.0/cdc_ncm-fix-endianness-problem.patch @@ -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 index 0000000000..552c6666d5 --- /dev/null +++ b/queue-3.0/ehci-add-pci-quirk-for-ordissimo-and-rm-slate-100-too.patch @@ -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 index 0000000000..1e85ce6dac --- /dev/null +++ b/queue-3.0/ehci-refactor-pci-quirk-to-use-standard-dmi_check_system-method.patch @@ -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 index 0000000000..b521c25d7e --- /dev/null +++ b/queue-3.0/fcoe-unable-to-select-the-exchangeid-from-offload-pool-for-storage-targets.patch @@ -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 index 0000000000..5d728748d7 --- /dev/null +++ b/queue-3.0/ipc-mqueue.c-fix-mq_open-return-value.patch @@ -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 index 0000000000..9784fb6a8f --- /dev/null +++ b/queue-3.0/ipc-mqueue.c-refactor-failure-handling.patch @@ -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 index 0000000000..b748782939 --- /dev/null +++ b/queue-3.0/iscsi_tcp-fix-locking-around-iscsi-sk-user-data.patch @@ -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 index 0000000000..b33b12ca8d --- /dev/null +++ b/queue-3.0/libfc-enhancement-to-rport-state-machine-applicable-only-for-vn2vn-mode.patch @@ -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 index 0000000000..2218003605 --- /dev/null +++ b/queue-3.0/mpt2sas-added-did_no_connect-return-when-driver-remove-and-avoid-shutdown-call.patch @@ -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 index 0000000000..cfa08591b9 --- /dev/null +++ b/queue-3.0/mpt2sas-adding-support-for-customer-specific-branding.patch @@ -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 index 0000000000..0187703aec --- /dev/null +++ b/queue-3.0/perf-x86-add-model-45-sandybridge-support.patch @@ -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 index 0000000000..0dbb462fb4 --- /dev/null +++ b/queue-3.0/qdio-clear-shared-dsci-before-scheduling-the-queue-handler.patch @@ -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) diff --git a/queue-3.0/series b/queue-3.0/series index aa120adeea..9ebe3bab16 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 0000000000..8bcf3b44c6 --- /dev/null +++ b/queue-3.0/tg3-add-5719-and-5720-to-eee_cap-list.patch @@ -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 index 0000000000..4eb4a4bb2b --- /dev/null +++ b/queue-3.0/tg3-fix-int-selftest-for-recent-devices.patch @@ -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 index 0000000000..a1389f395f --- /dev/null +++ b/queue-3.0/tg3-fix-io-failures-after-chip-reset.patch @@ -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 index 0000000000..4db6fb8538 --- /dev/null +++ b/queue-3.0/usb-pl2303-correctly-handle-baudrates-above-115200.patch @@ -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 index 0000000000..3001a4faa5 --- /dev/null +++ b/queue-3.0/writeback-introduce-.tagged_writepages-for-the-wb_sync_none-sync-stage.patch @@ -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 index 0000000000..cb574cd6b8 --- /dev/null +++ b/queue-3.0/writeback-update-dirtied_when-for-synced-inode-to-prevent-livelock.patch @@ -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() |