aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2012-03-17 16:16:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-09 16:07:35 -0400
commit5612a508d11f81c1ca3290260f86328dfb55d513 (patch)
tree8ff5d03365b9f7e7a0534c577d504b6bc757eabf
parenta9b9361dd5ef6c39703f2f0c8c18aa2e1f133fc5 (diff)
p54usb: Load firmware asynchronously
Drivers that load firmware from their probe routine have problems with the latest versions of udev as they get timeouts while waiting for user space to start. The problem is fixed by using request_firmware_nowait() and delaying the start of mac80211 until the firmware is loaded. To prevent the possibility of the driver being unloaded while the firmware loading callback is still active, a completion queue entry is used. Also, to simplify the firmware loading procedure, this patch removes the old, unofficial and confusing fallback firmware names. However, they are still supported! So any user - who is still using them - is hereby advised to link/rename their old firmware filenames: isl3890usb to isl3886usb isl3887usb_bare to isl3887usb Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/p54/p54usb.c195
-rw-r--r--drivers/net/wireless/p54/p54usb.h3
2 files changed, 130 insertions, 68 deletions
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index f4d28c39aac7..bac3d03f5786 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -117,21 +117,18 @@ static const struct {
117 u32 intf; 117 u32 intf;
118 enum p54u_hw_type type; 118 enum p54u_hw_type type;
119 const char *fw; 119 const char *fw;
120 const char *fw_legacy;
121 char hw[20]; 120 char hw[20];
122} p54u_fwlist[__NUM_P54U_HWTYPES] = { 121} p54u_fwlist[__NUM_P54U_HWTYPES] = {
123 { 122 {
124 .type = P54U_NET2280, 123 .type = P54U_NET2280,
125 .intf = FW_LM86, 124 .intf = FW_LM86,
126 .fw = "isl3886usb", 125 .fw = "isl3886usb",
127 .fw_legacy = "isl3890usb",
128 .hw = "ISL3886 + net2280", 126 .hw = "ISL3886 + net2280",
129 }, 127 },
130 { 128 {
131 .type = P54U_3887, 129 .type = P54U_3887,
132 .intf = FW_LM87, 130 .intf = FW_LM87,
133 .fw = "isl3887usb", 131 .fw = "isl3887usb",
134 .fw_legacy = "isl3887usb_bare",
135 .hw = "ISL3887", 132 .hw = "ISL3887",
136 }, 133 },
137}; 134};
@@ -208,6 +205,16 @@ static void p54u_free_urbs(struct ieee80211_hw *dev)
208 usb_kill_anchored_urbs(&priv->submitted); 205 usb_kill_anchored_urbs(&priv->submitted);
209} 206}
210 207
208static void p54u_stop(struct ieee80211_hw *dev)
209{
210 /*
211 * TODO: figure out how to reliably stop the 3887 and net2280 so
212 * the hardware is still usable next time we want to start it.
213 * until then, we just stop listening to the hardware..
214 */
215 p54u_free_urbs(dev);
216}
217
211static int p54u_init_urbs(struct ieee80211_hw *dev) 218static int p54u_init_urbs(struct ieee80211_hw *dev)
212{ 219{
213 struct p54u_priv *priv = dev->priv; 220 struct p54u_priv *priv = dev->priv;
@@ -257,6 +264,16 @@ static int p54u_init_urbs(struct ieee80211_hw *dev)
257 return ret; 264 return ret;
258} 265}
259 266
267static int p54u_open(struct ieee80211_hw *dev)
268{
269 /*
270 * TODO: Because we don't know how to reliably stop the 3887 and
271 * the isl3886+net2280, other than brutally cut off all
272 * communications. We have to reinitialize the urbs on every start.
273 */
274 return p54u_init_urbs(dev);
275}
276
260static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) 277static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
261{ 278{
262 u32 chk = 0; 279 u32 chk = 0;
@@ -836,70 +853,137 @@ fail:
836 return err; 853 return err;
837} 854}
838 855
839static int p54u_load_firmware(struct ieee80211_hw *dev) 856static int p54_find_type(struct p54u_priv *priv)
840{ 857{
841 struct p54u_priv *priv = dev->priv; 858 int i;
842 int err, i;
843
844 BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
845 859
846 for (i = 0; i < __NUM_P54U_HWTYPES; i++) 860 for (i = 0; i < __NUM_P54U_HWTYPES; i++)
847 if (p54u_fwlist[i].type == priv->hw_type) 861 if (p54u_fwlist[i].type == priv->hw_type)
848 break; 862 break;
849
850 if (i == __NUM_P54U_HWTYPES) 863 if (i == __NUM_P54U_HWTYPES)
851 return -EOPNOTSUPP; 864 return -EOPNOTSUPP;
852 865
853 err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev); 866 return i;
854 if (err) { 867}
855 dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
856 "(%d)!\n", p54u_fwlist[i].fw, err);
857 868
858 err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy, 869static int p54u_start_ops(struct p54u_priv *priv)
859 &priv->udev->dev); 870{
860 if (err) 871 struct ieee80211_hw *dev = priv->common.hw;
861 return err; 872 int ret;
862 }
863 873
864 err = p54_parse_firmware(dev, priv->fw); 874 ret = p54_parse_firmware(dev, priv->fw);
865 if (err) 875 if (ret)
866 goto out; 876 goto err_out;
877
878 ret = p54_find_type(priv);
879 if (ret < 0)
880 goto err_out;
867 881
868 if (priv->common.fw_interface != p54u_fwlist[i].intf) { 882 if (priv->common.fw_interface != p54u_fwlist[ret].intf) {
869 dev_err(&priv->udev->dev, "wrong firmware, please get " 883 dev_err(&priv->udev->dev, "wrong firmware, please get "
870 "a firmware for \"%s\" and try again.\n", 884 "a firmware for \"%s\" and try again.\n",
871 p54u_fwlist[i].hw); 885 p54u_fwlist[ret].hw);
872 err = -EINVAL; 886 ret = -ENODEV;
887 goto err_out;
873 } 888 }
874 889
875out: 890 ret = priv->upload_fw(dev);
876 if (err) 891 if (ret)
877 release_firmware(priv->fw); 892 goto err_out;
878 893
879 return err; 894 ret = p54u_open(dev);
895 if (ret)
896 goto err_out;
897
898 ret = p54_read_eeprom(dev);
899 if (ret)
900 goto err_stop;
901
902 p54u_stop(dev);
903
904 ret = p54_register_common(dev, &priv->udev->dev);
905 if (ret)
906 goto err_stop;
907
908 return 0;
909
910err_stop:
911 p54u_stop(dev);
912
913err_out:
914 /*
915 * p54u_disconnect will do the rest of the
916 * cleanup
917 */
918 return ret;
880} 919}
881 920
882static int p54u_open(struct ieee80211_hw *dev) 921static void p54u_load_firmware_cb(const struct firmware *firmware,
922 void *context)
883{ 923{
884 struct p54u_priv *priv = dev->priv; 924 struct p54u_priv *priv = context;
925 struct usb_device *udev = priv->udev;
885 int err; 926 int err;
886 927
887 err = p54u_init_urbs(dev); 928 complete(&priv->fw_wait_load);
888 if (err) { 929 if (firmware) {
889 return err; 930 priv->fw = firmware;
931 err = p54u_start_ops(priv);
932 } else {
933 err = -ENOENT;
934 dev_err(&udev->dev, "Firmware not found.\n");
890 } 935 }
891 936
892 priv->common.open = p54u_init_urbs; 937 if (err) {
938 struct device *parent = priv->udev->dev.parent;
893 939
894 return 0; 940 dev_err(&udev->dev, "failed to initialize device (%d)\n", err);
941
942 if (parent)
943 device_lock(parent);
944
945 device_release_driver(&udev->dev);
946 /*
947 * At this point p54u_disconnect has already freed
948 * the "priv" context. Do not use it anymore!
949 */
950 priv = NULL;
951
952 if (parent)
953 device_unlock(parent);
954 }
955
956 usb_put_dev(udev);
895} 957}
896 958
897static void p54u_stop(struct ieee80211_hw *dev) 959static int p54u_load_firmware(struct ieee80211_hw *dev,
960 struct usb_interface *intf)
898{ 961{
899 /* TODO: figure out how to reliably stop the 3887 and net2280 so 962 struct usb_device *udev = interface_to_usbdev(intf);
900 the hardware is still usable next time we want to start it. 963 struct p54u_priv *priv = dev->priv;
901 until then, we just stop listening to the hardware.. */ 964 struct device *device = &udev->dev;
902 p54u_free_urbs(dev); 965 int err, i;
966
967 BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES);
968
969 init_completion(&priv->fw_wait_load);
970 i = p54_find_type(priv);
971 if (i < 0)
972 return i;
973
974 dev_info(&priv->udev->dev, "Loading firmware file %s\n",
975 p54u_fwlist[i].fw);
976
977 usb_get_dev(udev);
978 err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw,
979 device, GFP_KERNEL, priv,
980 p54u_load_firmware_cb);
981 if (err) {
982 dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
983 "(%d)!\n", p54u_fwlist[i].fw, err);
984 }
985
986 return err;
903} 987}
904 988
905static int __devinit p54u_probe(struct usb_interface *intf, 989static int __devinit p54u_probe(struct usb_interface *intf,
@@ -969,33 +1053,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
969 priv->common.tx = p54u_tx_net2280; 1053 priv->common.tx = p54u_tx_net2280;
970 priv->upload_fw = p54u_upload_firmware_net2280; 1054 priv->upload_fw = p54u_upload_firmware_net2280;
971 } 1055 }
972 err = p54u_load_firmware(dev); 1056 err = p54u_load_firmware(dev, intf);
973 if (err)
974 goto err_free_dev;
975
976 err = priv->upload_fw(dev);
977 if (err)
978 goto err_free_fw;
979
980 p54u_open(dev);
981 err = p54_read_eeprom(dev);
982 p54u_stop(dev);
983 if (err)
984 goto err_free_fw;
985
986 err = p54_register_common(dev, &udev->dev);
987 if (err)
988 goto err_free_fw;
989
990 return 0;
991
992err_free_fw:
993 release_firmware(priv->fw);
994
995err_free_dev:
996 p54_free_common(dev);
997 usb_set_intfdata(intf, NULL);
998 usb_put_dev(udev);
999 return err; 1057 return err;
1000} 1058}
1001 1059
@@ -1007,9 +1065,10 @@ static void __devexit p54u_disconnect(struct usb_interface *intf)
1007 if (!dev) 1065 if (!dev)
1008 return; 1066 return;
1009 1067
1068 priv = dev->priv;
1069 wait_for_completion(&priv->fw_wait_load);
1010 p54_unregister_common(dev); 1070 p54_unregister_common(dev);
1011 1071
1012 priv = dev->priv;
1013 usb_put_dev(interface_to_usbdev(intf)); 1072 usb_put_dev(interface_to_usbdev(intf));
1014 release_firmware(priv->fw); 1073 release_firmware(priv->fw);
1015 p54_free_common(dev); 1074 p54_free_common(dev);
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index ed4034ade59a..d273be7272b9 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -143,6 +143,9 @@ struct p54u_priv {
143 struct sk_buff_head rx_queue; 143 struct sk_buff_head rx_queue;
144 struct usb_anchor submitted; 144 struct usb_anchor submitted;
145 const struct firmware *fw; 145 const struct firmware *fw;
146
147 /* asynchronous firmware callback */
148 struct completion fw_wait_load;
146}; 149};
147 150
148#endif /* P54USB_H */ 151#endif /* P54USB_H */