[PATCH] libertas: remove internal buffers from GSPI driver

Dan Williams dcbw at redhat.com
Wed Oct 28 13:13:18 EDT 2009


On Tue, 2009-10-27 at 16:51 -0700, Andrey Yurovsky wrote:
> 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.
> 
> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>

Looks OK to me, but I don't have any of the SPI hardware so when you get
a Tested-by:, let me know and I'll ack.

Dan

> ---
>  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... */




More information about the libertas-dev mailing list