/* alloc percpu var in the corresponding NUMA nodes */ void percpu_init(void) { size_t percpu_size = ROUNDUP(__percpu_end - __percpu_start, CACHELINE); if(!percpu_size || sysconf.lcpu_count<=1) return; int i, j; for(i=0; i<sysconf.lnuma_count;i++){ struct numa_node *node = &numa_nodes[i]; int nr_cpus = node->nr_cpus; for(j=0;j<node->nr_cpus;j++){ if(node->cpu_ids[j] == myid()){ nr_cpus--; break; } } size_t totalsize = percpu_size * nr_cpus; unsigned int pages = ROUNDUP_DIV(totalsize, PGSIZE); if(!pages) continue; kprintf("percpu_init: node%d alloc %d pages for percpu variables\n", i, pages); struct Page *p = alloc_pages_numa(node, pages); assert(p != NULL); void *kva = page2kva(p); /* zero it out */ memset(kva, 0, pages * PGSIZE); for(j=0;j<node->nr_cpus;j++, kva += percpu_size){ if(node->cpu_ids[j] == myid()) continue; percpu_offsets[node->cpu_ids[j]] = kva; } } for(i=0;i<sysconf.lcpu_count;i++){ kprintf("percpu_init: cpu%d get 0x%016llx\n", i, percpu_offsets[i]); } }
/* * sfs_truncfile : reszie the file with new length */ static int sfs_truncfile(struct inode *node, off_t len) { if (len < 0 || len > SFS_MAX_FILE_SIZE) { return -E_INVAL; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); struct sfs_disk_inode *din = sin->din; int ret = 0; //new number of disk blocks of file uint32_t nblks, tblks = ROUNDUP_DIV(len, SFS_BLKSIZE); if (din->size == len) { assert(tblks == din->blocks); return 0; } lock_sin(sin); // old number of disk blocks of file nblks = din->blocks; if (nblks < tblks) { // try to enlarge the file size by add new disk block at the end of file while (nblks != tblks) { if ((ret = sfs_bmap_load_nolock(sfs, sin, nblks, NULL)) != 0) { goto out_unlock; } nblks ++; } } else if (tblks < nblks) { // try to reduce the file size while (tblks != nblks) { if ((ret = sfs_bmap_truncate_nolock(sfs, sin)) != 0) { goto out_unlock; } nblks --; } } assert(din->blocks == tblks); din->size = len; sin->dirty = 1; out_unlock: unlock_sin(sin); return ret; }
static int sfs_truncfile(struct inode *node, off_t len) { if (len < 0 || len > SFS_MAX_FILE_SIZE) { return -E_INVAL; } struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); struct sfs_disk_inode *din = sin->din; assert(din->type != SFS_TYPE_DIR); int ret = 0; uint32_t nblks, tblks = ROUNDUP_DIV(len, SFS_BLKSIZE); if (din->fileinfo.size == len) { assert(tblks == din->blocks); return 0; } if ((ret = trylock_sin(sin)) != 0) { return ret; } nblks = din->blocks; if (nblks < tblks) { while (nblks != tblks) { if ((ret = sfs_bmap_load_nolock(sfs, sin, nblks, NULL)) != 0) { goto out_unlock; } nblks ++; } } else if (tblks < nblks) { while (tblks != nblks) { if ((ret = sfs_bmap_truncate_nolock(sfs, sin)) != 0) { goto out_unlock; } nblks --; } } assert(din->blocks == tblks); din->fileinfo.size = len; sin->dirty = 1; out_unlock: unlock_sin(sin); return ret; }
/** * \brief Function to tune the AST prescalar frequency to the desired frequency * * \param ast Base address of the AST (i.e. &AVR32_AST). * \param input_freq Prescaled AST Clock Frequency * \param tuned_freq Desired AST frequency * * \retval false If invalid frequency is passed * \retval true If configuration succeeds * * \note Parameter Calculation: * Formula: \n * ADD=0 -> ft= fi(1 - (1/((roundup(256/value) * (2^exp)) + 1))) \n * ADD=1 -> ft= fi(1 + (1/((roundup(256/value) * (2^exp)) - 1))) \n * Specifications: \n * exp > 0, value > 1 \n * Let X = (2 ^ exp), Y = roundup(256 / value) \n * Tuned Frequency -> ft \n * Input Frequency -> fi \n * * IF ft < fi \n * ADD = 0 \n * Z = (ft / (fi - ft)) \n * ELSE IF ft > fi \n * ADD = 1 \n * Z = (ft / (ft - fi)) \n * ELSE \n * exit function -> Tuned Frequency = Input Frequency \n * * The equation can be reduced to (X * Y) = Z * * Frequency Limits \n * (1/((roundup(256/value) * (2^exp)) + 1)) should be min to get the lowest * possible output from Digital Tuner.\n * (1/((roundup(256/value) * (2^exp)) - 1)) should be min to get the highest * possible output from Digital Tuner.\n * For that, roundup(256/value) & (2^exp) should be minimum \n * min (EXP) = 1 (Note: EXP > 0) \n * min (roundup(256/value)) = 2 \n * max (Ft) = (4*fi)/3 \n * min (Ft) = (4*fi)/5 \n * * Using the above details, X & Y that will closely satisfy the equation is * found in this function. */ bool ast_configure_digital_tuner(volatile avr32_ast_t *ast, uint32_t input_freq, uint32_t tuned_freq) { bool add; uint8_t value; uint8_t exp; uint32_t x, y, z; uint32_t diff; if (tuned_freq < input_freq) { /* Check for Frequency Limit */ if (tuned_freq < ((4 * input_freq) / 5)) { return false; } /* Set the ADD to 0 when freq less than input freq */ add = false; /* Calculate the frequency difference */ diff = input_freq - tuned_freq; } else if (tuned_freq > input_freq) { /* Check for Frequency Limit */ if (tuned_freq > ((4 * input_freq) / 3)) { return false; } /* Set the ADD to 1 when freq greater than input freq */ add = true; /* Calculate the frequency difference */ diff = tuned_freq - input_freq; } else { /* required & input freq are equal */ return true; } z = (tuned_freq) / (diff); if ((tuned_freq % diff) > (diff / 2)) { z++; } /* * Initialize with minimum possible values. * exp value should be greater than zero, min(exp) = 1 -> min(x)= (2^1) *= 2 * y should be greater than one -> roundup(256/value) where value- 0 to * 255 * min(y) = roundup(256/255) = 2 */ y = 2; x = 2; exp = 1; /* * Keep exp constant and increase y value until it reaches its limit. * Increment exp and follow the same steps until we found the closest * possible match for the required frequency. */ do { if (y < 255) { y++; } else { x = x << 1; y = 2; exp++; } } while (z > (x * y)); /* Decrement y value after exit from loop */ y = y - 1; /* Find VALUE from y */ value = ROUNDUP_DIV(256, y); /* Initialize the Digital Tuner using the required parameters */ ast_init_digital_tuner(ast, add, value, exp); return true; }