123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2021 pureLiFi
- */
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/device.h>
- #include <linux/errno.h>
- #include <linux/slab.h>
- #include <linux/skbuff.h>
- #include <linux/usb.h>
- #include <linux/workqueue.h>
- #include <linux/proc_fs.h>
- #include <linux/fs.h>
- #include <linux/string.h>
- #include <linux/module.h>
- #include <net/mac80211.h>
- #include <asm/unaligned.h>
- #include <linux/sysfs.h>
- #include "mac.h"
- #include "usb.h"
- #include "chip.h"
- static const struct usb_device_id usb_ids[] = {
- { USB_DEVICE(PURELIFI_X_VENDOR_ID_0, PURELIFI_X_PRODUCT_ID_0),
- .driver_info = DEVICE_LIFI_X },
- { USB_DEVICE(PURELIFI_XC_VENDOR_ID_0, PURELIFI_XC_PRODUCT_ID_0),
- .driver_info = DEVICE_LIFI_XC },
- { USB_DEVICE(PURELIFI_XL_VENDOR_ID_0, PURELIFI_XL_PRODUCT_ID_0),
- .driver_info = DEVICE_LIFI_XL },
- {}
- };
- void plfxlc_send_packet_from_data_queue(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_tx *tx = &usb->tx;
- struct sk_buff *skb = NULL;
- unsigned long flags;
- u8 last_served_sidx;
- spin_lock_irqsave(&tx->lock, flags);
- last_served_sidx = usb->sidx;
- do {
- usb->sidx = (usb->sidx + 1) % MAX_STA_NUM;
- if (!(tx->station[usb->sidx].flag & STATION_CONNECTED_FLAG))
- continue;
- if (!(tx->station[usb->sidx].flag & STATION_FIFO_FULL_FLAG))
- skb = skb_peek(&tx->station[usb->sidx].data_list);
- } while ((usb->sidx != last_served_sidx) && (!skb));
- if (skb) {
- skb = skb_dequeue(&tx->station[usb->sidx].data_list);
- plfxlc_usb_wreq_async(usb, skb->data, skb->len, USB_REQ_DATA_TX,
- plfxlc_tx_urb_complete, skb);
- if (skb_queue_len(&tx->station[usb->sidx].data_list) <= 60)
- ieee80211_wake_queues(plfxlc_usb_to_hw(usb));
- }
- spin_unlock_irqrestore(&tx->lock, flags);
- }
- static void handle_rx_packet(struct plfxlc_usb *usb, const u8 *buffer,
- unsigned int length)
- {
- plfxlc_mac_rx(plfxlc_usb_to_hw(usb), buffer, length);
- }
- static void rx_urb_complete(struct urb *urb)
- {
- struct plfxlc_usb_tx *tx;
- struct plfxlc_usb *usb;
- unsigned int length;
- const u8 *buffer;
- u16 status;
- u8 sidx;
- int r;
- if (!urb) {
- pr_err("urb is NULL\n");
- return;
- }
- if (!urb->context) {
- pr_err("urb ctx is NULL\n");
- return;
- }
- usb = urb->context;
- if (usb->initialized != 1) {
- pr_err("usb is not initialized\n");
- return;
- }
- tx = &usb->tx;
- switch (urb->status) {
- case 0:
- break;
- case -ESHUTDOWN:
- case -EINVAL:
- case -ENODEV:
- case -ENOENT:
- case -ECONNRESET:
- case -EPIPE:
- dev_dbg(plfxlc_urb_dev(urb), "urb %p error %d\n", urb, urb->status);
- return;
- default:
- dev_dbg(plfxlc_urb_dev(urb), "urb %p error %d\n", urb, urb->status);
- if (tx->submitted_urbs++ < PURELIFI_URB_RETRY_MAX) {
- dev_dbg(plfxlc_urb_dev(urb), "urb %p resubmit %d", urb,
- tx->submitted_urbs++);
- goto resubmit;
- } else {
- dev_dbg(plfxlc_urb_dev(urb), "urb %p max resubmits reached", urb);
- tx->submitted_urbs = 0;
- return;
- }
- }
- buffer = urb->transfer_buffer;
- length = le32_to_cpu(*(__le32 *)(buffer + sizeof(struct rx_status)))
- + sizeof(u32);
- if (urb->actual_length != (PLF_MSG_STATUS_OFFSET + 1)) {
- if (usb->initialized && usb->link_up)
- handle_rx_packet(usb, buffer, length);
- goto resubmit;
- }
- status = buffer[PLF_MSG_STATUS_OFFSET];
- switch (status) {
- case STATION_FIFO_ALMOST_FULL_NOT_MESSAGE:
- dev_dbg(&usb->intf->dev,
- "FIFO full not packet receipt\n");
- tx->mac_fifo_full = 1;
- for (sidx = 0; sidx < MAX_STA_NUM; sidx++)
- tx->station[sidx].flag |= STATION_FIFO_FULL_FLAG;
- break;
- case STATION_FIFO_ALMOST_FULL_MESSAGE:
- dev_dbg(&usb->intf->dev, "FIFO full packet receipt\n");
- for (sidx = 0; sidx < MAX_STA_NUM; sidx++)
- tx->station[sidx].flag &= STATION_ACTIVE_FLAG;
- plfxlc_send_packet_from_data_queue(usb);
- break;
- case STATION_CONNECT_MESSAGE:
- usb->link_up = 1;
- dev_dbg(&usb->intf->dev, "ST_CONNECT_MSG packet receipt\n");
- break;
- case STATION_DISCONNECT_MESSAGE:
- usb->link_up = 0;
- dev_dbg(&usb->intf->dev, "ST_DISCONN_MSG packet receipt\n");
- break;
- default:
- dev_dbg(&usb->intf->dev, "Unknown packet receipt\n");
- break;
- }
- resubmit:
- r = usb_submit_urb(urb, GFP_ATOMIC);
- if (r)
- dev_dbg(plfxlc_urb_dev(urb), "urb %p resubmit fail (%d)\n", urb, r);
- }
- static struct urb *alloc_rx_urb(struct plfxlc_usb *usb)
- {
- struct usb_device *udev = plfxlc_usb_to_usbdev(usb);
- struct urb *urb;
- void *buffer;
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return NULL;
- buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
- &urb->transfer_dma);
- if (!buffer) {
- usb_free_urb(urb);
- return NULL;
- }
- usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
- buffer, USB_MAX_RX_SIZE,
- rx_urb_complete, usb);
- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- return urb;
- }
- static void free_rx_urb(struct urb *urb)
- {
- if (!urb)
- return;
- usb_free_coherent(urb->dev, urb->transfer_buffer_length,
- urb->transfer_buffer, urb->transfer_dma);
- usb_free_urb(urb);
- }
- static int __lf_x_usb_enable_rx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_rx *rx = &usb->rx;
- struct urb **urbs;
- int i, r;
- r = -ENOMEM;
- urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
- if (!urbs)
- goto error;
- for (i = 0; i < RX_URBS_COUNT; i++) {
- urbs[i] = alloc_rx_urb(usb);
- if (!urbs[i])
- goto error;
- }
- spin_lock_irq(&rx->lock);
- dev_dbg(plfxlc_usb_dev(usb), "irq_disabled %d\n", irqs_disabled());
- if (rx->urbs) {
- spin_unlock_irq(&rx->lock);
- r = 0;
- goto error;
- }
- rx->urbs = urbs;
- rx->urbs_count = RX_URBS_COUNT;
- spin_unlock_irq(&rx->lock);
- for (i = 0; i < RX_URBS_COUNT; i++) {
- r = usb_submit_urb(urbs[i], GFP_KERNEL);
- if (r)
- goto error_submit;
- }
- return 0;
- error_submit:
- for (i = 0; i < RX_URBS_COUNT; i++)
- usb_kill_urb(urbs[i]);
- spin_lock_irq(&rx->lock);
- rx->urbs = NULL;
- rx->urbs_count = 0;
- spin_unlock_irq(&rx->lock);
- error:
- if (urbs) {
- for (i = 0; i < RX_URBS_COUNT; i++)
- free_rx_urb(urbs[i]);
- }
- kfree(urbs);
- return r;
- }
- int plfxlc_usb_enable_rx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_rx *rx = &usb->rx;
- int r;
- mutex_lock(&rx->setup_mutex);
- r = __lf_x_usb_enable_rx(usb);
- if (!r)
- usb->rx_usb_enabled = 1;
- mutex_unlock(&rx->setup_mutex);
- return r;
- }
- static void __lf_x_usb_disable_rx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_rx *rx = &usb->rx;
- unsigned long flags;
- unsigned int count;
- struct urb **urbs;
- int i;
- spin_lock_irqsave(&rx->lock, flags);
- urbs = rx->urbs;
- count = rx->urbs_count;
- spin_unlock_irqrestore(&rx->lock, flags);
- if (!urbs)
- return;
- for (i = 0; i < count; i++) {
- usb_kill_urb(urbs[i]);
- free_rx_urb(urbs[i]);
- }
- kfree(urbs);
- rx->urbs = NULL;
- rx->urbs_count = 0;
- }
- void plfxlc_usb_disable_rx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_rx *rx = &usb->rx;
- mutex_lock(&rx->setup_mutex);
- __lf_x_usb_disable_rx(usb);
- usb->rx_usb_enabled = 0;
- mutex_unlock(&rx->setup_mutex);
- }
- void plfxlc_usb_disable_tx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_tx *tx = &usb->tx;
- unsigned long flags;
- clear_bit(PLF_BIT_ENABLED, &tx->enabled);
- /* kill all submitted tx-urbs */
- usb_kill_anchored_urbs(&tx->submitted);
- spin_lock_irqsave(&tx->lock, flags);
- WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
- WARN_ON(tx->submitted_urbs != 0);
- tx->submitted_urbs = 0;
- spin_unlock_irqrestore(&tx->lock, flags);
- /* The stopped state is ignored, relying on ieee80211_wake_queues()
- * in a potentionally following plfxlc_usb_enable_tx().
- */
- }
- void plfxlc_usb_enable_tx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_tx *tx = &usb->tx;
- unsigned long flags;
- spin_lock_irqsave(&tx->lock, flags);
- set_bit(PLF_BIT_ENABLED, &tx->enabled);
- tx->submitted_urbs = 0;
- ieee80211_wake_queues(plfxlc_usb_to_hw(usb));
- tx->stopped = 0;
- spin_unlock_irqrestore(&tx->lock, flags);
- }
- void plfxlc_tx_urb_complete(struct urb *urb)
- {
- struct ieee80211_tx_info *info;
- struct plfxlc_usb *usb;
- struct sk_buff *skb;
- skb = urb->context;
- info = IEEE80211_SKB_CB(skb);
- /* grab 'usb' pointer before handing off the skb (since
- * it might be freed by plfxlc_mac_tx_to_dev or mac80211)
- */
- usb = &plfxlc_hw_mac(info->rate_driver_data[0])->chip.usb;
- switch (urb->status) {
- case 0:
- break;
- case -ESHUTDOWN:
- case -EINVAL:
- case -ENODEV:
- case -ENOENT:
- case -ECONNRESET:
- case -EPIPE:
- dev_dbg(plfxlc_urb_dev(urb), "urb %p error %d\n", urb, urb->status);
- break;
- default:
- dev_dbg(plfxlc_urb_dev(urb), "urb %p error %d\n", urb, urb->status);
- return;
- }
- plfxlc_mac_tx_to_dev(skb, urb->status);
- plfxlc_send_packet_from_data_queue(usb);
- usb_free_urb(urb);
- }
- static inline void init_usb_rx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_rx *rx = &usb->rx;
- spin_lock_init(&rx->lock);
- mutex_init(&rx->setup_mutex);
- if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH)
- rx->usb_packet_size = 512;
- else
- rx->usb_packet_size = 64;
- if (rx->fragment_length != 0)
- dev_dbg(plfxlc_usb_dev(usb), "fragment_length error\n");
- }
- static inline void init_usb_tx(struct plfxlc_usb *usb)
- {
- struct plfxlc_usb_tx *tx = &usb->tx;
- spin_lock_init(&tx->lock);
- clear_bit(PLF_BIT_ENABLED, &tx->enabled);
- tx->stopped = 0;
- skb_queue_head_init(&tx->submitted_skbs);
- init_usb_anchor(&tx->submitted);
- }
- void plfxlc_usb_init(struct plfxlc_usb *usb, struct ieee80211_hw *hw,
- struct usb_interface *intf)
- {
- memset(usb, 0, sizeof(*usb));
- usb->intf = usb_get_intf(intf);
- usb_set_intfdata(usb->intf, hw);
- init_usb_tx(usb);
- init_usb_rx(usb);
- }
- void plfxlc_usb_release(struct plfxlc_usb *usb)
- {
- plfxlc_op_stop(plfxlc_usb_to_hw(usb));
- plfxlc_usb_disable_tx(usb);
- plfxlc_usb_disable_rx(usb);
- usb_set_intfdata(usb->intf, NULL);
- usb_put_intf(usb->intf);
- }
- const char *plfxlc_speed(enum usb_device_speed speed)
- {
- switch (speed) {
- case USB_SPEED_LOW:
- return "low";
- case USB_SPEED_FULL:
- return "full";
- case USB_SPEED_HIGH:
- return "high";
- default:
- return "unknown";
- }
- }
- int plfxlc_usb_init_hw(struct plfxlc_usb *usb)
- {
- int r;
- r = usb_reset_configuration(plfxlc_usb_to_usbdev(usb));
- if (r) {
- dev_err(plfxlc_usb_dev(usb), "cfg reset failed (%d)\n", r);
- return r;
- }
- return 0;
- }
- static void get_usb_req(struct usb_device *udev, void *buffer,
- u32 buffer_len, enum plf_usb_req_enum usb_req_id,
- struct plf_usb_req *usb_req)
- {
- __be32 payload_len_nw = cpu_to_be32(buffer_len + FCS_LEN);
- const u8 *buffer_src_p = buffer;
- u8 *buffer_dst = usb_req->buf;
- u32 temp_usb_len = 0;
- usb_req->id = cpu_to_be32(usb_req_id);
- usb_req->len = cpu_to_be32(0);
- /* Copy buffer length into the transmitted buffer, as it is important
- * for the Rx MAC to know its exact length.
- */
- if (usb_req->id == cpu_to_be32(USB_REQ_BEACON_WR)) {
- memcpy(buffer_dst, &payload_len_nw, sizeof(payload_len_nw));
- buffer_dst += sizeof(payload_len_nw);
- temp_usb_len += sizeof(payload_len_nw);
- }
- memcpy(buffer_dst, buffer_src_p, buffer_len);
- buffer_dst += buffer_len;
- buffer_src_p += buffer_len;
- temp_usb_len += buffer_len;
- /* Set the FCS_LEN (4) bytes as 0 for CRC checking. */
- memset(buffer_dst, 0, FCS_LEN);
- buffer_dst += FCS_LEN;
- temp_usb_len += FCS_LEN;
- /* Round the packet to be transmitted to 4 bytes. */
- if (temp_usb_len % PURELIFI_BYTE_NUM_ALIGNMENT) {
- memset(buffer_dst, 0, PURELIFI_BYTE_NUM_ALIGNMENT -
- (temp_usb_len %
- PURELIFI_BYTE_NUM_ALIGNMENT));
- buffer_dst += PURELIFI_BYTE_NUM_ALIGNMENT -
- (temp_usb_len %
- PURELIFI_BYTE_NUM_ALIGNMENT);
- temp_usb_len += PURELIFI_BYTE_NUM_ALIGNMENT -
- (temp_usb_len % PURELIFI_BYTE_NUM_ALIGNMENT);
- }
- usb_req->len = cpu_to_be32(temp_usb_len);
- }
- int plfxlc_usb_wreq_async(struct plfxlc_usb *usb, const u8 *buffer,
- int buffer_len, enum plf_usb_req_enum usb_req_id,
- usb_complete_t complete_fn,
- void *context)
- {
- struct usb_device *udev = interface_to_usbdev(usb->ez_usb);
- struct urb *urb = usb_alloc_urb(0, GFP_ATOMIC);
- int r;
- usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
- (void *)buffer, buffer_len, complete_fn, context);
- r = usb_submit_urb(urb, GFP_ATOMIC);
- if (r)
- dev_err(&udev->dev, "Async write submit failed (%d)\n", r);
- return r;
- }
- int plfxlc_usb_wreq(struct usb_interface *ez_usb, void *buffer, int buffer_len,
- enum plf_usb_req_enum usb_req_id)
- {
- struct usb_device *udev = interface_to_usbdev(ez_usb);
- unsigned char *dma_buffer = NULL;
- struct plf_usb_req usb_req;
- int usb_bulk_msg_len;
- int actual_length;
- int r;
- get_usb_req(udev, buffer, buffer_len, usb_req_id, &usb_req);
- usb_bulk_msg_len = sizeof(__le32) + sizeof(__le32) +
- be32_to_cpu(usb_req.len);
- dma_buffer = kmemdup(&usb_req, usb_bulk_msg_len, GFP_KERNEL);
- if (!dma_buffer) {
- r = -ENOMEM;
- goto error;
- }
- r = usb_bulk_msg(udev,
- usb_sndbulkpipe(udev, EP_DATA_OUT),
- dma_buffer, usb_bulk_msg_len,
- &actual_length, USB_BULK_MSG_TIMEOUT_MS);
- kfree(dma_buffer);
- error:
- if (r) {
- r = -ENOMEM;
- dev_err(&udev->dev, "usb_bulk_msg failed (%d)\n", r);
- }
- return r;
- }
- static void slif_data_plane_sap_timer_callb(struct timer_list *t)
- {
- struct plfxlc_usb *usb = from_timer(usb, t, tx.tx_retry_timer);
- plfxlc_send_packet_from_data_queue(usb);
- timer_setup(&usb->tx.tx_retry_timer,
- slif_data_plane_sap_timer_callb, 0);
- mod_timer(&usb->tx.tx_retry_timer, jiffies + TX_RETRY_BACKOFF_JIFF);
- }
- static void sta_queue_cleanup_timer_callb(struct timer_list *t)
- {
- struct plfxlc_usb *usb = from_timer(usb, t, sta_queue_cleanup);
- struct plfxlc_usb_tx *tx = &usb->tx;
- int sidx;
- for (sidx = 0; sidx < MAX_STA_NUM - 1; sidx++) {
- if (!(tx->station[sidx].flag & STATION_CONNECTED_FLAG))
- continue;
- if (tx->station[sidx].flag & STATION_HEARTBEAT_FLAG) {
- tx->station[sidx].flag ^= STATION_HEARTBEAT_FLAG;
- } else {
- eth_zero_addr(tx->station[sidx].mac);
- tx->station[sidx].flag = 0;
- }
- }
- timer_setup(&usb->sta_queue_cleanup,
- sta_queue_cleanup_timer_callb, 0);
- mod_timer(&usb->sta_queue_cleanup, jiffies + STA_QUEUE_CLEANUP_JIFF);
- }
- static int probe(struct usb_interface *intf,
- const struct usb_device_id *id)
- {
- u8 serial_number[PURELIFI_SERIAL_LEN];
- struct ieee80211_hw *hw = NULL;
- struct plfxlc_usb_tx *tx;
- struct plfxlc_chip *chip;
- struct plfxlc_usb *usb;
- u8 hw_address[ETH_ALEN];
- unsigned int i;
- int r = 0;
- hw = plfxlc_mac_alloc_hw(intf);
- if (!hw) {
- r = -ENOMEM;
- goto error;
- }
- chip = &plfxlc_hw_mac(hw)->chip;
- usb = &chip->usb;
- usb->ez_usb = intf;
- tx = &usb->tx;
- r = plfxlc_upload_mac_and_serial(intf, hw_address, serial_number);
- if (r) {
- dev_err(&intf->dev, "MAC and Serial upload failed (%d)\n", r);
- goto error;
- }
- chip->unit_type = STA;
- dev_err(&intf->dev, "Unit type is station");
- r = plfxlc_mac_preinit_hw(hw, hw_address);
- if (r) {
- dev_err(&intf->dev, "Init mac failed (%d)\n", r);
- goto error;
- }
- r = ieee80211_register_hw(hw);
- if (r) {
- dev_err(&intf->dev, "Register device failed (%d)\n", r);
- goto error;
- }
- if ((le16_to_cpu(interface_to_usbdev(intf)->descriptor.idVendor) ==
- PURELIFI_XL_VENDOR_ID_0) &&
- (le16_to_cpu(interface_to_usbdev(intf)->descriptor.idProduct) ==
- PURELIFI_XL_PRODUCT_ID_0)) {
- r = plfxlc_download_xl_firmware(intf);
- } else {
- r = plfxlc_download_fpga(intf);
- }
- if (r != 0) {
- dev_err(&intf->dev, "FPGA download failed (%d)\n", r);
- goto error;
- }
- tx->mac_fifo_full = 0;
- spin_lock_init(&tx->lock);
- msleep(PLF_MSLEEP_TIME);
- r = plfxlc_usb_init_hw(usb);
- if (r < 0) {
- dev_err(&intf->dev, "usb_init_hw failed (%d)\n", r);
- goto error;
- }
- msleep(PLF_MSLEEP_TIME);
- r = plfxlc_chip_switch_radio(chip, PLFXLC_RADIO_ON);
- if (r < 0) {
- dev_dbg(&intf->dev, "chip_switch_radio_on failed (%d)\n", r);
- goto error;
- }
- msleep(PLF_MSLEEP_TIME);
- r = plfxlc_chip_set_rate(chip, 8);
- if (r < 0) {
- dev_dbg(&intf->dev, "chip_set_rate failed (%d)\n", r);
- goto error;
- }
- msleep(PLF_MSLEEP_TIME);
- r = plfxlc_usb_wreq(usb->ez_usb,
- hw_address, ETH_ALEN, USB_REQ_MAC_WR);
- if (r < 0) {
- dev_dbg(&intf->dev, "MAC_WR failure (%d)\n", r);
- goto error;
- }
- plfxlc_chip_enable_rxtx(chip);
- /* Initialise the data plane Tx queue */
- for (i = 0; i < MAX_STA_NUM; i++) {
- skb_queue_head_init(&tx->station[i].data_list);
- tx->station[i].flag = 0;
- }
- tx->station[STA_BROADCAST_INDEX].flag |= STATION_CONNECTED_FLAG;
- for (i = 0; i < ETH_ALEN; i++)
- tx->station[STA_BROADCAST_INDEX].mac[i] = 0xFF;
- timer_setup(&tx->tx_retry_timer, slif_data_plane_sap_timer_callb, 0);
- tx->tx_retry_timer.expires = jiffies + TX_RETRY_BACKOFF_JIFF;
- add_timer(&tx->tx_retry_timer);
- timer_setup(&usb->sta_queue_cleanup,
- sta_queue_cleanup_timer_callb, 0);
- usb->sta_queue_cleanup.expires = jiffies + STA_QUEUE_CLEANUP_JIFF;
- add_timer(&usb->sta_queue_cleanup);
- plfxlc_mac_init_hw(hw);
- usb->initialized = true;
- return 0;
- error:
- if (hw) {
- plfxlc_mac_release(plfxlc_hw_mac(hw));
- ieee80211_unregister_hw(hw);
- ieee80211_free_hw(hw);
- }
- dev_err(&intf->dev, "pureLifi:Device error");
- return r;
- }
- static void disconnect(struct usb_interface *intf)
- {
- struct ieee80211_hw *hw = plfxlc_intf_to_hw(intf);
- struct plfxlc_mac *mac;
- struct plfxlc_usb *usb;
- /* Either something really bad happened, or
- * we're just dealing with a DEVICE_INSTALLER.
- */
- if (!hw)
- return;
- mac = plfxlc_hw_mac(hw);
- usb = &mac->chip.usb;
- del_timer_sync(&usb->tx.tx_retry_timer);
- del_timer_sync(&usb->sta_queue_cleanup);
- ieee80211_unregister_hw(hw);
- plfxlc_chip_disable_rxtx(&mac->chip);
- /* If the disconnect has been caused by a removal of the
- * driver module, the reset allows reloading of the driver. If the
- * reset will not be executed here, the upload of the firmware in the
- * probe function caused by the reloading of the driver will fail.
- */
- usb_reset_device(interface_to_usbdev(intf));
- plfxlc_mac_release(mac);
- ieee80211_free_hw(hw);
- }
- static void plfxlc_usb_resume(struct plfxlc_usb *usb)
- {
- struct plfxlc_mac *mac = plfxlc_usb_to_mac(usb);
- int r;
- r = plfxlc_op_start(plfxlc_usb_to_hw(usb));
- if (r < 0) {
- dev_warn(plfxlc_usb_dev(usb),
- "Device resume failed (%d)\n", r);
- if (usb->was_running)
- set_bit(PURELIFI_DEVICE_RUNNING, &mac->flags);
- usb_queue_reset_device(usb->intf);
- return;
- }
- if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
- r = plfxlc_restore_settings(mac);
- if (r < 0) {
- dev_dbg(plfxlc_usb_dev(usb),
- "Restore failed (%d)\n", r);
- return;
- }
- }
- }
- static void plfxlc_usb_stop(struct plfxlc_usb *usb)
- {
- plfxlc_op_stop(plfxlc_usb_to_hw(usb));
- plfxlc_usb_disable_tx(usb);
- plfxlc_usb_disable_rx(usb);
- usb->initialized = false;
- }
- static int pre_reset(struct usb_interface *intf)
- {
- struct ieee80211_hw *hw = usb_get_intfdata(intf);
- struct plfxlc_mac *mac;
- struct plfxlc_usb *usb;
- if (!hw || intf->condition != USB_INTERFACE_BOUND)
- return 0;
- mac = plfxlc_hw_mac(hw);
- usb = &mac->chip.usb;
- usb->was_running = test_bit(PURELIFI_DEVICE_RUNNING, &mac->flags);
- plfxlc_usb_stop(usb);
- return 0;
- }
- static int post_reset(struct usb_interface *intf)
- {
- struct ieee80211_hw *hw = usb_get_intfdata(intf);
- struct plfxlc_mac *mac;
- struct plfxlc_usb *usb;
- if (!hw || intf->condition != USB_INTERFACE_BOUND)
- return 0;
- mac = plfxlc_hw_mac(hw);
- usb = &mac->chip.usb;
- if (usb->was_running)
- plfxlc_usb_resume(usb);
- return 0;
- }
- #ifdef CONFIG_PM
- static struct plfxlc_usb *get_plfxlc_usb(struct usb_interface *intf)
- {
- struct ieee80211_hw *hw = plfxlc_intf_to_hw(intf);
- struct plfxlc_mac *mac;
- /* Either something really bad happened, or
- * we're just dealing with a DEVICE_INSTALLER.
- */
- if (!hw)
- return NULL;
- mac = plfxlc_hw_mac(hw);
- return &mac->chip.usb;
- }
- static int suspend(struct usb_interface *interface,
- pm_message_t message)
- {
- struct plfxlc_usb *pl = get_plfxlc_usb(interface);
- struct plfxlc_mac *mac = plfxlc_usb_to_mac(pl);
- if (!pl)
- return -ENODEV;
- if (pl->initialized == 0)
- return 0;
- pl->was_running = test_bit(PURELIFI_DEVICE_RUNNING, &mac->flags);
- plfxlc_usb_stop(pl);
- return 0;
- }
- static int resume(struct usb_interface *interface)
- {
- struct plfxlc_usb *pl = get_plfxlc_usb(interface);
- if (!pl)
- return -ENODEV;
- if (pl->was_running)
- plfxlc_usb_resume(pl);
- return 0;
- }
- #endif
- static struct usb_driver driver = {
- .name = KBUILD_MODNAME,
- .id_table = usb_ids,
- .probe = probe,
- .disconnect = disconnect,
- .pre_reset = pre_reset,
- .post_reset = post_reset,
- #ifdef CONFIG_PM
- .suspend = suspend,
- .resume = resume,
- #endif
- .disable_hub_initiated_lpm = 1,
- };
- static int __init usb_init(void)
- {
- int r;
- r = usb_register(&driver);
- if (r) {
- pr_err("%s usb_register() failed %d\n", driver.name, r);
- return r;
- }
- pr_debug("Driver initialized :%s\n", driver.name);
- return 0;
- }
- static void __exit usb_exit(void)
- {
- usb_deregister(&driver);
- pr_debug("%s %s\n", driver.name, __func__);
- }
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("USB driver for pureLiFi devices");
- MODULE_AUTHOR("pureLiFi");
- MODULE_VERSION("1.0");
- MODULE_FIRMWARE("plfxlc/lifi-x.bin");
- MODULE_DEVICE_TABLE(usb, usb_ids);
- module_init(usb_init);
- module_exit(usb_exit);
|