public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1.1 2/16 update] arcmsr:  Adding code to support MSI-X interrupt
@ 2014-05-05 11:15 ching
  2014-05-05 12:53 ` Tomas Henzl
  0 siblings, 1 reply; 3+ messages in thread
From: ching @ 2014-05-05 11:15 UTC (permalink / raw)
  To: jbottomley, dan.carpenter, thenzl, linux-scsi,
	linux-kernel@vger.kernel.org

From: Ching<ching2048@areca.com.tw>

Adding code for supporting MSI-X interrupt.

This update is for fixing bug of previous [PATCH v1.1 2/16].

Signed-off-by: Ching<ching2048@areca.com.tw>
---

diff -uprN a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
--- a/drivers/scsi/arcmsr/arcmsr.h	2014-04-28 16:02:46.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr.h	2014-04-28 16:25:06.000000000 +0800
@@ -64,6 +64,7 @@ struct device_attribute;
 #define ARCMSR_MAX_HBB_POSTQUEUE						264
 #define ARCMSR_MAX_XFER_LEN							0x26000 /* 152K */
 #define ARCMSR_CDB_SG_PAGE_LENGTH						256 
+#define ARCMST_NUM_MSIX_VECTORS		4
 #ifndef PCI_DEVICE_ID_ARECA_1880
 #define PCI_DEVICE_ID_ARECA_1880 0x1880
  #endif
@@ -508,6 +509,7 @@ struct AdapterControlBlock
 	struct pci_dev *		pdev;
 	struct Scsi_Host *		host;
 	unsigned long			vir2phy_offset;
+	struct msix_entry	entries[ARCMST_NUM_MSIX_VECTORS];
 	/* Offset is used in making arc cdb physical to virtual calculations */
 	uint32_t			outbound_int_enable;
 	uint32_t			cdb_phyaddr_hi32;
@@ -544,6 +546,8 @@ struct AdapterControlBlock
 	/* iop init */
 	#define ACB_F_ABORT				0x0200
 	#define ACB_F_FIRMWARE_TRAP           		0x0400
+	#define ACB_F_MSI_ENABLED		0x1000
+	#define ACB_F_MSIX_ENABLED		0x2000
 	struct CommandControlBlock *			pccb_pool[ARCMSR_MAX_FREECCB_NUM];
 	/* used for memory free */
 	struct list_head		ccb_free_list;
diff -uprN a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
--- a/drivers/scsi/arcmsr/arcmsr_hba.c	2014-04-28 15:58:34.000000000 +0800
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c	2014-05-05 18:57:03.000000000 +0800
@@ -603,6 +603,79 @@ static void arcmsr_message_isr_bh_fn(str
 	}
 }
 
+static int
+arcmsr_request_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb)
+{
+	int	i, j, r;
+	struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS];
+
+	if (!pci_find_capability(pdev, PCI_CAP_ID_MSIX))
+		goto msi_int;
+	for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++)
+		entries[i].entry = i;
+	r = pci_enable_msix(pdev, entries, ARCMST_NUM_MSIX_VECTORS);
+	if (r < 0)
+		goto msi_int;
+	if (r == 0) {
+		for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) {
+			if (request_irq(entries[i].vector,
+				arcmsr_do_interrupt, 0, "arcmsr", acb)) {
+				pr_warn("arcmsr%d: request_irq =%d failed!\n",
+					acb->host->host_no, pdev->irq);
+				for (j = 0 ; j < i ; j++)
+					free_irq(entries[j].vector, acb);
+				pci_disable_msix(pdev);
+				goto msi_int;
+			}
+			acb->entries[i] = entries[i];
+		}
+		acb->acb_flags |= ACB_F_MSIX_ENABLED;
+		pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
+		return ARC_SUCCESS;
+	} else {
+		if (pci_enable_msix(pdev, entries, r))
+			goto msi_int;
+		for (i = 0; i < r; i++) {
+			if (request_irq(entries[i].vector,
+				arcmsr_do_interrupt, 0, "arcmsr", acb)) {
+				pr_warn("arcmsr%d: request_irq =%d failed!\n",
+					acb->host->host_no, pdev->irq);
+				for (j = 0 ; j < i ; j++)
+					free_irq(entries[j].vector, acb);
+				pci_disable_msix(pdev);
+				goto msi_int;
+			}
+			acb->entries[i] = entries[i];
+		}
+		acb->acb_flags |= ACB_F_MSIX_ENABLED;
+		pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
+		return ARC_SUCCESS;
+	}
+msi_int:
+	if (!pci_find_capability(pdev, PCI_CAP_ID_MSI))
+		goto legacy_int;
+	if (pci_enable_msi(pdev))
+		goto legacy_int;
+	if (request_irq(pdev->irq, arcmsr_do_interrupt,
+		IRQF_SHARED, "arcmsr", acb)) {
+		pr_warn("arcmsr%d: request_irq =%d failed!\n",
+			acb->host->host_no, pdev->irq);
+		pci_disable_msi(pdev);
+		goto legacy_int;
+	}
+	acb->acb_flags |= ACB_F_MSI_ENABLED;
+	pr_info("arcmsr%d: msi enabled\n", acb->host->host_no);
+	return ARC_SUCCESS;
+legacy_int:
+	if (request_irq(pdev->irq, arcmsr_do_interrupt,
+		IRQF_SHARED, "arcmsr", acb)) {
+		pr_warn("arcmsr%d: request_irq = %d failed!\n",
+			acb->host->host_no, pdev->irq);
+		return ARC_FAILURE;
+	}
+	return ARC_SUCCESS;
+}
+
 static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct Scsi_Host *host;
@@ -667,16 +740,13 @@ static int arcmsr_probe(struct pci_dev *
 	if(error){
 		goto free_hbb_mu;
 	}
-	arcmsr_iop_init(acb);
 	error = scsi_add_host(host, &pdev->dev);
 	if(error){
 		goto RAID_controller_stop;
 	}
-	error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb);
-	if(error){
+	if (arcmsr_request_irq(pdev, acb) == ARC_FAILURE)
 		goto scsi_host_remove;
-	}
-	host->irq = pdev->irq;
+	arcmsr_iop_init(acb);
     	scsi_scan_host(host);
 	INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn);
 	atomic_set(&acb->rq_map_token, 16);
@@ -992,6 +1062,22 @@ static void arcmsr_done4abort_postqueue(
 	}
 	}
 }
+
+static void arcmsr_free_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb)
+{
+	int i;
+
+	if (acb->acb_flags & ACB_F_MSI_ENABLED) {
+		free_irq(pdev->irq, acb);
+		pci_disable_msi(pdev);
+	} else if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
+		for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++)
+			free_irq(acb->entries[i].vector, acb);
+		pci_disable_msix(pdev);
+	} else
+		free_irq(pdev->irq, acb);
+}
+
 static void arcmsr_remove(struct pci_dev *pdev)
 {
 	struct Scsi_Host *host = pci_get_drvdata(pdev);
@@ -1029,7 +1115,7 @@ static void arcmsr_remove(struct pci_dev
 			}
 		}
 	}
-	free_irq(pdev->irq, acb);
+	arcmsr_free_irq(pdev, acb);
 	arcmsr_free_ccb_pool(acb);
 	arcmsr_free_hbb_mu(acb);
 	arcmsr_unmap_pciregion(acb);
@@ -1045,6 +1131,7 @@ static void arcmsr_shutdown(struct pci_d
 		(struct AdapterControlBlock *)host->hostdata;
 	del_timer_sync(&acb->eternal_timer);
 	arcmsr_disable_outbound_ints(acb);
+	arcmsr_free_irq(pdev, acb);
 	flush_work(&acb->arcmsr_do_message_isr_bh);
 	arcmsr_stop_adapter_bgrb(acb);
 	arcmsr_flush_adapter_cache(acb);
@@ -2516,8 +2603,6 @@ static int arcmsr_iop_confirm(struct Ada
 	case ACB_ADAPTER_TYPE_A: {
 		if (cdb_phyaddr_hi32 != 0) {
 			struct MessageUnit_A __iomem *reg = acb->pmuA;
-			uint32_t intmask_org;
-			intmask_org = arcmsr_disable_outbound_ints(acb);
 			writel(ARCMSR_SIGNATURE_SET_CONFIG, \
 						&reg->message_rwbuffer[0]);
 			writel(cdb_phyaddr_hi32, &reg->message_rwbuffer[1]);
@@ -2529,7 +2614,6 @@ static int arcmsr_iop_confirm(struct Ada
 				acb->host->host_no);
 				return 1;
 			}
-			arcmsr_enable_outbound_ints(acb, intmask_org);
 		}
 		}
 		break;
@@ -2539,8 +2623,6 @@ static int arcmsr_iop_confirm(struct Ada
 		uint32_t __iomem *rwbuffer;
 
 		struct MessageUnit_B *reg = acb->pmuB;
-		uint32_t intmask_org;
-		intmask_org = arcmsr_disable_outbound_ints(acb);
 		reg->postq_index = 0;
 		reg->doneq_index = 0;
 		writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell);
@@ -2569,7 +2651,6 @@ static int arcmsr_iop_confirm(struct Ada
 			return 1;
 		}
 		arcmsr_hbb_enable_driver_mode(acb);
-		arcmsr_enable_outbound_ints(acb, intmask_org);
 		}
 		break;
 	case ACB_ADAPTER_TYPE_C: {



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v1.1 2/16 update] arcmsr:  Adding code to support MSI-X interrupt
  2014-05-05 11:15 [PATCH v1.1 2/16 update] arcmsr: Adding code to support MSI-X interrupt ching
@ 2014-05-05 12:53 ` Tomas Henzl
  2014-05-06  8:04   ` ching
  0 siblings, 1 reply; 3+ messages in thread
From: Tomas Henzl @ 2014-05-05 12:53 UTC (permalink / raw)
  To: ching, jbottomley, dan.carpenter, linux-scsi,
	linux-kernel@vger.kernel.org

On 05/05/2014 01:15 PM, ching wrote:
> From: Ching<ching2048@areca.com.tw>
>
> Adding code for supporting MSI-X interrupt.
>
> This update is for fixing bug of previous [PATCH v1.1 2/16].
>
> Signed-off-by: Ching<ching2048@areca.com.tw>
> ---
>
> diff -uprN a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
> --- a/drivers/scsi/arcmsr/arcmsr.h	2014-04-28 16:02:46.000000000 +0800
> +++ b/drivers/scsi/arcmsr/arcmsr.h	2014-04-28 16:25:06.000000000 +0800
> @@ -64,6 +64,7 @@ struct device_attribute;
>  #define ARCMSR_MAX_HBB_POSTQUEUE						264
>  #define ARCMSR_MAX_XFER_LEN							0x26000 /* 152K */
>  #define ARCMSR_CDB_SG_PAGE_LENGTH						256 
> +#define ARCMST_NUM_MSIX_VECTORS		4
>  #ifndef PCI_DEVICE_ID_ARECA_1880
>  #define PCI_DEVICE_ID_ARECA_1880 0x1880
>   #endif
> @@ -508,6 +509,7 @@ struct AdapterControlBlock
>  	struct pci_dev *		pdev;
>  	struct Scsi_Host *		host;
>  	unsigned long			vir2phy_offset;
> +	struct msix_entry	entries[ARCMST_NUM_MSIX_VECTORS];
>  	/* Offset is used in making arc cdb physical to virtual calculations */
>  	uint32_t			outbound_int_enable;
>  	uint32_t			cdb_phyaddr_hi32;
> @@ -544,6 +546,8 @@ struct AdapterControlBlock
>  	/* iop init */
>  	#define ACB_F_ABORT				0x0200
>  	#define ACB_F_FIRMWARE_TRAP           		0x0400
> +	#define ACB_F_MSI_ENABLED		0x1000
> +	#define ACB_F_MSIX_ENABLED		0x2000
>  	struct CommandControlBlock *			pccb_pool[ARCMSR_MAX_FREECCB_NUM];
>  	/* used for memory free */
>  	struct list_head		ccb_free_list;
> diff -uprN a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
> --- a/drivers/scsi/arcmsr/arcmsr_hba.c	2014-04-28 15:58:34.000000000 +0800
> +++ b/drivers/scsi/arcmsr/arcmsr_hba.c	2014-05-05 18:57:03.000000000 +0800
> @@ -603,6 +603,79 @@ static void arcmsr_message_isr_bh_fn(str
>  	}
>  }
>  
> +static int
> +arcmsr_request_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb)
> +{
> +	int	i, j, r;
> +	struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS];
> +
> +	if (!pci_find_capability(pdev, PCI_CAP_ID_MSIX))
> +		goto msi_int;
> +	for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++)
> +		entries[i].entry = i;
> +	r = pci_enable_msix(pdev, entries, ARCMST_NUM_MSIX_VECTORS);
> +	if (r < 0)
> +		goto msi_int;
> +	if (r == 0) {
> +		for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) {
> +			if (request_irq(entries[i].vector,
> +				arcmsr_do_interrupt, 0, "arcmsr", acb)) {
> +				pr_warn("arcmsr%d: request_irq =%d failed!\n",
> +					acb->host->host_no, pdev->irq);
> +				for (j = 0 ; j < i ; j++)
> +					free_irq(entries[j].vector, acb);
> +				pci_disable_msix(pdev);
> +				goto msi_int;
> +			}
> +			acb->entries[i] = entries[i];
> +		}
> +		acb->acb_flags |= ACB_F_MSIX_ENABLED;
> +		pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
> +		return ARC_SUCCESS;
> +	} else {
> +		if (pci_enable_msix(pdev, entries, r))
> +			goto msi_int;
> +		for (i = 0; i < r; i++) {
> +			if (request_irq(entries[i].vector,
> +				arcmsr_do_interrupt, 0, "arcmsr", acb)) {
> +				pr_warn("arcmsr%d: request_irq =%d failed!\n",
> +					acb->host->host_no, pdev->irq);
> +				for (j = 0 ; j < i ; j++)
> +					free_irq(entries[j].vector, acb);
> +				pci_disable_msix(pdev);
> +				goto msi_int;
> +			}
> +			acb->entries[i] = entries[i];
> +		}
> +		acb->acb_flags |= ACB_F_MSIX_ENABLED;
> +		pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
> +		return ARC_SUCCESS;
> +	}

Hi Ching, Dan,
the above construction might be simplified even a bit more - 
	if (r) 
		if (pci_enable_msix(pdev, entries, r))
			goto msi_int;
	else 
		r = ARCMST_NUM_MSIX_VECTORS;
		
	for (i = 0; i < r; i++) {
		if (request_irq(entries[i].vector,
			arcmsr_do_interrupt, 0, "arcmsr", acb)) {
			pr_warn("arcmsr%d: request_irq =%d failed!\n",
				acb->host->host_no, pdev->irq);
			for (j = 0 ; j < i ; j++)
				free_irq(entries[j].vector, acb);
			pci_disable_msix(pdev);
			goto msi_int;
		}
		acb->entries[i] = entries[i];
	}
	acb->acb_flags |= ACB_F_MSIX_ENABLED;
	pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
	return ARC_SUCCESS;
Otherwise as Dan said the function looks now good
thanks, tomas

> +msi_int:
> +	if (!pci_find_capability(pdev, PCI_CAP_ID_MSI))
> +		goto legacy_int;
> +	if (pci_enable_msi(pdev))
> +		goto legacy_int;
> +	if (request_irq(pdev->irq, arcmsr_do_interrupt,
> +		IRQF_SHARED, "arcmsr", acb)) {
> +		pr_warn("arcmsr%d: request_irq =%d failed!\n",
> +			acb->host->host_no, pdev->irq);
> +		pci_disable_msi(pdev);
> +		goto legacy_int;
> +	}
> +	acb->acb_flags |= ACB_F_MSI_ENABLED;
> +	pr_info("arcmsr%d: msi enabled\n", acb->host->host_no);
> +	return ARC_SUCCESS;
> +legacy_int:
> +	if (request_irq(pdev->irq, arcmsr_do_interrupt,
> +		IRQF_SHARED, "arcmsr", acb)) {
> +		pr_warn("arcmsr%d: request_irq = %d failed!\n",
> +			acb->host->host_no, pdev->irq);
> +		return ARC_FAILURE;
> +	}
> +	return ARC_SUCCESS;
> +}
> +
>  static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  {
>  	struct Scsi_Host *host;
> @@ -667,16 +740,13 @@ static int arcmsr_probe(struct pci_dev *
>  	if(error){
>  		goto free_hbb_mu;
>  	}
> -	arcmsr_iop_init(acb);
>  	error = scsi_add_host(host, &pdev->dev);
>  	if(error){
>  		goto RAID_controller_stop;
>  	}
> -	error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb);
> -	if(error){
> +	if (arcmsr_request_irq(pdev, acb) == ARC_FAILURE)
>  		goto scsi_host_remove;
> -	}
> -	host->irq = pdev->irq;
> +	arcmsr_iop_init(acb);
>      	scsi_scan_host(host);
>  	INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn);
>  	atomic_set(&acb->rq_map_token, 16);
> @@ -992,6 +1062,22 @@ static void arcmsr_done4abort_postqueue(
>  	}
>  	}
>  }
> +
> +static void arcmsr_free_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb)
> +{
> +	int i;
> +
> +	if (acb->acb_flags & ACB_F_MSI_ENABLED) {
> +		free_irq(pdev->irq, acb);
> +		pci_disable_msi(pdev);
> +	} else if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
> +		for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++)
> +			free_irq(acb->entries[i].vector, acb);
> +		pci_disable_msix(pdev);
> +	} else
> +		free_irq(pdev->irq, acb);
> +}
> +
>  static void arcmsr_remove(struct pci_dev *pdev)
>  {
>  	struct Scsi_Host *host = pci_get_drvdata(pdev);
> @@ -1029,7 +1115,7 @@ static void arcmsr_remove(struct pci_dev
>  			}
>  		}
>  	}
> -	free_irq(pdev->irq, acb);
> +	arcmsr_free_irq(pdev, acb);
>  	arcmsr_free_ccb_pool(acb);
>  	arcmsr_free_hbb_mu(acb);
>  	arcmsr_unmap_pciregion(acb);
> @@ -1045,6 +1131,7 @@ static void arcmsr_shutdown(struct pci_d
>  		(struct AdapterControlBlock *)host->hostdata;
>  	del_timer_sync(&acb->eternal_timer);
>  	arcmsr_disable_outbound_ints(acb);
> +	arcmsr_free_irq(pdev, acb);
>  	flush_work(&acb->arcmsr_do_message_isr_bh);
>  	arcmsr_stop_adapter_bgrb(acb);
>  	arcmsr_flush_adapter_cache(acb);
> @@ -2516,8 +2603,6 @@ static int arcmsr_iop_confirm(struct Ada
>  	case ACB_ADAPTER_TYPE_A: {
>  		if (cdb_phyaddr_hi32 != 0) {
>  			struct MessageUnit_A __iomem *reg = acb->pmuA;
> -			uint32_t intmask_org;
> -			intmask_org = arcmsr_disable_outbound_ints(acb);
>  			writel(ARCMSR_SIGNATURE_SET_CONFIG, \
>  						&reg->message_rwbuffer[0]);
>  			writel(cdb_phyaddr_hi32, &reg->message_rwbuffer[1]);
> @@ -2529,7 +2614,6 @@ static int arcmsr_iop_confirm(struct Ada
>  				acb->host->host_no);
>  				return 1;
>  			}
> -			arcmsr_enable_outbound_ints(acb, intmask_org);
>  		}
>  		}
>  		break;
> @@ -2539,8 +2623,6 @@ static int arcmsr_iop_confirm(struct Ada
>  		uint32_t __iomem *rwbuffer;
>  
>  		struct MessageUnit_B *reg = acb->pmuB;
> -		uint32_t intmask_org;
> -		intmask_org = arcmsr_disable_outbound_ints(acb);
>  		reg->postq_index = 0;
>  		reg->doneq_index = 0;
>  		writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell);
> @@ -2569,7 +2651,6 @@ static int arcmsr_iop_confirm(struct Ada
>  			return 1;
>  		}
>  		arcmsr_hbb_enable_driver_mode(acb);
> -		arcmsr_enable_outbound_ints(acb, intmask_org);
>  		}
>  		break;
>  	case ACB_ADAPTER_TYPE_C: {
>
>
> --
> 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


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v1.1 2/16 update] arcmsr:  Adding code to support MSI-X interrupt
  2014-05-05 12:53 ` Tomas Henzl
@ 2014-05-06  8:04   ` ching
  0 siblings, 0 replies; 3+ messages in thread
From: ching @ 2014-05-06  8:04 UTC (permalink / raw)
  To: Tomas Henzl
  Cc: jbottomley, dan.carpenter, linux-scsi,
	linux-kernel@vger.kernel.org

Thanks for Tomas' suggestion.
I will have a new update for this patch.

On Mon, 2014-05-05 at 14:53 +0200, Tomas Henzl wrote:
> On 05/05/2014 01:15 PM, ching wrote:
> > From: Ching<ching2048@areca.com.tw>
> >
> > Adding code for supporting MSI-X interrupt.
> >
> > This update is for fixing bug of previous [PATCH v1.1 2/16].
> >
> > Signed-off-by: Ching<ching2048@areca.com.tw>
> > ---
> >
> > diff -uprN a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
> > --- a/drivers/scsi/arcmsr/arcmsr.h	2014-04-28 16:02:46.000000000 +0800
> > +++ b/drivers/scsi/arcmsr/arcmsr.h	2014-04-28 16:25:06.000000000 +0800
> > @@ -64,6 +64,7 @@ struct device_attribute;
> >  #define ARCMSR_MAX_HBB_POSTQUEUE						264
> >  #define ARCMSR_MAX_XFER_LEN							0x26000 /* 152K */
> >  #define ARCMSR_CDB_SG_PAGE_LENGTH						256 
> > +#define ARCMST_NUM_MSIX_VECTORS		4
> >  #ifndef PCI_DEVICE_ID_ARECA_1880
> >  #define PCI_DEVICE_ID_ARECA_1880 0x1880
> >   #endif
> > @@ -508,6 +509,7 @@ struct AdapterControlBlock
> >  	struct pci_dev *		pdev;
> >  	struct Scsi_Host *		host;
> >  	unsigned long			vir2phy_offset;
> > +	struct msix_entry	entries[ARCMST_NUM_MSIX_VECTORS];
> >  	/* Offset is used in making arc cdb physical to virtual calculations */
> >  	uint32_t			outbound_int_enable;
> >  	uint32_t			cdb_phyaddr_hi32;
> > @@ -544,6 +546,8 @@ struct AdapterControlBlock
> >  	/* iop init */
> >  	#define ACB_F_ABORT				0x0200
> >  	#define ACB_F_FIRMWARE_TRAP           		0x0400
> > +	#define ACB_F_MSI_ENABLED		0x1000
> > +	#define ACB_F_MSIX_ENABLED		0x2000
> >  	struct CommandControlBlock *			pccb_pool[ARCMSR_MAX_FREECCB_NUM];
> >  	/* used for memory free */
> >  	struct list_head		ccb_free_list;
> > diff -uprN a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
> > --- a/drivers/scsi/arcmsr/arcmsr_hba.c	2014-04-28 15:58:34.000000000 +0800
> > +++ b/drivers/scsi/arcmsr/arcmsr_hba.c	2014-05-05 18:57:03.000000000 +0800
> > @@ -603,6 +603,79 @@ static void arcmsr_message_isr_bh_fn(str
> >  	}
> >  }
> >  
> > +static int
> > +arcmsr_request_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb)
> > +{
> > +	int	i, j, r;
> > +	struct msix_entry entries[ARCMST_NUM_MSIX_VECTORS];
> > +
> > +	if (!pci_find_capability(pdev, PCI_CAP_ID_MSIX))
> > +		goto msi_int;
> > +	for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++)
> > +		entries[i].entry = i;
> > +	r = pci_enable_msix(pdev, entries, ARCMST_NUM_MSIX_VECTORS);
> > +	if (r < 0)
> > +		goto msi_int;
> > +	if (r == 0) {
> > +		for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++) {
> > +			if (request_irq(entries[i].vector,
> > +				arcmsr_do_interrupt, 0, "arcmsr", acb)) {
> > +				pr_warn("arcmsr%d: request_irq =%d failed!\n",
> > +					acb->host->host_no, pdev->irq);
> > +				for (j = 0 ; j < i ; j++)
> > +					free_irq(entries[j].vector, acb);
> > +				pci_disable_msix(pdev);
> > +				goto msi_int;
> > +			}
> > +			acb->entries[i] = entries[i];
> > +		}
> > +		acb->acb_flags |= ACB_F_MSIX_ENABLED;
> > +		pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
> > +		return ARC_SUCCESS;
> > +	} else {
> > +		if (pci_enable_msix(pdev, entries, r))
> > +			goto msi_int;
> > +		for (i = 0; i < r; i++) {
> > +			if (request_irq(entries[i].vector,
> > +				arcmsr_do_interrupt, 0, "arcmsr", acb)) {
> > +				pr_warn("arcmsr%d: request_irq =%d failed!\n",
> > +					acb->host->host_no, pdev->irq);
> > +				for (j = 0 ; j < i ; j++)
> > +					free_irq(entries[j].vector, acb);
> > +				pci_disable_msix(pdev);
> > +				goto msi_int;
> > +			}
> > +			acb->entries[i] = entries[i];
> > +		}
> > +		acb->acb_flags |= ACB_F_MSIX_ENABLED;
> > +		pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
> > +		return ARC_SUCCESS;
> > +	}
> 
> Hi Ching, Dan,
> the above construction might be simplified even a bit more - 
> 	if (r) 
> 		if (pci_enable_msix(pdev, entries, r))
> 			goto msi_int;
> 	else 
> 		r = ARCMST_NUM_MSIX_VECTORS;
> 		
> 	for (i = 0; i < r; i++) {
> 		if (request_irq(entries[i].vector,
> 			arcmsr_do_interrupt, 0, "arcmsr", acb)) {
> 			pr_warn("arcmsr%d: request_irq =%d failed!\n",
> 				acb->host->host_no, pdev->irq);
> 			for (j = 0 ; j < i ; j++)
> 				free_irq(entries[j].vector, acb);
> 			pci_disable_msix(pdev);
> 			goto msi_int;
> 		}
> 		acb->entries[i] = entries[i];
> 	}
> 	acb->acb_flags |= ACB_F_MSIX_ENABLED;
> 	pr_info("arcmsr%d: msi-x enabled\n", acb->host->host_no);
> 	return ARC_SUCCESS;
> Otherwise as Dan said the function looks now good
> thanks, tomas
> 
> > +msi_int:
> > +	if (!pci_find_capability(pdev, PCI_CAP_ID_MSI))
> > +		goto legacy_int;
> > +	if (pci_enable_msi(pdev))
> > +		goto legacy_int;
> > +	if (request_irq(pdev->irq, arcmsr_do_interrupt,
> > +		IRQF_SHARED, "arcmsr", acb)) {
> > +		pr_warn("arcmsr%d: request_irq =%d failed!\n",
> > +			acb->host->host_no, pdev->irq);
> > +		pci_disable_msi(pdev);
> > +		goto legacy_int;
> > +	}
> > +	acb->acb_flags |= ACB_F_MSI_ENABLED;
> > +	pr_info("arcmsr%d: msi enabled\n", acb->host->host_no);
> > +	return ARC_SUCCESS;
> > +legacy_int:
> > +	if (request_irq(pdev->irq, arcmsr_do_interrupt,
> > +		IRQF_SHARED, "arcmsr", acb)) {
> > +		pr_warn("arcmsr%d: request_irq = %d failed!\n",
> > +			acb->host->host_no, pdev->irq);
> > +		return ARC_FAILURE;
> > +	}
> > +	return ARC_SUCCESS;
> > +}
> > +
> >  static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> >  {
> >  	struct Scsi_Host *host;
> > @@ -667,16 +740,13 @@ static int arcmsr_probe(struct pci_dev *
> >  	if(error){
> >  		goto free_hbb_mu;
> >  	}
> > -	arcmsr_iop_init(acb);
> >  	error = scsi_add_host(host, &pdev->dev);
> >  	if(error){
> >  		goto RAID_controller_stop;
> >  	}
> > -	error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb);
> > -	if(error){
> > +	if (arcmsr_request_irq(pdev, acb) == ARC_FAILURE)
> >  		goto scsi_host_remove;
> > -	}
> > -	host->irq = pdev->irq;
> > +	arcmsr_iop_init(acb);
> >      	scsi_scan_host(host);
> >  	INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn);
> >  	atomic_set(&acb->rq_map_token, 16);
> > @@ -992,6 +1062,22 @@ static void arcmsr_done4abort_postqueue(
> >  	}
> >  	}
> >  }
> > +
> > +static void arcmsr_free_irq(struct pci_dev *pdev, struct AdapterControlBlock *acb)
> > +{
> > +	int i;
> > +
> > +	if (acb->acb_flags & ACB_F_MSI_ENABLED) {
> > +		free_irq(pdev->irq, acb);
> > +		pci_disable_msi(pdev);
> > +	} else if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
> > +		for (i = 0; i < ARCMST_NUM_MSIX_VECTORS; i++)
> > +			free_irq(acb->entries[i].vector, acb);
> > +		pci_disable_msix(pdev);
> > +	} else
> > +		free_irq(pdev->irq, acb);
> > +}
> > +
> >  static void arcmsr_remove(struct pci_dev *pdev)
> >  {
> >  	struct Scsi_Host *host = pci_get_drvdata(pdev);
> > @@ -1029,7 +1115,7 @@ static void arcmsr_remove(struct pci_dev
> >  			}
> >  		}
> >  	}
> > -	free_irq(pdev->irq, acb);
> > +	arcmsr_free_irq(pdev, acb);
> >  	arcmsr_free_ccb_pool(acb);
> >  	arcmsr_free_hbb_mu(acb);
> >  	arcmsr_unmap_pciregion(acb);
> > @@ -1045,6 +1131,7 @@ static void arcmsr_shutdown(struct pci_d
> >  		(struct AdapterControlBlock *)host->hostdata;
> >  	del_timer_sync(&acb->eternal_timer);
> >  	arcmsr_disable_outbound_ints(acb);
> > +	arcmsr_free_irq(pdev, acb);
> >  	flush_work(&acb->arcmsr_do_message_isr_bh);
> >  	arcmsr_stop_adapter_bgrb(acb);
> >  	arcmsr_flush_adapter_cache(acb);
> > @@ -2516,8 +2603,6 @@ static int arcmsr_iop_confirm(struct Ada
> >  	case ACB_ADAPTER_TYPE_A: {
> >  		if (cdb_phyaddr_hi32 != 0) {
> >  			struct MessageUnit_A __iomem *reg = acb->pmuA;
> > -			uint32_t intmask_org;
> > -			intmask_org = arcmsr_disable_outbound_ints(acb);
> >  			writel(ARCMSR_SIGNATURE_SET_CONFIG, \
> >  						&reg->message_rwbuffer[0]);
> >  			writel(cdb_phyaddr_hi32, &reg->message_rwbuffer[1]);
> > @@ -2529,7 +2614,6 @@ static int arcmsr_iop_confirm(struct Ada
> >  				acb->host->host_no);
> >  				return 1;
> >  			}
> > -			arcmsr_enable_outbound_ints(acb, intmask_org);
> >  		}
> >  		}
> >  		break;
> > @@ -2539,8 +2623,6 @@ static int arcmsr_iop_confirm(struct Ada
> >  		uint32_t __iomem *rwbuffer;
> >  
> >  		struct MessageUnit_B *reg = acb->pmuB;
> > -		uint32_t intmask_org;
> > -		intmask_org = arcmsr_disable_outbound_ints(acb);
> >  		reg->postq_index = 0;
> >  		reg->doneq_index = 0;
> >  		writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell);
> > @@ -2569,7 +2651,6 @@ static int arcmsr_iop_confirm(struct Ada
> >  			return 1;
> >  		}
> >  		arcmsr_hbb_enable_driver_mode(acb);
> > -		arcmsr_enable_outbound_ints(acb, intmask_org);
> >  		}
> >  		break;
> >  	case ACB_ADAPTER_TYPE_C: {
> >
> >
> > --
> > 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
> 



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-05-06  8:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-05 11:15 [PATCH v1.1 2/16 update] arcmsr: Adding code to support MSI-X interrupt ching
2014-05-05 12:53 ` Tomas Henzl
2014-05-06  8:04   ` ching

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox