linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: <vikas.chaudhary@qlogic.com>
To: jbottomley@parallels.com, michaelc@cs.wisc.edu
Cc: linux-scsi@vger.kernel.org, vikas.chaudhary@qlogic.com,
	lalit.chandivade@qlogic.com
Subject: [PATCH 3/8] qla4xxx: Add host statistics support
Date: Fri, 22 Nov 2013 05:28:19 -0500	[thread overview]
Message-ID: <1385116104-19784-4-git-send-email-vikas.chaudhary@qlogic.com> (raw)
In-Reply-To: <1385116104-19784-1-git-send-email-vikas.chaudhary@qlogic.com>

From: Lalit Chandivade <lalit.chandivade@qlogic.com>

The statistics include MAC, TCP/IP & iSCSI statistics.

Signed-off-by: Lalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
---
 drivers/scsi/qla4xxx/ql4_fw.h |  83 ++++++++++++++++-
 drivers/scsi/qla4xxx/ql4_os.c | 205 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 287 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index fef311d..8d4092b 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -1297,7 +1297,88 @@ struct response {
 };
 
 struct ql_iscsi_stats {
-	uint8_t reserved1[656]; /* 0000-028F */
+	uint64_t mac_tx_frames; /* 0000–0007 */
+	uint64_t mac_tx_bytes; /* 0008–000F */
+	uint64_t mac_tx_multicast_frames; /* 0010–0017 */
+	uint64_t mac_tx_broadcast_frames; /* 0018–001F */
+	uint64_t mac_tx_pause_frames; /* 0020–0027 */
+	uint64_t mac_tx_control_frames; /* 0028–002F */
+	uint64_t mac_tx_deferral; /* 0030–0037 */
+	uint64_t mac_tx_excess_deferral; /* 0038–003F */
+	uint64_t mac_tx_late_collision; /* 0040–0047 */
+	uint64_t mac_tx_abort; /* 0048–004F */
+	uint64_t mac_tx_single_collision; /* 0050–0057 */
+	uint64_t mac_tx_multiple_collision; /* 0058–005F */
+	uint64_t mac_tx_collision; /* 0060–0067 */
+	uint64_t mac_tx_frames_dropped; /* 0068–006F */
+	uint64_t mac_tx_jumbo_frames; /* 0070–0077 */
+	uint64_t mac_rx_frames; /* 0078–007F */
+	uint64_t mac_rx_bytes; /* 0080–0087 */
+	uint64_t mac_rx_unknown_control_frames; /* 0088–008F */
+	uint64_t mac_rx_pause_frames; /* 0090–0097 */
+	uint64_t mac_rx_control_frames; /* 0098–009F */
+	uint64_t mac_rx_dribble; /* 00A0–00A7 */
+	uint64_t mac_rx_frame_length_error; /* 00A8–00AF */
+	uint64_t mac_rx_jabber; /* 00B0–00B7 */
+	uint64_t mac_rx_carrier_sense_error; /* 00B8–00BF */
+	uint64_t mac_rx_frame_discarded; /* 00C0–00C7 */
+	uint64_t mac_rx_frames_dropped; /* 00C8–00CF */
+	uint64_t mac_crc_error; /* 00D0–00D7 */
+	uint64_t mac_encoding_error; /* 00D8–00DF */
+	uint64_t mac_rx_length_error_large; /* 00E0–00E7 */
+	uint64_t mac_rx_length_error_small; /* 00E8–00EF */
+	uint64_t mac_rx_multicast_frames; /* 00F0–00F7 */
+	uint64_t mac_rx_broadcast_frames; /* 00F8–00FF */
+	uint64_t ip_tx_packets; /* 0100–0107 */
+	uint64_t ip_tx_bytes; /* 0108–010F */
+	uint64_t ip_tx_fragments; /* 0110–0117 */
+	uint64_t ip_rx_packets; /* 0118–011F */
+	uint64_t ip_rx_bytes; /* 0120–0127 */
+	uint64_t ip_rx_fragments; /* 0128–012F */
+	uint64_t ip_datagram_reassembly; /* 0130–0137 */
+	uint64_t ip_invalid_address_error; /* 0138–013F */
+	uint64_t ip_error_packets; /* 0140–0147 */
+	uint64_t ip_fragrx_overlap; /* 0148–014F */
+	uint64_t ip_fragrx_outoforder; /* 0150–0157 */
+	uint64_t ip_datagram_reassembly_timeout; /* 0158–015F */
+	uint64_t ipv6_tx_packets; /* 0160–0167 */
+	uint64_t ipv6_tx_bytes; /* 0168–016F */
+	uint64_t ipv6_tx_fragments; /* 0170–0177 */
+	uint64_t ipv6_rx_packets; /* 0178–017F */
+	uint64_t ipv6_rx_bytes; /* 0180–0187 */
+	uint64_t ipv6_rx_fragments; /* 0188–018F */
+	uint64_t ipv6_datagram_reassembly; /* 0190–0197 */
+	uint64_t ipv6_invalid_address_error; /* 0198–019F */
+	uint64_t ipv6_error_packets; /* 01A0–01A7 */
+	uint64_t ipv6_fragrx_overlap; /* 01A8–01AF */
+	uint64_t ipv6_fragrx_outoforder; /* 01B0–01B7 */
+	uint64_t ipv6_datagram_reassembly_timeout; /* 01B8–01BF */
+	uint64_t tcp_tx_segments; /* 01C0–01C7 */
+	uint64_t tcp_tx_bytes; /* 01C8–01CF */
+	uint64_t tcp_rx_segments; /* 01D0–01D7 */
+	uint64_t tcp_rx_byte; /* 01D8–01DF */
+	uint64_t tcp_duplicate_ack_retx; /* 01E0–01E7 */
+	uint64_t tcp_retx_timer_expired; /* 01E8–01EF */
+	uint64_t tcp_rx_duplicate_ack; /* 01F0–01F7 */
+	uint64_t tcp_rx_pure_ackr; /* 01F8–01FF */
+	uint64_t tcp_tx_delayed_ack; /* 0200–0207 */
+	uint64_t tcp_tx_pure_ack; /* 0208–020F */
+	uint64_t tcp_rx_segment_error; /* 0210–0217 */
+	uint64_t tcp_rx_segment_outoforder; /* 0218–021F */
+	uint64_t tcp_rx_window_probe; /* 0220–0227 */
+	uint64_t tcp_rx_window_update; /* 0228–022F */
+	uint64_t tcp_tx_window_probe_persist; /* 0230–0237 */
+	uint64_t ecc_error_correction; /* 0238–023F */
+	uint64_t iscsi_pdu_tx; /* 0240-0247 */
+	uint64_t iscsi_data_bytes_tx; /* 0248-024F */
+	uint64_t iscsi_pdu_rx; /* 0250-0257 */
+	uint64_t iscsi_data_bytes_rx; /* 0258-025F */
+	uint64_t iscsi_io_completed; /* 0260-0267 */
+	uint64_t iscsi_unexpected_io_rx; /* 0268-026F */
+	uint64_t iscsi_format_error; /* 0270-0277 */
+	uint64_t iscsi_hdr_digest_error; /* 0278-027F */
+	uint64_t iscsi_data_digest_error; /* 0280-0287 */
+	uint64_t iscsi_sequence_error; /* 0288-028F */
 	uint32_t tx_cmd_pdu; /* 0290-0293 */
 	uint32_t tx_resp_pdu; /* 0294-0297 */
 	uint32_t rx_cmd_pdu; /* 0298-029B */
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 60d050e..aa438f2 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -151,6 +151,7 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
 static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx);
 static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void  *data,
 				  int len);
+static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len);
 
 /*
  * SCSI host template entry points
@@ -262,6 +263,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
 	.login_flashnode	= qla4xxx_sysfs_ddb_login,
 	.logout_flashnode	= qla4xxx_sysfs_ddb_logout,
 	.logout_flashnode_sid	= qla4xxx_sysfs_ddb_logout_sid,
+	.get_host_stats		= qla4xxx_get_host_stats,
 };
 
 static struct scsi_transport_template *qla4xxx_scsi_transport;
@@ -947,6 +949,209 @@ exit_set_chap:
 	return rc;
 }
 
+
+static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len)
+{
+	struct scsi_qla_host *ha = to_qla_host(shost);
+	struct iscsi_offload_host_stats *host_stats = NULL;
+	int host_stats_size;
+	int ret = 0;
+	int ddb_idx = 0;
+	struct ql_iscsi_stats *ql_iscsi_stats = NULL;
+	int stats_size;
+	dma_addr_t iscsi_stats_dma;
+
+	DEBUG2(ql4_printk(KERN_INFO, ha, "Func: %s\n", __func__));
+
+	host_stats_size = sizeof(struct iscsi_offload_host_stats);
+
+	if (host_stats_size != len) {
+		ql4_printk(KERN_INFO, ha, "%s: host_stats size mismatch expected = %d, is = %d\n",
+			   __func__, len, host_stats_size);
+		ret = -EINVAL;
+		goto exit_host_stats;
+	}
+	host_stats = (struct iscsi_offload_host_stats *)buf;
+
+	if (!buf) {
+		ret = -ENOMEM;
+		goto exit_host_stats;
+	}
+
+	stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats));
+
+	ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size,
+					    &iscsi_stats_dma, GFP_KERNEL);
+	if (!ql_iscsi_stats) {
+		ql4_printk(KERN_ERR, ha,
+			   "Unable to allocate memory for iscsi stats\n");
+		goto exit_host_stats;
+	}
+
+	ret =  qla4xxx_get_mgmt_data(ha, ddb_idx, stats_size,
+				     iscsi_stats_dma);
+	if (ret != QLA_SUCCESS) {
+		ql4_printk(KERN_ERR, ha,
+			   "Unable to retrieve iscsi stats\n");
+		goto exit_host_stats;
+	}
+	host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames);
+	host_stats->mactx_bytes = le64_to_cpu(ql_iscsi_stats->mac_tx_bytes);
+	host_stats->mactx_multicast_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_multicast_frames);
+	host_stats->mactx_broadcast_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_broadcast_frames);
+	host_stats->mactx_pause_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_pause_frames);
+	host_stats->mactx_control_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_control_frames);
+	host_stats->mactx_deferral =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_deferral);
+	host_stats->mactx_excess_deferral =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_excess_deferral);
+	host_stats->mactx_late_collision =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_late_collision);
+	host_stats->mactx_abort	= le64_to_cpu(ql_iscsi_stats->mac_tx_abort);
+	host_stats->mactx_single_collision =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_single_collision);
+	host_stats->mactx_multiple_collision =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_multiple_collision);
+	host_stats->mactx_collision =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_collision);
+	host_stats->mactx_frames_dropped =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_frames_dropped);
+	host_stats->mactx_jumbo_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_tx_jumbo_frames);
+	host_stats->macrx_frames = le64_to_cpu(ql_iscsi_stats->mac_rx_frames);
+	host_stats->macrx_bytes = le64_to_cpu(ql_iscsi_stats->mac_rx_bytes);
+	host_stats->macrx_unknown_control_frames =
+		le64_to_cpu(ql_iscsi_stats->mac_rx_unknown_control_frames);
+	host_stats->macrx_pause_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_pause_frames);
+	host_stats->macrx_control_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_control_frames);
+	host_stats->macrx_dribble =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_dribble);
+	host_stats->macrx_frame_length_error =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_frame_length_error);
+	host_stats->macrx_jabber = le64_to_cpu(ql_iscsi_stats->mac_rx_jabber);
+	host_stats->macrx_carrier_sense_error =
+		le64_to_cpu(ql_iscsi_stats->mac_rx_carrier_sense_error);
+	host_stats->macrx_frame_discarded =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_frame_discarded);
+	host_stats->macrx_frames_dropped =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_frames_dropped);
+	host_stats->mac_crc_error = le64_to_cpu(ql_iscsi_stats->mac_crc_error);
+	host_stats->mac_encoding_error =
+			le64_to_cpu(ql_iscsi_stats->mac_encoding_error);
+	host_stats->macrx_length_error_large =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_large);
+	host_stats->macrx_length_error_small =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_small);
+	host_stats->macrx_multicast_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_multicast_frames);
+	host_stats->macrx_broadcast_frames =
+			le64_to_cpu(ql_iscsi_stats->mac_rx_broadcast_frames);
+	host_stats->iptx_packets = le64_to_cpu(ql_iscsi_stats->ip_tx_packets);
+	host_stats->iptx_bytes = le64_to_cpu(ql_iscsi_stats->ip_tx_bytes);
+	host_stats->iptx_fragments =
+			le64_to_cpu(ql_iscsi_stats->ip_tx_fragments);
+	host_stats->iprx_packets = le64_to_cpu(ql_iscsi_stats->ip_rx_packets);
+	host_stats->iprx_bytes = le64_to_cpu(ql_iscsi_stats->ip_rx_bytes);
+	host_stats->iprx_fragments =
+			le64_to_cpu(ql_iscsi_stats->ip_rx_fragments);
+	host_stats->ip_datagram_reassembly =
+			le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly);
+	host_stats->ip_invalid_address_error =
+			le64_to_cpu(ql_iscsi_stats->ip_invalid_address_error);
+	host_stats->ip_error_packets =
+			le64_to_cpu(ql_iscsi_stats->ip_error_packets);
+	host_stats->ip_fragrx_overlap =
+			le64_to_cpu(ql_iscsi_stats->ip_fragrx_overlap);
+	host_stats->ip_fragrx_outoforder =
+			le64_to_cpu(ql_iscsi_stats->ip_fragrx_outoforder);
+	host_stats->ip_datagram_reassembly_timeout =
+		le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly_timeout);
+	host_stats->ipv6tx_packets =
+			le64_to_cpu(ql_iscsi_stats->ipv6_tx_packets);
+	host_stats->ipv6tx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_tx_bytes);
+	host_stats->ipv6tx_fragments =
+			le64_to_cpu(ql_iscsi_stats->ipv6_tx_fragments);
+	host_stats->ipv6rx_packets =
+			le64_to_cpu(ql_iscsi_stats->ipv6_rx_packets);
+	host_stats->ipv6rx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_rx_bytes);
+	host_stats->ipv6rx_fragments =
+			le64_to_cpu(ql_iscsi_stats->ipv6_rx_fragments);
+	host_stats->ipv6_datagram_reassembly =
+			le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly);
+	host_stats->ipv6_invalid_address_error =
+		le64_to_cpu(ql_iscsi_stats->ipv6_invalid_address_error);
+	host_stats->ipv6_error_packets =
+			le64_to_cpu(ql_iscsi_stats->ipv6_error_packets);
+	host_stats->ipv6_fragrx_overlap =
+			le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_overlap);
+	host_stats->ipv6_fragrx_outoforder =
+			le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_outoforder);
+	host_stats->ipv6_datagram_reassembly_timeout =
+		le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly_timeout);
+	host_stats->tcptx_segments =
+			le64_to_cpu(ql_iscsi_stats->tcp_tx_segments);
+	host_stats->tcptx_bytes	= le64_to_cpu(ql_iscsi_stats->tcp_tx_bytes);
+	host_stats->tcprx_segments =
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_segments);
+	host_stats->tcprx_byte = le64_to_cpu(ql_iscsi_stats->tcp_rx_byte);
+	host_stats->tcp_duplicate_ack_retx =
+			le64_to_cpu(ql_iscsi_stats->tcp_duplicate_ack_retx);
+	host_stats->tcp_retx_timer_expired =
+			le64_to_cpu(ql_iscsi_stats->tcp_retx_timer_expired);
+	host_stats->tcprx_duplicate_ack	=
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_duplicate_ack);
+	host_stats->tcprx_pure_ackr =
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_pure_ackr);
+	host_stats->tcptx_delayed_ack =
+			le64_to_cpu(ql_iscsi_stats->tcp_tx_delayed_ack);
+	host_stats->tcptx_pure_ack =
+			le64_to_cpu(ql_iscsi_stats->tcp_tx_pure_ack);
+	host_stats->tcprx_segment_error =
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_error);
+	host_stats->tcprx_segment_outoforder =
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_outoforder);
+	host_stats->tcprx_window_probe =
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_window_probe);
+	host_stats->tcprx_window_update =
+			le64_to_cpu(ql_iscsi_stats->tcp_rx_window_update);
+	host_stats->tcptx_window_probe_persist =
+		le64_to_cpu(ql_iscsi_stats->tcp_tx_window_probe_persist);
+	host_stats->ecc_error_correction =
+			le64_to_cpu(ql_iscsi_stats->ecc_error_correction);
+	host_stats->iscsi_pdu_tx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_tx);
+	host_stats->iscsi_data_bytes_tx =
+			le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_tx);
+	host_stats->iscsi_pdu_rx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_rx);
+	host_stats->iscsi_data_bytes_rx	=
+			le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_rx);
+	host_stats->iscsi_io_completed =
+			le64_to_cpu(ql_iscsi_stats->iscsi_io_completed);
+	host_stats->iscsi_unexpected_io_rx =
+			le64_to_cpu(ql_iscsi_stats->iscsi_unexpected_io_rx);
+	host_stats->iscsi_format_error =
+			le64_to_cpu(ql_iscsi_stats->iscsi_format_error);
+	host_stats->iscsi_hdr_digest_error =
+			le64_to_cpu(ql_iscsi_stats->iscsi_hdr_digest_error);
+	host_stats->iscsi_data_digest_error =
+			le64_to_cpu(ql_iscsi_stats->iscsi_data_digest_error);
+	host_stats->iscsi_sequence_error =
+			le64_to_cpu(ql_iscsi_stats->iscsi_sequence_error);
+exit_host_stats:
+	if (ql_iscsi_stats)
+		dma_free_coherent(&ha->pdev->dev, host_stats_size,
+				  ql_iscsi_stats, iscsi_stats_dma);
+
+	ql4_printk(KERN_INFO, ha, "%s: Get host stats done\n",
+		   __func__);
+	return ret;
+}
+
 static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
 				   enum iscsi_param_type param_type,
 				   int param, char *buf)
-- 
1.8.2.GIT

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2013-11-22 11:01 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-22 10:28 [PATCH 0/8] qla4xxx: 5.04.00-k3: Updates for scsi "misc" branch vikas.chaudhary
2013-11-22 10:28 ` [PATCH 1/8] qla4xxx: Added support for Diagnostics MBOX command vikas.chaudhary
2013-11-22 10:28 ` [PATCH 2/8] scsi_transport_iscsi: Add host statistics support vikas.chaudhary
2013-11-22 10:28 ` vikas.chaudhary [this message]
2013-11-22 10:28 ` [PATCH 4/8] scsi_transport_iscsi: Export ISCSI_PARAM_LOCAL_IPADDR attr for iscsi_connection vikas.chaudhary
2013-11-22 10:28 ` [PATCH 5/8] libiscsi: Add local_ipaddr parameter in iscsi_conn struct vikas.chaudhary
2013-11-22 10:28 ` [PATCH 6/8] qla4xxx: Add support for ISCSI_PARAM_LOCAL_IPADDR sysfs attr vikas.chaudhary
2013-11-22 10:28 ` [PATCH 7/8] qla4xxx: Recreate chap data list during get chap operation vikas.chaudhary
2013-11-22 10:28 ` [PATCH 8/8] qla4xxx: Update driver version to 5.04.00-k3 vikas.chaudhary
2013-12-17  7:23 ` [PATCH 0/8] qla4xxx: 5.04.00-k3: Updates for scsi "misc" branch Mike Christie

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=1385116104-19784-4-git-send-email-vikas.chaudhary@qlogic.com \
    --to=vikas.chaudhary@qlogic.com \
    --cc=jbottomley@parallels.com \
    --cc=lalit.chandivade@qlogic.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=michaelc@cs.wisc.edu \
    /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;
as well as URLs for NNTP newsgroup(s).