aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54usb.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@web.de>2008-09-04 06:29:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-05 16:19:52 -0400
commit2b80848e3818fb1c8ccddc105b065a86c68afa9d (patch)
tree02a8d14e9af88e79668d2b0b5414cf8438997a84 /drivers/net/wireless/p54/p54usb.c
parentd203b8ef8e5acf9dad5a53d7067ef146e6b2e837 (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.c72
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
234static 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
213static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, 257static 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