diff options
Diffstat (limited to 'drivers/net/usb/rtl8150.c')
-rw-r--r-- | drivers/net/usb/rtl8150.c | 100 |
1 files changed, 46 insertions, 54 deletions
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index a491d3a95393..6cbdac67f3a0 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c | |||
@@ -130,19 +130,23 @@ struct rtl8150 { | |||
130 | struct usb_device *udev; | 130 | struct usb_device *udev; |
131 | struct tasklet_struct tl; | 131 | struct tasklet_struct tl; |
132 | struct net_device *netdev; | 132 | struct net_device *netdev; |
133 | struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb; | 133 | struct urb *rx_urb, *tx_urb, *intr_urb; |
134 | struct sk_buff *tx_skb, *rx_skb; | 134 | struct sk_buff *tx_skb, *rx_skb; |
135 | struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE]; | 135 | struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE]; |
136 | spinlock_t rx_pool_lock; | 136 | spinlock_t rx_pool_lock; |
137 | struct usb_ctrlrequest dr; | 137 | struct usb_ctrlrequest dr; |
138 | int intr_interval; | 138 | int intr_interval; |
139 | __le16 rx_creg; | ||
140 | u8 *intr_buff; | 139 | u8 *intr_buff; |
141 | u8 phy; | 140 | u8 phy; |
142 | }; | 141 | }; |
143 | 142 | ||
144 | typedef struct rtl8150 rtl8150_t; | 143 | typedef struct rtl8150 rtl8150_t; |
145 | 144 | ||
145 | struct async_req { | ||
146 | struct usb_ctrlrequest dr; | ||
147 | u16 rx_creg; | ||
148 | }; | ||
149 | |||
146 | static const char driver_name [] = "rtl8150"; | 150 | static const char driver_name [] = "rtl8150"; |
147 | 151 | ||
148 | /* | 152 | /* |
@@ -164,51 +168,47 @@ static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) | |||
164 | indx, 0, data, size, 500); | 168 | indx, 0, data, size, 500); |
165 | } | 169 | } |
166 | 170 | ||
167 | static void ctrl_callback(struct urb *urb) | 171 | static void async_set_reg_cb(struct urb *urb) |
168 | { | 172 | { |
169 | rtl8150_t *dev; | 173 | struct async_req *req = (struct async_req *)urb->context; |
170 | int status = urb->status; | 174 | int status = urb->status; |
171 | 175 | ||
172 | switch (status) { | 176 | if (status < 0) |
173 | case 0: | 177 | dev_dbg(&urb->dev->dev, "%s failed with %d", __func__, status); |
174 | break; | 178 | kfree(req); |
175 | case -EINPROGRESS: | 179 | usb_free_urb(urb); |
176 | break; | ||
177 | case -ENOENT: | ||
178 | break; | ||
179 | default: | ||
180 | if (printk_ratelimit()) | ||
181 | dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status); | ||
182 | } | ||
183 | dev = urb->context; | ||
184 | clear_bit(RX_REG_SET, &dev->flags); | ||
185 | } | 180 | } |
186 | 181 | ||
187 | static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) | 182 | static int async_set_registers(rtl8150_t *dev, u16 indx, u16 size, u16 reg) |
188 | { | 183 | { |
189 | int ret; | 184 | int res = -ENOMEM; |
190 | 185 | struct urb *async_urb; | |
191 | if (test_bit(RX_REG_SET, &dev->flags)) | 186 | struct async_req *req; |
192 | return -EAGAIN; | ||
193 | 187 | ||
194 | dev->dr.bRequestType = RTL8150_REQT_WRITE; | 188 | req = kmalloc(sizeof(struct async_req), GFP_ATOMIC); |
195 | dev->dr.bRequest = RTL8150_REQ_SET_REGS; | 189 | if (req == NULL) |
196 | dev->dr.wValue = cpu_to_le16(indx); | 190 | return res; |
197 | dev->dr.wIndex = 0; | 191 | async_urb = usb_alloc_urb(0, GFP_ATOMIC); |
198 | dev->dr.wLength = cpu_to_le16(size); | 192 | if (async_urb == NULL) { |
199 | dev->ctrl_urb->transfer_buffer_length = size; | 193 | kfree(req); |
200 | usb_fill_control_urb(dev->ctrl_urb, dev->udev, | 194 | return res; |
201 | usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, | 195 | } |
202 | &dev->rx_creg, size, ctrl_callback, dev); | 196 | req->rx_creg = cpu_to_le16(reg); |
203 | if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { | 197 | req->dr.bRequestType = RTL8150_REQT_WRITE; |
204 | if (ret == -ENODEV) | 198 | req->dr.bRequest = RTL8150_REQ_SET_REGS; |
199 | req->dr.wIndex = 0; | ||
200 | req->dr.wValue = cpu_to_le16(indx); | ||
201 | req->dr.wLength = cpu_to_le16(size); | ||
202 | usb_fill_control_urb(async_urb, dev->udev, | ||
203 | usb_sndctrlpipe(dev->udev, 0), (void *)&req->dr, | ||
204 | &req->rx_creg, size, async_set_reg_cb, req); | ||
205 | res = usb_submit_urb(async_urb, GFP_ATOMIC); | ||
206 | if (res) { | ||
207 | if (res == -ENODEV) | ||
205 | netif_device_detach(dev->netdev); | 208 | netif_device_detach(dev->netdev); |
206 | dev_err(&dev->udev->dev, | 209 | dev_err(&dev->udev->dev, "%s failed with %d\n", __func__, res); |
207 | "control request submission failed: %d\n", ret); | 210 | } |
208 | } else | 211 | return res; |
209 | set_bit(RX_REG_SET, &dev->flags); | ||
210 | |||
211 | return ret; | ||
212 | } | 212 | } |
213 | 213 | ||
214 | static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) | 214 | static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) |
@@ -330,13 +330,6 @@ static int alloc_all_urbs(rtl8150_t * dev) | |||
330 | usb_free_urb(dev->tx_urb); | 330 | usb_free_urb(dev->tx_urb); |
331 | return 0; | 331 | return 0; |
332 | } | 332 | } |
333 | dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
334 | if (!dev->ctrl_urb) { | ||
335 | usb_free_urb(dev->rx_urb); | ||
336 | usb_free_urb(dev->tx_urb); | ||
337 | usb_free_urb(dev->intr_urb); | ||
338 | return 0; | ||
339 | } | ||
340 | 333 | ||
341 | return 1; | 334 | return 1; |
342 | } | 335 | } |
@@ -346,7 +339,6 @@ static void free_all_urbs(rtl8150_t * dev) | |||
346 | usb_free_urb(dev->rx_urb); | 339 | usb_free_urb(dev->rx_urb); |
347 | usb_free_urb(dev->tx_urb); | 340 | usb_free_urb(dev->tx_urb); |
348 | usb_free_urb(dev->intr_urb); | 341 | usb_free_urb(dev->intr_urb); |
349 | usb_free_urb(dev->ctrl_urb); | ||
350 | } | 342 | } |
351 | 343 | ||
352 | static void unlink_all_urbs(rtl8150_t * dev) | 344 | static void unlink_all_urbs(rtl8150_t * dev) |
@@ -354,7 +346,6 @@ static void unlink_all_urbs(rtl8150_t * dev) | |||
354 | usb_kill_urb(dev->rx_urb); | 346 | usb_kill_urb(dev->rx_urb); |
355 | usb_kill_urb(dev->tx_urb); | 347 | usb_kill_urb(dev->tx_urb); |
356 | usb_kill_urb(dev->intr_urb); | 348 | usb_kill_urb(dev->intr_urb); |
357 | usb_kill_urb(dev->ctrl_urb); | ||
358 | } | 349 | } |
359 | 350 | ||
360 | static inline struct sk_buff *pull_skb(rtl8150_t *dev) | 351 | static inline struct sk_buff *pull_skb(rtl8150_t *dev) |
@@ -629,7 +620,6 @@ static int enable_net_traffic(rtl8150_t * dev) | |||
629 | } | 620 | } |
630 | /* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */ | 621 | /* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */ |
631 | rcr = 0x9e; | 622 | rcr = 0x9e; |
632 | dev->rx_creg = cpu_to_le16(rcr); | ||
633 | tcr = 0xd8; | 623 | tcr = 0xd8; |
634 | cr = 0x0c; | 624 | cr = 0x0c; |
635 | if (!(rcr & 0x80)) | 625 | if (!(rcr & 0x80)) |
@@ -662,20 +652,22 @@ static void rtl8150_tx_timeout(struct net_device *netdev) | |||
662 | static void rtl8150_set_multicast(struct net_device *netdev) | 652 | static void rtl8150_set_multicast(struct net_device *netdev) |
663 | { | 653 | { |
664 | rtl8150_t *dev = netdev_priv(netdev); | 654 | rtl8150_t *dev = netdev_priv(netdev); |
655 | u16 rx_creg = 0x9e; | ||
656 | |||
665 | netif_stop_queue(netdev); | 657 | netif_stop_queue(netdev); |
666 | if (netdev->flags & IFF_PROMISC) { | 658 | if (netdev->flags & IFF_PROMISC) { |
667 | dev->rx_creg |= cpu_to_le16(0x0001); | 659 | rx_creg |= 0x0001; |
668 | dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name); | 660 | dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name); |
669 | } else if (!netdev_mc_empty(netdev) || | 661 | } else if (!netdev_mc_empty(netdev) || |
670 | (netdev->flags & IFF_ALLMULTI)) { | 662 | (netdev->flags & IFF_ALLMULTI)) { |
671 | dev->rx_creg &= cpu_to_le16(0xfffe); | 663 | rx_creg &= 0xfffe; |
672 | dev->rx_creg |= cpu_to_le16(0x0002); | 664 | rx_creg |= 0x0002; |
673 | dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name); | 665 | dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name); |
674 | } else { | 666 | } else { |
675 | /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ | 667 | /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ |
676 | dev->rx_creg &= cpu_to_le16(0x00fc); | 668 | rx_creg &= 0x00fc; |
677 | } | 669 | } |
678 | async_set_registers(dev, RCR, 2); | 670 | async_set_registers(dev, RCR, sizeof(rx_creg), rx_creg); |
679 | netif_wake_queue(netdev); | 671 | netif_wake_queue(netdev); |
680 | } | 672 | } |
681 | 673 | ||