mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Paul Louvel" <paul.louvel@bootlin.com>
To: "Christophe Leroy (CS GROUP)" <chleroy@kernel.org>,
	"Paul Louvel" <paul.louvel@bootlin.com>,
	"Herbert Xu" <herbert@gondor.apana.org.au>,
	"David S. Miller" <davem@davemloft.net>
Cc: "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
	"Herve Codina" <herve.codina@bootlin.com>,
	<linux-crypto@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 18/29] crypto: talitos - Split SEC1/SEC2 code into separate function variants
Date: Thu, 04 Jun 2026 14:46:33 +0200	[thread overview]
Message-ID: <DJ09XQD7J67V.1UV4MA8CQMSZU@bootlin.com> (raw)
In-Reply-To: <d998ea38-8770-468f-bfdd-9bb4c34e54a7@kernel.org>

On Mon Jun 1, 2026 at 2:32 PM CEST, Christophe Leroy (CS GROUP) wrote:
>
>
> Le 28/05/2026 à 11:08, Paul Louvel a écrit :
>> Split the functions that have SEC1/SEC2-specific behavior into
>> separate sec1_ and sec2_ function variants, removing the runtime
>> is_sec1 checks from within each function body.
>
> Regarding naming, I would prefer prefixing with talitos1_ and talitos2_ 
> to stick with the already existing naming we already have today:
> - talitos1_done_ch0
> - talitos1_done_4ch
> - talitos1_interrupt_4ch,
> - talitos2_done_ch0_2,
> - talitos2_done_ch1_3,
> - talitos2_done_ch0,
> - talitos2_done_4ch,
> - talitos2_interrupt_4ch,
> - talitos2_interrupt_ch0_2,
> - talitos2_interrupt_ch1_3,
>
> Christophe
>

Understood.

>> 
>> The callers still dispatch between the two variants using local
>> is_sec1 variables and if/else checks.
>> 
>> Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
>> ---
>>   drivers/crypto/talitos/talitos.c | 524 +++++++++++++++++++++++++--------------
>>   drivers/crypto/talitos/talitos.h |  36 ++-
>>   2 files changed, 357 insertions(+), 203 deletions(-)
>> 
>> diff --git a/drivers/crypto/talitos/talitos.c b/drivers/crypto/talitos/talitos.c
>> index f38a156a0459..b6793d97735e 100644
>> --- a/drivers/crypto/talitos/talitos.c
>> +++ b/drivers/crypto/talitos/talitos.c
>> @@ -133,75 +133,124 @@ void unmap_single_talitos_ptr(struct device *dev,
>>   			 from_talitos_ptr_len(ptr, is_sec1), dir);
>>   }
>>   
>> -static int reset_channel(struct device *dev, int ch)
>> +static int sec1_reset_channel(struct device *dev, int ch)
>>   {
>>   	struct talitos_private *priv = dev_get_drvdata(dev);
>>   	unsigned int timeout = TALITOS_TIMEOUT;
>> -	bool is_sec1 = has_ftr_sec1(priv);
>>   
>> -	if (is_sec1) {
>> -		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
>> -			  TALITOS1_CCCR_LO_RESET);
>> +	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS1_CCCR_LO_RESET);
>>   
>> -		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
>> -			TALITOS1_CCCR_LO_RESET) && --timeout)
>> -			cpu_relax();
>> -	} else {
>> -		setbits32(priv->chan[ch].reg + TALITOS_CCCR,
>> -			  TALITOS2_CCCR_RESET);
>> +	while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR_LO) &
>> +		TALITOS1_CCCR_LO_RESET) &&
>> +	       --timeout)
>> +		cpu_relax();
>>   
>> -		while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
>> -			TALITOS2_CCCR_RESET) && --timeout)
>> -			cpu_relax();
>> +	if (timeout == 0) {
>> +		dev_err(dev, "failed to reset sec1 channel %d\n", ch);
>> +		return -EIO;
>>   	}
>>   
>> +	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
>> +		  TALITOS_CCCR_LO_NE | TALITOS_CCCR_LO_CDIE |
>> +			  TALITOS_CCCR_LO_CDWE);
>> +
>> +	return 0;
>> +}
>> +
>> +static int sec2_reset_channel(struct device *dev, int ch)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +	unsigned int timeout = TALITOS_TIMEOUT;
>> +
>> +	setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS2_CCCR_RESET);
>> +
>> +	while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
>> +		TALITOS2_CCCR_RESET) &&
>> +	       --timeout)
>> +		cpu_relax();
>> +
>>   	if (timeout == 0) {
>> -		dev_err(dev, "failed to reset channel %d\n", ch);
>> +		dev_err(dev, "failed to reset sec2 channel %d\n", ch);
>>   		return -EIO;
>>   	}
>>   
>> -	/* set 36-bit addressing, done writeback enable and done IRQ enable */
>> -	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
>> -		  TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
>> -	/* enable chaining descriptors */
>> -	if (is_sec1)
>> -		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
>> -			  TALITOS_CCCR_LO_NE);
>> +	setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
>> +		  TALITOS_CCCR_LO_EAE | TALITOS_CCCR_LO_CDWE |
>> +			  TALITOS_CCCR_LO_CDIE);
>>   
>> -	/* and ICCR writeback, if available */
>> +	/* ICCR writeback, if available */
>>   	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
>>   		setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
>> -		          TALITOS_CCCR_LO_IWSE);
>> +			  TALITOS_CCCR_LO_IWSE);
>>   
>>   	return 0;
>>   }
>>   
>> -static int reset_device(struct device *dev)
>> +static int sec1_reset_device(struct device *dev)
>>   {
>>   	struct talitos_private *priv = dev_get_drvdata(dev);
>>   	unsigned int timeout = TALITOS_TIMEOUT;
>> -	bool is_sec1 = has_ftr_sec1(priv);
>> -	u32 mcr = is_sec1 ? TALITOS1_MCR_SWR : TALITOS2_MCR_SWR;
>>   
>> -	setbits32(priv->reg + TALITOS_MCR, mcr);
>> +	setbits32(priv->reg + TALITOS_MCR, TALITOS1_MCR_SWR);
>>   
>> -	while ((in_be32(priv->reg + TALITOS_MCR) & mcr)
>> -	       && --timeout)
>> +	while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS1_MCR_SWR) &&
>> +	       --timeout)
>>   		cpu_relax();
>>   
>> -	if (priv->irq[1]) {
>> -		mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
>> -		setbits32(priv->reg + TALITOS_MCR, mcr);
>> +	if (timeout == 0) {
>> +		dev_err(dev, "failed to reset sec1 device\n");
>> +		return -EIO;
>>   	}
>>   
>> +	return 0;
>> +}
>> +
>> +static int sec2_reset_device(struct device *dev)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +	unsigned int timeout = TALITOS_TIMEOUT;
>> +
>> +	setbits32(priv->reg + TALITOS_MCR, TALITOS2_MCR_SWR);
>> +
>> +	while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS2_MCR_SWR) &&
>> +	       --timeout)
>> +		cpu_relax();
>> +
>> +	if (priv->irq[1])
>> +		setbits32(priv->reg + TALITOS_MCR,
>> +			  TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3);
>> +
>>   	if (timeout == 0) {
>> -		dev_err(dev, "failed to reset device\n");
>> +		dev_err(dev, "failed to reset sec2 device\n");
>>   		return -EIO;
>>   	}
>>   
>>   	return 0;
>>   }
>>   
>> +static void sec1_configure_device(struct device *dev)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +
>> +	clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
>> +	clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
>> +	/* disable parity error check in DEU (erroneous? test vect.) */
>> +	setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
>> +}
>> +
>> +static void sec2_configure_device(struct device *dev)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +
>> +	setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
>> +	setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
>> +
>> +	/* disable integrity check error interrupts (use writeback instead) */
>> +	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
>> +		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
>> +			  TALITOS_MDEUICR_LO_ICE);
>> +}
>> +
>>   /*
>>    * Reset and initialize the device
>>    */
>> @@ -217,80 +266,81 @@ static int init_device(struct device *dev)
>>   	 * are not fully cleared by writing the MCR:SWR bit,
>>   	 * set bit twice to completely reset
>>   	 */
>> -	err = reset_device(dev);
>> +	if (is_sec1)
>> +		err = sec1_reset_device(dev);
>> +	else
>> +		err = sec2_reset_device(dev);
>> +
>>   	if (err)
>>   		return err;
>>   
>> -	err = reset_device(dev);
>> +	if (is_sec1)
>> +		err = sec1_reset_device(dev);
>> +	else
>> +		err = sec2_reset_device(dev);
>>   	if (err)
>>   		return err;
>>   
>>   	/* reset channels */
>>   	for (ch = 0; ch < priv->num_channels; ch++) {
>> -		err = reset_channel(dev, ch);
>> +		if (is_sec1)
>> +			err = sec1_reset_channel(dev, ch);
>> +		else
>> +			err = sec2_reset_channel(dev, ch);
>>   		if (err)
>>   			return err;
>>   	}
>>   
>> -	/* enable channel done and error interrupts */
>> -	if (is_sec1) {
>> -		clrbits32(priv->reg + TALITOS_IMR, TALITOS1_IMR_INIT);
>> -		clrbits32(priv->reg + TALITOS_IMR_LO, TALITOS1_IMR_LO_INIT);
>> -		/* disable parity error check in DEU (erroneous? test vect.) */
>> -		setbits32(priv->reg_deu + TALITOS_EUICR, TALITOS1_DEUICR_KPE);
>> -	} else {
>> -		setbits32(priv->reg + TALITOS_IMR, TALITOS2_IMR_INIT);
>> -		setbits32(priv->reg + TALITOS_IMR_LO, TALITOS2_IMR_LO_INIT);
>> -	}
>> -
>> -	/* disable integrity check error interrupts (use writeback instead) */
>> -	if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
>> -		setbits32(priv->reg_mdeu + TALITOS_EUICR_LO,
>> -		          TALITOS_MDEUICR_LO_ICE);
>> +	if (is_sec1)
>> +		sec1_configure_device(dev);
>> +	else
>> +		sec2_configure_device(dev);
>>   
>>   	return 0;
>>   }
>>   
>> -static void dma_map_request(struct device *dev, struct talitos_request *request,
>> -			    struct talitos_desc *desc, bool is_sec1)
>> +static void sec1_dma_map_request(struct device *dev,
>> +				 struct talitos_request *request,
>> +				 struct talitos_desc *desc)
>>   {
>>   	struct talitos_edesc *edesc =
>>   		container_of(desc, struct talitos_edesc, desc);
>>   	dma_addr_t dma_desc, prev_dma_desc;
>>   	struct talitos_edesc *prev_edesc = NULL;
>>   
>> -	if (is_sec1) {
>> -		while (edesc) {
>> -			edesc->desc.hdr1 = edesc->desc.hdr;
>> +	while (edesc) {
>> +		edesc->desc.hdr1 = edesc->desc.hdr;
>>   
>> -			dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
>> -						  TALITOS_DESC_SIZE,
>> -						  DMA_BIDIRECTIONAL);
>> +		dma_desc = dma_map_single(dev, &edesc->desc.hdr1,
>> +					  TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>>   
>> -			if (!prev_edesc) {
>> -				request->dma_desc = dma_desc;
>> -				goto next;
>> -			}
>> +		if (!prev_edesc) {
>> +			request->dma_desc = dma_desc;
>> +			goto next;
>> +		}
>>   
>> -			/* Chain in any previous descriptors. */
>> +		/* Chain in any previous descriptors. */
>>   
>> -			prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
>> +		prev_edesc->desc.next_desc = cpu_to_be32(dma_desc);
>>   
>> -			dma_sync_single_for_device(dev, prev_dma_desc,
>> -						   TALITOS_DESC_SIZE,
>> -						   DMA_TO_DEVICE);
>> +		dma_sync_single_for_device(dev, prev_dma_desc,
>> +					   TALITOS_DESC_SIZE, DMA_TO_DEVICE);
>>   
>>   next:
>> -			prev_edesc = edesc;
>> -			prev_dma_desc = dma_desc;
>> -			edesc = edesc->next_desc;
>> -		}
>> -	} else {
>> -		request->dma_desc = dma_map_single(dev, desc, TALITOS_DESC_SIZE,
>> -						   DMA_BIDIRECTIONAL);
>> +		prev_edesc = edesc;
>> +		prev_dma_desc = dma_desc;
>> +		edesc = edesc->next_desc;
>>   	}
>>   }
>>   
>> +static void sec2_dma_map_request(struct device *dev,
>> +				 struct talitos_request *request,
>> +				 struct talitos_desc *desc)
>> +{
>> +	request->dma_desc =
>> +		dma_map_single(dev, desc, TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>> +}
>> +
>>   /**
>>    * talitos_submit - submits a descriptor to the device for processing
>>    * @dev:	the SEC device to be used
>> @@ -327,7 +377,10 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
>>   	request = &priv->chan[ch].fifo[head];
>>   
>>   	/* map descriptor and save caller data */
>> -	dma_map_request(dev, request, desc, is_sec1);
>> +	if (is_sec1)
>> +		sec1_dma_map_request(dev, request, desc);
>> +	else
>> +		sec2_dma_map_request(dev, request, desc);
>>   	request->callback = callback;
>>   	request->context = context;
>>   
>> @@ -349,19 +402,12 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
>>   	return -EINPROGRESS;
>>   }
>>   
>> -static __be32 get_request_hdr(struct device *dev,
>> -			      struct talitos_request *request, bool is_sec1)
>> +static __be32 sec1_get_request_hdr(struct device *dev,
>> +				   struct talitos_request *request)
>>   {
>>   	struct talitos_edesc *edesc;
>>   	dma_addr_t dma_desc;
>>   
>> -	if (!is_sec1) {
>> -		dma_sync_single_for_cpu(dev, request->dma_desc,
>> -					TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>> -
>> -		return request->desc->hdr;
>> -	}
>> -
>>   	edesc = container_of(request->desc, struct talitos_edesc, desc);
>>   	dma_desc = request->dma_desc;
>>   	while (edesc->next_desc) {
>> @@ -375,27 +421,37 @@ static __be32 get_request_hdr(struct device *dev,
>>   	return edesc->desc.hdr1;
>>   }
>>   
>> -static void dma_unmap_request(struct device *dev,
>> -			      struct talitos_request *request, bool is_sec1)
>> +static __be32 sec2_get_request_hdr(struct device *dev,
>> +				   struct talitos_request *request)
>> +{
>> +	dma_sync_single_for_cpu(dev, request->dma_desc, TALITOS_DESC_SIZE,
>> +				DMA_BIDIRECTIONAL);
>> +
>> +	return request->desc->hdr;
>> +}
>> +
>> +static void sec1_dma_unmap_request(struct device *dev,
>> +				   struct talitos_request *request)
>>   {
>>   	struct talitos_edesc *edesc;
>>   
>> -	if (is_sec1) {
>> -		dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
>> -				 DMA_BIDIRECTIONAL);
>> -		edesc = container_of(request->desc, struct talitos_edesc, desc);
>> -		while (edesc->next_desc) {
>> -			dma_unmap_single(dev,
>> -					 be32_to_cpu(edesc->desc.next_desc),
>> -					 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>> -			edesc = edesc->next_desc;
>> -		}
>> -	} else {
>> -		dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
>> -				 DMA_BIDIRECTIONAL);
>> +	dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
>> +			 DMA_BIDIRECTIONAL);
>> +	edesc = container_of(request->desc, struct talitos_edesc, desc);
>> +	while (edesc->next_desc) {
>> +		dma_unmap_single(dev, be32_to_cpu(edesc->desc.next_desc),
>> +				 TALITOS_DESC_SIZE, DMA_BIDIRECTIONAL);
>> +		edesc = edesc->next_desc;
>>   	}
>>   }
>>   
>> +static void sec2_dma_unmap_request(struct device *dev,
>> +				   struct talitos_request *request)
>> +{
>> +	dma_unmap_single(dev, request->dma_desc, TALITOS_DESC_SIZE,
>> +			 DMA_BIDIRECTIONAL);
>> +}
>> +
>>   /*
>>    * process what was done, notify callback of error if not
>>    */
>> @@ -417,7 +473,10 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
>>   
>>   		/* descriptors with their done bits set don't get the error */
>>   		rmb();
>> -		hdr = get_request_hdr(dev, request, is_sec1);
>> +		if (is_sec1)
>> +			hdr = sec1_get_request_hdr(dev, request);
>> +		else
>> +			hdr = sec2_get_request_hdr(dev, request);
>>   
>>   		if ((hdr & DESC_HDR_DONE) == DESC_HDR_DONE)
>>   			status = 0;
>> @@ -427,7 +486,10 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
>>   			else
>>   				status = error;
>>   
>> -		dma_unmap_request(dev, request, is_sec1);
>> +		if (is_sec1)
>> +			sec1_dma_unmap_request(dev, request);
>> +		else
>> +			sec2_dma_unmap_request(dev, request);
>>   
>>   		/* copy entries so we can call callback outside lock */
>>   		saved_req.desc = request->desc;
>> @@ -516,21 +578,30 @@ DEF_TALITOS2_DONE(ch0, TALITOS2_ISR_CH_0_DONE)
>>   DEF_TALITOS2_DONE(ch0_2, TALITOS2_ISR_CH_0_2_DONE)
>>   DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE)
>>   
>> -static __be32 search_desc_hdr_in_request(struct talitos_request *request,
>> -					 dma_addr_t cur_desc, bool is_sec1)
>> +static __be32 sec1_search_desc_hdr_in_request(struct talitos_request *request,
>> +					      dma_addr_t cur_desc)
>>   {
>>   	struct talitos_edesc *edesc;
>>   
>> -	if (request->dma_desc == cur_desc) {
>> +
>> +	if (request->dma_desc == cur_desc)
>>   		return request->desc->hdr;
>> -	} else if (is_sec1) {
>> -		edesc = container_of(request->desc, struct talitos_edesc, desc);
>> -		while (edesc->next_desc) {
>> -			if (edesc->desc.next_desc == cpu_to_be32(cur_desc))
>> -				return edesc->next_desc->desc.hdr1;
>> -			edesc = edesc->next_desc;
>> -		}
>> +
>> +	edesc = container_of(request->desc, struct talitos_edesc, desc);
>> +	while (edesc->next_desc) {
>> +		if (edesc->desc.next_desc == cpu_to_be32(cur_desc))
>> +			return edesc->next_desc->desc.hdr1;
>> +		edesc = edesc->next_desc;
>>   	}
>> +
>> +	return 0;
>> +}
>> +
>> +static __be32 sec2_search_desc_hdr_in_request(struct talitos_request *request,
>> +					      dma_addr_t cur_desc)
>> +{
>> +	if (request->dma_desc == cur_desc)
>> +		return request->desc->hdr;
>>   	return 0;
>>   }
>>   
>> @@ -559,7 +630,10 @@ static __be32 current_desc_hdr(struct device *dev, int ch)
>>   	do {
>>   		request = &priv->chan[ch].fifo[iter];
>>   
>> -		hdr = search_desc_hdr_in_request(request, cur_desc, is_sec1);
>> +		if (is_sec1)
>> +			hdr = sec1_search_desc_hdr_in_request(request, cur_desc);
>> +		else
>> +			hdr = sec2_search_desc_hdr_in_request(request, cur_desc);
>>   		if (hdr)
>>   			break;
>>   
>> @@ -647,79 +721,100 @@ static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
>>   			in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
>>   }
>>   
>> -/*
>> - * recover from error interrupts
>> - */
>> -static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
>> +static int sec1_talitos_handle_error(struct device *dev, u32 isr, u32 isr_lo)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +	int ch, error;
>> +	u32 v_lo;
>> +
>> +	for (ch = 0; ch < priv->num_channels; ch++) {
>> +		if (!TALITOS1_CH_HAS_ERROR(isr, ch))
>> +			continue;
>> +
>> +		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
>> +
>> +		error = -EINVAL;
>> +
>> +		if (v_lo & TALITOS1_CCPSR_LO_TEA)
>> +			dev_err(dev, "transfer error acknowledge\n");
>> +		if (v_lo & TALITOS1_CCPSR_LO_PTRNC)
>> +			dev_err(dev, "pointer not complete error\n");
>> +		if (v_lo & TALITOS1_CCPSR_LO_PE)
>> +			dev_err(dev, "parity error\n");
>> +		if (v_lo & TALITOS1_CCPSR_LO_IDH)
>> +			dev_err(dev, "illegal descriptor header error\n");
>> +		if (v_lo & TALITOS1_CCPSR_LO_SA)
>> +			dev_err(dev, "static assignment error\n");
>> +		if (v_lo & TALITOS1_CCPSR_LO_EU)
>> +			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
>> +
>> +		flush_channel(dev, ch, error, 1);
>> +		priv->ops->reset_channel(dev, ch);
>> +	}
>> +
>> +	if (isr_lo & TALITOS1_ISR_TEA_ERR)
>> +		dev_err(dev, "TEA error: ISR 0x%08x_%08x\n", isr, isr_lo);
>> +
>> +	return (isr & ~TALITOS1_ISR_4CHERR) || isr_lo;
>> +}
>> +
>> +static int sec2_talitos_handle_error(struct device *dev, u32 isr, u32 isr_lo)
>>   {
>>   	struct talitos_private *priv = dev_get_drvdata(dev);
>>   	unsigned int timeout = TALITOS_TIMEOUT;
>>   	int ch, error, reset_dev = 0;
>>   	u32 v_lo;
>> -	bool is_sec1 = has_ftr_sec1(priv);
>> -	int reset_ch = is_sec1 ? 1 : 0; /* only SEC2 supports continuation */
>> +	int reset_ch = 0;
>>   
>>   	for (ch = 0; ch < priv->num_channels; ch++) {
>> -		/* skip channels without errors */
>> -		if (is_sec1) {
>> -			/* bits 29, 31, 17, 19 */
>> -			if (!(isr & (1 << (29 + (ch & 1) * 2 - (ch & 2) * 6))))
>> -				continue;
>> -		} else {
>> -			if (!(isr & (1 << (ch * 2 + 1))))
>> -				continue;
>> -		}
>> +		if (!TALITOS2_CH_HAS_ERROR(isr, ch))
>> +			continue;
>>   
>>   		error = -EINVAL;
>>   
>>   		v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
>>   
>> -		if (v_lo & TALITOS_CCPSR_LO_DOF) {
>> +		if (v_lo & TALITOS2_CCPSR_LO_DOF) {
>>   			dev_err(dev, "double fetch fifo overflow error\n");
>>   			error = -EAGAIN;
>>   			reset_ch = 1;
>>   		}
>> -		if (v_lo & TALITOS_CCPSR_LO_SOF) {
>> +		if (v_lo & TALITOS2_CCPSR_LO_SOF) {
>>   			/* h/w dropped descriptor */
>>   			dev_err(dev, "single fetch fifo overflow error\n");
>>   			error = -EAGAIN;
>>   		}
>> -		if (v_lo & TALITOS_CCPSR_LO_MDTE)
>> +		if (v_lo & TALITOS2_CCPSR_LO_MDTE)
>>   			dev_err(dev, "master data transfer error\n");
>> -		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
>> -			dev_err(dev, is_sec1 ? "pointer not complete error\n"
>> -					     : "s/g data length zero error\n");
>> -		if (v_lo & TALITOS_CCPSR_LO_FPZ)
>> -			dev_err(dev, is_sec1 ? "parity error\n"
>> -					     : "fetch pointer zero error\n");
>> -		if (v_lo & TALITOS_CCPSR_LO_IDH)
>> +		if (v_lo & TALITOS2_CCPSR_LO_SGDLZ)
>> +			dev_err(dev, "s/g data length zero error\n");
>> +		if (v_lo & TALITOS2_CCPSR_LO_FPZ)
>> +			dev_err(dev, "fetch pointer zero error\n");
>> +		if (v_lo & TALITOS2_CCPSR_LO_IDH)
>>   			dev_err(dev, "illegal descriptor header error\n");
>> -		if (v_lo & TALITOS_CCPSR_LO_IEU)
>> -			dev_err(dev, is_sec1 ? "static assignment error\n"
>> -					     : "invalid exec unit error\n");
>> -		if (v_lo & TALITOS_CCPSR_LO_EU)
>> +		if (v_lo & TALITOS2_CCPSR_LO_IEU)
>> +			dev_err(dev, "invalid exec unit error\n");
>> +		if (v_lo & TALITOS2_CCPSR_LO_EU)
>>   			report_eu_error(dev, ch, current_desc_hdr(dev, ch));
>> -		if (!is_sec1) {
>> -			if (v_lo & TALITOS_CCPSR_LO_GB)
>> -				dev_err(dev, "gather boundary error\n");
>> -			if (v_lo & TALITOS_CCPSR_LO_GRL)
>> -				dev_err(dev, "gather return/length error\n");
>> -			if (v_lo & TALITOS_CCPSR_LO_SB)
>> -				dev_err(dev, "scatter boundary error\n");
>> -			if (v_lo & TALITOS_CCPSR_LO_SRL)
>> -				dev_err(dev, "scatter return/length error\n");
>> -		}
>> +		if (v_lo & TALITOS2_CCPSR_LO_GB)
>> +			dev_err(dev, "gather boundary error\n");
>> +		if (v_lo & TALITOS2_CCPSR_LO_GRL)
>> +			dev_err(dev, "gather return/length error\n");
>> +		if (v_lo & TALITOS2_CCPSR_LO_SB)
>> +			dev_err(dev, "scatter boundary error\n");
>> +		if (v_lo & TALITOS2_CCPSR_LO_SRL)
>> +			dev_err(dev, "scatter return/length error\n");
>>   
>>   		flush_channel(dev, ch, error, reset_ch);
>>   
>>   		if (reset_ch) {
>> -			reset_channel(dev, ch);
>> +			priv->ops->reset_channel(dev, ch);
>>   		} else {
>>   			setbits32(priv->chan[ch].reg + TALITOS_CCCR,
>>   				  TALITOS2_CCCR_CONT);
>>   			setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
>>   			while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
>> -			       TALITOS2_CCCR_CONT) && --timeout)
>> +				TALITOS2_CCCR_CONT) && --timeout)
>>   				cpu_relax();
>>   			if (timeout == 0) {
>>   				dev_err(dev, "failed to restart channel %d\n",
>> @@ -728,14 +823,29 @@ static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
>>   			}
>>   		}
>>   	}
>> -	if (reset_dev || (is_sec1 && isr & ~TALITOS1_ISR_4CHERR) ||
>> -	    (!is_sec1 && isr & ~TALITOS2_ISR_4CHERR) || isr_lo) {
>> -		if (is_sec1 && (isr_lo & TALITOS1_ISR_TEA_ERR))
>> -			dev_err(dev, "TEA error: ISR 0x%08x_%08x\n",
>> -				isr, isr_lo);
>> -		else
>> -			dev_err(dev, "done overflow, internal time out, or "
>> -				"rngu error: ISR 0x%08x_%08x\n", isr, isr_lo);
>> +
>> +	return reset_dev || (isr & ~TALITOS2_ISR_4CHERR) || isr_lo;
>> +}
>> +
>> +/*
>> + * recover from error interrupts
>> + */
>> +static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +	bool is_sec1 = has_ftr_sec1(priv);
>> +	int ch, reset_dev;
>> +
>> +	if (is_sec1)
>> +		reset_dev = sec1_talitos_handle_error(dev, isr, isr_lo);
>> +	else
>> +		reset_dev = sec2_talitos_handle_error(dev, isr, isr_lo);
>> +
>> +	if (reset_dev) {
>> +		dev_err(dev,
>> +			"done overflow, internal time out, or "
>> +			"rngu error: ISR 0x%08x_%08x\n",
>> +			isr, isr_lo);
>>   
>>   		/* purge request queues */
>>   		for (ch = 0; ch < priv->num_channels; ch++)
>> @@ -1181,25 +1291,41 @@ int talitos_register_common(struct device *dev,
>>   	return 0;
>>   }
>>   
>> -static int talitos_probe_irq(struct platform_device *ofdev)
>> +static int sec1_talitos_probe_irq(struct platform_device *ofdev)
>>   {
>>   	struct device *dev = &ofdev->dev;
>>   	struct device_node *np = ofdev->dev.of_node;
>>   	struct talitos_private *priv = dev_get_drvdata(dev);
>>   	int err;
>> -	bool is_sec1 = has_ftr_sec1(priv);
>>   
>>   	priv->irq[0] = irq_of_parse_and_map(np, 0);
>>   	if (!priv->irq[0]) {
>>   		dev_err(dev, "failed to map irq\n");
>>   		return -EINVAL;
>>   	}
>> -	if (is_sec1) {
>> -		err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
>> -				  dev_driver_string(dev), dev);
>> -		goto primary_out;
>> +	err = request_irq(priv->irq[0], talitos1_interrupt_4ch, 0,
>> +			  dev_driver_string(dev), dev);
>> +	if (err) {
>> +		dev_err(dev, "failed to request primary irq\n");
>> +		irq_dispose_mapping(priv->irq[0]);
>> +		priv->irq[0] = 0;
>>   	}
>>   
>> +	return err;
>> +}
>> +
>> +static int sec2_talitos_probe_irq(struct platform_device *ofdev)
>> +{
>> +	struct device *dev = &ofdev->dev;
>> +	struct device_node *np = ofdev->dev.of_node;
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +	int err;
>> +
>> +	priv->irq[0] = irq_of_parse_and_map(np, 0);
>> +	if (!priv->irq[0]) {
>> +		dev_err(dev, "failed to map irq\n");
>> +		return -EINVAL;
>> +	}
>>   	priv->irq[1] = irq_of_parse_and_map(np, 1);
>>   
>>   	/* get the primary irq line */
>> @@ -1235,6 +1361,36 @@ static int talitos_probe_irq(struct platform_device *ofdev)
>>   	return err;
>>   }
>>   
>> +static void sec1_init_task(struct device *dev)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +
>> +	if (priv->num_channels == 1)
>> +		tasklet_init(&priv->done_task[0], talitos1_done_ch0,
>> +			     (unsigned long)dev);
>> +	else
>> +		tasklet_init(&priv->done_task[0], talitos1_done_4ch,
>> +			     (unsigned long)dev);
>> +}
>> +
>> +static void sec2_init_task(struct device *dev)
>> +{
>> +	struct talitos_private *priv = dev_get_drvdata(dev);
>> +
>> +	if (priv->irq[1]) {
>> +		tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
>> +			     (unsigned long)dev);
>> +		tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
>> +			     (unsigned long)dev);
>> +	} else if (priv->num_channels == 1) {
>> +		tasklet_init(&priv->done_task[0], talitos2_done_ch0,
>> +			     (unsigned long)dev);
>> +	} else {
>> +		tasklet_init(&priv->done_task[0], talitos2_done_4ch,
>> +			     (unsigned long)dev);
>> +	}
>> +}
>> +
>>   static int talitos_probe(struct platform_device *ofdev)
>>   {
>>   	struct device *dev = &ofdev->dev;
>> @@ -1317,31 +1473,17 @@ static int talitos_probe(struct platform_device *ofdev)
>>   		stride = TALITOS2_CH_STRIDE;
>>   	}
>>   
>> -	err = talitos_probe_irq(ofdev);
>> +	if (has_ftr_sec1(priv))
>> +		err = sec1_talitos_probe_irq(ofdev);
>> +	else
>> +		err = sec2_talitos_probe_irq(ofdev);
>>   	if (err)
>>   		goto err_out;
>>   
>> -	if (has_ftr_sec1(priv)) {
>> -		if (priv->num_channels == 1)
>> -			tasklet_init(&priv->done_task[0], talitos1_done_ch0,
>> -				     (unsigned long)dev);
>> -		else
>> -			tasklet_init(&priv->done_task[0], talitos1_done_4ch,
>> -				     (unsigned long)dev);
>> -	} else {
>> -		if (priv->irq[1]) {
>> -			tasklet_init(&priv->done_task[0], talitos2_done_ch0_2,
>> -				     (unsigned long)dev);
>> -			tasklet_init(&priv->done_task[1], talitos2_done_ch1_3,
>> -				     (unsigned long)dev);
>> -		} else if (priv->num_channels == 1) {
>> -			tasklet_init(&priv->done_task[0], talitos2_done_ch0,
>> -				     (unsigned long)dev);
>> -		} else {
>> -			tasklet_init(&priv->done_task[0], talitos2_done_4ch,
>> -				     (unsigned long)dev);
>> -		}
>> -	}
>> +	if (has_ftr_sec1(priv))
>> +		sec1_init_task(dev);
>> +	else
>> +		sec2_init_task(dev);
>>   
>>   	priv->fifo_len = roundup_pow_of_two(priv->chfifo_len);
>>   
>> diff --git a/drivers/crypto/talitos/talitos.h b/drivers/crypto/talitos/talitos.h
>> index 6cf3628c52c2..904fdc9dec80 100644
>> --- a/drivers/crypto/talitos/talitos.h
>> +++ b/drivers/crypto/talitos/talitos.h
>> @@ -301,20 +301,32 @@ static inline bool has_ftr_sec1(struct talitos_private *priv)
>>   #define   TALITOS1_CCCR_LO_RESET	0x1    /* channel reset on SEC1 */
>>   
>>   /* CCPSR: channel pointer status register */
>> +
>> +/* bits 29, 31, 17, 19 */
>> +#define TALITOS1_CH_HAS_ERROR(isr, ch) \
>> +	((isr) & (1 << (29 + ((ch) & 1) * 2 - ((ch) & 2) * 6)))
>> +#define TALITOS2_CH_HAS_ERROR(isr, ch) ((isr) & (1 << ((ch) * 2 + 1)))
>> +
>>   #define TALITOS_CCPSR			0x10
>>   #define TALITOS_CCPSR_LO		0x14
>> -#define   TALITOS_CCPSR_LO_DOF		0x8000 /* double FF write oflow error */
>> -#define   TALITOS_CCPSR_LO_SOF		0x4000 /* single FF write oflow error */
>> -#define   TALITOS_CCPSR_LO_MDTE		0x2000 /* master data transfer error */
>> -#define   TALITOS_CCPSR_LO_SGDLZ	0x1000 /* s/g data len zero error */
>> -#define   TALITOS_CCPSR_LO_FPZ		0x0800 /* fetch ptr zero error */
>> -#define   TALITOS_CCPSR_LO_IDH		0x0400 /* illegal desc hdr error */
>> -#define   TALITOS_CCPSR_LO_IEU		0x0200 /* invalid EU error */
>> -#define   TALITOS_CCPSR_LO_EU		0x0100 /* EU error detected */
>> -#define   TALITOS_CCPSR_LO_GB		0x0080 /* gather boundary error */
>> -#define   TALITOS_CCPSR_LO_GRL		0x0040 /* gather return/length error */
>> -#define   TALITOS_CCPSR_LO_SB		0x0020 /* scatter boundary error */
>> -#define   TALITOS_CCPSR_LO_SRL		0x0010 /* scatter return/length error */
>> +#define   TALITOS1_CCPSR_LO_TEA		0x2000 /* transfer error acknowledge */
>> +#define   TALITOS1_CCPSR_LO_PTRNC	0x1000 /* pointer not complete error */
>> +#define   TALITOS1_CCPSR_LO_PE		0x0800 /* parity error */
>> +#define   TALITOS1_CCPSR_LO_IDH		0x0400 /* illegal desc hdr error */
>> +#define   TALITOS1_CCPSR_LO_SA		0x0200 /* static assignment error */
>> +#define   TALITOS1_CCPSR_LO_EU		0x0100 /* EU error detected */
>> +#define   TALITOS2_CCPSR_LO_DOF		0x8000 /* double FF write oflow error */
>> +#define   TALITOS2_CCPSR_LO_SOF		0x4000 /* single FF write oflow error */
>> +#define   TALITOS2_CCPSR_LO_MDTE	0x2000 /* master data transfer error */
>> +#define   TALITOS2_CCPSR_LO_SGDLZ	0x1000 /* s/g data len zero error */
>> +#define   TALITOS2_CCPSR_LO_FPZ		0x0800 /* fetch ptr zero error */
>> +#define   TALITOS2_CCPSR_LO_IDH		0x0400 /* illegal desc hdr error */
>> +#define   TALITOS2_CCPSR_LO_IEU		0x0200 /* invalid EU error */
>> +#define   TALITOS2_CCPSR_LO_EU		0x0100 /* EU error detected */
>> +#define   TALITOS2_CCPSR_LO_GB		0x0080 /* gather boundary error */
>> +#define   TALITOS2_CCPSR_LO_GRL		0x0040 /* gather return/length error */
>> +#define   TALITOS2_CCPSR_LO_SB		0x0020 /* scatter boundary error */
>> +#define   TALITOS2_CCPSR_LO_SRL		0x0010 /* scatter return/length error */
>>   
>>   /* channel fetch fifo register */
>>   #define TALITOS_FF			0x48
>> 




-- 
Paul Louvel, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


  reply	other threads:[~2026-06-04 12:46 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-28  9:08 [PATCH 00/29] crypto: talitos - Driver cleanup Paul Louvel
2026-05-28  9:08 ` [PATCH 01/29] crypto: talitos/hash - Use CRYPTO_AHASH_BLOCK_ONLY API Paul Louvel
2026-05-29 11:25   ` Christophe Leroy (CS GROUP)
2026-06-01  5:40   ` Christophe Leroy (CS GROUP)
2026-06-01  8:06     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 02/29] crypto: talitos - Move driver into dedicated directory Paul Louvel
2026-05-29 11:25   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 03/29] crypto: talitos - Add missing includes to driver header file Paul Louvel
2026-05-29 11:26   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 04/29] crypto: talitos/hwrng - Move into separate file Paul Louvel
2026-05-29 11:26   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 05/29] crypto: talitos - Prepare crypto implementation file splitting Paul Louvel
2026-05-29 13:21   ` Christophe Leroy (CS GROUP)
2026-05-29 16:24     ` David Laight
2026-06-01  8:49     ` Paul Louvel
2026-06-01 10:16       ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 06/29] crypto: talitos - Introduce registration helper Paul Louvel
2026-06-01  5:45   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 07/29] crypto: talitos/hash - Move into separate file Paul Louvel
2026-06-01 11:47   ` Christophe Leroy (CS GROUP)
2026-06-04 12:31     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 08/29] crypto: talitos/skcipher " Paul Louvel
2026-06-01 11:47   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 09/29] crypto: talitos/aead " Paul Louvel
2026-06-01 11:48   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 10/29] crypto: talitos - Remove alg settings in talitos_register_common() Paul Louvel
2026-06-01 11:53   ` Christophe Leroy (CS GROUP)
2026-06-04 12:38     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 11/29] crypto: talitos - Remove unused priority field in struct talitos_alg_template Paul Louvel
2026-06-01 11:54   ` Christophe Leroy (CS GROUP)
2026-06-04 12:39     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 12/29] crypto: talitos/hash - Convert to init_tfm/exit_tfm type-specific API Paul Louvel
2026-06-01 11:57   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 13/29] crypto: talitos/skcipher - Convert to init/exit " Paul Louvel
2026-06-01 11:58   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 14/29] crypto: talitos/aead " Paul Louvel
2026-06-01 11:59   ` Christophe Leroy (CS GROUP)
2026-06-04 12:44     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 15/29] crypto: talitos/hash - Use macro for algorithm definitions Paul Louvel
2026-06-01 12:02   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 16/29] crypto: talitos/skcipher " Paul Louvel
2026-06-01 12:02   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 17/29] crypto: talitos/aead " Paul Louvel
2026-06-01 12:12   ` Christophe Leroy (CS GROUP)
2026-06-10 14:41     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 18/29] crypto: talitos - Split SEC1/SEC2 code into separate function variants Paul Louvel
2026-06-01  5:51   ` Christophe Leroy (CS GROUP)
2026-06-01 12:32   ` Christophe Leroy (CS GROUP)
2026-06-04 12:46     ` Paul Louvel [this message]
2026-05-28  9:08 ` [PATCH 19/29] crypto: talitos - Introduce struct talitos_ops Paul Louvel
2026-05-28  9:08 ` [PATCH 20/29] crypto: talitos - Replace SEC1/SEC2 conditionals with ops dispatch Paul Louvel
2026-06-04  9:37   ` Christophe Leroy (CS GROUP)
2026-06-04 13:05     ` Paul Louvel
2026-06-04 15:26       ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 21/29] crypto: talitos - Export common channel and error handling routines Paul Louvel
2026-05-28  9:08 ` [PATCH 22/29] crypto: talitos - Move SEC1 ops into talitos-sec1.c Paul Louvel
2026-05-28  9:08 ` [PATCH 23/29] crypto: talitos - Move SEC2 ops into talitos-sec2.c Paul Louvel
2026-05-28  9:08 ` [PATCH 24/29] crypto: talitos - Introduce per-SEC-version pointer helper ops Paul Louvel
2026-06-04  9:48   ` Christophe Leroy (CS GROUP)
2026-05-28  9:08 ` [PATCH 25/29] crypto: talitos - Dispatch pointer helpers through ptr_ops Paul Louvel
2026-05-28  9:08 ` [PATCH 26/29] crypto: talitos - Remove now-unused global pointer helpers Paul Louvel
2026-05-28  9:08 ` [PATCH 27/29] crypto: talitos - Introduce per-SEC-version descriptor structures and ops Paul Louvel
2026-06-04  9:57   ` Christophe Leroy (CS GROUP)
2026-06-04 13:01     ` Paul Louvel
2026-05-28  9:08 ` [PATCH 28/29] crypto: talitos - Clean up includes in core driver file Paul Louvel
2026-05-28  9:08 ` [PATCH 29/29] crypto: talitos - Remove TALITOS_DESC_SIZE macro Paul Louvel
2026-06-04  9:59   ` Christophe Leroy (CS GROUP)
2026-06-04 13:01     ` Paul Louvel
2026-06-01  6:15 ` [PATCH 00/29] crypto: talitos - Driver cleanup Christophe Leroy (CS GROUP)
2026-06-01  9:17   ` Paul Louvel
2026-06-01 10:27     ` Christophe Leroy (CS GROUP)

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=DJ09XQD7J67V.1UV4MA8CQMSZU@bootlin.com \
    --to=paul.louvel@bootlin.com \
    --cc=chleroy@kernel.org \
    --cc=davem@davemloft.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=herve.codina@bootlin.com \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=thomas.petazzoni@bootlin.com \
    /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

Powered by JetHome