[PATCH] libertas: remove internal buffers from GSPI driver

George Shore George.Shore at imgtec.com
Thu Oct 29 10:27:58 EDT 2009


> -----Original Message-----
> From: linux-wireless-owner at vger.kernel.org [mailto:linux-wireless-
> owner at vger.kernel.org] On Behalf Of Andrey Yurovsky
> Sent: 27 October 2009 23:52
> To: linux-wireless at vger.kernel.org
> Cc: libertas-dev at lists.infradead.org; sebatian at breakpoint.cc;
> dcbw at redhat.com; Andrey Yurovsky
> Subject: [PATCH] libertas: remove internal buffers from GSPI driver
> 
> This patch removes the internal command and data buffers that the GSPI
> driver
> maintained and instead relies on the Libertas core to synchronize
access
> to the command and data ports as with the other interface drivers.
This
> cleanup reduces the GSPI driver's memory footprint and should improve
> performance by removing the need to copy to these internal buffers.
> This also simplifies the bottom half of the interrupt handler.
> 
> This is an incremental cleanup: after removing the redundant buffers,
we
> can further improve the driver to use a threaded IRQ handler instead
of
> maintaining its own thread.  However I would like a few folks to test
> the buffer removal first and make sure that I'm not introducing
> regressions.
> 
> Tested on Blackfin BF527 with DMA disabled due to an issue with the
SPI
> host controller driver in the current bleeding-edge Blackfin kernel.
I
> would appreciate it if someone with working DMA could test this patch
> and provide feedback.
> 
I've tested this on our in-house dev board with our in-house CPU, on the
8686 in GSPI mode. Everything works as expected :)

Tested-by: George Shore <george.shore at imgtec.com>

> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
> ---
>  drivers/net/wireless/libertas/if_spi.c |  136
++-------------------------
> -----
>  1 files changed, 6 insertions(+), 130 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/if_spi.c
> b/drivers/net/wireless/libertas/if_spi.c
> index 06df2e1..9e0096d 100644
> --- a/drivers/net/wireless/libertas/if_spi.c
> +++ b/drivers/net/wireless/libertas/if_spi.c
> @@ -32,12 +32,6 @@
>  #include "dev.h"
>  #include "if_spi.h"
> 
> -struct if_spi_packet {
> -	struct list_head		list;
> -	u16				blen;
> -	u8				buffer[0]
__attribute__((aligned(4)));
> -};
> -
>  struct if_spi_card {
>  	struct spi_device		*spi;
>  	struct lbs_private		*priv;
> @@ -66,33 +60,10 @@ struct if_spi_card {
>  	struct semaphore		spi_thread_terminated;
> 
>  	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
> -
> -	/* A buffer of incoming packets from libertas core.
> -	 * Since we can't sleep in hw_host_to_card, we have to buffer
> -	 * them. */
> -	struct list_head		cmd_packet_list;
> -	struct list_head		data_packet_list;
> -
> -	/* Protects cmd_packet_list and data_packet_list */
> -	spinlock_t			buffer_lock;
>  };
> 
>  static void free_if_spi_card(struct if_spi_card *card)
>  {
> -	struct list_head *cursor, *next;
> -	struct if_spi_packet *packet;
> -
> -	BUG_ON(card->run_thread);
> -	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
> -		packet = container_of(cursor, struct if_spi_packet,
list);
> -		list_del(&packet->list);
> -		kfree(packet);
> -	}
> -	list_for_each_safe(cursor, next, &card->data_packet_list) {
> -		packet = container_of(cursor, struct if_spi_packet,
list);
> -		list_del(&packet->list);
> -		kfree(packet);
> -	}
>  	spi_set_drvdata(card->spi, NULL);
>  	kfree(card);
>  }
> @@ -774,40 +745,6 @@ out:
>  	return err;
>  }
> 
> -/* Move data or a command from the host to the card. */
> -static void if_spi_h2c(struct if_spi_card *card,
> -			struct if_spi_packet *packet, int type)
> -{
> -	int err = 0;
> -	u16 int_type, port_reg;
> -
> -	switch (type) {
> -	case MVMS_DAT:
> -		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
> -		port_reg = IF_SPI_DATA_RDWRPORT_REG;
> -		break;
> -	case MVMS_CMD:
> -		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
> -		port_reg = IF_SPI_CMD_RDWRPORT_REG;
> -		break;
> -	default:
> -		lbs_pr_err("can't transfer buffer of type %d\n", type);
> -		err = -EINVAL;
> -		goto out;
> -	}
> -
> -	/* Write the data to the card */
> -	err = spu_write(card, port_reg, packet->buffer, packet->blen);
> -	if (err)
> -		goto out;
> -
> -out:
> -	kfree(packet);
> -
> -	if (err)
> -		lbs_pr_err("%s: error %d\n", __func__, err);
> -}
> -
>  /* Inform the host about a card event */
>  static void if_spi_e2h(struct if_spi_card *card)
>  {
> @@ -837,8 +774,6 @@ static int lbs_spi_thread(void *data)
>  	int err;
>  	struct if_spi_card *card = data;
>  	u16 hiStatus;
> -	unsigned long flags;
> -	struct if_spi_packet *packet;
> 
>  	while (1) {
>  		/* Wait to be woken up by one of two things.  First, our
ISR
> @@ -877,43 +812,9 @@ static int lbs_spi_thread(void *data)
>  		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
>  		   (card->priv->psstate != PS_STATE_FULL_POWER &&
>  		    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
> -			/* This means two things. First of all,
> -			 * if there was a previous command sent, the
card has
> -			 * successfully received it.
> -			 * Secondly, it is now ready to download another
> -			 * command.
> -			 */
>  			lbs_host_to_card_done(card->priv);
> -
> -			/* Do we have any command packets from the host
to
> -			 * send? */
> -			packet = NULL;
> -			spin_lock_irqsave(&card->buffer_lock, flags);
> -			if (!list_empty(&card->cmd_packet_list)) {
> -				packet = (struct if_spi_packet *)(card->
> -						cmd_packet_list.next);
> -				list_del(&packet->list);
> -			}
> -			spin_unlock_irqrestore(&card->buffer_lock,
flags);
> -
> -			if (packet)
> -				if_spi_h2c(card, packet, MVMS_CMD);
>  		}
> -		if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
> -			/* Do we have any data packets from the host to
> -			 * send? */
> -			packet = NULL;
> -			spin_lock_irqsave(&card->buffer_lock, flags);
> -			if (!list_empty(&card->data_packet_list)) {
> -				packet = (struct if_spi_packet *)(card->
> -						data_packet_list.next);
> -				list_del(&packet->list);
> -			}
> -			spin_unlock_irqrestore(&card->buffer_lock,
flags);
> 
> -			if (packet)
> -				if_spi_h2c(card, packet, MVMS_DAT);
> -		}
>  		if (hiStatus & IF_SPI_HIST_CARD_EVENT)
>  			if_spi_e2h(card);
> 
> @@ -942,40 +843,18 @@ static int if_spi_host_to_card(struct
lbs_private
> *priv,
>  				u8 type, u8 *buf, u16 nb)
>  {
>  	int err = 0;
> -	unsigned long flags;
>  	struct if_spi_card *card = priv->card;
> -	struct if_spi_packet *packet;
> -	u16 blen;
> 
>  	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
> 
> -	if (nb == 0) {
> -		lbs_pr_err("%s: invalid size requested: %d\n", __func__,
nb);
> -		err = -EINVAL;
> -		goto out;
> -	}
> -	blen = ALIGN(nb, 4);
> -	packet = kzalloc(sizeof(struct if_spi_packet) + blen,
GFP_ATOMIC);
> -	if (!packet) {
> -		err = -ENOMEM;
> -		goto out;
> -	}
> -	packet->blen = blen;
> -	memcpy(packet->buffer, buf, nb);
> -	memset(packet->buffer + nb, 0, blen - nb);
> +	nb = ALIGN(nb, 4);
> 
>  	switch (type) {
>  	case MVMS_CMD:
> -		priv->dnld_sent = DNLD_CMD_SENT;
> -		spin_lock_irqsave(&card->buffer_lock, flags);
> -		list_add_tail(&packet->list, &card->cmd_packet_list);
> -		spin_unlock_irqrestore(&card->buffer_lock, flags);
> +		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb);
>  		break;
>  	case MVMS_DAT:
> -		priv->dnld_sent = DNLD_DATA_SENT;
> -		spin_lock_irqsave(&card->buffer_lock, flags);
> -		list_add_tail(&packet->list, &card->data_packet_list);
> -		spin_unlock_irqrestore(&card->buffer_lock, flags);
> +		err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf,
nb);
>  		break;
>  	default:
>  		lbs_pr_err("can't transfer buffer of type %d", type);
> @@ -983,9 +862,6 @@ static int if_spi_host_to_card(struct lbs_private
> *priv,
>  		break;
>  	}
> 
> -	/* Wake up the spi thread */
> -	up(&card->spi_ready);
> -out:
>  	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
>  	return err;
>  }
> @@ -1062,9 +938,6 @@ static int __devinit if_spi_probe(struct
spi_device
> *spi)
> 
>  	sema_init(&card->spi_ready, 0);
>  	sema_init(&card->spi_thread_terminated, 0);
> -	INIT_LIST_HEAD(&card->cmd_packet_list);
> -	INIT_LIST_HEAD(&card->data_packet_list);
> -	spin_lock_init(&card->buffer_lock);
> 
>  	/* Initialize the SPI Interface Unit */
>  	err = spu_init(card, pdata->use_dummy_writes);
> @@ -1141,6 +1014,9 @@ static int __devinit if_spi_probe(struct
spi_device
> *spi)
>  		goto terminate_thread;
>  	}
> 
> +	/* poke the IRQ handler so that we don't miss the first
interrupt */
> +	up(&card->spi_ready);
> +
>  	/* Start the card.
>  	 * This will call register_netdev, and we'll start
>  	 * getting interrupts... */
> --
> 1.5.6.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe
linux-wireless"
> in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
-
This message is subject to Imagination Technologies' e-mail terms: http://www.imgtec.com/e-mail.htm

Imagination Technologies Ltd is a limited company registered in England No:  1306335 
Registered Office: Imagination House, Home Park Estate, Kings Langley, Hertfordshire, WD4 8LZ.  

Email to and from the company may be monitored for compliance and other administrative purposes.  
-




More information about the libertas-dev mailing list