aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/rtl8150.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/rtl8150.c')
-rw-r--r--drivers/net/usb/rtl8150.c100
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
144typedef struct rtl8150 rtl8150_t; 143typedef struct rtl8150 rtl8150_t;
145 144
145struct async_req {
146 struct usb_ctrlrequest dr;
147 u16 rx_creg;
148};
149
146static const char driver_name [] = "rtl8150"; 150static 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
167static void ctrl_callback(struct urb *urb) 171static 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
187static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) 182static 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
214static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) 214static 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
352static void unlink_all_urbs(rtl8150_t * dev) 344static 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
360static inline struct sk_buff *pull_skb(rtl8150_t *dev) 351static 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)
662static void rtl8150_set_multicast(struct net_device *netdev) 652static 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