/* * page_retire_hunt() callback for mdboot(). * * It is necessary to scrub any failing pages prior to reboot in order to * prevent a latent error trap from occurring on the next boot. */ void page_retire_mdboot_cb(page_t *pp) { /* * Don't scrub the kernel, since we might still need it, unless * we have UEs on the page, in which case we have nothing to lose. */ if (!PP_ISKVP(pp) || PP_TOXIC(pp)) { pp->p_selock = -1; /* pacify ASSERTs */ PP_CLRFREE(pp); pagescrub(pp, 0, PAGESIZE); pp->p_selock = 0; } pp->p_toxic = 0; }
int vmxnet3s_txcache_init(vmxnet3s_softc_t *dp, vmxnet3s_txq_t *txq) { int i; int ndescrs; int node; page_t *page; struct seg kseg; vmxnet3s_txcache_t *cache = &dp->txcache; dev_info_t *dip = dp->dip; cache->num_pages = ((txq->cmdring.size * VMXNET3_HDR_COPY_SIZE) + (PAGESIZE - 1)) / PAGESIZE; /* Allocate pages */ if (!page_resv(cache->num_pages, KM_SLEEP)) { dev_err(dip, CE_WARN, "failed to reserve %d pages", cache->num_pages); goto out; } if (!page_create_wait(cache->num_pages, 0)) { dev_err(dip, CE_WARN, "failed to create %d pages", cache->num_pages); goto unresv_pages; } cache->pages = kmem_zalloc(cache->num_pages * sizeof (page_t *), KM_SLEEP); cache->page_maps = kmem_zalloc(cache->num_pages * sizeof (page_t *), KM_SLEEP); kseg.s_as = &kas; for (i = 0; i < cache->num_pages; i++) { page = page_get_freelist(&kvp, 0, &kseg, (caddr_t)(i*PAGESIZE), PAGESIZE, 0, NULL); if (page == NULL) { page = page_get_cachelist(&kvp, 0, &kseg, (caddr_t)(i * PAGESIZE), 0, NULL); if (page == NULL) goto free_pages; if (!PP_ISAGED(page)) page_hashout(page, NULL); } PP_CLRFREE(page); PP_CLRAGED(page); cache->pages[i] = page; } for (i = 0; i < cache->num_pages; i++) page_downgrade(cache->pages[i]); /* Allocate virtual address range for mapping pages */ cache->window = vmem_alloc(heap_arena, ptob(cache->num_pages), VM_SLEEP); ASSERT(cache->window); cache->num_nodes = txq->cmdring.size; /* Map pages */ for (i = 0; i < cache->num_pages; i++) { cache->page_maps[i] = cache->window + ptob(i); hat_devload(kas.a_hat, cache->page_maps[i], ptob(1), cache->pages[i]->p_pagenum, PROT_READ | PROT_WRITE | HAT_STRICTORDER, HAT_LOAD_LOCK); } /* Now setup cache items */ cache->nodes = kmem_zalloc(txq->cmdring.size * sizeof (vmxnet3s_txcache_node_t), KM_SLEEP); ndescrs = txq->cmdring.size; node = 0; for (i = 0; i < cache->num_pages; i++) { caddr_t va; int j; int lim; uint64_t pa; lim = (ndescrs <= VMXNET3_TX_CACHE_ITEMS_PER_PAGE) ? ndescrs : VMXNET3_TX_CACHE_ITEMS_PER_PAGE; va = cache->page_maps[i]; pa = cache->pages[i]->p_pagenum << PAGESHIFT; for (j = 0; j < lim; j++) { cache->nodes[node].pa = pa; cache->nodes[node].va = va; pa += VMXNET3_HDR_COPY_SIZE; va += VMXNET3_HDR_COPY_SIZE; node++; } ndescrs -= lim; } return (DDI_SUCCESS); free_pages: page_create_putback(cache->num_pages - i); while (--i >= 0) { if (!page_tryupgrade(cache->pages[i])) { page_unlock(cache->pages[i]); while (!page_lock(cache->pages[i], SE_EXCL, NULL, P_RECLAIM)) ; } page_free(cache->pages[i], 0); } kmem_free(cache->pages, cache->num_pages * PAGESIZE); unresv_pages: page_unresv(cache->num_pages); out: cache->num_pages = cache->num_nodes = 0; return (DDI_FAILURE); }