diff options
author | Christian Lamparter <chunkeey@web.de> | 2008-09-04 06:29:38 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-05 16:19:52 -0400 |
commit | 2b80848e3818fb1c8ccddc105b065a86c68afa9d (patch) | |
tree | 02a8d14e9af88e79668d2b0b5414cf8438997a84 /drivers/net/wireless/p54/p54usb.c | |
parent | d203b8ef8e5acf9dad5a53d7067ef146e6b2e837 (diff) |
p54usb: support LM87 firmwares
This patch adds the necessary changes to support LM87 firmwares.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54/p54usb.c')
-rw-r--r-- | drivers/net/wireless/p54/p54usb.c | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index eca858c40b1f..7444f3729779 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -91,8 +91,13 @@ static void p54u_rx_cb(struct urb *urb) | |||
91 | 91 | ||
92 | skb_unlink(skb, &priv->rx_queue); | 92 | skb_unlink(skb, &priv->rx_queue); |
93 | skb_put(skb, urb->actual_length); | 93 | skb_put(skb, urb->actual_length); |
94 | if (!priv->hw_type) | 94 | |
95 | skb_pull(skb, sizeof(struct net2280_tx_hdr)); | 95 | if (priv->hw_type == P54U_NET2280) |
96 | skb_pull(skb, priv->common.tx_hdr_len); | ||
97 | if (priv->common.fw_interface == FW_LM87) { | ||
98 | skb_pull(skb, 4); | ||
99 | skb_put(skb, 4); | ||
100 | } | ||
96 | 101 | ||
97 | if (p54_rx(dev, skb)) { | 102 | if (p54_rx(dev, skb)) { |
98 | skb = dev_alloc_skb(priv->common.rx_mtu + 32); | 103 | skb = dev_alloc_skb(priv->common.rx_mtu + 32); |
@@ -109,9 +114,12 @@ static void p54u_rx_cb(struct urb *urb) | |||
109 | urb->context = skb; | 114 | urb->context = skb; |
110 | skb_queue_tail(&priv->rx_queue, skb); | 115 | skb_queue_tail(&priv->rx_queue, skb); |
111 | } else { | 116 | } else { |
112 | if (!priv->hw_type) | 117 | if (priv->hw_type == P54U_NET2280) |
113 | skb_push(skb, sizeof(struct net2280_tx_hdr)); | 118 | skb_push(skb, priv->common.tx_hdr_len); |
114 | 119 | if (priv->common.fw_interface == FW_LM87) { | |
120 | skb_push(skb, 4); | ||
121 | skb_put(skb, 4); | ||
122 | } | ||
115 | skb_reset_tail_pointer(skb); | 123 | skb_reset_tail_pointer(skb); |
116 | skb_trim(skb, 0); | 124 | skb_trim(skb, 0); |
117 | if (urb->transfer_buffer != skb_tail_pointer(skb)) { | 125 | if (urb->transfer_buffer != skb_tail_pointer(skb)) { |
@@ -210,6 +218,42 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data, | |||
210 | usb_submit_urb(data_urb, GFP_ATOMIC); | 218 | usb_submit_urb(data_urb, GFP_ATOMIC); |
211 | } | 219 | } |
212 | 220 | ||
221 | __le32 p54u_lm87_chksum(const u32 *data, size_t length) | ||
222 | { | ||
223 | __le32 chk = 0; | ||
224 | |||
225 | length >>= 2; | ||
226 | while (length--) { | ||
227 | chk ^= cpu_to_le32(*data++); | ||
228 | chk = (chk >> 5) ^ (chk << 3); | ||
229 | } | ||
230 | |||
231 | return chk; | ||
232 | } | ||
233 | |||
234 | static void p54u_tx_lm87(struct ieee80211_hw *dev, | ||
235 | struct p54_control_hdr *data, | ||
236 | size_t len, int free_on_tx) | ||
237 | { | ||
238 | struct p54u_priv *priv = dev->priv; | ||
239 | struct urb *data_urb; | ||
240 | struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr); | ||
241 | |||
242 | data_urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
243 | if (!data_urb) | ||
244 | return; | ||
245 | |||
246 | hdr->chksum = p54u_lm87_chksum((u32 *)data, len); | ||
247 | hdr->device_addr = data->req_id; | ||
248 | |||
249 | usb_fill_bulk_urb(data_urb, priv->udev, | ||
250 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, | ||
251 | len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, | ||
252 | dev); | ||
253 | |||
254 | usb_submit_urb(data_urb, GFP_ATOMIC); | ||
255 | } | ||
256 | |||
213 | static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, | 257 | static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, |
214 | size_t len, int free_on_tx) | 258 | size_t len, int free_on_tx) |
215 | { | 259 | { |
@@ -776,21 +820,23 @@ static int __devinit p54u_probe(struct usb_interface *intf, | |||
776 | } | 820 | } |
777 | } | 821 | } |
778 | priv->common.open = p54u_open; | 822 | priv->common.open = p54u_open; |
779 | 823 | priv->common.stop = p54u_stop; | |
780 | if (recognized_pipes < P54U_PIPE_NUMBER) { | 824 | if (recognized_pipes < P54U_PIPE_NUMBER) { |
781 | priv->hw_type = P54U_3887; | 825 | priv->hw_type = P54U_3887; |
782 | priv->common.tx = p54u_tx_3887; | 826 | err = p54u_upload_firmware_3887(dev); |
827 | if (priv->common.fw_interface == FW_LM87) { | ||
828 | dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); | ||
829 | priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); | ||
830 | priv->common.tx = p54u_tx_lm87; | ||
831 | } else | ||
832 | priv->common.tx = p54u_tx_3887; | ||
783 | } else { | 833 | } else { |
834 | priv->hw_type = P54U_NET2280; | ||
784 | dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); | 835 | dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); |
785 | priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); | 836 | priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); |
786 | priv->common.tx = p54u_tx_net2280; | 837 | priv->common.tx = p54u_tx_net2280; |
787 | } | ||
788 | priv->common.stop = p54u_stop; | ||
789 | |||
790 | if (priv->hw_type) | ||
791 | err = p54u_upload_firmware_3887(dev); | ||
792 | else | ||
793 | err = p54u_upload_firmware_net2280(dev); | 838 | err = p54u_upload_firmware_net2280(dev); |
839 | } | ||
794 | if (err) | 840 | if (err) |
795 | goto err_free_dev; | 841 | goto err_free_dev; |
796 | 842 | ||