[Prism54-devel] Avoid Oops with [gs]etoid on other ethernet device

Michael Mueller malware@t-online.de
Sat, 1 Nov 2003 08:38:04 +0100


Hi ppl,

I noticed the dev_put() calls in islpci_mgt are only there because the
originally used dev_get_by_index() does lock the device. So they have to
be removed when using the newly introduced islpci_dev_get_by_index().

The updated patch is attached.

Michael

--- linux-2.4.23-pre9-opti-prism/drivers/net/wireless/prism54/isl_mgt.c	2003-10-31 22:29:49.000000000 +0100
+++ linux-2.4.23-pre9/drivers/net/wireless/prism54/isl_mgt.c	2003-10-31 22:00:26.000000000 +0100
@@ -368,14 +368,18 @@
                 pimfor_decode_header(header, &version, &operation, &oid, &dev_id, &flags, &length);
 				
                 if (version == PIMFOR_VERSION_1) {
-                    
-                    err = mgt_request( DEV_NETWORK, dev_id, pid, seq, operation, oid, data, length );
+                    if ( NULL != islpci_dev_get_by_index(dev_id) )
+                    {
+                        err = mgt_request( DEV_NETWORK, dev_id, pid, seq, operation, oid, data, length );
 
-                    if ( err < 0 ) {
-                        printk(KERN_INFO "ntl_receive: mgt_request returned %d\n", err );
-                        netlink_ack(skb, nl_header, -EOPNOTSUPP );
+                        if ( err < 0 )
+                            printk(KERN_INFO "ntl_receive: mgt_request returned %d\n", err );
                     }
-    
+                    else
+                       err = -EOPNOTSUPP;
+
+                    if ( err < 0 )
+                        netlink_ack(skb, nl_header, -EOPNOTSUPP );
                 } else { 
                     printk(KERN_ERR "ntl_receive: version (%d) != PIMFOR_VERSION_1\n", version );
                     netlink_ack(skb, nl_header, -EOPNOTSUPP );
--- linux-2.4.23-pre9-opti-prism/drivers/net/wireless/prism54/islpci_dev.c	2003-10-31 22:29:49.000000000 +0100
+++ linux-2.4.23-pre9/drivers/net/wireless/prism54/islpci_dev.c	2003-10-31 22:45:59.000000000 +0100
@@ -43,8 +43,7 @@
 ******************************************************************************/
 extern int pc_debug;
 
-struct net_device *root_islpci_device = NULL;
-
+LIST_HEAD(islpci_devlist);	/* List of all devices managed by this code  */
 
 /******************************************************************************
     Device Interrupt Handler
@@ -683,6 +682,7 @@
 
     private_config->my_module = nwdev;
     private_config->pci_device = pci_device;
+    INIT_LIST_HEAD(&private_config->device_list_entry);
 
     // remap the PCI device base address to accessable
     DEBUG(SHOW_TRACING, "%s: private_config->remapped_device_base = ioremap()\n", "prism54");
@@ -829,4 +829,14 @@
     return NULL;
 }
 
+struct net_device * islpci_dev_get_by_index(int idx)
+{
+    islpci_private *pos,*tmp;
+
+    list_for_each_entry_safe(pos, tmp, &islpci_devlist, device_list_entry) {
+        if ( pos->my_module->ifindex == idx )
+        	return pos->my_module;
+    }
 
+    return NULL;
+}
--- linux-2.4.23-pre9-opti-prism/drivers/net/wireless/prism54/islpci_dev.h	2003-10-31 22:29:49.000000000 +0100
+++ linux-2.4.23-pre9/drivers/net/wireless/prism54/islpci_dev.h	2003-11-01 02:05:58.000000000 +0100
@@ -23,6 +23,7 @@
 
 #include <linux/version.h>
 #include <linux/netdevice.h>
+#include <linux/list.h>
 
 #include "isl_38xx.h"
 #ifdef WDS_LINKS
@@ -113,6 +114,8 @@
     struct wds_priv *wdsp;
 #endif
 //    address_entry wds_link_table[ISL38XX_MAX_WDS_LINKS]; // WDS Link table
+
+    struct list_head device_list_entry;
 };
 
 typedef struct net_local    islpci_private;
@@ -135,4 +138,7 @@
 int islpci_free_memory( islpci_private *, int );
 struct net_device * islpci_probe(struct net_device *nwdev, struct pci_dev *pci_device, long ioaddr, int irq);
 
+extern struct list_head islpci_devlist;
+struct net_device * islpci_dev_get_by_index(int);
+
 #endif  // _ISLPCI_DEV_H
--- linux-2.4.23-pre9-opti-prism/drivers/net/wireless/prism54/islpci_hotplug.c	2003-10-31 22:29:49.000000000 +0100
+++ linux-2.4.23-pre9/drivers/net/wireless/prism54/islpci_hotplug.c	2003-10-31 22:47:50.000000000 +0100
@@ -178,6 +178,10 @@
         goto do_pci_release_regions;
     }
 
+    private_config = nw_device->priv;
+
+    list_add(&islpci_devlist, &private_config->device_list_entry);
+
 #ifdef WDS_LINKS
     mgt_indication_handler ( DEV_NETWORK, nw_device->ifindex, DOT11_OID_WDSLINKADD, islpci_wdslink_add_hndl );
     mgt_indication_handler ( DEV_NETWORK, nw_device->ifindex, DOT11_OID_WDSLINKREMOVE, islpci_wdslink_del_hndl );
@@ -186,7 +190,6 @@
     // save the interrupt request line and use the remapped device base address
     // as the device identification both for uniqueness and parameter passing
     // to the interrupt handler
-    private_config = nw_device->priv;
     private_config->pci_irq = irq;
     private_config->pci_dev_id = dev_id;
     private_config->device_id = private_config->remapped_device_base;
@@ -234,6 +237,7 @@
     DEBUG(SHOW_TRACING, "%s: free_irq(irq, private_config)\n", DRIVER_NAME);
     free_irq(irq, private_config);
 do_unregister_netdev:
+    list_del(&private_config->device_list_entry);
     //??? next_dev = private_config->next_module;
     DEBUG(SHOW_TRACING, "%s: unregister_netdev(nw_device)\n", DRIVER_NAME);
     unregister_netdev(nw_device);
@@ -273,6 +277,7 @@
     if (!private_config)
       BUG();
 
+    list_del(&private_config->device_list_entry);
     unregister_netdev (ndev);
 
     // free the interrupt request
--- linux-2.4.23-pre9-opti-prism/drivers/net/wireless/prism54/islpci_mgt.c	2003-10-31 22:29:49.000000000 +0100
+++ linux-2.4.23-pre9/drivers/net/wireless/prism54/islpci_mgt.c	2003-11-01 01:35:32.000000000 +0100
@@ -1116,10 +1116,9 @@
     int err = 0;
     int operation;
     printk("islpci_mgt_indication: Seeking dev for dev_seq %d\n", dev_seq);
-    if ( ! (dev = dev_get_by_index(dev_seq)) )
+    if ( ! (dev = islpci_dev_get_by_index(dev_seq)) )
         return -1;
-	dev_put( dev );
-	
+
     private_config = dev->priv;
     
     islpci_mgt_queue(private_config, op, oid, 0, data, len, 0);
@@ -1167,9 +1166,8 @@
     if ( len != sizeof(struct wds_link_msg)) 
         return -1;
     
-    if ( ! (dev = dev_get_by_index(dev_seq)) )
+    if ( ! (dev = islpci_dev_get_by_index(dev_seq)) )
         return -1;
-	dev_put( dev );
 
     private_config = dev->priv;
 
@@ -1213,9 +1211,8 @@
     if ( len != sizeof(struct wds_link_msg)) 
         return -1;
     
-    if ( ! (dev = dev_get_by_index(dev_seq)) )
+    if ( ! (dev = islpci_dev_get_by_index(dev_seq)) )
         return -1;
-	dev_put( dev );
 
     private_config = dev->priv;
 
@@ -1297,9 +1294,8 @@
     int err = 0;
     int operation;
 printk("Find dev_get_by_index(%d)\n", dev_seq);
-    if ( ! (dev = dev_get_by_index(dev_seq)) )
+    if ( ! (dev = islpci_dev_get_by_index(dev_seq)) )
         return -1;
-	dev_put( dev );
 
     private_config = dev->priv;