|
7 | 7 | */
|
8 | 8 |
|
9 | 9 | #include <linux/crc32.h>
|
| 10 | +#include <linux/cleanup.h> |
10 | 11 | #include <linux/delay.h>
|
11 | 12 | #include <linux/fs.h>
|
12 | 13 | #include <linux/io.h>
|
@@ -275,31 +276,60 @@ static const u32 bar_test_pattern[] = {
|
275 | 276 | 0xA5A5A5A5,
|
276 | 277 | };
|
277 | 278 |
|
| 279 | +static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test, |
| 280 | + enum pci_barno barno, int offset, |
| 281 | + void *write_buf, void *read_buf, |
| 282 | + int size) |
| 283 | +{ |
| 284 | + memset(write_buf, bar_test_pattern[barno], size); |
| 285 | + memcpy_toio(test->bar[barno] + offset, write_buf, size); |
| 286 | + |
| 287 | + memcpy_fromio(read_buf, test->bar[barno] + offset, size); |
| 288 | + |
| 289 | + return memcmp(write_buf, read_buf, size); |
| 290 | +} |
| 291 | + |
278 | 292 | static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
|
279 | 293 | enum pci_barno barno)
|
280 | 294 | {
|
281 |
| - int j; |
282 |
| - u32 val; |
283 |
| - int size; |
| 295 | + int j, bar_size, buf_size, iters, remain; |
| 296 | + void *write_buf __free(kfree) = NULL; |
| 297 | + void *read_buf __free(kfree) = NULL; |
284 | 298 | struct pci_dev *pdev = test->pdev;
|
285 | 299 |
|
286 | 300 | if (!test->bar[barno])
|
287 | 301 | return false;
|
288 | 302 |
|
289 |
| - size = pci_resource_len(pdev, barno); |
| 303 | + bar_size = pci_resource_len(pdev, barno); |
290 | 304 |
|
291 | 305 | if (barno == test->test_reg_bar)
|
292 |
| - size = 0x4; |
| 306 | + bar_size = 0x4; |
293 | 307 |
|
294 |
| - for (j = 0; j < size; j += 4) |
295 |
| - pci_endpoint_test_bar_writel(test, barno, j, |
296 |
| - bar_test_pattern[barno]); |
| 308 | + /* |
| 309 | + * Allocate a buffer of max size 1MB, and reuse that buffer while |
| 310 | + * iterating over the whole BAR size (which might be much larger). |
| 311 | + */ |
| 312 | + buf_size = min(SZ_1M, bar_size); |
297 | 313 |
|
298 |
| - for (j = 0; j < size; j += 4) { |
299 |
| - val = pci_endpoint_test_bar_readl(test, barno, j); |
300 |
| - if (val != bar_test_pattern[barno]) |
| 314 | + write_buf = kmalloc(buf_size, GFP_KERNEL); |
| 315 | + if (!write_buf) |
| 316 | + return false; |
| 317 | + |
| 318 | + read_buf = kmalloc(buf_size, GFP_KERNEL); |
| 319 | + if (!read_buf) |
| 320 | + return false; |
| 321 | + |
| 322 | + iters = bar_size / buf_size; |
| 323 | + for (j = 0; j < iters; j++) |
| 324 | + if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * j, |
| 325 | + write_buf, read_buf, buf_size)) |
| 326 | + return false; |
| 327 | + |
| 328 | + remain = bar_size % buf_size; |
| 329 | + if (remain) |
| 330 | + if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * iters, |
| 331 | + write_buf, read_buf, remain)) |
301 | 332 | return false;
|
302 |
| - } |
303 | 333 |
|
304 | 334 | return true;
|
305 | 335 | }
|
|
0 commit comments