diff options
author | Bing Zhao <bzhao@marvell.com> | 2009-04-06 18:50:56 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:54:41 -0400 |
commit | e45d8e534b67580eedd9b4910ccc16d6dd3cceff (patch) | |
tree | a8062a38ed2a5217bf034031e5193d9e17480939 /drivers | |
parent | 87cbfd06889256cac945b37c7f62f4ce7f44b34a (diff) |
libertas: add support for Marvell SD8688 chip
libertas: add support for Marvell SD8688 chip
Use RxPD->pkt_ptr to locate eth803 header in the packet
received since SD8688/v10 firmware allows a gap between
RxPD and eth803 header.
Set SDIO block size to 256 for CMD53.
The maximum block size for SD8688 WLAN function is set
to 512 in TPLFE_MAX_BLK_SIZE. But using 512 as block size
results upto 2K bytes data (4 blocks) being transferred
and causes buffer overflow in firmware.
Both changes above are backward compatible with earlier
firmware versions for SD8385/SD8686.
The SDIO_DEVICE_IDs for SD8688 chip are added in
include/linux/mmc/sdio_ids.h
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/rx.c | 15 |
4 files changed, 25 insertions, 13 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 8f279e7bd049..ad99470ae92d 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -146,10 +146,10 @@ config LIBERTAS_CS | |||
146 | A driver for Marvell Libertas 8385 CompactFlash devices. | 146 | A driver for Marvell Libertas 8385 CompactFlash devices. |
147 | 147 | ||
148 | config LIBERTAS_SDIO | 148 | config LIBERTAS_SDIO |
149 | tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards" | 149 | tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" |
150 | depends on LIBERTAS && MMC | 150 | depends on LIBERTAS && MMC |
151 | ---help--- | 151 | ---help--- |
152 | A driver for Marvell Libertas 8385 and 8686 SDIO devices. | 152 | A driver for Marvell Libertas 8385/8686/8688 SDIO devices. |
153 | 153 | ||
154 | config LIBERTAS_SPI | 154 | config LIBERTAS_SPI |
155 | tristate "Marvell Libertas 8686 SPI 802.11b/g cards" | 155 | tristate "Marvell Libertas 8686 SPI 802.11b/g cards" |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 76f4c653d641..55864c10f9f1 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -48,8 +48,11 @@ static char *lbs_fw_name = NULL; | |||
48 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | 48 | module_param_named(fw_name, lbs_fw_name, charp, 0644); |
49 | 49 | ||
50 | static const struct sdio_device_id if_sdio_ids[] = { | 50 | static const struct sdio_device_id if_sdio_ids[] = { |
51 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, | 51 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, |
52 | { /* end: all zeroes */ }, | 52 | SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, |
53 | { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, | ||
54 | SDIO_DEVICE_ID_MARVELL_8688WLAN) }, | ||
55 | { /* end: all zeroes */ }, | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); | 58 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); |
@@ -73,6 +76,12 @@ static struct if_sdio_model if_sdio_models[] = { | |||
73 | .helper = "sd8686_helper.bin", | 76 | .helper = "sd8686_helper.bin", |
74 | .firmware = "sd8686.bin", | 77 | .firmware = "sd8686.bin", |
75 | }, | 78 | }, |
79 | { | ||
80 | /* 8688 */ | ||
81 | .model = 0x10, | ||
82 | .helper = "sd8688_helper.bin", | ||
83 | .firmware = "sd8688.bin", | ||
84 | }, | ||
76 | }; | 85 | }; |
77 | 86 | ||
78 | struct if_sdio_packet { | 87 | struct if_sdio_packet { |
@@ -488,7 +497,7 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
488 | ret = 0; | 497 | ret = 0; |
489 | 498 | ||
490 | release: | 499 | release: |
491 | sdio_set_block_size(card->func, 0); | 500 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); |
492 | sdio_release_host(card->func); | 501 | sdio_release_host(card->func); |
493 | kfree(chunk_buffer); | 502 | kfree(chunk_buffer); |
494 | release_fw: | 503 | release_fw: |
@@ -624,7 +633,7 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
624 | ret = 0; | 633 | ret = 0; |
625 | 634 | ||
626 | release: | 635 | release: |
627 | sdio_set_block_size(card->func, 0); | 636 | sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); |
628 | sdio_release_host(card->func); | 637 | sdio_release_host(card->func); |
629 | kfree(chunk_buffer); | 638 | kfree(chunk_buffer); |
630 | release_fw: | 639 | release_fw: |
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 533bdfbf5d2a..37ada2c29aa9 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h | |||
@@ -42,4 +42,6 @@ | |||
42 | 42 | ||
43 | #define IF_SDIO_EVENT 0x80fc | 43 | #define IF_SDIO_EVENT 0x80fc |
44 | 44 | ||
45 | #define IF_SDIO_BLOCK_SIZE 256 | ||
46 | |||
45 | #endif | 47 | #endif |
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 820c22d9220f..bd845d09f174 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -25,7 +25,6 @@ struct rfc1042hdr { | |||
25 | } __attribute__ ((packed)); | 25 | } __attribute__ ((packed)); |
26 | 26 | ||
27 | struct rxpackethdr { | 27 | struct rxpackethdr { |
28 | struct rxpd rx_pd; | ||
29 | struct eth803hdr eth803_hdr; | 28 | struct eth803hdr eth803_hdr; |
30 | struct rfc1042hdr rfc1042_hdr; | 29 | struct rfc1042hdr rfc1042_hdr; |
31 | } __attribute__ ((packed)); | 30 | } __attribute__ ((packed)); |
@@ -158,8 +157,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
158 | if (priv->monitormode) | 157 | if (priv->monitormode) |
159 | return process_rxed_802_11_packet(priv, skb); | 158 | return process_rxed_802_11_packet(priv, skb); |
160 | 159 | ||
161 | p_rx_pkt = (struct rxpackethdr *) skb->data; | 160 | p_rx_pd = (struct rxpd *) skb->data; |
162 | p_rx_pd = &p_rx_pkt->rx_pd; | 161 | p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + |
162 | le32_to_cpu(p_rx_pd->pkt_ptr)); | ||
163 | if (priv->mesh_dev) { | 163 | if (priv->mesh_dev) { |
164 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | 164 | if (priv->mesh_fw_ver == MESH_FW_OLD) { |
165 | if (p_rx_pd->rx_control & RxPD_MESH_FRAME) | 165 | if (p_rx_pd->rx_control & RxPD_MESH_FRAME) |
@@ -181,8 +181,9 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
181 | goto done; | 181 | goto done; |
182 | } | 182 | } |
183 | 183 | ||
184 | lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", | 184 | lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n", |
185 | skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); | 185 | skb->len, le32_to_cpu(p_rx_pd->pkt_ptr), |
186 | skb->len - le32_to_cpu(p_rx_pd->pkt_ptr)); | ||
186 | 187 | ||
187 | lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, | 188 | lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, |
188 | sizeof(p_rx_pkt->eth803_hdr.dest_addr)); | 189 | sizeof(p_rx_pkt->eth803_hdr.dest_addr)); |
@@ -216,14 +217,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
216 | /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header | 217 | /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header |
217 | * that was removed | 218 | * that was removed |
218 | */ | 219 | */ |
219 | hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt; | 220 | hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; |
220 | } else { | 221 | } else { |
221 | lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", | 222 | lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", |
222 | (u8 *) & p_rx_pkt->rfc1042_hdr, | 223 | (u8 *) & p_rx_pkt->rfc1042_hdr, |
223 | sizeof(p_rx_pkt->rfc1042_hdr)); | 224 | sizeof(p_rx_pkt->rfc1042_hdr)); |
224 | 225 | ||
225 | /* Chop off the rxpd */ | 226 | /* Chop off the rxpd */ |
226 | hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt; | 227 | hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd; |
227 | } | 228 | } |
228 | 229 | ||
229 | /* Chop off the leading header bytes so the skb points to the start of | 230 | /* Chop off the leading header bytes so the skb points to the start of |