LINUX.ORG.RU

перезапись конфигурационного пространства PCI

 ,


0

1

Доброго времени суток, ЛОР!

Столкнулся с такой проблемой, что не получается внести изменнения в конфигурационное пространство... Вот пример того, что я пытаюсь сделать:

 483     plxphys0 = pci_resource_start(dev, 0);
 484     printk("plxphys0 = 0x%x\n", plxphys0);
 
 485     plxphys = plxphys0 & PAGE_MASK;
 486     printk("plxphys = 0x%x\n", plxphys);
 
 487     pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, plxphys);
 488     udelay(500UL);
 489     pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &plxphys);
 490     printk("plxphys = 0x%x\n", plxphys);
 491 
 492     for (reg = 0; reg < DEVICE_COUNT_RESOURCE; reg++) {
 493         if (flags & IORESOURCE_MEM) {
 493             device->core.mem_base[n] = pci_resource_start(dev, reg);
....
 521                 printk(KERN_INFO "mkopci%d: BAR%d = 0x%08lx, linear = 0x%08lx, len = 0x%x, flags = 0x%x\n", device->core.n_dev, reg, device->core.mem_base[n], device->core.lin_base[n], device->core.mem_size[n], flags);

но сообщение в pci_resource_start возвращает старое значение:

[ 1137.176830] plxphys0 = 0xdfdffc00

[ 1137.182472] plxphys = 0xdfdff000

[ 1137.188373] plxphys = 0xdfdff000

[ 1137.193649] mkopci0: BAR0 = 0xdfdffc00, linear = 0xffffc900050fec00, len = 0x80, flags = 0x40200

Подскажите, плиз, где может быть проблема?

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 6)

Потому что pci_resource_start - это:

#define pci_resource_start(dev, bar)    ((dev)->resource[(bar)].start)

Т.е. значение во время инициализации. И твои записи в регистр его не меняют.

ttnl ★★★★★
()
Ответ на: комментарий от mv
ioremap_nocache(pci_resource_start(dev, 0),
                           pci_resource_len(dev, 0));

так я получаю lin_base[n]

я плохо объяснил, чего хочу....

есть пример такой штуки, когда на plx9050, если в регистре0 7-ой бит был не нулевым, то было невозможно читать из памяти устройства. Вот более вменяемое описание бага: http://www.jungo.com/st/support/tech_docs/td83.html

и они одним из решение предлагают «Reprogram the BARs yourself»

и вот такой workaround есть в linux-3.3.7/drivers/net/wan/pc300too.c:

338     plxphys = pci_resource_start(pdev, 0) & PCI_BASE_ADDRESS_MEM_MASK;
339     card->plxbase = ioremap(plxphys, PC300_PLX_SIZE);
340 
341     scaphys = pci_resource_start(pdev, 2) & PCI_BASE_ADDRESS_MEM_MASK;
342     card->scabase = ioremap(scaphys, PC300_SCA_SIZE);
343 
344     ramphys = pci_resource_start(pdev, 3) & PCI_BASE_ADDRESS_MEM_MASK;
345     card->rambase = pci_ioremap_bar(pdev, 3);
346 
347     if (card->plxbase == NULL ||
348         card->scabase == NULL ||
349         card->rambase == NULL) {
350         pr_err("ioremap() failed\n");
351         pc300_pci_remove_one(pdev);
352     }
353 
354     /* PLX PCI 9050 workaround for local configuration register read bug */
355     pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, scaphys);
356     card->init_ctrl_value = readl(&((plx9050 __iomem *)card->scabase)->init_ctrl);
357     pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, plxphys);

а у меня регистр не сохраняяется (как было видно в выводе dmesg'a), но тесты карточки начинают валиться %)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

Адреса ресурсов лежат в физическом адресном пространстве, тебе нужно замапить его в виртуальное (если ядро с MMU).

mv ★★★★★
()
Ответ на: комментарий от mv

так та ошибка как раз на физический адрес реагирует...

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

неужели просто

dev->resource[(bar)].start = plxphys

По идее — записать нужное значение в регистр и сделать что-нибудь типа того, как ты написал.

Но это только на первый взгляд. Потому что откалиброванные start и size могут использоваться еще где-нибудь. И менять необходимо, соответственно, во всех местах.

Короче, сразу не скажу.

ttnl ★★★★★
()
Ответ на: комментарий от mv

Адреса ресурсов лежат в физическом адресном пространстве, тебе нужно замапить его в виртуальное (если ядро с MMU).

Нужно сделать так, чтобы определенный диапазон физадресов не имел отношения к железке. Виртуальные тут ни при чем.

ttnl ★★★★★
()
Ответ на: комментарий от metawishmaster

Я не понимаю, где гарантия того, что ты не пересечешься по адресам с другой железкой.

Седьмой бит - это с нуля, т.е. 0x100?

Рабочий диапазон новых адресов попадает в [pci_resource_start, pci_resource_start + pci_resource_size] старого?

ttnl ★★★★★
()
Ответ на: комментарий от ttnl

Седьмой бит с нуля это 0x80, вроде...

как я понял фразу «обнулить бит», похоже да, попадает. но так рекомендовали где-то...

да и про то, что может пересечься с другой железеой - просто уповаю та то, что не бывает двух железок в одной странице %)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от ttnl

но тогда ведь вместо

plxphys = plxphys0 & PAGE_MASK;
лучше писать
plxphys = plxphys0 & (PAGE_MASK | 0xf00);
у меня просто нет таких железок, которые бы выдавали подходящие «адреса», поэтому приходится аккуратно и «теоретически» %) все адреса, что выдаются материнкой у меня кратны 32-ум, поэтому и проверял на PAGE_MASK...

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от ttnl

а вот еще вопрос... если мне нужно будет действительно переаллоцировать кусок памяти, то нужно будет бежать по всем устройствам в системе и смотреть где попадется пустое место подходящего размера?

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от ttnl

а хотя, я вроде нашел request_mem_region

тогда получится что-то типа такого:

for (i=0; i<0xffffff; i++) {
    plxphys += 0x1000;
    // танцы с бубном, request_mem_region и (для I/O ports) request_region
...

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

а у меня регистр не сохраняяется (как было видно в выводе dmesg'a), но тесты карточки начинают валиться %)

Я не очень понял, к чему разговор о «калибровке» (что вы вообще называетет калибровкой?), но в работающем workaround'е делается запись-чтение-запись (причем чтение какого-то волшебного адреса), а у тебя - запись-пауза-чтение.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ну... вчера получилось заменить адреса (0xdfdffc00 -> 0xdfdff000 и 0xc800 -> 0xc000) так чтобы тесты не падали. я сделал

 482     plxphys = pci_resource_start(dev, 0);
 483     if (plxphys & 0x80) {
 484         len = pci_resource_len(dev, 0);
 485         plxphys = plxphys & (PAGE_MASK | 0xf00);
 486         pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, plxphys);
 487         udelay(500UL);
 488         dev->resource[0].start = plxphys;
 489         dev->resource[0].end = dev->resource[0].start + len - 1;
 490     }
но теперь эта штука не будет происходить на моем железе (и биос новый, и карточка тут на plx9052, а он типа багфри). но с закомментированной 483-ей строчкой все меняется и тестыуже ночь в цикле проработали. Похоже те друзья делают то же самое, но вид получается «сбоку» %)

ну и я думаю выкинуть udelay - я его туда вставил хорошо не подумав...

единственное, что, наверное, память нужно еще и переаллоцировать

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от ttnl

не получается нормально выделить память на шине :(

вроде все делаю правильно...

 482         plxphys = pci_resource_start(dev, 0);
 483         if (plxphys & 0xf00) {
 484             len = pci_resource_len(dev, 0);
 485             plxphys = plxphys & (PAGE_MASK/* | 0xf00*/);
 486 
 487             for (n = 0; n < 0xffffff; n++) {
 488                 plxphys += 0x1000;
 489                 if ((err = check_mem_region(plxphys, len)) == 0) {
 490                     device->plx9050bug = 1;
 491                     break;
 492                 }
 493             }
 494             if (err) {
 495                 printk(KERN_ERR "mkopci%d: no valid mem region\n", device->core.n_dev);
 496                 return -ENOMEM;
 497             }
 498             device->plx9050bug = 1;
 499 
 500             request_mem_region(plxphys, len, device->core.name);
 501             pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, plxphys);
 502             udelay(500UL);
 503             dev->resource[0].start = plxphys;
 504             dev->resource[0].end = dev->resource[0].start + len - 1;
 505         }

metawishmaster ★★★★★
() автор топика

вопрос снимается :)

хочу выразить благодарность и спасибо огромное за участие (в алфавитном порядке) mv, tailgunner, и особенно ttnl :)

а выделить пространство получилось только из кусочка, принадлежащего данному устройству... и только после инициализации остальных регистров.

metawishmaster ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.