pm8001_pci_probe函数分析之pm8001_pci_alloc

来源:互联网 发布:会计出纳软件 编辑:程序博客网 时间:2024/05/16 06:31
接着分析pm8001_pci_probe中调用的pm8001_pci_alloc和scsi_scan_host。先分析pm8001_pci_alloc,在下一篇文章中分析scsi_scan_host

先把pm8001_pci_alloc的代码贴在下面:

/** * pm8001_pci_alloc - initialize our ha card structure * @pdev: pci device. * @ent: ent * @shost: scsi host struct which has been initialized before. */static struct pm8001_hba_info *__devinitpm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost){struct pm8001_hba_info *pm8001_ha;//struct pm8001_hba_info represent HBA in lldd layerstruct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);//struct sas_ha_struct represent HBA in libsas layerpm8001_ha = sha->lldd_ha;//mem alloced in pm8001_prep_sas_ha_init with kzallocif (!pm8001_ha)return NULL;                //init part of struct pm8001_hba_info pm8001_ha->pdev = pdev;pm8001_ha->dev = &pdev->dev;pm8001_ha->chip_id = chip_id;pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id];pm8001_ha->irq = pdev->irq;pm8001_ha->sas = sha;pm8001_ha->shost = shost;pm8001_ha->id = pm8001_id++;pm8001_ha->logging_level = logging_level;pm8001_ha->ses = 0x0;sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);                //remap the pci high physical address to kernel virtual  pm8001_ioremap(pm8001_ha);//注意1if (!pm8001_alloc(pm8001_ha))//注意2return pm8001_ha;pm8001_free(pm8001_ha);return NULL;}

注意1:pm8001_ioremap - remap the pci high physical address to kernal virtual address so that we can access them.

pm8001_ioremap的代码如下:

/** * pm8001_ioremap - remap the pci high physical address to kernal virtual * address so that we can access them. * @pm8001_ha:our hba structure. */static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha){u32 bar;u32 logicalBar = 0;struct pci_dev *pdev;pdev = pm8001_ha->pdev;/* map pci mem (PMC pci base 0-3)*/for (bar = 0; bar < 6; bar++) {/*** logical BARs for SPC:** bar 0 and 1 - logical BAR0** bar 2 and 3 - logical BAR1** bar4 - logical BAR2** bar5 - logical BAR3** Skip the appropriate assignments:*/if ((bar == 1) || (bar == 3))continue;if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {pm8001_ha->io_mem[logicalBar].membase =pci_resource_start(pdev, bar);pm8001_ha->io_mem[logicalBar].membase &=(u32)PCI_BASE_ADDRESS_MEM_MASK;pm8001_ha->io_mem[logicalBar].memsize =pci_resource_len(pdev, bar);pm8001_ha->io_mem[logicalBar].flags = pci_resource_flags(pdev, bar);if (pm8001_ha->io_mem[logicalBar].flags & IORESOURCE_CACHEABLE) {        pm8001_ha->io_mem[logicalBar].memvirtaddr =ioremap(pm8001_ha->io_mem[logicalBar].membase,pm8001_ha->io_mem[logicalBar].memsize);}else {pm8001_ha->io_mem[logicalBar].memvirtaddr =ioremap_nocache(pm8001_ha->io_mem[logicalBar].membase,pm8001_ha->io_mem[logicalBar].memsize);}PM8001_INIT_DBG(pm8001_ha,pm8001_printk("PCI: bar %d, logicalBar %d ""virt_addr=%lx,len=%d\n", bar, logicalBar,(unsigned long)pm8001_ha->io_mem[logicalBar].memvirtaddr,pm8001_ha->io_mem[logicalBar].memsize));} else {pm8001_ha->io_mem[logicalBar].membase= 0;pm8001_ha->io_mem[logicalBar].memsize= 0;pm8001_ha->io_mem[logicalBar].memvirtaddr = 0;}logicalBar++;}return 0;}

pm8001_ioremap函数主要是调用ioremap将pci设备的物理地址映射到内核的逻辑地址,以便内核能够访问pci设备。

注意2:pm8001_alloc - initiate our hba structure and 6 DMAs area

pm8001_alloc的代码如下:

/** * pm8001_alloc - initiate our hba structure and 6 DMAs area. * @pm8001_ha:our hba structure. */static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha){int i;int ccbs_count1 = 0;int ccbs_count2 = 0;int max_mem = USI_MAX_MEMCNT;spin_lock_init(&pm8001_ha->lock);for (i = 0; i < pm8001_ha->chip->n_phy; i++) {pm8001_phy_init(pm8001_ha, i);pm8001_ha->port[i].wide_port_phymap = 0;pm8001_ha->port[i].port_attached = 0;pm8001_ha->port[i].port_state = 0;}pm8001_ha->tags = kzalloc(sizeof(unsigned long) * BITS_TO_LONGS(max_ccbs), GFP_KERNEL);//alloc bitmap memif (!pm8001_ha->tags)goto err_out;pm8001_logging_size = ((pm8001_logging_size + 31) / 32) * 32;if (pm8001_logging_size < 64)pm8001_logging_size = 64;/* MPI Memory region 1 for AAP Event Log for fw */pm8001_ha->memoryMap.region[AAP1].num_elements = 1;pm8001_ha->memoryMap.region[AAP1].element_size = pm8001_logging_size;pm8001_ha->memoryMap.region[AAP1].total_len = pm8001_logging_size;pm8001_ha->memoryMap.region[AAP1].alignment = 32;/* MPI Memory region 2 for IOP Event Log for fw */pm8001_ha->memoryMap.region[IOP].num_elements = 1;pm8001_ha->memoryMap.region[IOP].element_size = pm8001_logging_size;pm8001_ha->memoryMap.region[IOP].total_len = pm8001_logging_size;pm8001_ha->memoryMap.region[IOP].alignment = 32;for(i = CI; i < (CI + PM8001_MAX_INB_NUM); i++){/* MPI Memory region 3 for consumer Index of inbound queues */pm8001_ha->memoryMap.region[i].num_elements = 1;pm8001_ha->memoryMap.region[i].element_size = 4;pm8001_ha->memoryMap.region[i].total_len = 4;pm8001_ha->memoryMap.region[i].alignment = 4;}for(i = PI; i < (PI + PM8001_MAX_OUTB_NUM); i++){/* MPI Memory region 4 for producer Index of outbound queues */pm8001_ha->memoryMap.region[i].num_elements = 1;pm8001_ha->memoryMap.region[i].element_size = 4;pm8001_ha->memoryMap.region[i].total_len = 4;pm8001_ha->memoryMap.region[i].alignment = 4;}for(i = IB; i < (IB + PM8001_MAX_INB_NUM); i++){/* MPI Memory region 5 inbound queues */pm8001_ha->memoryMap.region[i].num_elements = INBOUND_DEPTH_SIZE;pm8001_ha->memoryMap.region[i].element_size = IOMB_SIZE128;pm8001_ha->memoryMap.region[i].total_len = INBOUND_DEPTH_SIZE * IOMB_SIZE128;pm8001_ha->memoryMap.region[i].alignment = IOMB_SIZE128;}for(i = OB; i < (OB + PM8001_MAX_OUTB_NUM); i++){/* MPI Memory region 6 outbound queues */pm8001_ha->memoryMap.region[i].num_elements = OUTBOUND_DEPTH_SIZE;pm8001_ha->memoryMap.region[i].element_size = IOMB_SIZE64;pm8001_ha->memoryMap.region[i].total_len = OUTBOUND_DEPTH_SIZE * IOMB_SIZE64;pm8001_ha->memoryMap.region[i].alignment = IOMB_SIZE64;}/* Memory region write DMA*/pm8001_ha->memoryMap.region[NVMD].num_elements = 1;pm8001_ha->memoryMap.region[NVMD].element_size = 4096;pm8001_ha->memoryMap.region[NVMD].total_len = 4096;/* Memory region for devices*/pm8001_ha->memoryMap.region[DEV_MEM].num_elements = 1;pm8001_ha->memoryMap.region[DEV_MEM].element_size = PM8001_MAX_DEVICES *sizeof(struct pm8001_device);pm8001_ha->memoryMap.region[DEV_MEM].total_len = PM8001_MAX_DEVICES *sizeof(struct pm8001_device);/* Memory region for ccb_info*/if (max_ccbs > PM8001_MAX_CCB_UNIT) {//how can this hanppen??ccbs_count1 = PM8001_MAX_CCB_UNIT;ccbs_count2 = max_ccbs - ccbs_count1;} else {ccbs_count1 = max_ccbs;max_mem = max_mem -1;}pm8001_ha->memoryMap.region[CCB_MEM].num_elements = 1;pm8001_ha->memoryMap.region[CCB_MEM].element_size = ccbs_count1 *sizeof(struct pm8001_ccb_info);pm8001_ha->memoryMap.region[CCB_MEM].total_len = ccbs_count1 *sizeof(struct pm8001_ccb_info);/* Memory region for ccb_info*/pm8001_ha->memoryMap.region[CCB_MEM1].num_elements = 1;pm8001_ha->memoryMap.region[CCB_MEM1].element_size = ccbs_count2 *sizeof(struct pm8001_ccb_info);pm8001_ha->memoryMap.region[CCB_MEM1].total_len = ccbs_count2 *sizeof(struct pm8001_ccb_info);        //alloc the memfor (i = 0; i < max_mem; i++) {                //注意3                if (pm8001_mem_alloc(pm8001_ha->pdev,&pm8001_ha->memoryMap.region[i].virt_ptr,&pm8001_ha->memoryMap.region[i].phys_addr,&pm8001_ha->memoryMap.region[i].phys_addr_hi,&pm8001_ha->memoryMap.region[i].phys_addr_lo,pm8001_ha->memoryMap.region[i].total_len,pm8001_ha->memoryMap.region[i].alignment) != 0) {PM8001_FAIL_DBG(pm8001_ha,pm8001_printk("Mem%d alloc failed\n",i));goto err_out;}}pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr;for (i = 0; i < PM8001_MAX_DEVICES; i++) {pm8001_ha->devices[i].dev_type = NO_DEVICE;pm8001_ha->devices[i].sas_device = NULL;pm8001_ha->devices[i].attached_phy = 0;pm8001_ha->devices[i].id = i;pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;pm8001_ha->devices[i].dcompletion = NULL;pm8001_ha->devices[i].setds_completion = NULL;pm8001_ha->devices[i].running_req = 0;}pm8001_ha->ccb_info = pm8001_ha->memoryMap.region[CCB_MEM].virt_ptr;if (max_ccbs > PM8001_MAX_CCB_UNIT) {pm8001_ha->ccb_info1 = pm8001_ha->memoryMap.region[CCB_MEM1].virt_ptr;for (i = 0; i < ccbs_count1; i++) {pm8001_ha->ccb_info[i].ccb_dma_handle =pm8001_ha->memoryMap.region[CCB_MEM].phys_addr +i * sizeof(struct pm8001_ccb_info);pm8001_ha->ccb_info[i].task = NULL;pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;pm8001_ha->ccb_info[i].device = NULL;pm8001_ha->ccb_info[i].event_flag = 0x0;pm8001_ha->ccb_info[i].n_elem = 0x0;pm8001_ha->ccb_info[i].fw_control_context = NULL;memset(pm8001_ha->ccb_info[i].buf_prd, 0, sizeof(pm8001_ha->ccb_info[i].buf_prd));++pm8001_ha->tags_num;}for (i = 0; i < ccbs_count2; i++) {pm8001_ha->ccb_info1[i].ccb_dma_handle =pm8001_ha->memoryMap.region[CCB_MEM1].phys_addr +i * sizeof(struct pm8001_ccb_info);pm8001_ha->ccb_info1[i].task = NULL;pm8001_ha->ccb_info1[i].ccb_tag = 0xffffffff;pm8001_ha->ccb_info1[i].device = NULL;pm8001_ha->ccb_info1[i].event_flag = 0x0;pm8001_ha->ccb_info1[i].n_elem = 0x0;pm8001_ha->ccb_info1[i].fw_control_context = NULL;memset(pm8001_ha->ccb_info1[i].buf_prd, 0, sizeof(pm8001_ha->ccb_info1[i].buf_prd));++pm8001_ha->tags_num;}} else {for (i = 0; i < max_ccbs; i++) {pm8001_ha->ccb_info[i].ccb_dma_handle =pm8001_ha->memoryMap.region[CCB_MEM].phys_addr +i * sizeof(struct pm8001_ccb_info);pm8001_ha->ccb_info[i].task = NULL;pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;pm8001_ha->ccb_info[i].device = NULL;pm8001_ha->ccb_info[i].event_flag = 0x0;pm8001_ha->ccb_info[i].n_elem = 0x0;pm8001_ha->ccb_info[i].fw_control_context = NULL;memset(pm8001_ha->ccb_info[i].buf_prd, 0, sizeof(pm8001_ha->ccb_info[i].buf_prd));++pm8001_ha->tags_num;}}pm8001_ha->flags = PM8001F_INIT_TIME;/* Initialize tags */pm8001_tag_init(pm8001_ha);return 0;err_out:return 1;}

pm8001_alloc中首先将参数(调用实际的内存分配时使用)保存在region数组中,然后再调用pm8001_mem_alloc执行实际的内存分配。

注意3:pm8001_mem_alloc-alloc mem for pm8001

代码如下

/**  * pm8001_mem_alloc - allocate memory for pm8001.  * @pdev: pci device.  * @virt_addr: the allocated virtual address  * @pphys_addr_hi: the physical address high byte address.  * @pphys_addr_lo: the physical address low byte address.  * @mem_size: memory size.  */int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,dma_addr_t *pphys_addr, u32 *pphys_addr_hi,u32 *pphys_addr_lo, u32 mem_size, u32 align){caddr_t mem_virt_alloc;dma_addr_t mem_dma_handle;u64 phys_align;u64 align_offset = 0;if (align)align_offset = (dma_addr_t)align - 1;mem_virt_alloc =pci_alloc_consistent(pdev, mem_size + align, &mem_dma_handle);if (!mem_virt_alloc) {pm8001_printk("memory allocation error\n");return -1;}memset((void *)mem_virt_alloc, 0, mem_size+align);*pphys_addr = mem_dma_handle;       /*phy_align == *pphys_addr,*因为*pphys_addr的低12位为0,而align_offset<4k*/phys_align = (*pphys_addr + align_offset) & ~align_offset;*virt_addr = (void *)mem_virt_alloc + phys_align - *pphys_addr;*pphys_addr_hi = upper_32_bits(phys_align);   *pphys_addr_lo = (u32)(phys_align);return 0;}

至此,pm8001_pci_alloc函数分析结束。

后面会接着分析scsi_scan_host函数,待续。。。