diff options
Diffstat (limited to 'drivers/usb/net/gl620a.c')
-rw-r--r-- | drivers/usb/net/gl620a.c | 180 |
1 files changed, 12 insertions, 168 deletions
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c index a3242be21959..31e5fe363fdc 100644 --- a/drivers/usb/net/gl620a.c +++ b/drivers/usb/net/gl620a.c | |||
@@ -70,184 +70,29 @@ | |||
70 | (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4) | 70 | (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4) |
71 | 71 | ||
72 | struct gl_packet { | 72 | struct gl_packet { |
73 | u32 packet_length; | 73 | __le32 packet_length; |
74 | char packet_data [1]; | 74 | char packet_data [1]; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct gl_header { | 77 | struct gl_header { |
78 | u32 packet_count; | 78 | __le32 packet_count; |
79 | struct gl_packet packets; | 79 | struct gl_packet packets; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | #ifdef GENELINK_ACK | ||
83 | |||
84 | // FIXME: this code is incomplete, not debugged; it doesn't | ||
85 | // handle interrupts correctly; it should use the generic | ||
86 | // status IRQ code (which didn't exist back in 2001). | ||
87 | |||
88 | struct gl_priv { | ||
89 | struct urb *irq_urb; | ||
90 | char irq_buf [INTERRUPT_BUFSIZE]; | ||
91 | }; | ||
92 | |||
93 | static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value) | ||
94 | { | ||
95 | int retval; | ||
96 | |||
97 | retval = usb_control_msg(dev->udev, | ||
98 | usb_sndctrlpipe(dev->udev, 0), | ||
99 | request, | ||
100 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
101 | value, | ||
102 | 0, // index | ||
103 | 0, // data buffer | ||
104 | 0, // size | ||
105 | USB_CTRL_SET_TIMEOUT); | ||
106 | return retval; | ||
107 | } | ||
108 | |||
109 | static void gl_interrupt_complete(struct urb *urb) | ||
110 | { | ||
111 | int status = urb->status; | ||
112 | |||
113 | switch (status) { | ||
114 | case 0: | ||
115 | /* success */ | ||
116 | break; | ||
117 | case -ECONNRESET: | ||
118 | case -ENOENT: | ||
119 | case -ESHUTDOWN: | ||
120 | /* this urb is terminated, clean up */ | ||
121 | dbg("%s - urb shutting down with status: %d", | ||
122 | __FUNCTION__, status); | ||
123 | return; | ||
124 | default: | ||
125 | dbg("%s - nonzero urb status received: %d", | ||
126 | __FUNCTION__, urb->status); | ||
127 | } | ||
128 | |||
129 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
130 | if (status) | ||
131 | err("%s - usb_submit_urb failed with result %d", | ||
132 | __FUNCTION__, status); | ||
133 | } | ||
134 | |||
135 | static int gl_interrupt_read(struct usbnet *dev) | ||
136 | { | ||
137 | struct gl_priv *priv = dev->priv_data; | ||
138 | int retval; | ||
139 | |||
140 | // issue usb interrupt read | ||
141 | if (priv && priv->irq_urb) { | ||
142 | // submit urb | ||
143 | if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0) | ||
144 | dbg("gl_interrupt_read: submit fail - %X...", retval); | ||
145 | else | ||
146 | dbg("gl_interrupt_read: submit success..."); | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | // check whether another side is connected | ||
153 | static int genelink_check_connect(struct usbnet *dev) | ||
154 | { | ||
155 | int retval; | ||
156 | |||
157 | dbg("genelink_check_connect..."); | ||
158 | |||
159 | // detect whether another side is connected | ||
160 | if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) { | ||
161 | dbg("%s: genelink_check_connect write fail - %X", | ||
162 | dev->net->name, retval); | ||
163 | return retval; | ||
164 | } | ||
165 | |||
166 | // usb interrupt read to ack another side | ||
167 | if ((retval = gl_interrupt_read(dev)) != 0) { | ||
168 | dbg("%s: genelink_check_connect read fail - %X", | ||
169 | dev->net->name, retval); | ||
170 | return retval; | ||
171 | } | ||
172 | |||
173 | dbg("%s: genelink_check_connect read success", dev->net->name); | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | // allocate and initialize the private data for genelink | ||
178 | static int genelink_init(struct usbnet *dev) | ||
179 | { | ||
180 | struct gl_priv *priv; | ||
181 | |||
182 | // allocate the private data structure | ||
183 | if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) { | ||
184 | dbg("%s: cannot allocate private data per device", | ||
185 | dev->net->name); | ||
186 | return -ENOMEM; | ||
187 | } | ||
188 | |||
189 | // allocate irq urb | ||
190 | if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) { | ||
191 | dbg("%s: cannot allocate private irq urb per device", | ||
192 | dev->net->name); | ||
193 | kfree(priv); | ||
194 | return -ENOMEM; | ||
195 | } | ||
196 | |||
197 | // fill irq urb | ||
198 | usb_fill_int_urb(priv->irq_urb, dev->udev, | ||
199 | usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE), | ||
200 | priv->irq_buf, INTERRUPT_BUFSIZE, | ||
201 | gl_interrupt_complete, 0, | ||
202 | GENELINK_INTERRUPT_INTERVAL); | ||
203 | |||
204 | // set private data pointer | ||
205 | dev->priv_data = priv; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | // release the private data | ||
211 | static int genelink_free(struct usbnet *dev) | ||
212 | { | ||
213 | struct gl_priv *priv = dev->priv_data; | ||
214 | |||
215 | if (!priv) | ||
216 | return 0; | ||
217 | |||
218 | // FIXME: can't cancel here; it's synchronous, and | ||
219 | // should have happened earlier in any case (interrupt | ||
220 | // handling needs to be generic) | ||
221 | |||
222 | // cancel irq urb first | ||
223 | usb_kill_urb(priv->irq_urb); | ||
224 | |||
225 | // free irq urb | ||
226 | usb_free_urb(priv->irq_urb); | ||
227 | |||
228 | // free the private data structure | ||
229 | kfree(priv); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | #endif | ||
235 | |||
236 | static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | 82 | static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) |
237 | { | 83 | { |
238 | struct gl_header *header; | 84 | struct gl_header *header; |
239 | struct gl_packet *packet; | 85 | struct gl_packet *packet; |
240 | struct sk_buff *gl_skb; | 86 | struct sk_buff *gl_skb; |
241 | u32 size; | 87 | u32 size; |
88 | u32 count; | ||
242 | 89 | ||
243 | header = (struct gl_header *) skb->data; | 90 | header = (struct gl_header *) skb->data; |
244 | 91 | ||
245 | // get the packet count of the received skb | 92 | // get the packet count of the received skb |
246 | le32_to_cpus(&header->packet_count); | 93 | count = le32_to_cpu(header->packet_count); |
247 | if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS) | 94 | if (count > GL_MAX_TRANSMIT_PACKETS) { |
248 | || (header->packet_count < 0)) { | 95 | dbg("genelink: invalid received packet count %u", count); |
249 | dbg("genelink: invalid received packet count %d", | ||
250 | header->packet_count); | ||
251 | return 0; | 96 | return 0; |
252 | } | 97 | } |
253 | 98 | ||
@@ -257,7 +102,7 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
257 | // decrement the length for the packet count size 4 bytes | 102 | // decrement the length for the packet count size 4 bytes |
258 | skb_pull(skb, 4); | 103 | skb_pull(skb, 4); |
259 | 104 | ||
260 | while (header->packet_count > 1) { | 105 | while (count > 1) { |
261 | // get the packet length | 106 | // get the packet length |
262 | size = le32_to_cpu(packet->packet_length); | 107 | size = le32_to_cpu(packet->packet_length); |
263 | 108 | ||
@@ -278,9 +123,8 @@ static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
278 | } | 123 | } |
279 | 124 | ||
280 | // advance to the next packet | 125 | // advance to the next packet |
281 | packet = (struct gl_packet *) | 126 | packet = (struct gl_packet *)&packet->packet_data[size]; |
282 | &packet->packet_data [size]; | 127 | count--; |
283 | header->packet_count--; | ||
284 | 128 | ||
285 | // shift the data pointer to the next gl_packet | 129 | // shift the data pointer to the next gl_packet |
286 | skb_pull(skb, size + 4); | 130 | skb_pull(skb, size + 4); |
@@ -303,8 +147,8 @@ genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | |||
303 | int length = skb->len; | 147 | int length = skb->len; |
304 | int headroom = skb_headroom(skb); | 148 | int headroom = skb_headroom(skb); |
305 | int tailroom = skb_tailroom(skb); | 149 | int tailroom = skb_tailroom(skb); |
306 | u32 *packet_count; | 150 | __le32 *packet_count; |
307 | u32 *packet_len; | 151 | __le32 *packet_len; |
308 | 152 | ||
309 | // FIXME: magic numbers, bleech | 153 | // FIXME: magic numbers, bleech |
310 | padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1; | 154 | padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1; |
@@ -326,7 +170,7 @@ genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | |||
326 | } | 170 | } |
327 | 171 | ||
328 | // attach the packet count to the header | 172 | // attach the packet count to the header |
329 | packet_count = (u32 *) skb_push(skb, (4 + 4*1)); | 173 | packet_count = (__le32 *) skb_push(skb, (4 + 4*1)); |
330 | packet_len = packet_count + 1; | 174 | packet_len = packet_count + 1; |
331 | 175 | ||
332 | *packet_count = cpu_to_le32(1); | 176 | *packet_count = cpu_to_le32(1); |