25
25
#define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32))
26
26
#define NUM_IRQ_MSGS 10
27
27
28
- #define HANDLE_NO_FREE (ptr ) ((void *)((unsigned long)(ptr) | 1))
29
- #define HANDLE_IS_NO_FREE (ptr ) ((unsigned long)(ptr) & 1)
28
+ struct um_pci_message_buffer {
29
+ struct virtio_pcidev_msg hdr ;
30
+ u8 data [8 ];
31
+ };
30
32
31
33
struct um_pci_device {
32
34
struct virtio_device * vdev ;
@@ -36,6 +38,11 @@ struct um_pci_device {
36
38
37
39
struct virtqueue * cmd_vq , * irq_vq ;
38
40
41
+ #define UM_PCI_WRITE_BUFS 20
42
+ struct um_pci_message_buffer bufs [UM_PCI_WRITE_BUFS + 1 ];
43
+ void * extra_ptrs [UM_PCI_WRITE_BUFS + 1 ];
44
+ DECLARE_BITMAP (used_bufs , UM_PCI_WRITE_BUFS );
45
+
39
46
#define UM_PCI_STAT_WAITING 0
40
47
unsigned long status ;
41
48
@@ -61,12 +68,40 @@ static unsigned long um_pci_msi_used[BITS_TO_LONGS(MAX_MSI_VECTORS)];
61
68
static unsigned int um_pci_max_delay_us = 40000 ;
62
69
module_param_named (max_delay_us , um_pci_max_delay_us , uint , 0644 );
63
70
64
- struct um_pci_message_buffer {
65
- struct virtio_pcidev_msg hdr ;
66
- u8 data [8 ];
67
- };
71
+ static int um_pci_get_buf (struct um_pci_device * dev , bool * posted )
72
+ {
73
+ int i ;
74
+
75
+ for (i = 0 ; i < UM_PCI_WRITE_BUFS ; i ++ ) {
76
+ if (!test_and_set_bit (i , dev -> used_bufs ))
77
+ return i ;
78
+ }
68
79
69
- static struct um_pci_message_buffer __percpu * um_pci_msg_bufs ;
80
+ * posted = false;
81
+ return UM_PCI_WRITE_BUFS ;
82
+ }
83
+
84
+ static void um_pci_free_buf (struct um_pci_device * dev , void * buf )
85
+ {
86
+ int i ;
87
+
88
+ if (buf == & dev -> bufs [UM_PCI_WRITE_BUFS ]) {
89
+ kfree (dev -> extra_ptrs [UM_PCI_WRITE_BUFS ]);
90
+ dev -> extra_ptrs [UM_PCI_WRITE_BUFS ] = NULL ;
91
+ return ;
92
+ }
93
+
94
+ for (i = 0 ; i < UM_PCI_WRITE_BUFS ; i ++ ) {
95
+ if (buf == & dev -> bufs [i ]) {
96
+ kfree (dev -> extra_ptrs [i ]);
97
+ dev -> extra_ptrs [i ] = NULL ;
98
+ WARN_ON (!test_and_clear_bit (i , dev -> used_bufs ));
99
+ return ;
100
+ }
101
+ }
102
+
103
+ WARN_ON (1 );
104
+ }
70
105
71
106
static int um_pci_send_cmd (struct um_pci_device * dev ,
72
107
struct virtio_pcidev_msg * cmd ,
@@ -82,7 +117,9 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
82
117
};
83
118
struct um_pci_message_buffer * buf ;
84
119
int delay_count = 0 ;
120
+ bool bounce_out ;
85
121
int ret , len ;
122
+ int buf_idx ;
86
123
bool posted ;
87
124
88
125
if (WARN_ON (cmd_size < sizeof (* cmd ) || cmd_size > sizeof (* buf )))
@@ -101,66 +138,69 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
101
138
break ;
102
139
}
103
140
104
- buf = get_cpu_var (um_pci_msg_bufs );
105
- if (buf )
106
- memcpy (buf , cmd , cmd_size );
141
+ bounce_out = !posted && cmd_size <= sizeof (* cmd ) &&
142
+ out && out_size <= sizeof (buf -> data );
107
143
108
- if (posted ) {
109
- u8 * ncmd = kmalloc (cmd_size + extra_size , GFP_ATOMIC );
110
-
111
- if (ncmd ) {
112
- memcpy (ncmd , cmd , cmd_size );
113
- if (extra )
114
- memcpy (ncmd + cmd_size , extra , extra_size );
115
- cmd = (void * )ncmd ;
116
- cmd_size += extra_size ;
117
- extra = NULL ;
118
- extra_size = 0 ;
119
- } else {
120
- /* try without allocating memory */
121
- posted = false;
122
- cmd = (void * )buf ;
144
+ buf_idx = um_pci_get_buf (dev , & posted );
145
+ buf = & dev -> bufs [buf_idx ];
146
+ memcpy (buf , cmd , cmd_size );
147
+
148
+ if (posted && extra && extra_size > sizeof (buf ) - cmd_size ) {
149
+ dev -> extra_ptrs [buf_idx ] = kmemdup (extra , extra_size ,
150
+ GFP_ATOMIC );
151
+
152
+ if (!dev -> extra_ptrs [buf_idx ]) {
153
+ um_pci_free_buf (dev , buf );
154
+ return - ENOMEM ;
123
155
}
156
+ extra = dev -> extra_ptrs [buf_idx ];
157
+ } else if (extra && extra_size <= sizeof (buf ) - cmd_size ) {
158
+ memcpy ((u8 * )buf + cmd_size , extra , extra_size );
159
+ cmd_size += extra_size ;
160
+ extra_size = 0 ;
161
+ extra = NULL ;
162
+ cmd = (void * )buf ;
124
163
} else {
125
164
cmd = (void * )buf ;
126
165
}
127
166
128
167
sg_init_one (& out_sg , cmd , cmd_size );
129
168
if (extra )
130
169
sg_init_one (& extra_sg , extra , extra_size );
131
- if (out )
170
+ /* allow stack for small buffers */
171
+ if (bounce_out )
172
+ sg_init_one (& in_sg , buf -> data , out_size );
173
+ else if (out )
132
174
sg_init_one (& in_sg , out , out_size );
133
175
134
176
/* add to internal virtio queue */
135
177
ret = virtqueue_add_sgs (dev -> cmd_vq , sgs_list ,
136
178
extra ? 2 : 1 ,
137
179
out ? 1 : 0 ,
138
- posted ? cmd : HANDLE_NO_FREE (cmd ),
139
- GFP_ATOMIC );
180
+ cmd , GFP_ATOMIC );
140
181
if (ret ) {
141
- if (posted )
142
- kfree (cmd );
143
- goto out ;
182
+ um_pci_free_buf (dev , buf );
183
+ return ret ;
144
184
}
145
185
146
186
if (posted ) {
147
187
virtqueue_kick (dev -> cmd_vq );
148
- ret = 0 ;
149
- goto out ;
188
+ return 0 ;
150
189
}
151
190
152
191
/* kick and poll for getting a response on the queue */
153
192
set_bit (UM_PCI_STAT_WAITING , & dev -> status );
154
193
virtqueue_kick (dev -> cmd_vq );
194
+ ret = 0 ;
155
195
156
196
while (1 ) {
157
197
void * completed = virtqueue_get_buf (dev -> cmd_vq , & len );
158
198
159
- if (completed == HANDLE_NO_FREE ( cmd ) )
199
+ if (completed == buf )
160
200
break ;
161
201
162
- if (completed && ! HANDLE_IS_NO_FREE ( completed ) )
163
- kfree ( completed );
202
+ if (completed )
203
+ um_pci_free_buf ( dev , completed );
164
204
165
205
if (WARN_ONCE (virtqueue_is_broken (dev -> cmd_vq ) ||
166
206
++ delay_count > um_pci_max_delay_us ,
@@ -172,8 +212,11 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
172
212
}
173
213
clear_bit (UM_PCI_STAT_WAITING , & dev -> status );
174
214
175
- out :
176
- put_cpu_var (um_pci_msg_bufs );
215
+ if (bounce_out )
216
+ memcpy (out , buf -> data , out_size );
217
+
218
+ um_pci_free_buf (dev , buf );
219
+
177
220
return ret ;
178
221
}
179
222
@@ -187,20 +230,13 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
187
230
.size = size ,
188
231
.addr = offset ,
189
232
};
190
- /* buf->data is maximum size - we may only use parts of it */
191
- struct um_pci_message_buffer * buf ;
192
- u8 * data ;
193
- unsigned long ret = ULONG_MAX ;
194
- size_t bytes = sizeof (buf -> data );
233
+ /* max 8, we might not use it all */
234
+ u8 data [8 ];
195
235
196
236
if (!dev )
197
237
return ULONG_MAX ;
198
238
199
- buf = get_cpu_var (um_pci_msg_bufs );
200
- data = buf -> data ;
201
-
202
- if (buf )
203
- memset (data , 0xff , bytes );
239
+ memset (data , 0xff , sizeof (data ));
204
240
205
241
switch (size ) {
206
242
case 1 :
@@ -212,34 +248,26 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
212
248
break ;
213
249
default :
214
250
WARN (1 , "invalid config space read size %d\n" , size );
215
- goto out ;
251
+ return ULONG_MAX ;
216
252
}
217
253
218
- if (um_pci_send_cmd (dev , & hdr , sizeof (hdr ), NULL , 0 , data , bytes ))
219
- goto out ;
254
+ if (um_pci_send_cmd (dev , & hdr , sizeof (hdr ), NULL , 0 , data , size ))
255
+ return ULONG_MAX ;
220
256
221
257
switch (size ) {
222
258
case 1 :
223
- ret = data [0 ];
224
- break ;
259
+ return data [0 ];
225
260
case 2 :
226
- ret = le16_to_cpup ((void * )data );
227
- break ;
261
+ return le16_to_cpup ((void * )data );
228
262
case 4 :
229
- ret = le32_to_cpup ((void * )data );
230
- break ;
263
+ return le32_to_cpup ((void * )data );
231
264
#ifdef CONFIG_64BIT
232
265
case 8 :
233
- ret = le64_to_cpup ((void * )data );
234
- break ;
266
+ return le64_to_cpup ((void * )data );
235
267
#endif
236
268
default :
237
- break ;
269
+ return ULONG_MAX ;
238
270
}
239
-
240
- out :
241
- put_cpu_var (um_pci_msg_bufs );
242
- return ret ;
243
271
}
244
272
245
273
static void um_pci_cfgspace_write (void * priv , unsigned int offset , int size ,
@@ -312,13 +340,8 @@ static void um_pci_bar_copy_from(void *priv, void *buffer,
312
340
static unsigned long um_pci_bar_read (void * priv , unsigned int offset ,
313
341
int size )
314
342
{
315
- /* buf->data is maximum size - we may only use parts of it */
316
- struct um_pci_message_buffer * buf ;
317
- u8 * data ;
318
- unsigned long ret = ULONG_MAX ;
319
-
320
- buf = get_cpu_var (um_pci_msg_bufs );
321
- data = buf -> data ;
343
+ /* 8 is maximum size - we may only use parts of it */
344
+ u8 data [8 ];
322
345
323
346
switch (size ) {
324
347
case 1 :
@@ -330,33 +353,25 @@ static unsigned long um_pci_bar_read(void *priv, unsigned int offset,
330
353
break ;
331
354
default :
332
355
WARN (1 , "invalid config space read size %d\n" , size );
333
- goto out ;
356
+ return ULONG_MAX ;
334
357
}
335
358
336
359
um_pci_bar_copy_from (priv , data , offset , size );
337
360
338
361
switch (size ) {
339
362
case 1 :
340
- ret = data [0 ];
341
- break ;
363
+ return data [0 ];
342
364
case 2 :
343
- ret = le16_to_cpup ((void * )data );
344
- break ;
365
+ return le16_to_cpup ((void * )data );
345
366
case 4 :
346
- ret = le32_to_cpup ((void * )data );
347
- break ;
367
+ return le32_to_cpup ((void * )data );
348
368
#ifdef CONFIG_64BIT
349
369
case 8 :
350
- ret = le64_to_cpup ((void * )data );
351
- break ;
370
+ return le64_to_cpup ((void * )data );
352
371
#endif
353
372
default :
354
- break ;
373
+ return ULONG_MAX ;
355
374
}
356
-
357
- out :
358
- put_cpu_var (um_pci_msg_bufs );
359
- return ret ;
360
375
}
361
376
362
377
static void um_pci_bar_copy_to (void * priv , unsigned int offset ,
@@ -523,11 +538,8 @@ static void um_pci_cmd_vq_cb(struct virtqueue *vq)
523
538
if (test_bit (UM_PCI_STAT_WAITING , & dev -> status ))
524
539
return ;
525
540
526
- while ((cmd = virtqueue_get_buf (vq , & len ))) {
527
- if (WARN_ON (HANDLE_IS_NO_FREE (cmd )))
528
- continue ;
529
- kfree (cmd );
530
- }
541
+ while ((cmd = virtqueue_get_buf (vq , & len )))
542
+ um_pci_free_buf (dev , cmd );
531
543
}
532
544
533
545
static void um_pci_irq_vq_cb (struct virtqueue * vq )
@@ -1006,10 +1018,6 @@ static int __init um_pci_init(void)
1006
1018
"No virtio device ID configured for PCI - no PCI support\n" ))
1007
1019
return 0 ;
1008
1020
1009
- um_pci_msg_bufs = alloc_percpu (struct um_pci_message_buffer );
1010
- if (!um_pci_msg_bufs )
1011
- return - ENOMEM ;
1012
-
1013
1021
bridge = pci_alloc_host_bridge (0 );
1014
1022
if (!bridge ) {
1015
1023
err = - ENOMEM ;
@@ -1070,7 +1078,6 @@ static int __init um_pci_init(void)
1070
1078
pci_free_resource_list (& bridge -> windows );
1071
1079
pci_free_host_bridge (bridge );
1072
1080
}
1073
- free_percpu (um_pci_msg_bufs );
1074
1081
return err ;
1075
1082
}
1076
1083
module_init (um_pci_init );
@@ -1082,6 +1089,5 @@ static void __exit um_pci_exit(void)
1082
1089
irq_domain_remove (um_pci_inner_domain );
1083
1090
pci_free_resource_list (& bridge -> windows );
1084
1091
pci_free_host_bridge (bridge );
1085
- free_percpu (um_pci_msg_bufs );
1086
1092
}
1087
1093
module_exit (um_pci_exit );
0 commit comments