@@ -2079,3 +2079,238 @@ struct virtio_ops virtio_mei_ops = {
2079
2079
.apply_features = NULL ,
2080
2080
.set_status = NULL ,
2081
2081
};
2082
+
2083
+ static int filter_dirs (const struct dirent * d )
2084
+ {
2085
+ return !((strcmp (d -> d_name , "." ) == 0 ) ||
2086
+ (strcmp (d -> d_name , ".." ) == 0 ));
2087
+ }
2088
+
2089
+ static int
2090
+ vmei_get_devname (char * name , size_t namesize ,
2091
+ unsigned int bus , unsigned int slot , unsigned int func )
2092
+ {
2093
+ char path [256 ];
2094
+ struct stat buf ;
2095
+ struct dirent * * namelist = NULL ;
2096
+ int n , ret = 0 ;
2097
+
2098
+ snprintf (path , sizeof (path ),
2099
+ "/sys/bus/pci/drivers/mei_me/0000:%02x:%02x.%1u/mei/" ,
2100
+ bus , slot , func );
2101
+
2102
+ if (stat (path , & buf ) < 0 )
2103
+ return -1 ;
2104
+
2105
+ n = scandir (path , & namelist , filter_dirs , alphasort );
2106
+ if (n == 1 )
2107
+ snprintf (name , namesize , "%s" , namelist [0 ]-> d_name );
2108
+ else
2109
+ ret = -1 ;
2110
+
2111
+ while (n -- > 0 )
2112
+ free (namelist [n ]);
2113
+ free (namelist );
2114
+
2115
+ return ret ;
2116
+ }
2117
+
2118
+ static int
2119
+ vmei_init (struct vmctx * ctx , struct pci_vdev * dev , char * opts )
2120
+ {
2121
+ struct virtio_mei * vmei ;
2122
+ char tname [MAXCOMLEN + 1 ];
2123
+ pthread_mutexattr_t attr ;
2124
+ int i , rc ;
2125
+ char * endptr = NULL ;
2126
+ char * opt ;
2127
+ unsigned int bus = 0 , slot = 0 , func = 0 ;
2128
+ char name [DEV_NAME_SIZE + 1 ];
2129
+
2130
+ vmei_debug = 0 ;
2131
+
2132
+ if (!opts )
2133
+ goto init ;
2134
+
2135
+ while ((opt = strsep (& opts , "," )) != NULL ) {
2136
+ if (sscanf (opt , "%x/%x/%x" , & bus , & slot , & func ) == 3 )
2137
+ continue ;
2138
+ if (!strncmp (opt , "d" , 1 )) {
2139
+ vmei_debug = strtoul (opt + 1 , & endptr , 10 );
2140
+ if (endptr == opt || vmei_debug > 8 ) {
2141
+ vmei_debug = 0 ;
2142
+ WPRINTF ("init: unknown debug flag %s\n" ,
2143
+ opts + 1 );
2144
+ }
2145
+ continue ;
2146
+ }
2147
+ WPRINTF ("Invalid option: %s\n" , opt );
2148
+ }
2149
+
2150
+ if (vmei_debug )
2151
+ vmei_dbg_file = fopen ("/tmp/vmei_log" , "a+" );
2152
+
2153
+ init :
2154
+ rc = vmei_get_devname (name , sizeof (name ), bus , slot , func );
2155
+ if (rc ) {
2156
+ WPRINTF ("init: fail to get mei path!\n" );
2157
+ strncpy (name , "mei0" , sizeof (name ));
2158
+ }
2159
+
2160
+ DPRINTF ("init: starting\n" );
2161
+ vmei = calloc (1 , sizeof (* vmei ));
2162
+ if (!vmei ) {
2163
+ WPRINTF ("init: fail to alloc virtio_heci!\n" );
2164
+ goto fail ;
2165
+ }
2166
+
2167
+ vmei -> config = calloc (1 , sizeof (* vmei -> config ));
2168
+ if (!vmei -> config ) {
2169
+ WPRINTF ("init: fail to alloc vmei_config!\n" );
2170
+ goto fail ;
2171
+ }
2172
+
2173
+ /* FIXME: fix get correct mapping */
2174
+ vmei -> vtag = ctx -> vmid ;
2175
+ if (!vmei -> vtag )
2176
+ vmei -> vtag = 1 ;
2177
+
2178
+ vmei -> config -> buf_depth = VMEI_BUF_DEPTH ;
2179
+ vmei -> config -> hw_ready = 0 ;
2180
+
2181
+ strncpy (vmei -> name , name , sizeof (vmei -> name ));
2182
+ vmei -> name [sizeof (vmei -> name ) - 1 ] = 0 ;
2183
+ snprintf (vmei -> devnode , sizeof (vmei -> devnode ) - 1 ,
2184
+ "/dev/%s" , vmei -> name );
2185
+
2186
+ DPRINTF ("devnode = %s\n" , vmei -> devnode );
2187
+
2188
+ if (vmei_add_reset_event (vmei ) < 0 )
2189
+ WPRINTF ("init: resets won't be detected\n" );
2190
+
2191
+ /* init mutex attribute properly */
2192
+ rc = pthread_mutexattr_init (& attr );
2193
+ if (rc ) {
2194
+ WPRINTF ("init: mutexattr init fail, error %d!\n" , rc );
2195
+ goto fail ;
2196
+ }
2197
+
2198
+ if (virtio_uses_msix ()) {
2199
+ rc = pthread_mutexattr_settype (& attr , PTHREAD_MUTEX_DEFAULT );
2200
+ if (rc ) {
2201
+ WPRINTF ("init: mutexattr_settype failed, error %d!\n" ,
2202
+ rc );
2203
+ goto fail ;
2204
+ }
2205
+ } else {
2206
+ rc = pthread_mutexattr_settype (& attr , PTHREAD_MUTEX_RECURSIVE );
2207
+ if (rc ) {
2208
+ WPRINTF ("init: mutexattr_settype failed, error %d!\n" ,
2209
+ rc );
2210
+ goto fail ;
2211
+ }
2212
+ }
2213
+ rc = pthread_mutex_init (& vmei -> mutex , & attr );
2214
+ pthread_mutexattr_destroy (& attr );
2215
+ if (rc ) {
2216
+ WPRINTF ("init: mutex init failed, error %d!\n" , rc );
2217
+ goto fail ;
2218
+ }
2219
+
2220
+ virtio_linkup (& vmei -> base , & virtio_mei_ops , vmei , dev , vmei -> vqs );
2221
+ vmei -> base .mtx = & vmei -> mutex ;
2222
+
2223
+ for (i = 0 ; i < VMEI_VQ_NUM ; i ++ )
2224
+ vmei -> vqs [i ].qsize = VMEI_RING_SZ ;
2225
+ vmei -> vqs [VMEI_RXQ ].notify = vmei_notify_rx ;
2226
+ vmei -> vqs [VMEI_TXQ ].notify = vmei_notify_tx ;
2227
+
2228
+ /* initialize config space */
2229
+ pci_set_cfgdata16 (dev , PCIR_DEVICE , VIRTIO_DEV_HECI );
2230
+ pci_set_cfgdata16 (dev , PCIR_VENDOR , INTEL_VENDOR_ID );
2231
+ pci_set_cfgdata8 (dev , PCIR_CLASS , PCIC_SIMPLECOMM );
2232
+ pci_set_cfgdata8 (dev , PCIR_SUBCLASS , PCIS_SIMPLECOMM_OTHER );
2233
+ pci_set_cfgdata16 (dev , PCIR_SUBDEV_0 , VIRTIO_TYPE_HECI );
2234
+ pci_set_cfgdata16 (dev , PCIR_SUBVEND_0 , INTEL_VENDOR_ID );
2235
+
2236
+ if (virtio_interrupt_init (& vmei -> base , virtio_uses_msix ()))
2237
+ goto setup_fail ;
2238
+ virtio_set_io_bar (& vmei -> base , 0 );
2239
+
2240
+ /*
2241
+ * tx stuff, thread, mutex, cond
2242
+ */
2243
+ pthread_mutex_init (& vmei -> tx_mutex , NULL );
2244
+ pthread_cond_init (& vmei -> tx_cond , NULL );
2245
+ pthread_create (& vmei -> tx_thread , NULL ,
2246
+ vmei_tx_thread , vmei );
2247
+ snprintf (tname , sizeof (tname ), "vmei-%d:%d tx" , dev -> slot , dev -> func );
2248
+ pthread_setname_np (vmei -> tx_thread , tname );
2249
+
2250
+ /*
2251
+ * rx stuff
2252
+ */
2253
+ pthread_mutex_init (& vmei -> rx_mutex , NULL );
2254
+ pthread_cond_init (& vmei -> rx_cond , NULL );
2255
+ pthread_create (& vmei -> rx_thread , NULL ,
2256
+ vmei_rx_thread , (void * )vmei );
2257
+ snprintf (tname , sizeof (tname ), "vmei-%d:%d rx" , dev -> slot , dev -> func );
2258
+ pthread_setname_np (vmei -> rx_thread , tname );
2259
+
2260
+ /*
2261
+ * init clients
2262
+ */
2263
+ pthread_mutexattr_init (& attr );
2264
+ pthread_mutexattr_settype (& attr , PTHREAD_MUTEX_RECURSIVE );
2265
+ pthread_mutex_init (& vmei -> list_mutex , & attr );
2266
+ pthread_mutexattr_destroy (& attr );
2267
+ LIST_INIT (& vmei -> active_clients );
2268
+
2269
+ /*
2270
+ * start mei backend
2271
+ */
2272
+ if (vmei_start (vmei , true) < 0 )
2273
+ goto start_fail ;
2274
+
2275
+ return 0 ;
2276
+
2277
+ start_fail :
2278
+ vmei_stop (vmei );
2279
+ setup_fail :
2280
+ pthread_mutex_destroy (& vmei -> mutex );
2281
+ fail :
2282
+ if (vmei ) {
2283
+ free (vmei -> config );
2284
+ free (vmei );
2285
+ }
2286
+
2287
+ WPRINTF ("init: error\n" );
2288
+ return -1 ;
2289
+ }
2290
+
2291
+ static void
2292
+ vmei_deinit (struct vmctx * ctx , struct pci_vdev * dev , char * opts )
2293
+ {
2294
+ struct virtio_mei * vmei = (struct virtio_mei * )dev -> arg ;
2295
+
2296
+ (void )opts ;
2297
+
2298
+ if (!vmei )
2299
+ return ;
2300
+
2301
+ vmei_del_reset_event (vmei );
2302
+ vmei_stop (vmei );
2303
+
2304
+ pthread_mutex_destroy (& vmei -> mutex );
2305
+ free (vmei -> config );
2306
+ free (vmei );
2307
+ }
2308
+
2309
+ const struct pci_vdev_ops pci_ops_vmei = {
2310
+ .class_name = "virtio-heci" ,
2311
+ .vdev_init = vmei_init ,
2312
+ .vdev_barwrite = virtio_pci_write ,
2313
+ .vdev_barread = virtio_pci_read ,
2314
+ .vdev_deinit = vmei_deinit
2315
+ };
2316
+ DEFINE_PCI_DEVTYPE (pci_ops_vmei );
0 commit comments