[PATCH] libertas: fix RESET logic at unload time

Dan Williams dcbw at redhat.com
Sat Mar 17 00:56:50 EDT 2007


On Sat, 2007-02-24 at 21:19 +0100, Holger Schurig wrote:
> Previously, we had a fixed array of 5 elements where we remembered all
> initialized devices. This has been changed to use a "struct list_head"
> organization, which is IMHO cleaner.
> 
> Also renamed usb_cardp to cardp, as in the reset of the code.
> 
> Renamed reset_device() to if_usb_reset_device() like many other functions.

Applied.

> Signed-off-by: Holger Schurig <hs4233 at mail.mn-solutions.de>
> ---
>  drivers/net/wireless/libertas/if_usb.c |   87 ++++++++++++++------------------
>  drivers/net/wireless/libertas/if_usb.h |    7 +++
>  2 files changed, 45 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
> index d19b390..d9c2844 100644
> --- a/drivers/net/wireless/libertas/if_usb.c
> +++ b/drivers/net/wireless/libertas/if_usb.c
> @@ -5,6 +5,7 @@
>  #include <linux/moduleparam.h>
>  #include <linux/firmware.h>
>  #include <linux/netdevice.h>
> +#include <linux/list.h>
>  #include <linux/usb.h>
>  
>  #include "host.h"
> @@ -21,10 +22,14 @@ static u8 *default_fw_name = "usb8388.bin";
>  char *libertas_fw_name = NULL;
>  module_param_named(fw_name, libertas_fw_name, charp, 0644);
>  
> -
> -#define MAX_DEVS 5
> -static struct net_device *libertas_devs[MAX_DEVS];
> -static int libertas_found = 0;
> +/*
> + * We need to send a RESET command to all USB devices before
> + * we tear down the USB connection. Otherwise we would not
> + * be able to re-init device the device if the module get's
> + * loaded again. This is a list of all initialized USB devices,
> + * for the reset code see if_usb_reset_device()
> +*/
> +static LIST_HEAD(usb_devices);
>  
>  static struct usb_device_id if_usb_table[] = {
>  	/* Enter the device signature inside */
> @@ -37,7 +42,7 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
>  
>  static void if_usb_receive(struct urb *urb);
>  static void if_usb_receive_fwload(struct urb *urb);
> -static int reset_device(wlan_private *priv);
> +static int if_usb_reset_device(wlan_private *priv);
>  static int if_usb_register_dev(wlan_private * priv);
>  static int if_usb_unregister_dev(wlan_private *);
>  static int if_usb_prog_firmware(wlan_private *);
> @@ -116,18 +121,17 @@ static int if_usb_probe(struct usb_interface *intf,
>  	struct usb_host_interface *iface_desc;
>  	struct usb_endpoint_descriptor *endpoint;
>  	wlan_private *priv = NULL;
> -	struct usb_card_rec *usb_cardp;
> +	struct usb_card_rec *cardp;
>  	int i;
>  
>  	udev = interface_to_usbdev(intf);
>  
> -	usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
> -	if (!usb_cardp) {
> +	cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
> +	if (!cardp) {
>  		lbs_pr_err("Out of memory allocating private data.\n");
>  		goto error;
>  	}
> -
> -	usb_cardp->udev = udev;
> +	cardp->udev = udev;
>  	iface_desc = intf->cur_altsetting;
>  
>  	lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
> @@ -146,17 +150,17 @@ static int if_usb_probe(struct usb_interface *intf,
>  			lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n",
>  			       endpoint->wMaxPacketSize);
>  			if (!
> -			    (usb_cardp->rx_urb =
> +			    (cardp->rx_urb =
>  			     usb_alloc_urb(0, GFP_KERNEL))) {
>  				lbs_deb_usbd(&udev->dev,
>  				       "Rx URB allocation failed\n");
>  				goto dealloc;
>  			}
> -			usb_cardp->rx_urb_recall = 0;
> +			cardp->rx_urb_recall = 0;
>  
> -			usb_cardp->bulk_in_size =
> +			cardp->bulk_in_size =
>  			    endpoint->wMaxPacketSize;
> -			usb_cardp->bulk_in_endpointAddr =
> +			cardp->bulk_in_endpointAddr =
>  			    (endpoint->
>  			     bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
>  			lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n",
> @@ -170,27 +174,27 @@ static int if_usb_probe(struct usb_interface *intf,
>  			USB_ENDPOINT_XFER_BULK)) {
>  			/* We found bulk out endpoint */
>  			if (!
> -			    (usb_cardp->tx_urb =
> +			    (cardp->tx_urb =
>  			     usb_alloc_urb(0, GFP_KERNEL))) {
>  				lbs_deb_usbd(&udev->dev,
>  				       "Tx URB allocation failed\n");
>  				goto dealloc;
>  			}
>  
> -			usb_cardp->bulk_out_size =
> +			cardp->bulk_out_size =
>  			    endpoint->wMaxPacketSize;
>  			lbs_deb_usbd(&udev->dev,
>  				    "Bulk out size is %d\n",
>  				    endpoint->wMaxPacketSize);
> -			usb_cardp->bulk_out_endpointAddr =
> +			cardp->bulk_out_endpointAddr =
>  			    endpoint->bEndpointAddress;
>  			lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n",
>  				    endpoint->bEndpointAddress);
> -			usb_cardp->bulk_out_buffer =
> +			cardp->bulk_out_buffer =
>  			    kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
>  				    GFP_KERNEL);
>  
> -			if (!usb_cardp->bulk_out_buffer) {
> +			if (!cardp->bulk_out_buffer) {
>  				lbs_deb_usbd(&udev->dev,
>  				       "Could not allocate buffer\n");
>  				goto dealloc;
> @@ -203,7 +207,7 @@ static int if_usb_probe(struct usb_interface *intf,
>  	 * about keeping priv around since it will be set on our
>  	 * usb device data in -> add() -> hw_register_dev() -> if_usb_register_dev.
>  	 */
> -	if (!(priv = libertas_add_card(usb_cardp)))
> +	if (!(priv = libertas_add_card(cardp)))
>  		goto dealloc;
>  
>  	priv->hw_register_dev = if_usb_register_dev;
> @@ -216,29 +220,21 @@ static int if_usb_probe(struct usb_interface *intf,
>  	if (libertas_activate_card(priv, libertas_fw_name))
>  		goto dealloc;
>  
> -	if (libertas_found < MAX_DEVS) {
> -		libertas_devs[libertas_found] = priv->wlan_dev.netdev;
> -		libertas_found++;
> -	}
> -
>  	/* TODO: check somehow if the firmware is mesh-capable */
>  	if (libertas_add_mesh(priv))
>  		goto dealloc;
>  
> +	list_add_tail(&cardp->list, &usb_devices);
> +
>  	usb_get_dev(udev);
> -	usb_set_intfdata(intf, usb_cardp);
> +	usb_set_intfdata(intf, cardp);
>  
> -	/* 
> -	 * return card structure, which can be got back in the 
> -	 * diconnect function as the ptr
> -	 * argument.
> -	 */
>  	return 0;
>  
>  dealloc:
>  	libertas_remove_mesh(priv);
>  	libertas_remove_card(priv);
> -	if_usb_free(usb_cardp);
> +	if_usb_free(cardp);
>  
>  error:
>  	return -ENOMEM;
> @@ -246,8 +242,7 @@ error:
>  
>  /** 
>   *  @brief free resource and cleanup
> - *  @param udev		pointer to usb_device
> - *  @param ptr		pointer to usb_cardp
> + *  @param intf		USB interface structure
>   *  @return 	   	N/A
>   */
>  static void if_usb_disconnect(struct usb_interface *intf)
> @@ -255,7 +250,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
>  	struct usb_card_rec *cardp = usb_get_intfdata(intf);
>  	wlan_private *priv = (wlan_private *) cardp->priv;
>  	wlan_adapter *adapter = NULL;
> -	int i;
>  
>  	adapter = priv->adapter;
>  
> @@ -264,13 +258,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
>  	 */
>  	adapter->surpriseremoved = 1;
>  
> -	for (i = 0; i<libertas_found; i++) {
> -		if (libertas_devs[i]==priv->wlan_dev.netdev) {
> -			libertas_devs[i] = libertas_devs[--libertas_found];
> -			libertas_devs[libertas_found] = NULL;
> -			break;
> -		}
> -	}
> +	list_del(&cardp->list);
>  
>  	/* card is removed and we can call wlan_remove_card */
>  	lbs_deb_usbd(&cardp->udev->dev, "call remove card\n");
> @@ -377,7 +365,7 @@ static int libertas_do_reset(wlan_private *priv)
>  	ret = usb_reset_device(cardp->udev);
>  	if (!ret) {
>  		msleep(10);
> -		reset_device(priv);
> +		if_usb_reset_device(priv);
>  		msleep(10);
>  	}
>  
> @@ -764,7 +752,7 @@ static int if_usb_read_event_cause(wlan_private * priv)
>  	return 0;
>  }
>  
> -static int reset_device(wlan_private *priv)
> +static int if_usb_reset_device(wlan_private *priv)
>  {
>  	int ret;
>  
> @@ -787,7 +775,7 @@ static int if_usb_unregister_dev(wlan_private * priv)
>  	 * again.
>  	 */
>  	if (priv)
> -		reset_device(priv);
> +		if_usb_reset_device(priv);
>  
>  	return ret;
>  }
> @@ -977,13 +965,14 @@ static int if_usb_init_module(void)
>  
>  static void if_usb_exit_module(void)
>  {
> -	int i;
> +	struct list_head *ptr;
> +	struct usb_card_rec *cardp;
>  
>  	lbs_deb_enter(LBS_DEB_MAIN);
>  
> -	for (i = 0; i<libertas_found; i++) {
> -		wlan_private *priv = libertas_devs[i]->priv;
> -		reset_device(priv);
> +	list_for_each(ptr, &usb_devices) {
> +		cardp = list_entry(ptr, struct usb_card_rec, list);
> +		if_usb_reset_device((wlan_private *) cardp->priv);
>  	}
>  
>  	/* API unregisters the driver from USB subsystem */
> diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
> index 5935989..52666f6 100644
> --- a/drivers/net/wireless/libertas/if_usb.h
> +++ b/drivers/net/wireless/libertas/if_usb.h
> @@ -1,3 +1,8 @@
> +#ifndef _LIBERTAS_IF_USB_H
> +#define _LIBERTAS_IF_USB_H
> +
> +#include <linux/list.h>
> +
>  /** 
>    * This file contains definition for USB interface.
>    */
> @@ -39,6 +44,7 @@ struct read_cb_info {
>  
>  /** USB card description structure*/
>  struct usb_card_rec {
> +	struct list_head list;
>  	struct net_device *eth_dev;
>  	struct usb_device *udev;
>  	struct urb *rx_urb, *tx_urb;
> @@ -100,3 +106,4 @@ int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
>  void if_usb_free(struct usb_card_rec *cardp);
>  int if_usb_issue_boot_command(wlan_private *priv, int ivalue);
>  
> +#endif




More information about the libertas-dev mailing list