aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/utils/comgt
Commit message (Expand)AuthorAgeFilesLines
* comgt: add new script to send ussd request and get the answerKirill Lukonin2020-07-081-0/+21
* comgt-ncm: do not attempt to connect if the control device is invalidRozhuk Ivan2020-06-171-16/+46
* comgt: replace backticks by $(...)Adrian Schmutzler2020-05-131-2/+2
* comgt: fix hotplug event handlingRozhuk Ivan2020-03-162-5/+5
* comgt-ncm: add driver dependencies againVincent Wiemann2019-08-081-1/+1
* comgt: add delay option for 3g protoFlorian Eckert2019-07-031-0/+4
* uqmi: inherit firewall zone membership to virtual sub interfacesJo-Philipp Wich2019-03-051-0/+10
* comgt: Fix 3g.sh permissionsRosen Penev2018-12-061-2/+2
* comgt: Install hotplug and netifd files as 600Rosen Penev2018-10-111-3/+3
* comgt: increase timeout on runcommandsGiuseppe Lippolis2018-08-291-1/+1
* treewide: fix shellscript syntax errors/typosLorenzo Santina2017-09-133-4/+3
* DWR-512: adding wwan support for the dwr-512 3G modemGiuseppe Lippolis2017-05-252-2/+36
* comgt-3g: enable modem before to setpinGiuseppe Lippolis2017-05-182-1/+2
* comgt: mark as nonshared because of the usb dependenciesFelix Fietkau2017-01-131-0/+2
* Revert the recent dependency and metadata scanning reworkFelix Fietkau2017-01-111-1/+1
* comgt: allow build without USB_SUPPORTFelix Fietkau2017-01-111-1/+1
* comgt-ncm: fix typo Fix typo in ncm.sh. Resolves:Cezary Jackiewicz2016-12-221-1/+1
* comgt: add support of using device symlinks.Nickolay Ledovskikh2016-12-203-0/+5
* treewide: clean up download hashesFelix Fietkau2016-12-161-1/+1
* comgt-ncm: Add support for specifying profile indexMatti Laakso2016-12-144-56/+51
* comgt: move to WWAN submenu, fixed linkAlberto Bursi2016-11-081-3/+4
* gcom: Fix 'mode' option for ncmCezary Jackiewicz2016-11-081-1/+1
* comgt: add metric, defaultroute and peerdns options for directip protocolMarcin Jurkowski2016-10-261-2/+5
* comgt: add metric, defaultroute and peerdns options for ncm protocolMarcin Jurkowski2016-10-261-2/+5
* treewide: replace nbd@openwrt.org with nbd@nbd.nameFelix Fietkau2016-06-071-1/+1
* ppp: use more reliable way to set script environmentSteven Barth2015-09-152-4/+2
* comgt-ncm: Add possibility to choose PDP context typeSteven Barth2015-09-113-14/+50
* comgt/umbim/uqmi: enable RFC 7278 for 3g/4g by defaultSteven Barth2015-09-033-0/+5
* comgt: make ncm proto work via wwan protoJohn Crispin2015-07-081-0/+2
* comgt: the package contained too many filesJohn Crispin2015-05-231-1/+0
* network: also shorten virtual interface names of ppp and 3g/4g connectionsSteven Barth2015-04-172-4/+4
* packages: use $(LN) macro, make symlinks relativeNicolas Thill2015-04-031-1/+1
* ncm, qmi, mbim: Add dependency on wwan packageJohn Crispin2015-03-091-1/+1
* ncm: Remove unnecessary proto_set_available commandsJohn Crispin2015-03-091-5/+0
* comgt, wwan: Move USB data files to wwan packageJohn Crispin2015-03-09348-1739/+0
* comgt: Use TCGETS and TCSETS ioctls for struct termiosJohn Crispin2015-02-223-14/+90
* comgt-ncm: Fix NCM protocolJohn Crispin2015-01-284-36/+61
* comgt: Allow using non-TTY devicesJohn Crispin2015-01-201-0/+68
* license info - revert r43155John Crispin2014-11-031-3/+0
* Add more license tags with SPDX identifiersJohn Crispin2014-11-031-0/+3
* Add a few SPDX tagsSteven Barth2014-11-021-0/+1
* comgt: fix typo in the ncm proto handlerJohn Crispin2014-10-261-1/+1
* comgt: drop the use of the non-standard XCASE termios flag (#18186)Felix Fietkau2014-10-211-0/+20
* fix compile against muslImre Kaloz2014-10-202-2/+31
* comgt: add ncm proto supportJohn Crispin2014-10-105-1/+247
* wwan: add a generic 3g/4g protoJohn Crispin2014-10-08350-9/+1762
* comgt: split directip support into its own packageJohn Crispin2014-10-081-3/+19
* comgt: fix directip auth typeFelix Fietkau2014-09-261-2/+2
* comgt: fireup a dhcpv6-client for directip as wellSteven Barth2014-09-261-0/+6
* comgt: in directip, derive the wwan ifname automatically instead of specifyin...Felix Fietkau2014-09-261-3/+6
n> **************************************************************************** * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include <os.h> #include <hypervisor.h> #include <mm.h> #include <types.h> #include <lib.h> #include <xmalloc.h> #ifdef MM_DEBUG #define DEBUG(_f, _a...) \ printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a) #else #define DEBUG(_f, _a...) ((void)0) #endif /********************* * ALLOCATION BITMAP * One bit per page of memory. Bit set => page is allocated. */ static unsigned long *alloc_bitmap; #define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8) #define allocated_in_map(_pn) \ (alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & (1<<((_pn)&(PAGES_PER_MAPWORD-1)))) /* * Hint regarding bitwise arithmetic in map_{alloc,free}: * -(1<<n) sets all bits >= n. * (1<<n)-1 sets all bits < n. * Variable names in map_{alloc,free}: * *_idx == Index into `alloc_bitmap' array. * *_off == Bit offset within an element of the `alloc_bitmap' array. */ static void map_alloc(unsigned long first_page, unsigned long nr_pages) { unsigned long start_off, end_off, curr_idx, end_idx; curr_idx = first_page / PAGES_PER_MAPWORD; start_off = first_page & (PAGES_PER_MAPWORD-1); end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD; end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1); if ( curr_idx == end_idx ) { alloc_bitmap[curr_idx] |= ((1<<end_off)-1) & -(1<<start_off); } else { alloc_bitmap[curr_idx] |= -(1<<start_off); while ( ++curr_idx < end_idx ) alloc_bitmap[curr_idx] = ~0L; alloc_bitmap[curr_idx] |= (1<<end_off)-1; } } static void map_free(unsigned long first_page, unsigned long nr_pages) { unsigned long start_off, end_off, curr_idx, end_idx; curr_idx = first_page / PAGES_PER_MAPWORD; start_off = first_page & (PAGES_PER_MAPWORD-1); end_idx = (first_page + nr_pages) / PAGES_PER_MAPWORD; end_off = (first_page + nr_pages) & (PAGES_PER_MAPWORD-1); if ( curr_idx == end_idx ) { alloc_bitmap[curr_idx] &= -(1<<end_off) | ((1<<start_off)-1); } else { alloc_bitmap[curr_idx] &= (1<<start_off)-1; while ( ++curr_idx != end_idx ) alloc_bitmap[curr_idx] = 0; alloc_bitmap[curr_idx] &= -(1<<end_off); } } /************************* * BINARY BUDDY ALLOCATOR */ typedef struct chunk_head_st chunk_head_t; typedef struct chunk_tail_st chunk_tail_t; struct chunk_head_st { chunk_head_t *next; chunk_head_t **pprev; int level; }; struct chunk_tail_st { int level; }; /* Linked lists of free chunks of different powers-of-two in size. */ #define FREELIST_SIZE ((sizeof(void*)<<3)-PAGE_SHIFT) static chunk_head_t *free_head[FREELIST_SIZE]; static chunk_head_t free_tail[FREELIST_SIZE]; #define FREELIST_EMPTY(_l) ((_l)->next == NULL) #define round_pgdown(_p) ((_p)&PAGE_MASK) #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) #ifdef MM_DEBUG /* * Prints allocation[0/1] for @nr_pages, starting at @start * address (virtual). */ USED static void print_allocation(void *start, int nr_pages) { unsigned long pfn_start = virt_to_pfn(start); int count; for(count = 0; count < nr_pages; count++) if(allocated_in_map(pfn_start + count)) printk("1"); else printk("0"); printk("\n"); } /* * Prints chunks (making them with letters) for @nr_pages starting * at @start (virtual). */ USED static void print_chunks(void *start, int nr_pages) { char chunks[1001], current='A'; int order, count; chunk_head_t *head; unsigned long pfn_start = virt_to_pfn(start); memset(chunks, (int)'_', 1000); if(nr_pages > 1000) { DEBUG("Can only pring 1000 pages. Increase buffer size."); } for(order=0; order < FREELIST_SIZE; order++) { head = free_head[order]; while(!FREELIST_EMPTY(head)) { for(count = 0; count < 1<< head->level; count++) { if(count + virt_to_pfn(head) - pfn_start < 1000) chunks[count + virt_to_pfn(head) - pfn_start] = current; } head = head->next; current++; } } chunks[nr_pages] = '\0'; printk("%s\n", chunks); } #endif /* * Initialise allocator, placing addresses [@min,@max] in free pool. * @min and @max are PHYSICAL addresses. */ static void init_page_allocator(unsigned long min, unsigned long max) { int i; unsigned long range, bitmap_size; chunk_head_t *ch; chunk_tail_t *ct; for ( i = 0; i < FREELIST_SIZE; i++ ) { free_head[i] = &free_tail[i]; free_tail[i].pprev = &free_head[i]; free_tail[i].next = NULL; } min = round_pgup (min); max = round_pgdown(max); /* Allocate space for the allocation bitmap. */ bitmap_size = (max+1) >> (PAGE_SHIFT+3); bitmap_size = round_pgup(bitmap_size); alloc_bitmap = (unsigned long *)to_virt(min); min += bitmap_size; range = max - min; /* All allocated by default. */ memset(alloc_bitmap, ~0, bitmap_size); /* Free up the memory we've been given to play with. */ map_free(PHYS_PFN(min), range>>PAGE_SHIFT); /* The buddy lists are addressed in high memory. */ min = (unsigned long) to_virt(min); max = (unsigned long) to_virt(max); while ( range != 0 ) { /* * Next chunk is limited by alignment of min, but also * must not be bigger than remaining range. */ for ( i = PAGE_SHIFT; (1<<(i+1)) <= range; i++ ) if ( min & (1<<i) ) break; ch = (chunk_head_t *)min; min += (1<<i); range -= (1<<i); ct = (chunk_tail_t *)min-1; i -= PAGE_SHIFT; ch->level = i; ch->next = free_head[i]; ch->pprev = &free_head[i]; ch->next->pprev = &ch->next; free_head[i] = ch; ct->level = i; } } /* Allocate 2^@order contiguous pages. Returns a VIRTUAL address. */ unsigned long alloc_pages(int order) { int i; chunk_head_t *alloc_ch, *spare_ch; chunk_tail_t *spare_ct; /* Find smallest order which can satisfy the request. */ for ( i = order; i < FREELIST_SIZE; i++ ) { if ( !FREELIST_EMPTY(free_head[i]) ) break; } if ( i == FREELIST_SIZE ) goto no_memory; /* Unlink a chunk. */ alloc_ch = free_head[i]; free_head[i] = alloc_ch->next; alloc_ch->next->pprev = alloc_ch->pprev; /* We may have to break the chunk a number of times. */ while ( i != order ) { /* Split into two equal parts. */ i--; spare_ch = (chunk_head_t *)((char *)alloc_ch + (1<<(i+PAGE_SHIFT))); spare_ct = (chunk_tail_t *)((char *)spare_ch + (1<<(i+PAGE_SHIFT)))-1; /* Create new header for spare chunk. */ spare_ch->level = i; spare_ch->next = free_head[i]; spare_ch->pprev = &free_head[i]; spare_ct->level = i; /* Link in the spare chunk. */ spare_ch->next->pprev = &spare_ch->next; free_head[i] = spare_ch; } map_alloc(PHYS_PFN(to_phys(alloc_ch)), 1<<order); return((unsigned long)alloc_ch); no_memory: printk("Cannot handle page request order %d!\n", order); return 0; } void free_pages(void *pointer, int order) { chunk_head_t *freed_ch, *to_merge_ch; chunk_tail_t *freed_ct; unsigned long mask; /* First free the chunk */ map_free(virt_to_pfn(pointer), 1 << order); /* Create free chunk */ freed_ch = (chunk_head_t *)pointer; freed_ct = (chunk_tail_t *)((char *)pointer + (1<<(order + PAGE_SHIFT)))-1; /* Now, possibly we can conseal chunks together */ while(order < FREELIST_SIZE) { mask = 1 << (order + PAGE_SHIFT); if((unsigned long)freed_ch & mask) { to_merge_ch = (chunk_head_t *)((char *)freed_ch - mask); if(allocated_in_map(virt_to_pfn(to_merge_ch)) || to_merge_ch->level != order) break; /* Merge with predecessor */ freed_ch = to_merge_ch; } else { to_merge_ch = (chunk_head_t *)((char *)freed_ch + mask); if(allocated_in_map(virt_to_pfn(to_merge_ch)) || to_merge_ch->level != order) break; /* Merge with successor */ freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask) - 1; } /* We are commited to merging, unlink the chunk */ *(to_merge_ch->pprev) = to_merge_ch->next; to_merge_ch->next->pprev = to_merge_ch->pprev; order++; } /* Link the new chunk */ freed_ch->level = order; freed_ch->next = free_head[order]; freed_ch->pprev = &free_head[order]; freed_ct->level = order; freed_ch->next->pprev = &freed_ch->next; free_head[order] = freed_ch; } #ifdef HAVE_LIBC void *sbrk(ptrdiff_t increment) { unsigned long old_brk = brk; unsigned long new_brk = old_brk + increment; if (new_brk > heap_end) { printk("Heap exhausted: %p + %lx = %p > %p\n", old_brk, increment, new_brk, heap_end); return NULL; } if (new_brk > heap_mapped) { unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE; do_map_zero(heap_mapped, n); heap_mapped += n * PAGE_SIZE; } brk = new_brk; return (void *) old_brk; } #endif void init_mm(void) { unsigned long start_pfn, max_pfn; printk("MM: Init\n"); arch_init_mm(&start_pfn, &max_pfn); /* * now we can initialise the page allocator */ printk("MM: Initialise page allocator for %lx(%lx)-%lx(%lx)\n", (u_long)to_virt(PFN_PHYS(start_pfn)), PFN_PHYS(start_pfn), (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn)); init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn)); printk("MM: done\n"); arch_init_p2m(max_pfn); arch_init_demand_mapping_area(max_pfn); } void sanity_check(void) { int x; chunk_head_t *head; for (x = 0; x < FREELIST_SIZE; x++) { for (head = free_head[x]; !FREELIST_EMPTY(head); head = head->next) { ASSERT(!allocated_in_map(virt_to_pfn(head))); if (head->next) ASSERT(head->next->pprev == &head->next); } if (free_head[x]) { ASSERT(free_head[x]->pprev == &free_head[x]); } } }