Exemple #1
0
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 */
}
Exemple #2
0
/*
 * 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;
		}
	}
Exemple #3
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;
}