Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ce53822 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley
Browse files

advansys: Use dma_pool for sg elements



The sg elements should be allocated from a dma pool.
And rename the structure to 'adv_sg_block' as they
are only used by the wide board.

Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 4b47e464
Loading
Loading
Loading
Loading
+45 −63
Original line number Diff line number Diff line
@@ -1815,15 +1815,15 @@ typedef struct adv_dvc_cfg {
struct adv_dvc_var;
struct adv_scsi_req_q;

typedef struct asc_sg_block {
typedef struct adv_sg_block {
	uchar reserved1;
	uchar reserved2;
	uchar reserved3;
	uchar sg_cnt;		/* Valid entries in block. */
	ADV_PADDR sg_ptr;	/* Pointer to next sg block. */
	__le32 sg_ptr;	/* Pointer to next sg block. */
	struct {
		ADV_PADDR sg_addr;	/* SG element address. */
		ADV_DCNT sg_count;	/* SG element count. */
		__le32 sg_addr;	/* SG element address. */
		__le32 sg_count;	/* SG element count. */
	} sg_list[NO_OF_SG_PER_BLOCK];
} ADV_SG_BLOCK;

@@ -1888,7 +1888,7 @@ typedef struct adv_scsi_req_q {
 */
typedef struct adv_sgblk {
	ADV_SG_BLOCK sg_block;	/* Sgblock structure. */
	uchar align[32];	/* Sgblock structure padding. */
	dma_addr_t sg_addr;	/* Physical address */
	struct adv_sgblk *next_sgblkp;	/* Next scatter-gather structure. */
} adv_sgblk_t;

@@ -2381,7 +2381,7 @@ struct asc_board {
	adv_req_t *adv_reqp;	/* Request structures. */
	dma_addr_t adv_reqp_addr;
	size_t adv_reqp_size;
	adv_sgblk_t *adv_sgblkp;	/* Scatter-gather structures. */
	struct dma_pool *adv_sgblk_pool;	/* Scatter-gather structures. */
	ushort bios_signature;	/* BIOS Signature. */
	ushort bios_version;	/* BIOS Version. */
	ushort bios_codeseg;	/* BIOS Code Segment. */
@@ -2650,7 +2650,7 @@ static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
{
	int i;

	printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
	printk(" ADV_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
	       (ulong)b, sgblockno);
	printk("  sg_cnt %u, sg_ptr 0x%lx\n",
	       b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
@@ -2672,7 +2672,8 @@ static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
{
	int sg_blk_cnt;
	struct asc_sg_block *sg_ptr;
	struct adv_sg_block *sg_ptr;
	adv_sgblk_t *sgblkp;

	printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);

@@ -2699,21 +2700,15 @@ static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)

	/* Display the request's ADV_SG_BLOCK structures. */
	if (q->sg_list_ptr != NULL) {
		sgblkp = container_of(q->sg_list_ptr, adv_sgblk_t, sg_block);
		sg_blk_cnt = 0;
		while (1) {
			/*
			 * 'sg_ptr' is a physical address. Convert it to a virtual
			 * address by indexing 'sg_blk_cnt' into the virtual address
			 * array 'sg_list_ptr'.
			 *
			 * XXX - Assumes all SG physical blocks are virtually contiguous.
			 */
			sg_ptr =
			    &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
		while (sgblkp) {
			sg_ptr = &sgblkp->sg_block;
			asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
			if (sg_ptr->sg_ptr == 0) {
				break;
			}
			sgblkp = sgblkp->next_sgblkp;
			sg_blk_cnt++;
		}
	}
@@ -6207,9 +6202,8 @@ static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
		/* Remove 'sgblkp' from the request list. */
		reqp->sgblkp = sgblkp->next_sgblkp;

		/* Add 'sgblkp' to the board free list. */
		sgblkp->next_sgblkp = boardp->adv_sgblkp;
		boardp->adv_sgblkp = sgblkp;
		dma_pool_free(boardp->adv_sgblk_pool, sgblkp,
			      sgblkp->sg_addr);
	}

	ASC_DBG(1, "done\n");
@@ -7903,15 +7897,16 @@ static int
adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp,
	       ADV_SCSI_REQ_Q *scsiqp, struct scsi_cmnd *scp, int use_sg)
{
	adv_sgblk_t *sgblkp;
	adv_sgblk_t *sgblkp, *prev_sgblkp;
	struct scatterlist *slp;
	int sg_elem_cnt;
	ADV_SG_BLOCK *sg_block, *prev_sg_block;
	ADV_PADDR sg_block_paddr;
	dma_addr_t sgblk_paddr;
	int i;

	slp = scsi_sglist(scp);
	sg_elem_cnt = use_sg;
	prev_sgblkp = NULL;
	prev_sg_block = NULL;
	reqp->sgblkp = NULL;

@@ -7921,7 +7916,9 @@ adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp,
		 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
		 * (15) scatter-gather elements.
		 */
		if ((sgblkp = boardp->adv_sgblkp) == NULL) {
		sgblkp = dma_pool_alloc(boardp->adv_sgblk_pool, GFP_ATOMIC,
					&sgblk_paddr);
		if (!sgblkp) {
			ASC_DBG(1, "no free adv_sgblk_t\n");
			ASC_STATS(scp->device->host, adv_build_nosg);

@@ -7932,24 +7929,16 @@ adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp,
			while ((sgblkp = reqp->sgblkp) != NULL) {
				/* Remove 'sgblkp' from the request list. */
				reqp->sgblkp = sgblkp->next_sgblkp;

				/* Add 'sgblkp' to the board free list. */
				sgblkp->next_sgblkp = boardp->adv_sgblkp;
				boardp->adv_sgblkp = sgblkp;
				sgblkp->next_sgblkp = NULL;
				dma_pool_free(boardp->adv_sgblk_pool, sgblkp,
					      sgblkp->sg_addr);
			}
			return ASC_BUSY;
		}

		/* Complete 'adv_sgblk_t' board allocation. */
		boardp->adv_sgblkp = sgblkp->next_sgblkp;
		sgblkp->sg_addr = sgblk_paddr;
		sgblkp->next_sgblkp = NULL;

		/*
		 * Get 8 byte aligned virtual and physical addresses
		 * for the allocated ADV_SG_BLOCK structure.
		 */
		sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
		sg_block_paddr = virt_to_bus(sg_block);
		sg_block = &sgblkp->sg_block;

		/*
		 * Check if this is the first 'adv_sgblk_t' for the
@@ -7964,17 +7953,16 @@ adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp,
			 * address pointers.
			 */
			scsiqp->sg_list_ptr = sg_block;
			scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr);
			scsiqp->sg_real_addr = cpu_to_le32(sgblk_paddr);
		} else {
			/* Request's second or later scatter-gather block. */
			sgblkp->next_sgblkp = reqp->sgblkp;
			reqp->sgblkp = sgblkp;
			prev_sgblkp->next_sgblkp = sgblkp;

			/*
			 * Point the previous ADV_SG_BLOCK structure to
			 * the newly allocated ADV_SG_BLOCK structure.
			 */
			prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr);
			prev_sg_block->sg_ptr = cpu_to_le32(sgblk_paddr);
		}

		for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
@@ -7985,7 +7973,10 @@ adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp,
			ASC_STATS_ADD(scp->device->host, xfer_sect,
				      DIV_ROUND_UP(sg_dma_len(slp), 512));

			if (--sg_elem_cnt == 0) {	/* Last ADV_SG_BLOCK and scatter-gather entry. */
			if (--sg_elem_cnt == 0) {
				/*
				 * Last ADV_SG_BLOCK and scatter-gather entry.
				 */
				sg_block->sg_cnt = i + 1;
				sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
				return ADV_SUCCESS;
@@ -7994,6 +7985,7 @@ adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp,
		}
		sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
		prev_sg_block = sg_block;
		prev_sgblkp = sgblkp;
	}
}

@@ -11157,8 +11149,7 @@ static int advansys_wide_init_chip(struct Scsi_Host *shost)
{
	struct asc_board *board = shost_priv(shost);
	struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var;
	int sg_cnt = 0;
	adv_sgblk_t *sgp;
	size_t sgblk_pool_size;
	int warn_code, err_code;

	/*
@@ -11195,22 +11186,14 @@ static int advansys_wide_init_chip(struct Scsi_Host *shost)
	 * Allocate up to ADV_TOT_SG_BLOCK request structures for
	 * the Wide board. Each structure is about 136 bytes.
	 */
	board->adv_sgblkp = NULL;
	for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
		sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);

		if (!sgp)
			break;

		sgp->next_sgblkp = board->adv_sgblkp;
		board->adv_sgblkp = sgp;

	}
	sgblk_pool_size = sizeof(adv_sgblk_t) * ADV_TOT_SG_BLOCK;
	board->adv_sgblk_pool = dma_pool_create("adv_sgblk", board->dev,
						sgblk_pool_size, 32, 0);

	ASC_DBG(1, "sg_cnt %d * %lu = %lu bytes\n", sg_cnt, sizeof(adv_sgblk_t),
		 sizeof(adv_sgblk_t) * sg_cnt);
	ASC_DBG(1, "sg_cnt %d * %lu = %lu bytes\n", ADV_TOT_SG_BLOCK,
		sizeof(adv_sgblk_t), sgblk_pool_size);

	if (!board->adv_sgblkp)
	if (!board->adv_sgblk_pool)
		goto kmalloc_failed;

	if (adv_dvc->chip_type == ADV_CHIP_ASC3550) {
@@ -11253,10 +11236,9 @@ static void advansys_wide_free_mem(struct asc_board *board)
				  board->adv_reqp, board->adv_reqp_addr);
		board->adv_reqp = NULL;
	}
	while (board->adv_sgblkp) {
		adv_sgblk_t *sgp = board->adv_sgblkp;
		board->adv_sgblkp = sgp->next_sgblkp;
		kfree(sgp);
	if (board->adv_sgblk_pool) {
		dma_pool_destroy(board->adv_sgblk_pool);
		board->adv_sgblk_pool = NULL;
	}
}