Commit b34243f6 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

[IRDA]: COnver irda-usb to dynamic device allocation.

parent 6890d1c6
...@@ -68,10 +68,6 @@ ...@@ -68,10 +68,6 @@
static int qos_mtt_bits = 0; static int qos_mtt_bits = 0;
/* Master instance for each hardware found */
#define NIRUSB 4 /* Max number of USB-IrDA dongles */
static struct irda_usb_cb irda_instance[NIRUSB];
/* These are the currently known IrDA USB dongles. Add new dongles here */ /* These are the currently known IrDA USB dongles. Add new dongles here */
static struct usb_device_id dongles[] = { static struct usb_device_id dongles[] = {
/* ACTiSYS Corp., ACT-IR2000U FIR-USB Adapter */ /* ACTiSYS Corp., ACT-IR2000U FIR-USB Adapter */
...@@ -108,7 +104,7 @@ static void irda_usb_disconnect(struct usb_interface *intf); ...@@ -108,7 +104,7 @@ static void irda_usb_disconnect(struct usb_interface *intf);
static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self);
static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev); static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev);
static int irda_usb_open(struct irda_usb_cb *self); static int irda_usb_open(struct irda_usb_cb *self);
static int irda_usb_close(struct irda_usb_cb *self); static void irda_usb_close(struct irda_usb_cb *self);
static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs); static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void write_bulk_callback(struct urb *urb, struct pt_regs *regs); static void write_bulk_callback(struct urb *urb, struct pt_regs *regs);
static void irda_usb_receive(struct urb *urb, struct pt_regs *regs); static void irda_usb_receive(struct urb *urb, struct pt_regs *regs);
...@@ -1157,36 +1153,12 @@ static inline void irda_usb_init_qos(struct irda_usb_cb *self) ...@@ -1157,36 +1153,12 @@ static inline void irda_usb_init_qos(struct irda_usb_cb *self)
*/ */
static inline int irda_usb_open(struct irda_usb_cb *self) static inline int irda_usb_open(struct irda_usb_cb *self)
{ {
struct net_device *netdev; struct net_device *netdev = self->netdev;
int err;
IRDA_DEBUG(1, "%s()\n", __FUNCTION__); IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
spin_lock_init(&self->lock);
irda_usb_init_qos(self); irda_usb_init_qos(self);
/* Allocate the buffer for speed changes */
/* Don't change this buffer size and allocation without doing
* some heavy and complete testing. Don't ask why :-(
* Jean II */
self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
if (self->speed_buff == NULL)
return -1;
memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
/* Create a network device for us */
netdev = alloc_irdadev(0);
if (!netdev) {
ERROR("%s(), alloc_net_dev() failed!\n", __FUNCTION__);
return -ENOMEM;
}
SET_MODULE_OWNER(dev);
self->netdev = netdev;
netdev->priv = (void *) self;
/* Override the network functions we need to use */ /* Override the network functions we need to use */
netdev->hard_start_xmit = irda_usb_hard_xmit; netdev->hard_start_xmit = irda_usb_hard_xmit;
netdev->tx_timeout = irda_usb_net_timeout; netdev->tx_timeout = irda_usb_net_timeout;
...@@ -1196,16 +1168,7 @@ static inline int irda_usb_open(struct irda_usb_cb *self) ...@@ -1196,16 +1168,7 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
netdev->get_stats = irda_usb_net_get_stats; netdev->get_stats = irda_usb_net_get_stats;
netdev->do_ioctl = irda_usb_net_ioctl; netdev->do_ioctl = irda_usb_net_ioctl;
err = register_netdev(netdev); return register_netdev(netdev);
if (err) {
ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
self->netdev = NULL;
free_netdev(netdev);
return err;
}
MESSAGE("IrDA: Registered device %s\n", netdev->name);
return 0;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
...@@ -1213,26 +1176,18 @@ static inline int irda_usb_open(struct irda_usb_cb *self) ...@@ -1213,26 +1176,18 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
* Cleanup the network side of the irda-usb instance * Cleanup the network side of the irda-usb instance
* Called when a USB instance is removed in irda_usb_disconnect() * Called when a USB instance is removed in irda_usb_disconnect()
*/ */
static inline int irda_usb_close(struct irda_usb_cb *self) static inline void irda_usb_close(struct irda_usb_cb *self)
{ {
IRDA_DEBUG(1, "%s()\n", __FUNCTION__); IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
ASSERT(self != NULL, return -1;);
/* Remove netdevice */ /* Remove netdevice */
if (self->netdev) {
unregister_netdev(self->netdev); unregister_netdev(self->netdev);
free_netdev(self->netdev);
self->netdev = NULL;
}
/* Remove the speed buffer */ /* Remove the speed buffer */
if (self->speed_buff != NULL) { if (self->speed_buff != NULL) {
kfree(self->speed_buff); kfree(self->speed_buff);
self->speed_buff = NULL; self->speed_buff = NULL;
} }
return 0;
} }
/********************** USB CONFIG SUBROUTINES **********************/ /********************** USB CONFIG SUBROUTINES **********************/
...@@ -1402,11 +1357,12 @@ static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interf ...@@ -1402,11 +1357,12 @@ static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interf
static int irda_usb_probe(struct usb_interface *intf, static int irda_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct net_device *net;
struct usb_device *dev = interface_to_usbdev(intf); struct usb_device *dev = interface_to_usbdev(intf);
struct irda_usb_cb *self = NULL; struct irda_usb_cb *self = NULL;
struct usb_host_interface *interface; struct usb_host_interface *interface;
struct irda_class_desc *irda_desc; struct irda_class_desc *irda_desc;
int ret; int ret = -ENOMEM;
int i; /* Driver instance index / Rx URB index */ int i; /* Driver instance index / Rx URB index */
/* Note : the probe make sure to call us only for devices that /* Note : the probe make sure to call us only for devices that
...@@ -1418,53 +1374,29 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1418,53 +1374,29 @@ static int irda_usb_probe(struct usb_interface *intf,
dev->devnum, dev->descriptor.idVendor, dev->devnum, dev->descriptor.idVendor,
dev->descriptor.idProduct); dev->descriptor.idProduct);
/* Try to cleanup all instance that have a pending disconnect net = alloc_irdadev(sizeof(*self));
* In theory, it can't happen any longer. if (!net)
* Jean II */ goto err_out;
for (i = 0; i < NIRUSB; i++) {
struct irda_usb_cb *irda = &irda_instance[i];
if((irda->usbdev != NULL) &&
(irda->present == 0) &&
(irda->netopen == 0)) {
IRDA_DEBUG(0, "%s(), found a zombie instance !!!\n", __FUNCTION__);
irda_usb_disconnect(irda->usbintf);
}
}
/* Find an free instance to handle this new device... */ self = net->priv;
self = NULL; self->netdev = net;
for (i = 0; i < NIRUSB; i++) { spin_lock_init(&self->lock);
if(irda_instance[i].usbdev == NULL) {
self = &irda_instance[i];
break;
}
}
if(self == NULL) {
WARNING("Too many USB IrDA devices !!! (max = %d)\n",
NIRUSB);
return -ENFILE;
}
/* Reset the instance */ SET_MODULE_OWNER(net);
self->present = 0;
self->netopen = 0;
/* Create all of the needed urbs */ /* Create all of the needed urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++) { for (i = 0; i < IU_MAX_RX_URBS; i++) {
self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!self->rx_urb[i]) { if (!self->rx_urb[i]) {
ret = -ENOMEM;
goto err_out_1; goto err_out_1;
} }
} }
self->tx_urb = usb_alloc_urb(0, GFP_KERNEL); self->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!self->tx_urb) { if (!self->tx_urb) {
ret = -ENOMEM;
goto err_out_1; goto err_out_1;
} }
self->speed_urb = usb_alloc_urb(0, GFP_KERNEL); self->speed_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!self->speed_urb) { if (!self->speed_urb) {
ret = -ENOMEM;
goto err_out_2; goto err_out_2;
} }
...@@ -1517,13 +1449,27 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1517,13 +1449,27 @@ static int irda_usb_probe(struct usb_interface *intf,
self->capability = id->driver_info; self->capability = id->driver_info;
self->usbdev = dev; self->usbdev = dev;
self->usbintf = intf; self->usbintf = intf;
/* Allocate the buffer for speed changes */
/* Don't change this buffer size and allocation without doing
* some heavy and complete testing. Don't ask why :-(
* Jean II */
self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);
if (self->speed_buff == NULL)
goto err_out_3;
memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);
ret = irda_usb_open(self); ret = irda_usb_open(self);
if (ret) if (ret)
goto err_out_3; goto err_out_4;
MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self); usb_set_intfdata(intf, self);
return 0; return 0;
err_out_4:
kfree(self->speed_buff);
err_out_3: err_out_3:
/* Free all urbs that we may have created */ /* Free all urbs that we may have created */
usb_free_urb(self->speed_urb); usb_free_urb(self->speed_urb);
...@@ -1534,7 +1480,8 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1534,7 +1480,8 @@ static int irda_usb_probe(struct usb_interface *intf,
if (self->rx_urb[i]) if (self->rx_urb[i])
usb_free_urb(self->rx_urb[i]); usb_free_urb(self->rx_urb[i]);
} }
free_netdev(net);
err_out:
return ret; return ret;
} }
...@@ -1602,6 +1549,8 @@ static void irda_usb_disconnect(struct usb_interface *intf) ...@@ -1602,6 +1549,8 @@ static void irda_usb_disconnect(struct usb_interface *intf)
usb_free_urb(self->tx_urb); usb_free_urb(self->tx_urb);
usb_free_urb(self->speed_urb); usb_free_urb(self->speed_urb);
/* Free self and network device */
free_netdev(self->netdev);
IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __FUNCTION__); IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __FUNCTION__);
} }
...@@ -1646,20 +1595,6 @@ module_init(usb_irda_init); ...@@ -1646,20 +1595,6 @@ module_init(usb_irda_init);
*/ */
static void __exit usb_irda_cleanup(void) static void __exit usb_irda_cleanup(void)
{ {
struct irda_usb_cb *irda = NULL;
int i;
/* Find zombie instances and kill them...
* In theory, it can't happen any longer. Jean II */
for (i = 0; i < NIRUSB; i++) {
irda = &irda_instance[i];
/* If the Device is zombie */
if((irda->usbdev != NULL) && (irda->present == 0)) {
IRDA_DEBUG(0, "%s(), disconnect zombie now !\n", __FUNCTION__);
irda_usb_disconnect(irda->usbintf);
}
}
/* Deregister the driver and remove all pending instances */ /* Deregister the driver and remove all pending instances */
usb_deregister(&irda_driver); usb_deregister(&irda_driver);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment