aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
authorAndrey Yurovsky <andrey@cozybit.com>2009-10-27 19:51:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-11-02 15:39:41 -0500
commit86c34fe89e9cad9e1ba4d1a8bbf98259035f4caf (patch)
treeb2bf5bb2f7c479ab04f2167937d89504e1b6ba09 /drivers/net/wireless/libertas
parentd2d8cda7fc0b7a133492e70332217a7f20757615 (diff)
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. Signed-off-by: Andrey Yurovsky <andrey@cozybit.com> Tested-by: George Shore <george.shore@imgtec.com> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/if_spi.c136
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 30d9d0ea28eb..d6a48dd3652c 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -32,12 +32,6 @@
32#include "dev.h" 32#include "dev.h"
33#include "if_spi.h" 33#include "if_spi.h"
34 34
35struct if_spi_packet {
36 struct list_head list;
37 u16 blen;
38 u8 buffer[0] __attribute__((aligned(4)));
39};
40
41struct if_spi_card { 35struct if_spi_card {
42 struct spi_device *spi; 36 struct spi_device *spi;
43 struct lbs_private *priv; 37 struct lbs_private *priv;
@@ -66,33 +60,10 @@ struct if_spi_card {
66 struct semaphore spi_thread_terminated; 60 struct semaphore spi_thread_terminated;
67 61
68 u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; 62 u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE];
69
70 /* A buffer of incoming packets from libertas core.
71 * Since we can't sleep in hw_host_to_card, we have to buffer
72 * them. */
73 struct list_head cmd_packet_list;
74 struct list_head data_packet_list;
75
76 /* Protects cmd_packet_list and data_packet_list */
77 spinlock_t buffer_lock;
78}; 63};
79 64
80static void free_if_spi_card(struct if_spi_card *card) 65static void free_if_spi_card(struct if_spi_card *card)
81{ 66{
82 struct list_head *cursor, *next;
83 struct if_spi_packet *packet;
84
85 BUG_ON(card->run_thread);
86 list_for_each_safe(cursor, next, &card->cmd_packet_list) {
87 packet = container_of(cursor, struct if_spi_packet, list);
88 list_del(&packet->list);
89 kfree(packet);
90 }
91 list_for_each_safe(cursor, next, &card->data_packet_list) {
92 packet = container_of(cursor, struct if_spi_packet, list);
93 list_del(&packet->list);
94 kfree(packet);
95 }
96 spi_set_drvdata(card->spi, NULL); 67 spi_set_drvdata(card->spi, NULL);
97 kfree(card); 68 kfree(card);
98} 69}
@@ -774,40 +745,6 @@ out:
774 return err; 745 return err;
775} 746}
776 747
777/* Move data or a command from the host to the card. */
778static void if_spi_h2c(struct if_spi_card *card,
779 struct if_spi_packet *packet, int type)
780{
781 int err = 0;
782 u16 int_type, port_reg;
783
784 switch (type) {
785 case MVMS_DAT:
786 int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
787 port_reg = IF_SPI_DATA_RDWRPORT_REG;
788 break;
789 case MVMS_CMD:
790 int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
791 port_reg = IF_SPI_CMD_RDWRPORT_REG;
792 break;
793 default:
794 lbs_pr_err("can't transfer buffer of type %d\n", type);
795 err = -EINVAL;
796 goto out;
797 }
798
799 /* Write the data to the card */
800 err = spu_write(card, port_reg, packet->buffer, packet->blen);
801 if (err)
802 goto out;
803
804out:
805 kfree(packet);
806
807 if (err)
808 lbs_pr_err("%s: error %d\n", __func__, err);
809}
810
811/* Inform the host about a card event */ 748/* Inform the host about a card event */
812static void if_spi_e2h(struct if_spi_card *card) 749static void if_spi_e2h(struct if_spi_card *card)
813{ 750{
@@ -837,8 +774,6 @@ static int lbs_spi_thread(void *data)
837 int err; 774 int err;
838 struct if_spi_card *card = data; 775 struct if_spi_card *card = data;
839 u16 hiStatus; 776 u16 hiStatus;
840 unsigned long flags;
841 struct if_spi_packet *packet;
842 777
843 while (1) { 778 while (1) {
844 /* Wait to be woken up by one of two things. First, our ISR 779 /* Wait to be woken up by one of two things. First, our ISR
@@ -877,43 +812,9 @@ static int lbs_spi_thread(void *data)
877 if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || 812 if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
878 (card->priv->psstate != PS_STATE_FULL_POWER && 813 (card->priv->psstate != PS_STATE_FULL_POWER &&
879 (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { 814 (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
880 /* This means two things. First of all,
881 * if there was a previous command sent, the card has
882 * successfully received it.
883 * Secondly, it is now ready to download another
884 * command.
885 */
886 lbs_host_to_card_done(card->priv); 815 lbs_host_to_card_done(card->priv);
887
888 /* Do we have any command packets from the host to
889 * send? */
890 packet = NULL;
891 spin_lock_irqsave(&card->buffer_lock, flags);
892 if (!list_empty(&card->cmd_packet_list)) {
893 packet = (struct if_spi_packet *)(card->
894 cmd_packet_list.next);
895 list_del(&packet->list);
896 }
897 spin_unlock_irqrestore(&card->buffer_lock, flags);
898
899 if (packet)
900 if_spi_h2c(card, packet, MVMS_CMD);
901 } 816 }
902 if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
903 /* Do we have any data packets from the host to
904 * send? */
905 packet = NULL;
906 spin_lock_irqsave(&card->buffer_lock, flags);
907 if (!list_empty(&card->data_packet_list)) {
908 packet = (struct if_spi_packet *)(card->
909 data_packet_list.next);
910 list_del(&packet->list);
911 }
912 spin_unlock_irqrestore(&card->buffer_lock, flags);
913 817
914 if (packet)
915 if_spi_h2c(card, packet, MVMS_DAT);
916 }
917 if (hiStatus & IF_SPI_HIST_CARD_EVENT) 818 if (hiStatus & IF_SPI_HIST_CARD_EVENT)
918 if_spi_e2h(card); 819 if_spi_e2h(card);
919 820
@@ -942,40 +843,18 @@ static int if_spi_host_to_card(struct lbs_private *priv,
942 u8 type, u8 *buf, u16 nb) 843 u8 type, u8 *buf, u16 nb)
943{ 844{
944 int err = 0; 845 int err = 0;
945 unsigned long flags;
946 struct if_spi_card *card = priv->card; 846 struct if_spi_card *card = priv->card;
947 struct if_spi_packet *packet;
948 u16 blen;
949 847
950 lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); 848 lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
951 849
952 if (nb == 0) { 850 nb = ALIGN(nb, 4);
953 lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
954 err = -EINVAL;
955 goto out;
956 }
957 blen = ALIGN(nb, 4);
958 packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
959 if (!packet) {
960 err = -ENOMEM;
961 goto out;
962 }
963 packet->blen = blen;
964 memcpy(packet->buffer, buf, nb);
965 memset(packet->buffer + nb, 0, blen - nb);
966 851
967 switch (type) { 852 switch (type) {
968 case MVMS_CMD: 853 case MVMS_CMD:
969 priv->dnld_sent = DNLD_CMD_SENT; 854 err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb);
970 spin_lock_irqsave(&card->buffer_lock, flags);
971 list_add_tail(&packet->list, &card->cmd_packet_list);
972 spin_unlock_irqrestore(&card->buffer_lock, flags);
973 break; 855 break;
974 case MVMS_DAT: 856 case MVMS_DAT:
975 priv->dnld_sent = DNLD_DATA_SENT; 857 err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb);
976 spin_lock_irqsave(&card->buffer_lock, flags);
977 list_add_tail(&packet->list, &card->data_packet_list);
978 spin_unlock_irqrestore(&card->buffer_lock, flags);
979 break; 858 break;
980 default: 859 default:
981 lbs_pr_err("can't transfer buffer of type %d", type); 860 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,
983 break; 862 break;
984 } 863 }
985 864
986 /* Wake up the spi thread */
987 up(&card->spi_ready);
988out:
989 lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); 865 lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
990 return err; 866 return err;
991} 867}
@@ -1062,9 +938,6 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1062 938
1063 sema_init(&card->spi_ready, 0); 939 sema_init(&card->spi_ready, 0);
1064 sema_init(&card->spi_thread_terminated, 0); 940 sema_init(&card->spi_thread_terminated, 0);
1065 INIT_LIST_HEAD(&card->cmd_packet_list);
1066 INIT_LIST_HEAD(&card->data_packet_list);
1067 spin_lock_init(&card->buffer_lock);
1068 941
1069 /* Initialize the SPI Interface Unit */ 942 /* Initialize the SPI Interface Unit */
1070 err = spu_init(card, pdata->use_dummy_writes); 943 err = spu_init(card, pdata->use_dummy_writes);
@@ -1141,6 +1014,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
1141 goto terminate_thread; 1014 goto terminate_thread;
1142 } 1015 }
1143 1016
1017 /* poke the IRQ handler so that we don't miss the first interrupt */
1018 up(&card->spi_ready);
1019
1144 /* Start the card. 1020 /* Start the card.
1145 * This will call register_netdev, and we'll start 1021 * This will call register_netdev, and we'll start
1146 * getting interrupts... */ 1022 * getting interrupts... */