[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