public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org,
	alan@lxorguk.ukuu.org.uk,
	Larry Finger <Larry.Finger@lwfinger.net>
Subject: [patch 76/86] staging: r8712u: Use asynchronous firmware loading
Date: Fri, 10 Feb 2012 14:30:35 -0800	[thread overview]
Message-ID: <20120210222951.788092831@clark.kroah.org> (raw)
In-Reply-To: <20120210223514.GA24190@kroah.com>

3.2-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Larry Finger <Larry.Finger@lwfinger.net>

commit 8c213fa59199f9673d66970d6940fa093186642f upstream.

In https://bugs.archlinux.org/task/27996, failure of driver r8712u is
reported, with a timeout during module loading due to synchronous loading
of the firmware. The code now uses request_firmware_nowait().

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/staging/rtl8712/drv_types.h   |    7 +++
 drivers/staging/rtl8712/hal_init.c    |   62 +++++++++++++++++++++++-----------
 drivers/staging/rtl8712/os_intfs.c    |   14 ++++++-
 drivers/staging/rtl8712/rtl8712_hal.h |    1 
 drivers/staging/rtl8712/usb_intf.c    |    9 +++-
 5 files changed, 68 insertions(+), 25 deletions(-)

--- a/drivers/staging/rtl8712/drv_types.h
+++ b/drivers/staging/rtl8712/drv_types.h
@@ -37,6 +37,8 @@ struct _adapter;
 #include "wlan_bssdef.h"
 #include "rtl8712_spec.h"
 #include "rtl8712_hal.h"
+#include <linux/mutex.h>
+#include <linux/completion.h>
 
 enum _NIC_VERSION {
 	RTL8711_NIC,
@@ -168,6 +170,7 @@ struct _adapter {
 	s32	bSurpriseRemoved;
 	u32	IsrContent;
 	u32	ImrContent;
+	bool	fw_found;
 	u8	EepromAddressSize;
 	u8	hw_init_completed;
 	struct task_struct *cmdThread;
@@ -184,6 +187,10 @@ struct _adapter {
 	_workitem wkFilterRxFF0;
 	u8 blnEnableRxFF0Filter;
 	spinlock_t lockRxFF0Filter;
+	const struct firmware *fw;
+	struct usb_interface *pusb_intf;
+	struct mutex mutex_start;
+	struct completion rtl8712_fw_ready;
 };
 
 static inline u8 *myid(struct eeprom_priv *peepriv)
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -42,29 +42,56 @@
 #define FWBUFF_ALIGN_SZ 512
 #define MAX_DUMP_FWSZ	49152 /*default = 49152 (48k)*/
 
-static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl,
-		    const u8 **ppmappedfw)
+static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
 {
+	struct _adapter *padapter = context;
+
+	complete(&padapter->rtl8712_fw_ready);
+	if (!firmware) {
+		struct usb_device *udev = padapter->dvobjpriv.pusbdev;
+		struct usb_interface *pusb_intf = padapter->pusb_intf;
+		printk(KERN_ERR "r8712u: Firmware request failed\n");
+		padapter->fw_found = false;
+		usb_put_dev(udev);
+		usb_set_intfdata(pusb_intf, NULL);
+		return;
+	}
+	padapter->fw = firmware;
+	padapter->fw_found = true;
+	/* firmware available - start netdev */
+	register_netdev(padapter->pnetdev);
+}
+
+static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+
+int rtl871x_load_fw(struct _adapter *padapter)
+{
+	struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
 	int rc;
-	const char firmware_file[] = "rtlwifi/rtl8712u.bin";
-	const struct firmware **praw = (const struct firmware **)
-				       (pphfwfile_hdl);
-	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
-					(&padapter->dvobjpriv);
-	struct usb_device *pusbdev = pdvobjpriv->pusbdev;
 
+	init_completion(&padapter->rtl8712_fw_ready);
 	printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",
 	       firmware_file);
-	rc = request_firmware(praw, firmware_file, &pusbdev->dev);
-	if (rc < 0) {
-		printk(KERN_ERR "r8712u: Unable to load firmware\n");
-		printk(KERN_ERR "r8712u: Install latest linux-firmware\n");
+	rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
+				     GFP_KERNEL, padapter, rtl871x_load_fw_cb);
+	if (rc)
+		printk(KERN_ERR "r8712u: Firmware request error %d\n", rc);
+	return rc;
+}
+MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
+
+static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw)
+{
+	const struct firmware **praw = &padapter->fw;
+
+	if (padapter->fw->size > 200000) {
+		printk(KERN_ERR "r8172u: Badfw->size of %d\n",
+		       (int)padapter->fw->size);
 		return 0;
 	}
 	*ppmappedfw = (u8 *)((*praw)->data);
 	return (*praw)->size;
 }
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
 
 static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
 {
@@ -142,18 +169,17 @@ static u8 rtl8712_dl_fw(struct _adapter
 	uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
 	struct fw_hdr fwhdr;
 	u32 ulfilelength;	/* FW file size */
-	void *phfwfile_hdl = NULL;
 	const u8 *pmappedfw = NULL;
 	u8 *ptmpchar = NULL, *ppayload, *ptr;
 	struct tx_desc *ptx_desc;
 	u32 txdscp_sz = sizeof(struct tx_desc);
 	u8 ret = _FAIL;
 
-	ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw);
+	ulfilelength = rtl871x_open_fw(padapter, &pmappedfw);
 	if (pmappedfw && (ulfilelength > 0)) {
 		update_fwhdr(&fwhdr, pmappedfw);
 		if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
-			goto firmware_rel;
+			return ret;
 		fill_fwpriv(padapter, &fwhdr.fwpriv);
 		/* firmware check ok */
 		maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
@@ -161,7 +187,7 @@ static u8 rtl8712_dl_fw(struct _adapter
 		maxlen += txdscp_sz;
 		ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ);
 		if (ptmpchar == NULL)
-			goto firmware_rel;
+			return ret;
 
 		ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ -
 			    ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1)));
@@ -297,8 +323,6 @@ static u8 rtl8712_dl_fw(struct _adapter
 
 exit_fail:
 	kfree(ptmpchar);
-firmware_rel:
-	release_firmware((struct firmware *)phfwfile_hdl);
 	return ret;
 }
 
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
+#include <linux/firmware.h>
 #include "osdep_service.h"
 #include "drv_types.h"
 #include "xmit_osdep.h"
@@ -264,12 +265,12 @@ static void start_drv_timers(struct _ada
 void r8712_stop_drv_timers(struct _adapter *padapter)
 {
 	_cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
-	_cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
-			 sitesurvey_ctrl_timer);
 	_cancel_timer_ex(&padapter->securitypriv.tkip_timer);
 	_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
 	_cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);
 	_cancel_timer_ex(&padapter->mlmepriv.wdg_timer);
+	_cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
+			 sitesurvey_ctrl_timer);
 }
 
 static u8 init_default_value(struct _adapter *padapter)
@@ -347,7 +348,8 @@ u8 r8712_free_drv_sw(struct _adapter *pa
 	r8712_free_mlme_priv(&padapter->mlmepriv);
 	r8712_free_io_queue(padapter);
 	_free_xmit_priv(&padapter->xmitpriv);
-	_r8712_free_sta_priv(&padapter->stapriv);
+	if (padapter->fw_found)
+		_r8712_free_sta_priv(&padapter->stapriv);
 	_r8712_free_recv_priv(&padapter->recvpriv);
 	mp871xdeinit(padapter);
 	if (pnetdev)
@@ -388,6 +390,7 @@ static int netdev_open(struct net_device
 {
 	struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
 
+	mutex_lock(&padapter->mutex_start);
 	if (padapter->bup == false) {
 		padapter->bDriverStopped = false;
 		padapter->bSurpriseRemoved = false;
@@ -435,11 +438,13 @@ static int netdev_open(struct net_device
 	/* start driver mlme relation timer */
 	start_drv_timers(padapter);
 	padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
+	mutex_unlock(&padapter->mutex_start);
 	return 0;
 netdev_open_error:
 	padapter->bup = false;
 	netif_carrier_off(pnetdev);
 	netif_stop_queue(pnetdev);
+	mutex_unlock(&padapter->mutex_start);
 	return -1;
 }
 
@@ -473,6 +478,9 @@ static int netdev_close(struct net_devic
 	r8712_free_network_queue(padapter);
 	/* The interface is no longer Up: */
 	padapter->bup = false;
+	release_firmware(padapter->fw);
+	/* never exit with a firmware callback pending */
+	wait_for_completion(&padapter->rtl8712_fw_ready);
 	return 0;
 }
 
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ b/drivers/staging/rtl8712/rtl8712_hal.h
@@ -145,5 +145,6 @@ struct hal_priv {
 };
 
 uint	 rtl8712_hal_init(struct _adapter *padapter);
+int rtl871x_load_fw(struct _adapter *padapter);
 
 #endif
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -390,6 +390,7 @@ static int r871xu_drv_init(struct usb_in
 	pdvobjpriv = &padapter->dvobjpriv;
 	pdvobjpriv->padapter = padapter;
 	padapter->dvobjpriv.pusbdev = udev;
+	padapter->pusb_intf = pusb_intf;
 	usb_set_intfdata(pusb_intf, pnetdev);
 	SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
 	/* step 2. */
@@ -596,10 +597,11 @@ static int r871xu_drv_init(struct usb_in
 			       "%pM\n", mac);
 		memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
 	}
-	/* step 6. Tell the network stack we exist */
-	if (register_netdev(pnetdev) != 0)
+	/* step 6. Load the firmware asynchronously */
+	if (rtl871x_load_fw(padapter))
 		goto error;
 	spin_lock_init(&padapter->lockRxFF0Filter);
+	mutex_init(&padapter->mutex_start);
 	return 0;
 error:
 	usb_put_dev(udev);
@@ -630,7 +632,8 @@ static void r871xu_dev_remove(struct usb
 		flush_scheduled_work();
 		udelay(1);
 		/*Stop driver mlme relation timer */
-		r8712_stop_drv_timers(padapter);
+		if (padapter->fw_found)
+			r8712_stop_drv_timers(padapter);
 		r871x_dev_unload(padapter);
 		r8712_free_drv_sw(padapter);
 	}



  parent reply	other threads:[~2012-02-10 23:08 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-10 22:35 [patch 00/86] 3.2.6-stable review Greg KH
2012-02-10 22:29 ` [patch 01/86] readahead: fix pipeline break caused by block plug Greg KH
2012-02-10 22:29 ` [patch 02/86] ALSA: hda - Fix the logic to detect VIA analog low-current mode Greg KH
2012-02-10 22:29 ` [patch 03/86] ALSA: HDA: Remove quirk for Asus N53Jq Greg KH
2012-02-10 22:29 ` [patch 04/86] ALSA: hda - Apply 0x0f-VREF fix to all ASUS laptops with ALC861/660 Greg KH
2012-02-10 22:29 ` [patch 05/86] ALSA: hda - Fix calling cs_automic twice for Cirrus codecs Greg KH
2012-02-10 22:29 ` [patch 06/86] ALSA: hda - Allow analog low-current mode when dynamic power-control is on Greg KH
2012-02-10 22:29 ` [patch 07/86] ALSA: HDA: Fix duplicated output to more than one codec Greg KH
2012-02-10 22:29 ` [patch 08/86] ALSA: hda - Disable dynamic-power control for VIA as default Greg KH
2012-02-10 22:29 ` [patch 09/86] ASoC: wm_hubs: Enable line out VMID buffer for single ended line outputs Greg KH
2012-02-10 22:29 ` [patch 10/86] ASoC: wm_hubs: fix wrong bits for LINEOUT2 N/P mixer Greg KH
2012-02-10 22:29 ` [patch 11/86] ARM: 7306/1: vfp: flush thread hwstate before restoring context from sigframe Greg KH
2012-02-10 22:29 ` [patch 12/86] ARM: 7307/1: vfp: fix ptrace regset modification race Greg KH
2012-02-10 22:29 ` [patch 13/86] ARM: 7308/1: vfp: flush thread hwstate before copying ptrace registers Greg KH
2012-02-10 22:29 ` [patch 14/86] ARM: OMAP2+: GPMC: fix device size setup Greg KH
2012-02-10 22:29 ` [patch 15/86] drivers/tty/vt/vt_ioctl.c: fix KDFONTOP 32bit compatibility layer Greg KH
2012-02-10 22:29 ` [patch 16/86] proc: mem_release() should check mm != NULL Greg KH
2012-02-10 22:29 ` [patch 17/86] proc: unify mem_read() and mem_write() Greg KH
2012-02-10 22:29 ` [patch 18/86] proc: make sure mem_open() doesnt pin the targets memory Greg KH
2012-02-10 22:29 ` [patch 19/86] firewire: ohci: add reset packet quirk for SB Audigy Greg KH
2012-02-10 22:29 ` [patch 20/86] firewire: ohci: disable MSI on Ricoh controllers Greg KH
2012-02-10 22:29 ` [patch 21/86] IB/mlx4: pass SMP vendor-specific attribute MADs to firmware Greg KH
2012-02-10 22:29 ` [patch 22/86] RDMA/core: Fix kernel panic by always initializing qp->usecnt Greg KH
2012-02-10 22:29 ` [patch 23/86] kprobes: fix a memory leak in function pre_handler_kretprobe() Greg KH
2012-02-10 22:29 ` [patch 24/86] mtd: gpmi-nand bugfix: reset the BCH module when it is not MX23 Greg KH
2012-02-10 22:29 ` [patch 25/86] Revert "mtd: atmel_nand: optimize read/write buffer functions" Greg KH
2012-02-10 22:29 ` [patch 26/86] at_hdmac: bugfix for enabling channel irq Greg KH
2012-02-10 22:29 ` [patch 27/86] mm/filemap_xip.c: fix race condition in xip_file_fault() Greg KH
2012-02-10 22:29 ` [patch 28/86] mm: compaction: check pfn_valid when entering a new MAX_ORDER_NR_PAGES block during isolation for migration Greg KH
2012-02-10 22:29 ` [patch 29/86] PM / Hibernate: Fix s2disk regression related to freezing workqueues Greg KH
2012-02-10 22:29 ` [patch 30/86] PM / QoS: CPU C-state breakage with PM Qos change Greg KH
2012-02-10 22:29 ` [patch 31/86] drm/radeon: Set DESKTOP_HEIGHT register to the framebuffer (not mode) height Greg KH
2012-02-10 22:29 ` [patch 32/86] drm/nouveau/gem: fix fence_sync race / oops Greg KH
2012-02-10 22:29 ` [patch 33/86] drm/radeon/kms: disable output polling when suspended Greg KH
2012-02-10 22:29 ` [patch 34/86] drm/radeon/kms: fix TRAVIS panel setup Greg KH
2012-02-10 22:29 ` [patch 35/86] sched/rt: Fix task stack corruption under __ARCH_WANT_INTERRUPTS_ON_CTXSW Greg KH
2012-02-10 22:29 ` [patch 36/86] PM / Hibernate: Thaw processes in SNAPSHOT_CREATE_IMAGE ioctl test path Greg KH
2012-02-10 22:29 ` [patch 37/86] PM / Hibernate: Thaw kernel threads in SNAPSHOT_CREATE_IMAGE ioctl path Greg KH
2012-02-10 22:29 ` [patch 38/86] 8139cp: fix missing napi_gro_flush Greg KH
2012-02-10 22:29 ` [patch 39/86] udf: Mark LVID buffer as uptodate before marking it dirty Greg KH
2012-02-10 22:29 ` [patch 40/86] drm/i915: HDMI hot remove notification to audio driver Greg KH
2012-02-10 22:30 ` [patch 41/86] drm/i915: DisplayPort " Greg KH
2012-02-10 22:30 ` [patch 42/86] drm/i915: check ACTHD of all rings Greg KH
2012-02-10 22:30 ` [patch 43/86] drm/i915: Fix TV Out refresh rate Greg KH
2012-02-10 22:30 ` [patch 44/86] drm/i915: handle 3rd pipe Greg KH
2012-02-10 22:30 ` [patch 45/86] drm/i915: convert force_wake_get to func pointer in the gpu reset code Greg KH
2012-02-10 22:30 ` [patch 46/86] drm/i915: protect force_wake_(get|put) with the gt_lock Greg KH
2012-02-10 22:30 ` [patch 47/86] eCryptfs: Infinite loop due to overflow in ecryptfs_write() Greg KH
2012-02-10 22:30 ` [patch 48/86] hwmon: (w83627ehf) Fix number of fans for NCT6776F Greg KH
2012-02-10 22:30 ` [patch 49/86] cifs: Fix oops in session setup code for null user mounts Greg KH
2012-02-10 22:30 ` [patch 50/86] atmel_lcdfb: fix usage of CONTRAST_CTR in suspend/resume Greg KH
2012-02-10 22:30 ` [patch 51/86] lockdep, bug: Exclude TAINT_FIRMWARE_WORKAROUND from disabling lockdep Greg KH
2012-02-10 22:30 ` [patch 52/86] lockdep, bug: Exclude TAINT_OOT_MODULE from disabling lock debugging Greg KH
2012-02-10 22:30 ` [patch 53/86] iscsi-target: Fix reject release handling in iscsit_free_cmd() Greg KH
2012-02-10 22:30 ` [patch 54/86] iscsi-target: Fix double list_add with iscsit_alloc_buffs reject Greg KH
2012-02-10 22:30 ` [patch 55/86] iscsi-target: Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT Greg KH
2012-02-10 22:30 ` [patch 56/86] ASoC: wm_hubs: Fix routing of input PGAs to line output mixer Greg KH
2012-02-10 22:30 ` [patch 57/86] ASoC: wm_hubs: Correct line input to line output 2 paths Greg KH
2012-02-10 22:30 ` [patch 58/86] ASoC: wm8962: Fix word length configuration Greg KH
2012-02-10 22:30 ` [patch 59/86] ASoC: wm8994: Enabling VMID should take a runtime PM reference Greg KH
2012-02-10 22:30 ` [patch 60/86] ASoC: wm8994: Fix typo in VMID ramp setting Greg KH
2012-02-10 22:30 ` [patch 61/86] pcmcia: fix socket refcount decrementing on each resume Greg KH
2012-02-10 22:30 ` [patch 62/86] ALSA: oxygen, virtuoso: fix exchanged L/R volumes of aux and CD inputs Greg KH
2012-02-10 22:30 ` [patch 63/86] iommu/amd: Work around broken IVRS tables Greg KH
2012-02-10 22:30 ` [patch 64/86] iommu/msm: Fix error handling in msm_iommu_unmap() Greg KH
2012-02-10 22:30 ` [patch 65/86] mm: compaction: check for overlapping nodes during isolation for migration Greg KH
2012-02-10 22:30 ` [patch 66/86] mm: fix UP THP spin_is_locked BUGs Greg KH
2012-02-10 22:30 ` [patch 67/86] target: Use correct preempted registration sense code Greg KH
2012-02-10 22:30 ` [patch 68/86] target: Allow PERSISTENT RESERVE IN for non-reservation holder Greg KH
2012-02-10 22:30 ` [patch 69/86] target: Correct sense key for INVALID FIELD IN {PARAMETER LIST,CDB} Greg KH
2012-02-10 22:30 ` [patch 70/86] target: Add workaround for zero-length control CDB handling Greg KH
2012-02-10 22:30 ` [patch 71/86] target: Return correct ASC for unimplemented VPD pages Greg KH
2012-02-10 22:30 ` [patch 72/86] target: Fail INQUIRY commands with EVPD==0 but PAGE CODE!=0 Greg KH
2012-02-10 22:30 ` [patch 73/86] Staging: asus_oled: fix image processing Greg KH
2012-02-10 22:30 ` [patch 74/86] Staging: asus_oled: fix NULL-ptr crash on unloading Greg KH
2012-02-10 22:30 ` [patch 75/86] staging: r8712u: Add new Sitecom UsB ID Greg KH
2012-02-10 22:30 ` Greg KH [this message]
2012-02-10 22:30 ` [patch 77/86] usb: ch9.h: usb_endpoint_maxp() uses __le16_to_cpu() Greg KH
2012-02-10 22:30 ` [patch 78/86] usb: gadget: zero: fix bug in loopback autoresume handling Greg KH
2012-02-10 22:30 ` [patch 79/86] usb: Skip PCI USB quirk handling for Netlogic XLP Greg KH
2012-02-10 22:30 ` [patch 80/86] USB: usbserial: add new PID number (0xa951) to the ftdi driver Greg KH
2012-02-10 22:30 ` [patch 81/86] USB: add new zte 3g-dongles pid to option.c Greg KH
2012-02-10 22:30 ` [patch 82/86] zcache: Set SWIZ_BITS to 8 to reduce tmem bucket lock contention Greg KH
2012-02-10 22:30 ` [patch 83/86] zcache: fix deadlock condition Greg KH
2012-02-10 22:30 ` [patch 84/86] mmc: cb710 core: Add missing spin_lock_init for irq_lock of struct cb710_chip Greg KH
2012-02-10 22:30 ` [patch 85/86] [CPUFREQ] powernow-k8: Avoid Pstate MSR accesses on systems supporting CPB Greg KH
2012-02-10 22:30 ` [patch 86/86] [CPUFREQ] powernow-k8: Fix indexing issue Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120210222951.788092831@clark.kroah.org \
    --to=gregkh@linuxfoundation.org \
    --cc=Larry.Finger@lwfinger.net \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox