pci posted/not posted

Non-Posted transactions are ones where the requester expects to receive a completion Transaction Layer Packet (TLP) from the device completing the request.  The TLP completion packet can be returned at a later time and doesn’t have to be returned right away.  The TLP confirms that the completer received the request.  For read requests, completions include read data.  If the completer was unable to return read data successfully, a completion packet is return containing an error status.  For write requests, the completion returns a completion packet without data indicating that it has received the write request.  As with read completions, the write completion may contain an error status if the write did not complete successfully.

Posted transactions are ones where the requester does not expect to and will not receive a completion Transaction Layer Packet (TLP).  If the write completer encounters an error, the requester will not know about it.  But, it is possible for the write completer to generate an error message notification to the Root Complex.

Requests that are considered posted transactions are:

  • Memory Writes
  • Messages

Requests that are non-posted transactions are:

  • Memory Reads
  • Memory Read Lock
  • I/O Reads
  • I/O Writes
  • Configuration Reads (both Type 0 and Type 1)
  • Configuration Writes (both Type 0 and Type 1)

A memory module includes a memory hub coupled to several memory devices. The memory hub includes a posted write buffer that stores write requests so that subsequently issued read requests can first be coupled to the memory devices. The write request addresses are also posted in the buffer and compared to subsequent read request addresses. In the event of a positive comparison indicating that a read request is directed to an address to which an earlier write request was directed, the read data are provided from the buffer. When the memory devices are not busy servicing read request, the write requests can be transferred from the posted write buffer to the memory devices. The write requests may also be accumulated in the posted write buffer until either a predetermined number of write requests have been accumulated or the write requests have been posted for a predetermined duration.

 

 

/**
643  * pci_process_bridge_OF_ranges - Parse PCI bridge resources from device tree
644  * @hose: newly allocated pci_controller to be setup
645  * @dev: device node of the host bridge
646  * @primary: set if primary bus (32 bits only, soon to be deprecated)
647  *
648  * This function will parse the "ranges" property of a PCI host bridge device
649  * node and setup the resource mapping of a pci controller based on its
650  * content.
651  *
652  * Life would be boring if it wasn't for a few issues that we have to deal
653  * with here:
654  *
655  *   - We can only cope with one IO space range and up to 3 Memory space
656  *     ranges. However, some machines (thanks Apple !) tend to split their
657  *     space into lots of small contiguous ranges. So we have to coalesce.
658  *
659  *   - Some busses have IO space not starting at 0, which causes trouble with
660  *     the way we do our IO resource renumbering. The code somewhat deals with
661  *     it for 64 bits but I would expect problems on 32 bits.
662  *
663  *   - Some 32 bits platforms such as 4xx can have physical space larger than
664  *     32 bits so we need to use 64 bits values for the parsing
665  */
666 void pci_process_bridge_OF_ranges(struct pci_controller *hose,
667                                   struct device_node *dev, int primary)
668 {
669         const __be32 *ranges;
670         int rlen;
671         int pna = of_n_addr_cells(dev);
672         int np = pna + 5;
673         int memno = 0;
674         u32 pci_space;
675         unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
676         struct resource *res;
677 
678         printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
679                dev->full_name, primary ? "(primary)" : "");
680 
681         /* Get ranges property */
682         ranges = of_get_property(dev, "ranges", &rlen);
683         if (ranges == NULL)
684                 return;
685 
686         /* Parse it */
687         while ((rlen -= np * 4) >= 0) {
688                 /* Read next ranges element */
689                 pci_space = of_read_number(ranges, 1);
690                 pci_addr = of_read_number(ranges + 1, 2);
691                 cpu_addr = of_translate_address(dev, ranges + 3);
692                 size = of_read_number(ranges + pna + 3, 2);
693                 ranges += np;
694 
695                 /* If we failed translation or got a zero-sized region
696                  * (some FW try to feed us with non sensical zero sized regions
697                  * such as power3 which look like some kind of attempt at exposing
698                  * the VGA memory hole)
699                  */
700                 if (cpu_addr == OF_BAD_ADDR || size == 0)
701                         continue;
702 
703                 /* Now consume following elements while they are contiguous */
704                 for (; rlen >= np * sizeof(u32);
705                      ranges += np, rlen -= np * 4) {
706                         if (of_read_number(ranges, 1) != pci_space)
707                                 break;
708                         pci_next = of_read_number(ranges + 1, 2);
709                         cpu_next = of_translate_address(dev, ranges + 3);
710                         if (pci_next != pci_addr + size ||
711                             cpu_next != cpu_addr + size)
712                                 break;
713                         size += of_read_number(ranges + pna + 3, 2);
714                 }
715 
716                 /* Act based on address space type */
717                 res = NULL;
718                 switch ((pci_space >> 24) & 0x3) {
719                 case 1:         /* PCI IO space */
720                         printk(KERN_INFO
721                                "  IO 0x%016llx..0x%016llx -> 0x%016llx\n",
722                                cpu_addr, cpu_addr + size - 1, pci_addr);
723 
724                         /* We support only one IO range */
725                         if (hose->pci_io_size) {
726                                 printk(KERN_INFO
727                                        " \\--> Skipped (too many) !\n");
728                                 continue;
729                         }
730 #ifdef CONFIG_PPC32
731                         /* On 32 bits, limit I/O space to 16MB */
732                         if (size > 0x01000000)
733                                 size = 0x01000000;
734 
735                         /* 32 bits needs to map IOs here */
736                         hose->io_base_virt = ioremap(cpu_addr, size);
737 
738                         /* Expect trouble if pci_addr is not 0 */
739                         if (primary)
740                                 isa_io_base =
741                                         (unsigned long)hose->io_base_virt;
742 #endif /* CONFIG_PPC32 */
743                         /* pci_io_size and io_base_phys always represent IO
744                          * space starting at 0 so we factor in pci_addr
745                          */
746                         hose->pci_io_size = pci_addr + size;
747                         hose->io_base_phys = cpu_addr - pci_addr;
748 
749                         /* Build resource */
750                         res = &hose->io_resource;
751                         res->flags = IORESOURCE_IO;
752                         res->start = pci_addr;
753                         break;
754                 case 2:         /* PCI Memory space */
755                 case 3:         /* PCI 64 bits Memory space */
756                         printk(KERN_INFO
757                                " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
758                                cpu_addr, cpu_addr + size - 1, pci_addr,
759                                (pci_space & 0x40000000) ? "Prefetch" : "");
760 
761                         /* We support only 3 memory ranges */
762                         if (memno >= 3) {
763                                 printk(KERN_INFO
764                                        " \\--> Skipped (too many) !\n");
765                                 continue;
766                         }
767                         /* Handles ISA memory hole space here */
768                         if (pci_addr == 0) {
769                                 if (primary || isa_mem_base == 0)
770                                         isa_mem_base = cpu_addr;
771                                 hose->isa_mem_phys = cpu_addr;
772                                 hose->isa_mem_size = size;
773                         }
774 
775                         /* Build resource */
776                         hose->mem_offset[memno] = cpu_addr - pci_addr;
777                         res = &hose->mem_resources[memno++];
778                         res->flags = IORESOURCE_MEM;
779                         if (pci_space & 0x40000000)
780                                 res->flags |= IORESOURCE_PREFETCH;
781                         res->start = cpu_addr;
782                         break;
783                 }
784                 if (res != NULL) {
785                         res->name = dev->full_name;
786                         res->end = res->start + size - 1;
787                         res->parent = NULL;
788                         res->sibling = NULL;
789                         res->child = NULL;
790                 }
791         }
792 }

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值