diff options
author | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-09-16 20:53:57 -0400 |
---|---|---|
committer | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-10-19 02:56:06 -0400 |
commit | 8f90f3ee83dc54e182d6a7548727cbae4b523e6e (patch) | |
tree | 8a81fd0076562a5c6e30a652c63fa25343783dc6 /drivers | |
parent | ac53aed9349242095a780f57ac0c995fb170c950 (diff) |
wimax/i2400m: cleanup initialization/destruction flow
Currently the i2400m driver was starting in a weird way: registering a
network device, setting the device up and then registering a WiMAX
device.
This is an historic artifact, and was causing issues, a some early
reports the device sends were getting lost by issue of the wimax_dev
not being registered.
Fix said situation by doing the wimax device registration in
i2400m_setup() after network device registration and before starting
thed device.
As well, removed spurious setting of the state to UNINITIALIZED;
i2400m.dev_start() does that already.
Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 32 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/i2400m.h | 30 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/netdev.c | 10 |
3 files changed, 41 insertions, 31 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index a33df0431020..a0ae19966c0c 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -754,13 +754,9 @@ EXPORT_SYMBOL_GPL(i2400m_bm_buf_free | |||
754 | * | 754 | * |
755 | * Returns: 0 if ok, < 0 errno code on error. | 755 | * Returns: 0 if ok, < 0 errno code on error. |
756 | * | 756 | * |
757 | * Initializes the bus-generic parts of the i2400m driver; the | 757 | * Sets up basic device comunication infrastructure, boots the ROM to |
758 | * bus-specific parts have been initialized, function pointers filled | 758 | * read the MAC address, registers with the WiMAX and network stacks |
759 | * out by the bus-specific probe function. | 759 | * and then brings up the device. |
760 | * | ||
761 | * As well, this registers the WiMAX and net device nodes. Once this | ||
762 | * function returns, the device is operative and has to be ready to | ||
763 | * receive and send network traffic and WiMAX control operations. | ||
764 | */ | 760 | */ |
765 | int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | 761 | int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) |
766 | { | 762 | { |
@@ -796,18 +792,13 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | |||
796 | } | 792 | } |
797 | netif_carrier_off(net_dev); | 793 | netif_carrier_off(net_dev); |
798 | 794 | ||
799 | result = i2400m_dev_start(i2400m, bm_flags); | ||
800 | if (result < 0) | ||
801 | goto error_dev_start; | ||
802 | |||
803 | i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user; | 795 | i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user; |
804 | i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle; | 796 | i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle; |
805 | i2400m->wimax_dev.op_reset = i2400m_op_reset; | 797 | i2400m->wimax_dev.op_reset = i2400m_op_reset; |
798 | |||
806 | result = wimax_dev_add(&i2400m->wimax_dev, net_dev); | 799 | result = wimax_dev_add(&i2400m->wimax_dev, net_dev); |
807 | if (result < 0) | 800 | if (result < 0) |
808 | goto error_wimax_dev_add; | 801 | goto error_wimax_dev_add; |
809 | /* User space needs to do some init stuff */ | ||
810 | wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); | ||
811 | 802 | ||
812 | /* Now setup all that requires a registered net and wimax device. */ | 803 | /* Now setup all that requires a registered net and wimax device. */ |
813 | result = sysfs_create_group(&net_dev->dev.kobj, &i2400m_dev_attr_group); | 804 | result = sysfs_create_group(&net_dev->dev.kobj, &i2400m_dev_attr_group); |
@@ -815,22 +806,27 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | |||
815 | dev_err(dev, "cannot setup i2400m's sysfs: %d\n", result); | 806 | dev_err(dev, "cannot setup i2400m's sysfs: %d\n", result); |
816 | goto error_sysfs_setup; | 807 | goto error_sysfs_setup; |
817 | } | 808 | } |
809 | |||
818 | result = i2400m_debugfs_add(i2400m); | 810 | result = i2400m_debugfs_add(i2400m); |
819 | if (result < 0) { | 811 | if (result < 0) { |
820 | dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); | 812 | dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); |
821 | goto error_debugfs_setup; | 813 | goto error_debugfs_setup; |
822 | } | 814 | } |
815 | |||
816 | result = i2400m_dev_start(i2400m, bm_flags); | ||
817 | if (result < 0) | ||
818 | goto error_dev_start; | ||
823 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | 819 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); |
824 | return result; | 820 | return result; |
825 | 821 | ||
822 | error_dev_start: | ||
823 | i2400m_debugfs_rm(i2400m); | ||
826 | error_debugfs_setup: | 824 | error_debugfs_setup: |
827 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, | 825 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, |
828 | &i2400m_dev_attr_group); | 826 | &i2400m_dev_attr_group); |
829 | error_sysfs_setup: | 827 | error_sysfs_setup: |
830 | wimax_dev_rm(&i2400m->wimax_dev); | 828 | wimax_dev_rm(&i2400m->wimax_dev); |
831 | error_wimax_dev_add: | 829 | error_wimax_dev_add: |
832 | i2400m_dev_stop(i2400m); | ||
833 | error_dev_start: | ||
834 | unregister_netdev(net_dev); | 830 | unregister_netdev(net_dev); |
835 | error_register_netdev: | 831 | error_register_netdev: |
836 | unregister_pm_notifier(&i2400m->pm_notifier); | 832 | unregister_pm_notifier(&i2400m->pm_notifier); |
@@ -854,15 +850,15 @@ void i2400m_release(struct i2400m *i2400m) | |||
854 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | 850 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); |
855 | netif_stop_queue(i2400m->wimax_dev.net_dev); | 851 | netif_stop_queue(i2400m->wimax_dev.net_dev); |
856 | 852 | ||
853 | i2400m_dev_stop(i2400m); | ||
854 | |||
857 | i2400m_debugfs_rm(i2400m); | 855 | i2400m_debugfs_rm(i2400m); |
858 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, | 856 | sysfs_remove_group(&i2400m->wimax_dev.net_dev->dev.kobj, |
859 | &i2400m_dev_attr_group); | 857 | &i2400m_dev_attr_group); |
860 | wimax_dev_rm(&i2400m->wimax_dev); | 858 | wimax_dev_rm(&i2400m->wimax_dev); |
861 | i2400m_dev_stop(i2400m); | ||
862 | unregister_netdev(i2400m->wimax_dev.net_dev); | 859 | unregister_netdev(i2400m->wimax_dev.net_dev); |
863 | unregister_pm_notifier(&i2400m->pm_notifier); | 860 | unregister_pm_notifier(&i2400m->pm_notifier); |
864 | kfree(i2400m->bm_ack_buf); | 861 | i2400m_bm_buf_free(i2400m); |
865 | kfree(i2400m->bm_cmd_buf); | ||
866 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | 862 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); |
867 | } | 863 | } |
868 | EXPORT_SYMBOL_GPL(i2400m_release); | 864 | EXPORT_SYMBOL_GPL(i2400m_release); |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 303eb78bce32..2b9c400810b5 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -117,16 +117,28 @@ | |||
117 | * well as i2400m->wimax_dev.net_dev and call i2400m_setup(). The | 117 | * well as i2400m->wimax_dev.net_dev and call i2400m_setup(). The |
118 | * i2400m driver will only register with the WiMAX and network stacks; | 118 | * i2400m driver will only register with the WiMAX and network stacks; |
119 | * the only access done to the device is to read the MAC address so we | 119 | * the only access done to the device is to read the MAC address so we |
120 | * can register a network device. This calls i2400m_dev_start() to | 120 | * can register a network device. |
121 | * load firmware, setup communication with the device and configure it | ||
122 | * for operation. | ||
123 | * | 121 | * |
124 | * At this point, control and data communications are possible. | 122 | * The high-level call flow is: |
123 | * | ||
124 | * bus_probe() | ||
125 | * i2400m_setup() | ||
126 | * boot rom initialization / read mac addr | ||
127 | * network / WiMAX stacks registration | ||
128 | * i2400m_dev_start() | ||
129 | * i2400m->bus_dev_start() | ||
130 | * i2400m_dev_initialize() | ||
131 | * | ||
132 | * The reverse applies for a disconnect() call: | ||
125 | * | 133 | * |
126 | * On disconnect/driver unload, the bus-specific disconnect function | 134 | * bus_disconnect() |
127 | * calls i2400m_release() to undo i2400m_setup(). i2400m_dev_stop() | 135 | * i2400m_release() |
128 | * shuts the firmware down and releases resources uses to communicate | 136 | * i2400m_dev_stop() |
129 | * with the device. | 137 | * i2400m_dev_shutdown() |
138 | * i2400m->bus_dev_stop() | ||
139 | * network / WiMAX stack unregistration | ||
140 | * | ||
141 | * At this point, control and data communications are possible. | ||
130 | * | 142 | * |
131 | * While the device is up, it might reset. The bus-specific driver has | 143 | * While the device is up, it might reset. The bus-specific driver has |
132 | * to catch that situation and call i2400m_dev_reset_handle() to deal | 144 | * to catch that situation and call i2400m_dev_reset_handle() to deal |
@@ -706,7 +718,7 @@ static inline int i2400m_debugfs_add(struct i2400m *i2400m) | |||
706 | static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {} | 718 | static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {} |
707 | #endif | 719 | #endif |
708 | 720 | ||
709 | /* Called by _dev_start()/_dev_stop() to initialize the device itself */ | 721 | /* Initialize/shutdown the device */ |
710 | extern int i2400m_dev_initialize(struct i2400m *); | 722 | extern int i2400m_dev_initialize(struct i2400m *); |
711 | extern void i2400m_dev_shutdown(struct i2400m *); | 723 | extern void i2400m_dev_shutdown(struct i2400m *); |
712 | 724 | ||
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 0e8f6a046b9b..fefd794087ad 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c | |||
@@ -102,11 +102,13 @@ int i2400m_open(struct net_device *net_dev) | |||
102 | struct device *dev = i2400m_dev(i2400m); | 102 | struct device *dev = i2400m_dev(i2400m); |
103 | 103 | ||
104 | d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); | 104 | d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); |
105 | if (i2400m->ready == 0) { | 105 | /* Make sure we wait until init is complete... */ |
106 | dev_err(dev, "Device is still initializing\n"); | 106 | mutex_lock(&i2400m->init_mutex); |
107 | result = -EBUSY; | 107 | if (i2400m->updown) |
108 | } else | ||
109 | result = 0; | 108 | result = 0; |
109 | else | ||
110 | result = -EBUSY; | ||
111 | mutex_unlock(&i2400m->init_mutex); | ||
110 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", | 112 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", |
111 | net_dev, i2400m, result); | 113 | net_dev, i2400m, result); |
112 | return result; | 114 | return result; |