aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c74
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h1
2 files changed, 69 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 5ab3084eb9cb..fde54446973f 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -52,6 +52,9 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
52 { USB_DEVICE(0x083A, 0xA704), 52 { USB_DEVICE(0x083A, 0xA704),
53 .driver_info = AR9280_USB }, /* SMC Networks */ 53 .driver_info = AR9280_USB }, /* SMC Networks */
54 54
55 { USB_DEVICE(0x0cf3, 0x20ff),
56 .driver_info = STORAGE_DEVICE },
57
55 { }, 58 { },
56}; 59};
57 60
@@ -934,6 +937,61 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
934 release_firmware(hif_dev->firmware); 937 release_firmware(hif_dev->firmware);
935} 938}
936 939
940/*
941 * An exact copy of the function from zd1211rw.
942 */
943static int send_eject_command(struct usb_interface *interface)
944{
945 struct usb_device *udev = interface_to_usbdev(interface);
946 struct usb_host_interface *iface_desc = &interface->altsetting[0];
947 struct usb_endpoint_descriptor *endpoint;
948 unsigned char *cmd;
949 u8 bulk_out_ep;
950 int r;
951
952 /* Find bulk out endpoint */
953 for (r = 1; r >= 0; r--) {
954 endpoint = &iface_desc->endpoint[r].desc;
955 if (usb_endpoint_dir_out(endpoint) &&
956 usb_endpoint_xfer_bulk(endpoint)) {
957 bulk_out_ep = endpoint->bEndpointAddress;
958 break;
959 }
960 }
961 if (r == -1) {
962 dev_err(&udev->dev,
963 "ath9k_htc: Could not find bulk out endpoint\n");
964 return -ENODEV;
965 }
966
967 cmd = kzalloc(31, GFP_KERNEL);
968 if (cmd == NULL)
969 return -ENODEV;
970
971 /* USB bulk command block */
972 cmd[0] = 0x55; /* bulk command signature */
973 cmd[1] = 0x53; /* bulk command signature */
974 cmd[2] = 0x42; /* bulk command signature */
975 cmd[3] = 0x43; /* bulk command signature */
976 cmd[14] = 6; /* command length */
977
978 cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
979 cmd[19] = 0x2; /* eject disc */
980
981 dev_info(&udev->dev, "Ejecting storage device...\n");
982 r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
983 cmd, 31, NULL, 2000);
984 kfree(cmd);
985 if (r)
986 return r;
987
988 /* At this point, the device disconnects and reconnects with the real
989 * ID numbers. */
990
991 usb_set_intfdata(interface, NULL);
992 return 0;
993}
994
937static int ath9k_hif_usb_probe(struct usb_interface *interface, 995static int ath9k_hif_usb_probe(struct usb_interface *interface,
938 const struct usb_device_id *id) 996 const struct usb_device_id *id)
939{ 997{
@@ -941,6 +999,9 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
941 struct hif_device_usb *hif_dev; 999 struct hif_device_usb *hif_dev;
942 int ret = 0; 1000 int ret = 0;
943 1001
1002 if (id->driver_info == STORAGE_DEVICE)
1003 return send_eject_command(interface);
1004
944 hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); 1005 hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
945 if (!hif_dev) { 1006 if (!hif_dev) {
946 ret = -ENOMEM; 1007 ret = -ENOMEM;
@@ -1027,12 +1088,13 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
1027 struct hif_device_usb *hif_dev = usb_get_intfdata(interface); 1088 struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
1028 bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; 1089 bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
1029 1090
1030 if (hif_dev) { 1091 if (!hif_dev)
1031 ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); 1092 return;
1032 ath9k_htc_hw_free(hif_dev->htc_handle); 1093
1033 ath9k_hif_usb_dev_deinit(hif_dev); 1094 ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
1034 usb_set_intfdata(interface, NULL); 1095 ath9k_htc_hw_free(hif_dev->htc_handle);
1035 } 1096 ath9k_hif_usb_dev_deinit(hif_dev);
1097 usb_set_intfdata(interface, NULL);
1036 1098
1037 if (!unplugged && (hif_dev->flags & HIF_USB_START)) 1099 if (!unplugged && (hif_dev->flags & HIF_USB_START))
1038 ath9k_hif_usb_reboot(udev); 1100 ath9k_hif_usb_reboot(udev);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 64b226a78b2e..8fa8acfde62e 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -878,6 +878,7 @@
878enum ath_usb_dev { 878enum ath_usb_dev {
879 AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ 879 AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
880 AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ 880 AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
881 STORAGE_DEVICE = 3,
881}; 882};
882 883
883#define AR_DEVID_7010(_ah) \ 884#define AR_DEVID_7010(_ah) \