void *scsi_malloc(unsigned int len) { unsigned int nbits, mask; unsigned long flags; int i, j; if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE) return NULL; nbits = len >> 9; mask = (1 << nbits) - 1; spin_lock_irqsave(&allocator_request_lock, flags); for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++) for (j = 0; j <= SECTORS_PER_PAGE - nbits; j++) { if ((dma_malloc_freelist[i] & (mask << j)) == 0) { dma_malloc_freelist[i] |= (mask << j); scsi_dma_free_sectors -= nbits; #ifdef DEBUG SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9))); printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9)); #endif spin_unlock_irqrestore(&allocator_request_lock, flags); return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); } } spin_unlock_irqrestore(&allocator_request_lock, flags); return NULL; /* Nope. No more */ }
/* * Function: scsi_free * * Purpose: Free memory into the DMA-safe pool. * * Arguments: ptr - data block we are freeing. * len - size of block we are freeing. * * Lock status: No locks assumed to be held. This function is SMP-safe. * * Returns: Nothing * * Notes: This function *must* only be used to free memory * allocated from scsi_malloc(). * * Prior to the new queue code, this function was not SMP-safe. * This function can only allocate in units of sectors * (i.e. 512 bytes). */ int scsi_free(void *obj, unsigned int len) { unsigned int page, sector, nbits, mask; unsigned long flags; #ifdef DEBUG unsigned long ret = 0; #ifdef __mips__ __asm__ __volatile__("move\t%0,$31":"=r"(ret)); #else ret = __builtin_return_address(0); #endif printk("scsi_free %p %d\n", obj, len); SCSI_LOG_MLQUEUE(3, printk("SFree: %p %d\n", obj, len)); #endif #ifdef CONFIG_BOARD_W90N745 obj = (void *)((unsigned long)obj&0x7fffffff); #endif spin_lock_irqsave(&allocator_request_lock, flags); for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) { unsigned long page_addr = (unsigned long) dma_malloc_pages[page]; if ((unsigned long) obj >= page_addr && (unsigned long) obj < page_addr + PAGE_SIZE) { sector = (((unsigned long) obj) - page_addr) >> 9; nbits = len >> 9; mask = (1 << nbits) - 1; if (sector + nbits > SECTORS_PER_PAGE) panic("scsi_free:Bad memory alignment"); if ((dma_malloc_freelist[page] & (mask << sector)) != (mask << sector)) { #ifdef DEBUG printk("scsi_free(obj=%p, len=%d) called from %08lx\n", obj, len, ret); #endif panic("scsi_free:Trying to free unused memory"); } scsi_dma_free_sectors += nbits; dma_malloc_freelist[page] &= ~(mask << sector); spin_unlock_irqrestore(&allocator_request_lock, flags); return 0; } }
/* * Function: scsi_mlqueue_insert() * * Purpose: Insert a command in the midlevel queue. * * Arguments: cmd - command that we are adding to queue. * reason - why we are inserting command to queue. * * Lock status: Assumed that lock is not held upon entry. * * Returns: Nothing. * * Notes: We do this for one of two cases. Either the host is busy * and it cannot accept any more commands for the time being, * or the device returned QUEUE_FULL and can accept no more * commands. * Notes: This could be called either from an interrupt context or a * normal process context. */ int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason) { struct Scsi_Host *host; unsigned long flags; SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd)); /* * We are inserting the command into the ml queue. First, we * cancel the timer, so it doesn't time out. */ scsi_delete_timer(cmd); host = cmd->host; /* * Next, set the appropriate busy bit for the device/host. */ if (reason == SCSI_MLQUEUE_HOST_BUSY) { /* * Protect against race conditions. If the host isn't busy, * assume that something actually completed, and that we should * be able to queue a command now. Note that there is an implicit * assumption that every host can always queue at least one command. * If a host is inactive and cannot queue any commands, I don't see * how things could possibly work anyways. */ if (host->host_busy == 0) { if (scsi_retry_command(cmd) == 0) { return 0; } } host->host_blocked = TRUE; } else { /* * Protect against race conditions. If the device isn't busy, * assume that something actually completed, and that we should * be able to queue a command now. Note that there is an implicit * assumption that every host can always queue at least one command. * If a host is inactive and cannot queue any commands, I don't see * how things could possibly work anyways. */ if (cmd->device->device_busy == 0) { if (scsi_retry_command(cmd) == 0) { return 0; } } cmd->device->device_blocked = TRUE; } /* * Register the fact that we own the thing for now. */ cmd->state = SCSI_STATE_MLQUEUE; cmd->owner = SCSI_OWNER_MIDLEVEL; cmd->bh_next = NULL; /* * Decrement the counters, since these commands are no longer * active on the host/device. */ spin_lock_irqsave(&io_request_lock, flags); cmd->host->host_busy--; cmd->device->device_busy--; spin_unlock_irqrestore(&io_request_lock, flags); /* * Insert this command at the head of the queue for it's device. * It will go before all other commands that are already in the queue. */ scsi_insert_special_cmd(cmd, 1); return 0; }