diff options
Diffstat (limited to 'drivers/net/wireless/libertas/if_spi.c')
-rw-r--r-- | drivers/net/wireless/libertas/if_spi.c | 145 |
1 files changed, 15 insertions, 130 deletions
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 5b3672c4d0cc..fe3f08028eb3 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/kthread.h> | 23 | #include <linux/kthread.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/netdevice.h> | 25 | #include <linux/netdevice.h> |
26 | #include <linux/semaphore.h> | ||
27 | #include <linux/slab.h> | ||
26 | #include <linux/spi/libertas_spi.h> | 28 | #include <linux/spi/libertas_spi.h> |
27 | #include <linux/spi/spi.h> | 29 | #include <linux/spi/spi.h> |
28 | 30 | ||
@@ -32,12 +34,6 @@ | |||
32 | #include "dev.h" | 34 | #include "dev.h" |
33 | #include "if_spi.h" | 35 | #include "if_spi.h" |
34 | 36 | ||
35 | struct if_spi_packet { | ||
36 | struct list_head list; | ||
37 | u16 blen; | ||
38 | u8 buffer[0] __attribute__((aligned(4))); | ||
39 | }; | ||
40 | |||
41 | struct if_spi_card { | 37 | struct if_spi_card { |
42 | struct spi_device *spi; | 38 | struct spi_device *spi; |
43 | struct lbs_private *priv; | 39 | struct lbs_private *priv; |
@@ -66,33 +62,10 @@ struct if_spi_card { | |||
66 | struct semaphore spi_thread_terminated; | 62 | struct semaphore spi_thread_terminated; |
67 | 63 | ||
68 | u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; | 64 | 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 | }; | 65 | }; |
79 | 66 | ||
80 | static void free_if_spi_card(struct if_spi_card *card) | 67 | static void free_if_spi_card(struct if_spi_card *card) |
81 | { | 68 | { |
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); | 69 | spi_set_drvdata(card->spi, NULL); |
97 | kfree(card); | 70 | kfree(card); |
98 | } | 71 | } |
@@ -774,40 +747,6 @@ out: | |||
774 | return err; | 747 | return err; |
775 | } | 748 | } |
776 | 749 | ||
777 | /* Move data or a command from the host to the card. */ | ||
778 | static 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 | |||
804 | out: | ||
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 */ | 750 | /* Inform the host about a card event */ |
812 | static void if_spi_e2h(struct if_spi_card *card) | 751 | static void if_spi_e2h(struct if_spi_card *card) |
813 | { | 752 | { |
@@ -837,8 +776,6 @@ static int lbs_spi_thread(void *data) | |||
837 | int err; | 776 | int err; |
838 | struct if_spi_card *card = data; | 777 | struct if_spi_card *card = data; |
839 | u16 hiStatus; | 778 | u16 hiStatus; |
840 | unsigned long flags; | ||
841 | struct if_spi_packet *packet; | ||
842 | 779 | ||
843 | while (1) { | 780 | while (1) { |
844 | /* Wait to be woken up by one of two things. First, our ISR | 781 | /* Wait to be woken up by one of two things. First, our ISR |
@@ -877,43 +814,9 @@ static int lbs_spi_thread(void *data) | |||
877 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || | 814 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || |
878 | (card->priv->psstate != PS_STATE_FULL_POWER && | 815 | (card->priv->psstate != PS_STATE_FULL_POWER && |
879 | (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { | 816 | (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); | 817 | 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 | } | 818 | } |
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 | 819 | ||
914 | if (packet) | ||
915 | if_spi_h2c(card, packet, MVMS_DAT); | ||
916 | } | ||
917 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) | 820 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) |
918 | if_spi_e2h(card); | 821 | if_spi_e2h(card); |
919 | 822 | ||
@@ -942,40 +845,18 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
942 | u8 type, u8 *buf, u16 nb) | 845 | u8 type, u8 *buf, u16 nb) |
943 | { | 846 | { |
944 | int err = 0; | 847 | int err = 0; |
945 | unsigned long flags; | ||
946 | struct if_spi_card *card = priv->card; | 848 | struct if_spi_card *card = priv->card; |
947 | struct if_spi_packet *packet; | ||
948 | u16 blen; | ||
949 | 849 | ||
950 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); | 850 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); |
951 | 851 | ||
952 | if (nb == 0) { | 852 | 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 | 853 | ||
967 | switch (type) { | 854 | switch (type) { |
968 | case MVMS_CMD: | 855 | case MVMS_CMD: |
969 | priv->dnld_sent = DNLD_CMD_SENT; | 856 | 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; | 857 | break; |
974 | case MVMS_DAT: | 858 | case MVMS_DAT: |
975 | priv->dnld_sent = DNLD_DATA_SENT; | 859 | 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; | 860 | break; |
980 | default: | 861 | default: |
981 | lbs_pr_err("can't transfer buffer of type %d", type); | 862 | lbs_pr_err("can't transfer buffer of type %d", type); |
@@ -983,9 +864,6 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
983 | break; | 864 | break; |
984 | } | 865 | } |
985 | 866 | ||
986 | /* Wake up the spi thread */ | ||
987 | up(&card->spi_ready); | ||
988 | out: | ||
989 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); | 867 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); |
990 | return err; | 868 | return err; |
991 | } | 869 | } |
@@ -1026,6 +904,10 @@ static int if_spi_calculate_fw_names(u16 card_id, | |||
1026 | chip_id_to_device_name[i].name); | 904 | chip_id_to_device_name[i].name); |
1027 | return 0; | 905 | return 0; |
1028 | } | 906 | } |
907 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
908 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
909 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
1029 | 911 | ||
1030 | static int __devinit if_spi_probe(struct spi_device *spi) | 912 | static int __devinit if_spi_probe(struct spi_device *spi) |
1031 | { | 913 | { |
@@ -1062,9 +944,6 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1062 | 944 | ||
1063 | sema_init(&card->spi_ready, 0); | 945 | sema_init(&card->spi_ready, 0); |
1064 | sema_init(&card->spi_thread_terminated, 0); | 946 | 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 | 947 | ||
1069 | /* Initialize the SPI Interface Unit */ | 948 | /* Initialize the SPI Interface Unit */ |
1070 | err = spu_init(card, pdata->use_dummy_writes); | 949 | err = spu_init(card, pdata->use_dummy_writes); |
@@ -1117,6 +996,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1117 | card->priv = priv; | 996 | card->priv = priv; |
1118 | priv->card = card; | 997 | priv->card = card; |
1119 | priv->hw_host_to_card = if_spi_host_to_card; | 998 | priv->hw_host_to_card = if_spi_host_to_card; |
999 | priv->enter_deep_sleep = NULL; | ||
1000 | priv->exit_deep_sleep = NULL; | ||
1001 | priv->reset_deep_sleep_wakeup = NULL; | ||
1120 | priv->fw_ready = 1; | 1002 | priv->fw_ready = 1; |
1121 | 1003 | ||
1122 | /* Initialize interrupt handling stuff. */ | 1004 | /* Initialize interrupt handling stuff. */ |
@@ -1138,6 +1020,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1138 | goto terminate_thread; | 1020 | goto terminate_thread; |
1139 | } | 1021 | } |
1140 | 1022 | ||
1023 | /* poke the IRQ handler so that we don't miss the first interrupt */ | ||
1024 | up(&card->spi_ready); | ||
1025 | |||
1141 | /* Start the card. | 1026 | /* Start the card. |
1142 | * This will call register_netdev, and we'll start | 1027 | * This will call register_netdev, and we'll start |
1143 | * getting interrupts... */ | 1028 | * getting interrupts... */ |