📄 pcibr_rrb.c
字号:
pcibr_soft->bs_rrb_avail[pciio_slot & 1] = pcibr_soft->bs_rrb_avail[pciio_slot & 1] + pcibr_soft->bs_rrb_res[pciio_slot] - delta_vchan0 - delta_vchan1; pcibr_soft->bs_rrb_res[pciio_slot] = 0; /* * Reserve enough RRBs so this slot's RRB configuration can be * reset to its boot-time default following a hot-plug shut-down */ res_rrbs = (pcibr_soft->bs_rrb_res_dflt[pciio_slot] - pcibr_soft->bs_rrb_res[pciio_slot]); for (vchan = 0; vchan < vchan_total; vchan++) { res_rrbs += (pcibr_soft->bs_rrb_valid_dflt[pciio_slot][vchan] - pcibr_soft->bs_rrb_valid[pciio_slot][vchan]); } if (res_rrbs > 0) { pcibr_soft->bs_rrb_res[pciio_slot] = res_rrbs; pcibr_soft->bs_rrb_avail[pciio_slot & 1] = pcibr_soft->bs_rrb_avail[pciio_slot & 1] - res_rrbs; } pcibr_rrb_debug("pcibr_rrb_alloc", pcibr_soft); error = 0; } pcibr_unlock(pcibr_soft, s); return error;}/* * Device driver interface to check the current state * of the RRB allocations. * * pconn_vhdl is your PCI connection point (specifies which * PCI bus and which slot). * * count_vchan0 points to where to return the number of RRBs * assigned to the primary DMA channel, used by all DMA * that does not explicitly ask for the alternate virtual * channel. * * count_vchan1 points to where to return the number of RRBs * assigned to the secondary DMA channel, used when * PCIBR_VCHAN1 and PCIIO_DMA_A64 are specified. * * count_reserved points to where to return the number of RRBs * that have been automatically reserved for your device at * startup, but which have not been assigned to a * channel. RRBs must be assigned to a channel to be used; * this can be done either with an explicit pcibr_rrb_alloc * call, or automatically by the infrastructure when a DMA * translation is constructed. Any call to pcibr_rrb_alloc * will release any unassigned reserved RRBs back to the * free pool. * * count_pool points to where to return the number of RRBs * that are currently unassigned and unreserved. This * number can (and will) change as other drivers make calls * to pcibr_rrb_alloc, or automatically allocate RRBs for * DMA beyond their initial reservation. * * NULL may be passed for any of the return value pointers * the caller is not interested in. * * The return value is "0" if all went well, or "-1" if * there is a problem. Additionally, if the wrong vertex * is passed in, one of the subsidiary support functions * could panic with a "bad pciio fingerprint." */intpcibr_rrb_check(devfs_handle_t pconn_vhdl, int *count_vchan0, int *count_vchan1, int *count_reserved, int *count_pool){ pciio_info_t pciio_info; pciio_slot_t pciio_slot; pcibr_soft_t pcibr_soft; unsigned long s; int error = -1; if ((pciio_info = pciio_info_get(pconn_vhdl)) && (pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info)) && ((pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info)) < PCIBR_NUM_SLOTS(pcibr_soft))) { s = pcibr_lock(pcibr_soft); if (count_vchan0) *count_vchan0 = pcibr_soft->bs_rrb_valid[pciio_slot][VCHAN0]; if (count_vchan1) *count_vchan1 = pcibr_soft->bs_rrb_valid[pciio_slot][VCHAN1]; if (count_reserved) *count_reserved = pcibr_soft->bs_rrb_res[pciio_slot]; if (count_pool) *count_pool = pcibr_soft->bs_rrb_avail[pciio_slot & 1]; error = 0; pcibr_unlock(pcibr_soft, s); } return error;}/* * pcibr_slot_initial_rrb_alloc * Allocate a default number of rrbs for this slot on * the two channels. This is dictated by the rrb allocation * strategy routine defined per platform. */intpcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; bridge_t *bridge; int vchan_total; int vchan; int chan[4]; pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) return(EINVAL); if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(EINVAL); bridge = pcibr_soft->bs_base; /* How many RRBs are on this slot? */ vchan_total = NUMBER_VCHANNELS(bridge); for (vchan = 0; vchan < vchan_total; vchan++) chan[vchan] = do_pcibr_rrb_count_valid(bridge, slot, vchan); if (IS_PIC_SOFT(pcibr_soft)) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_vhdl, "pcibr_slot_initial_rrb_alloc: slot %d started with %d+%d+%d+%d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), chan[VCHAN0], chan[VCHAN1], chan[VCHAN2], chan[VCHAN3])); } else { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_vhdl, "pcibr_slot_initial_rrb_alloc: slot %d started with %d+%d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), chan[VCHAN0], chan[VCHAN1])); } /* Do we really need any? */ pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; pcibr_info = pcibr_infoh[0]; if (PCIBR_WAR_ENABLED(PV856866, pcibr_soft) && IS_PIC_SOFT(pcibr_soft) && (slot == 2 || slot == 3) && (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) && !pcibr_soft->bs_slot[slot].has_host) { for (vchan = 0; vchan < 2; vchan++) { do_pcibr_rrb_free(bridge, slot, vchan, 8); pcibr_soft->bs_rrb_valid[slot][vchan] = 0; } pcibr_soft->bs_rrb_valid[slot][3] = chan[3]; return(ENODEV); } for (vchan = 0; vchan < vchan_total; vchan++) pcibr_soft->bs_rrb_valid[slot][vchan] = chan[vchan]; return(0);}voidrrb_reserved_free(pcibr_soft_t pcibr_soft, int slot){ int res = pcibr_soft->bs_rrb_res[slot]; if (res) { pcibr_soft->bs_rrb_avail[slot & 1] += res; pcibr_soft->bs_rrb_res[slot] = 0; }}/* * pcibr_initial_rrb * Assign an equal total number of RRBs to all candidate slots, * where the total is the sum of the number of RRBs assigned to * the normal channel, the number of RRBs assigned to the virtual * channels, and the number of RRBs assigned as reserved. * * A candidate slot is any existing (populated or empty) slot. * Empty SN1 slots need RRBs to support hot-plug operations. */intpcibr_initial_rrb(devfs_handle_t pcibr_vhdl, pciio_slot_t first, pciio_slot_t last){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); bridge_t *bridge = pcibr_soft->bs_base; pciio_slot_t slot; int rrb_total; int vchan_total; int vchan; int have[2][3]; int res[2]; int eo; have[0][0] = have[0][1] = have[0][2] = 0; have[1][0] = have[1][1] = have[1][2] = 0; res[0] = res[1] = 0; vchan_total = NUMBER_VCHANNELS(bridge); for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { /* Initial RRB management; give back RRBs in all non-existent slots */ (void) pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot); /* Base calculations only on existing slots */ if ((slot >= first) && (slot <= last)) { rrb_total = 0; for (vchan = 0; vchan < vchan_total; vchan++) rrb_total += pcibr_soft->bs_rrb_valid[slot][vchan]; if (rrb_total < 3) have[slot & 1][rrb_total]++; } } /* Initialize even/odd slot available RRB counts */ pcibr_soft->bs_rrb_avail[0] = do_pcibr_rrb_count_avail(bridge, 0); pcibr_soft->bs_rrb_avail[1] = do_pcibr_rrb_count_avail(bridge, 1); /* * Calculate reserved RRBs for slots based on current RRB usage */ for (eo = 0; eo < 2; eo++) { if ((3 * have[eo][0] + 2 * have[eo][1] + have[eo][2]) <= pcibr_soft->bs_rrb_avail[eo]) res[eo] = 3; else if ((2 * have[eo][0] + have[eo][1]) <= pcibr_soft->bs_rrb_avail[eo]) res[eo] = 2; else if (have[eo][0] <= pcibr_soft->bs_rrb_avail[eo]) res[eo] = 1; else res[eo] = 0; } /* Assign reserved RRBs to existing slots */ for (slot = first; slot <= last; ++slot) { int r; rrb_total = 0; for (vchan = 0; vchan < vchan_total; vchan++) rrb_total += pcibr_soft->bs_rrb_valid[slot][vchan]; r = res[slot & 1] - (rrb_total); if (r > 0) { pcibr_soft->bs_rrb_res[slot] = r; pcibr_soft->bs_rrb_avail[slot & 1] -= r; } } pcibr_rrb_debug("pcibr_initial_rrb", pcibr_soft); return 0;}/* * Dump the pcibr_soft_t RRB state variable */voidpcibr_rrb_debug(char *calling_func, pcibr_soft_t pcibr_soft){ pciio_slot_t slot; char tmp_str[256]; if (pcibr_debug_mask & PCIBR_DEBUG_RRB) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, "%s: rrbs available, even=%d, odd=%d\n", calling_func, pcibr_soft->bs_rrb_avail[0], pcibr_soft->bs_rrb_avail[1])); if (IS_PIC_SOFT(pcibr_soft)) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, "\tslot\tvchan0\tvchan1\tvchan2\tvchan3\treserved\n")); } else { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, "\tslot\tvchan0\tvchan1\treserved\n")); } for (slot=0; slot < PCIBR_NUM_SLOTS(pcibr_soft); slot++) { /* * The kernel only allows functions to have so many variable args, * attempting to call PCIBR_DEBUG_ALWAYS() with more than 5 printf * arguments fails so sprintf() it into a temporary string. */ if (IS_PIC_SOFT(pcibr_soft)) { sprintf(tmp_str, "\t %d\t %d\t %d\t %d\t %d\t %d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN0], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN1], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN2], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN3], pcibr_soft->bs_rrb_res[slot]); } else { sprintf(tmp_str, "\t %d\t %d\t %d\t %d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN0], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN1], pcibr_soft->bs_rrb_res[slot]); } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, "%s", tmp_str)); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -