1111#include <linux/dmaengine.h>
1212#include <linux/io.h>
1313#include <linux/module.h>
14+ #include <linux/msi.h>
1415#include <linux/slab.h>
1516#include <linux/pci_ids.h>
1617#include <linux/random.h>
1718
1819#include <linux/pci-epc.h>
1920#include <linux/pci-epf.h>
21+ #include <linux/pci-ep-msi.h>
2022#include <linux/pci_regs.h>
2123
2224#define IRQ_TYPE_INTX 0
2931#define COMMAND_READ BIT(3)
3032#define COMMAND_WRITE BIT(4)
3133#define COMMAND_COPY BIT(5)
34+ #define COMMAND_ENABLE_DOORBELL BIT(6)
35+ #define COMMAND_DISABLE_DOORBELL BIT(7)
3236
3337#define STATUS_READ_SUCCESS BIT(0)
3438#define STATUS_READ_FAIL BIT(1)
3943#define STATUS_IRQ_RAISED BIT(6)
4044#define STATUS_SRC_ADDR_INVALID BIT(7)
4145#define STATUS_DST_ADDR_INVALID BIT(8)
46+ #define STATUS_DOORBELL_SUCCESS BIT(9)
47+ #define STATUS_DOORBELL_ENABLE_SUCCESS BIT(10)
48+ #define STATUS_DOORBELL_ENABLE_FAIL BIT(11)
49+ #define STATUS_DOORBELL_DISABLE_SUCCESS BIT(12)
50+ #define STATUS_DOORBELL_DISABLE_FAIL BIT(13)
4251
4352#define FLAG_USE_DMA BIT(0)
4453
@@ -66,6 +75,7 @@ struct pci_epf_test {
6675 bool dma_supported ;
6776 bool dma_private ;
6877 const struct pci_epc_features * epc_features ;
78+ struct pci_epf_bar db_bar ;
6979};
7080
7181struct pci_epf_test_reg {
@@ -80,6 +90,9 @@ struct pci_epf_test_reg {
8090 __le32 irq_number ;
8191 __le32 flags ;
8292 __le32 caps ;
93+ __le32 doorbell_bar ;
94+ __le32 doorbell_offset ;
95+ __le32 doorbell_data ;
8396} __packed ;
8497
8598static struct pci_epf_header test_header = {
@@ -667,6 +680,115 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test,
667680 }
668681}
669682
683+ static irqreturn_t pci_epf_test_doorbell_handler (int irq , void * data )
684+ {
685+ struct pci_epf_test * epf_test = data ;
686+ enum pci_barno test_reg_bar = epf_test -> test_reg_bar ;
687+ struct pci_epf_test_reg * reg = epf_test -> reg [test_reg_bar ];
688+ u32 status = le32_to_cpu (reg -> status );
689+
690+ status |= STATUS_DOORBELL_SUCCESS ;
691+ reg -> status = cpu_to_le32 (status );
692+ pci_epf_test_raise_irq (epf_test , reg );
693+
694+ return IRQ_HANDLED ;
695+ }
696+
697+ static void pci_epf_test_doorbell_cleanup (struct pci_epf_test * epf_test )
698+ {
699+ struct pci_epf_test_reg * reg = epf_test -> reg [epf_test -> test_reg_bar ];
700+ struct pci_epf * epf = epf_test -> epf ;
701+
702+ free_irq (epf -> db_msg [0 ].virq , epf_test );
703+ reg -> doorbell_bar = cpu_to_le32 (NO_BAR );
704+
705+ pci_epf_free_doorbell (epf );
706+ }
707+
708+ static void pci_epf_test_enable_doorbell (struct pci_epf_test * epf_test ,
709+ struct pci_epf_test_reg * reg )
710+ {
711+ u32 status = le32_to_cpu (reg -> status );
712+ struct pci_epf * epf = epf_test -> epf ;
713+ struct pci_epc * epc = epf -> epc ;
714+ struct msi_msg * msg ;
715+ enum pci_barno bar ;
716+ size_t offset ;
717+ int ret ;
718+
719+ ret = pci_epf_alloc_doorbell (epf , 1 );
720+ if (ret )
721+ goto set_status_err ;
722+
723+ msg = & epf -> db_msg [0 ].msg ;
724+ bar = pci_epc_get_next_free_bar (epf_test -> epc_features , epf_test -> test_reg_bar + 1 );
725+ if (bar < BAR_0 )
726+ goto err_doorbell_cleanup ;
727+
728+ ret = request_irq (epf -> db_msg [0 ].virq , pci_epf_test_doorbell_handler , 0 ,
729+ "pci-ep-test-doorbell" , epf_test );
730+ if (ret ) {
731+ dev_err (& epf -> dev ,
732+ "Failed to request doorbell IRQ: %d\n" ,
733+ epf -> db_msg [0 ].virq );
734+ goto err_doorbell_cleanup ;
735+ }
736+
737+ reg -> doorbell_data = cpu_to_le32 (msg -> data );
738+ reg -> doorbell_bar = cpu_to_le32 (bar );
739+
740+ msg = & epf -> db_msg [0 ].msg ;
741+ ret = pci_epf_align_inbound_addr (epf , bar , ((u64 )msg -> address_hi << 32 ) | msg -> address_lo ,
742+ & epf_test -> db_bar .phys_addr , & offset );
743+
744+ if (ret )
745+ goto err_doorbell_cleanup ;
746+
747+ reg -> doorbell_offset = cpu_to_le32 (offset );
748+
749+ epf_test -> db_bar .barno = bar ;
750+ epf_test -> db_bar .size = epf -> bar [bar ].size ;
751+ epf_test -> db_bar .flags = epf -> bar [bar ].flags ;
752+
753+ ret = pci_epc_set_bar (epc , epf -> func_no , epf -> vfunc_no , & epf_test -> db_bar );
754+ if (ret )
755+ goto err_doorbell_cleanup ;
756+
757+ status |= STATUS_DOORBELL_ENABLE_SUCCESS ;
758+ reg -> status = cpu_to_le32 (status );
759+ return ;
760+
761+ err_doorbell_cleanup :
762+ pci_epf_test_doorbell_cleanup (epf_test );
763+ set_status_err :
764+ status |= STATUS_DOORBELL_ENABLE_FAIL ;
765+ reg -> status = cpu_to_le32 (status );
766+ }
767+
768+ static void pci_epf_test_disable_doorbell (struct pci_epf_test * epf_test ,
769+ struct pci_epf_test_reg * reg )
770+ {
771+ enum pci_barno bar = le32_to_cpu (reg -> doorbell_bar );
772+ u32 status = le32_to_cpu (reg -> status );
773+ struct pci_epf * epf = epf_test -> epf ;
774+ struct pci_epc * epc = epf -> epc ;
775+
776+ if (bar < BAR_0 )
777+ goto set_status_err ;
778+
779+ pci_epf_test_doorbell_cleanup (epf_test );
780+ pci_epc_clear_bar (epc , epf -> func_no , epf -> vfunc_no , & epf_test -> db_bar );
781+
782+ status |= STATUS_DOORBELL_DISABLE_SUCCESS ;
783+ reg -> status = cpu_to_le32 (status );
784+
785+ return ;
786+
787+ set_status_err :
788+ status |= STATUS_DOORBELL_DISABLE_FAIL ;
789+ reg -> status = cpu_to_le32 (status );
790+ }
791+
670792static void pci_epf_test_cmd_handler (struct work_struct * work )
671793{
672794 u32 command ;
@@ -714,6 +836,14 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
714836 pci_epf_test_copy (epf_test , reg );
715837 pci_epf_test_raise_irq (epf_test , reg );
716838 break ;
839+ case COMMAND_ENABLE_DOORBELL :
840+ pci_epf_test_enable_doorbell (epf_test , reg );
841+ pci_epf_test_raise_irq (epf_test , reg );
842+ break ;
843+ case COMMAND_DISABLE_DOORBELL :
844+ pci_epf_test_disable_doorbell (epf_test , reg );
845+ pci_epf_test_raise_irq (epf_test , reg );
846+ break ;
717847 default :
718848 dev_err (dev , "Invalid command 0x%x\n" , command );
719849 break ;
0 commit comments