@@ -127,7 +127,6 @@ struct serial_port {
127127/* State of each mdev device */
128128struct mdev_state {
129129 struct vfio_device vdev ;
130- int irq_fd ;
131130 struct eventfd_ctx * intx_evtfd ;
132131 struct eventfd_ctx * msi_evtfd ;
133132 int irq_index ;
@@ -141,6 +140,7 @@ struct mdev_state {
141140 struct mutex rxtx_lock ;
142141 struct vfio_device_info dev_info ;
143142 int nr_ports ;
143+ u8 intx_mask :1 ;
144144};
145145
146146static struct mtty_type {
@@ -166,10 +166,6 @@ static const struct file_operations vd_fops = {
166166
167167static const struct vfio_device_ops mtty_dev_ops ;
168168
169- /* function prototypes */
170-
171- static int mtty_trigger_interrupt (struct mdev_state * mdev_state );
172-
173169/* Helper functions */
174170
175171static void dump_buffer (u8 * buf , uint32_t count )
@@ -186,6 +182,36 @@ static void dump_buffer(u8 *buf, uint32_t count)
186182#endif
187183}
188184
185+ static bool is_intx (struct mdev_state * mdev_state )
186+ {
187+ return mdev_state -> irq_index == VFIO_PCI_INTX_IRQ_INDEX ;
188+ }
189+
190+ static bool is_msi (struct mdev_state * mdev_state )
191+ {
192+ return mdev_state -> irq_index == VFIO_PCI_MSI_IRQ_INDEX ;
193+ }
194+
195+ static bool is_noirq (struct mdev_state * mdev_state )
196+ {
197+ return !is_intx (mdev_state ) && !is_msi (mdev_state );
198+ }
199+
200+ static void mtty_trigger_interrupt (struct mdev_state * mdev_state )
201+ {
202+ lockdep_assert_held (& mdev_state -> ops_lock );
203+
204+ if (is_msi (mdev_state )) {
205+ if (mdev_state -> msi_evtfd )
206+ eventfd_signal (mdev_state -> msi_evtfd , 1 );
207+ } else if (is_intx (mdev_state )) {
208+ if (mdev_state -> intx_evtfd && !mdev_state -> intx_mask ) {
209+ eventfd_signal (mdev_state -> intx_evtfd , 1 );
210+ mdev_state -> intx_mask = true;
211+ }
212+ }
213+ }
214+
189215static void mtty_create_config_space (struct mdev_state * mdev_state )
190216{
191217 /* PCI dev ID */
@@ -921,6 +947,25 @@ static ssize_t mtty_write(struct vfio_device *vdev, const char __user *buf,
921947 return - EFAULT ;
922948}
923949
950+ static void mtty_disable_intx (struct mdev_state * mdev_state )
951+ {
952+ if (mdev_state -> intx_evtfd ) {
953+ eventfd_ctx_put (mdev_state -> intx_evtfd );
954+ mdev_state -> intx_evtfd = NULL ;
955+ mdev_state -> intx_mask = false;
956+ mdev_state -> irq_index = -1 ;
957+ }
958+ }
959+
960+ static void mtty_disable_msi (struct mdev_state * mdev_state )
961+ {
962+ if (mdev_state -> msi_evtfd ) {
963+ eventfd_ctx_put (mdev_state -> msi_evtfd );
964+ mdev_state -> msi_evtfd = NULL ;
965+ mdev_state -> irq_index = -1 ;
966+ }
967+ }
968+
924969static int mtty_set_irqs (struct mdev_state * mdev_state , uint32_t flags ,
925970 unsigned int index , unsigned int start ,
926971 unsigned int count , void * data )
@@ -932,59 +977,113 @@ static int mtty_set_irqs(struct mdev_state *mdev_state, uint32_t flags,
932977 case VFIO_PCI_INTX_IRQ_INDEX :
933978 switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK ) {
934979 case VFIO_IRQ_SET_ACTION_MASK :
980+ if (!is_intx (mdev_state ) || start != 0 || count != 1 ) {
981+ ret = - EINVAL ;
982+ break ;
983+ }
984+
985+ if (flags & VFIO_IRQ_SET_DATA_NONE ) {
986+ mdev_state -> intx_mask = true;
987+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL ) {
988+ uint8_t mask = * (uint8_t * )data ;
989+
990+ if (mask )
991+ mdev_state -> intx_mask = true;
992+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD ) {
993+ ret = - ENOTTY ; /* No support for mask fd */
994+ }
995+ break ;
935996 case VFIO_IRQ_SET_ACTION_UNMASK :
997+ if (!is_intx (mdev_state ) || start != 0 || count != 1 ) {
998+ ret = - EINVAL ;
999+ break ;
1000+ }
1001+
1002+ if (flags & VFIO_IRQ_SET_DATA_NONE ) {
1003+ mdev_state -> intx_mask = false;
1004+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL ) {
1005+ uint8_t mask = * (uint8_t * )data ;
1006+
1007+ if (mask )
1008+ mdev_state -> intx_mask = false;
1009+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD ) {
1010+ ret = - ENOTTY ; /* No support for unmask fd */
1011+ }
9361012 break ;
9371013 case VFIO_IRQ_SET_ACTION_TRIGGER :
938- {
939- if (flags & VFIO_IRQ_SET_DATA_NONE ) {
940- pr_info ("%s: disable INTx\n" , __func__ );
941- if (mdev_state -> intx_evtfd )
942- eventfd_ctx_put (mdev_state -> intx_evtfd );
1014+ if (is_intx (mdev_state ) && !count &&
1015+ (flags & VFIO_IRQ_SET_DATA_NONE )) {
1016+ mtty_disable_intx (mdev_state );
1017+ break ;
1018+ }
1019+
1020+ if (!(is_intx (mdev_state ) || is_noirq (mdev_state )) ||
1021+ start != 0 || count != 1 ) {
1022+ ret = - EINVAL ;
9431023 break ;
9441024 }
9451025
9461026 if (flags & VFIO_IRQ_SET_DATA_EVENTFD ) {
9471027 int fd = * (int * )data ;
1028+ struct eventfd_ctx * evt ;
1029+
1030+ mtty_disable_intx (mdev_state );
1031+
1032+ if (fd < 0 )
1033+ break ;
9481034
949- if (fd > 0 ) {
950- struct eventfd_ctx * evt ;
951-
952- evt = eventfd_ctx_fdget (fd );
953- if (IS_ERR (evt )) {
954- ret = PTR_ERR (evt );
955- break ;
956- }
957- mdev_state -> intx_evtfd = evt ;
958- mdev_state -> irq_fd = fd ;
959- mdev_state -> irq_index = index ;
1035+ evt = eventfd_ctx_fdget (fd );
1036+ if (IS_ERR (evt )) {
1037+ ret = PTR_ERR (evt );
9601038 break ;
9611039 }
1040+ mdev_state -> intx_evtfd = evt ;
1041+ mdev_state -> irq_index = index ;
1042+ break ;
1043+ }
1044+
1045+ if (!is_intx (mdev_state )) {
1046+ ret = - EINVAL ;
1047+ break ;
1048+ }
1049+
1050+ if (flags & VFIO_IRQ_SET_DATA_NONE ) {
1051+ mtty_trigger_interrupt (mdev_state );
1052+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL ) {
1053+ uint8_t trigger = * (uint8_t * )data ;
1054+
1055+ if (trigger )
1056+ mtty_trigger_interrupt (mdev_state );
9621057 }
9631058 break ;
9641059 }
965- }
9661060 break ;
9671061 case VFIO_PCI_MSI_IRQ_INDEX :
9681062 switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK ) {
9691063 case VFIO_IRQ_SET_ACTION_MASK :
9701064 case VFIO_IRQ_SET_ACTION_UNMASK :
1065+ ret = - ENOTTY ;
9711066 break ;
9721067 case VFIO_IRQ_SET_ACTION_TRIGGER :
973- if (flags & VFIO_IRQ_SET_DATA_NONE ) {
974- if (mdev_state -> msi_evtfd )
975- eventfd_ctx_put (mdev_state -> msi_evtfd );
976- pr_info ("%s: disable MSI\n" , __func__ );
977- mdev_state -> irq_index = VFIO_PCI_INTX_IRQ_INDEX ;
1068+ if (is_msi (mdev_state ) && !count &&
1069+ (flags & VFIO_IRQ_SET_DATA_NONE )) {
1070+ mtty_disable_msi (mdev_state );
9781071 break ;
9791072 }
1073+
1074+ if (!(is_msi (mdev_state ) || is_noirq (mdev_state )) ||
1075+ start != 0 || count != 1 ) {
1076+ ret = - EINVAL ;
1077+ break ;
1078+ }
1079+
9801080 if (flags & VFIO_IRQ_SET_DATA_EVENTFD ) {
9811081 int fd = * (int * )data ;
9821082 struct eventfd_ctx * evt ;
9831083
984- if (fd <= 0 )
985- break ;
1084+ mtty_disable_msi (mdev_state );
9861085
987- if (mdev_state -> msi_evtfd )
1086+ if (fd < 0 )
9881087 break ;
9891088
9901089 evt = eventfd_ctx_fdget (fd );
@@ -993,54 +1092,44 @@ static int mtty_set_irqs(struct mdev_state *mdev_state, uint32_t flags,
9931092 break ;
9941093 }
9951094 mdev_state -> msi_evtfd = evt ;
996- mdev_state -> irq_fd = fd ;
9971095 mdev_state -> irq_index = index ;
1096+ break ;
1097+ }
1098+
1099+ if (!is_msi (mdev_state )) {
1100+ ret = - EINVAL ;
1101+ break ;
1102+ }
1103+
1104+ if (flags & VFIO_IRQ_SET_DATA_NONE ) {
1105+ mtty_trigger_interrupt (mdev_state );
1106+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL ) {
1107+ uint8_t trigger = * (uint8_t * )data ;
1108+
1109+ if (trigger )
1110+ mtty_trigger_interrupt (mdev_state );
9981111 }
9991112 break ;
1000- }
1001- break ;
1113+ }
1114+ break ;
10021115 case VFIO_PCI_MSIX_IRQ_INDEX :
1003- pr_info ("%s: MSIX_IRQ\n" , __func__ );
1116+ dev_dbg (mdev_state -> vdev .dev , "%s: MSIX_IRQ\n" , __func__ );
1117+ ret = - ENOTTY ;
10041118 break ;
10051119 case VFIO_PCI_ERR_IRQ_INDEX :
1006- pr_info ("%s: ERR_IRQ\n" , __func__ );
1120+ dev_dbg (mdev_state -> vdev .dev , "%s: ERR_IRQ\n" , __func__ );
1121+ ret = - ENOTTY ;
10071122 break ;
10081123 case VFIO_PCI_REQ_IRQ_INDEX :
1009- pr_info ("%s: REQ_IRQ\n" , __func__ );
1124+ dev_dbg (mdev_state -> vdev .dev , "%s: REQ_IRQ\n" , __func__ );
1125+ ret = - ENOTTY ;
10101126 break ;
10111127 }
10121128
10131129 mutex_unlock (& mdev_state -> ops_lock );
10141130 return ret ;
10151131}
10161132
1017- static int mtty_trigger_interrupt (struct mdev_state * mdev_state )
1018- {
1019- int ret = -1 ;
1020-
1021- if ((mdev_state -> irq_index == VFIO_PCI_MSI_IRQ_INDEX ) &&
1022- (!mdev_state -> msi_evtfd ))
1023- return - EINVAL ;
1024- else if ((mdev_state -> irq_index == VFIO_PCI_INTX_IRQ_INDEX ) &&
1025- (!mdev_state -> intx_evtfd )) {
1026- pr_info ("%s: Intr eventfd not found\n" , __func__ );
1027- return - EINVAL ;
1028- }
1029-
1030- if (mdev_state -> irq_index == VFIO_PCI_MSI_IRQ_INDEX )
1031- ret = eventfd_signal (mdev_state -> msi_evtfd , 1 );
1032- else
1033- ret = eventfd_signal (mdev_state -> intx_evtfd , 1 );
1034-
1035- #if defined(DEBUG_INTR )
1036- pr_info ("Intx triggered\n" );
1037- #endif
1038- if (ret != 1 )
1039- pr_err ("%s: eventfd signal failed (%d)\n" , __func__ , ret );
1040-
1041- return ret ;
1042- }
1043-
10441133static int mtty_get_region_info (struct mdev_state * mdev_state ,
10451134 struct vfio_region_info * region_info ,
10461135 u16 * cap_type_id , void * * cap_type )
@@ -1084,22 +1173,16 @@ static int mtty_get_region_info(struct mdev_state *mdev_state,
10841173
10851174static int mtty_get_irq_info (struct vfio_irq_info * irq_info )
10861175{
1087- switch (irq_info -> index ) {
1088- case VFIO_PCI_INTX_IRQ_INDEX :
1089- case VFIO_PCI_MSI_IRQ_INDEX :
1090- case VFIO_PCI_REQ_IRQ_INDEX :
1091- break ;
1092-
1093- default :
1176+ if (irq_info -> index != VFIO_PCI_INTX_IRQ_INDEX &&
1177+ irq_info -> index != VFIO_PCI_MSI_IRQ_INDEX )
10941178 return - EINVAL ;
1095- }
10961179
10971180 irq_info -> flags = VFIO_IRQ_INFO_EVENTFD ;
10981181 irq_info -> count = 1 ;
10991182
11001183 if (irq_info -> index == VFIO_PCI_INTX_IRQ_INDEX )
1101- irq_info -> flags |= ( VFIO_IRQ_INFO_MASKABLE |
1102- VFIO_IRQ_INFO_AUTOMASKED ) ;
1184+ irq_info -> flags |= VFIO_IRQ_INFO_MASKABLE |
1185+ VFIO_IRQ_INFO_AUTOMASKED ;
11031186 else
11041187 irq_info -> flags |= VFIO_IRQ_INFO_NORESIZE ;
11051188
@@ -1262,6 +1345,15 @@ static unsigned int mtty_get_available(struct mdev_type *mtype)
12621345 return atomic_read (& mdev_avail_ports ) / type -> nr_ports ;
12631346}
12641347
1348+ static void mtty_close (struct vfio_device * vdev )
1349+ {
1350+ struct mdev_state * mdev_state =
1351+ container_of (vdev , struct mdev_state , vdev );
1352+
1353+ mtty_disable_intx (mdev_state );
1354+ mtty_disable_msi (mdev_state );
1355+ }
1356+
12651357static const struct vfio_device_ops mtty_dev_ops = {
12661358 .name = "vfio-mtty" ,
12671359 .init = mtty_init_dev ,
@@ -1273,6 +1365,7 @@ static const struct vfio_device_ops mtty_dev_ops = {
12731365 .unbind_iommufd = vfio_iommufd_emulated_unbind ,
12741366 .attach_ioas = vfio_iommufd_emulated_attach_ioas ,
12751367 .detach_ioas = vfio_iommufd_emulated_detach_ioas ,
1368+ .close_device = mtty_close ,
12761369};
12771370
12781371static struct mdev_driver mtty_driver = {
0 commit comments