From d635711daa98be86d4c7fd01499c34f566b54ccb Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 10 Jun 2016 05:30:17 -0300 Subject: Linux-libre 4.6.2-gnu --- drivers/staging/gdm72xx/Kconfig | 63 --- drivers/staging/gdm72xx/Makefile | 6 - drivers/staging/gdm72xx/TODO | 2 - drivers/staging/gdm72xx/gdm_qos.c | 438 ------------------- drivers/staging/gdm72xx/gdm_qos.h | 74 ---- drivers/staging/gdm72xx/gdm_sdio.c | 700 ------------------------------- drivers/staging/gdm72xx/gdm_sdio.h | 63 --- drivers/staging/gdm72xx/gdm_usb.c | 789 ---------------------------------- drivers/staging/gdm72xx/gdm_usb.h | 78 ---- drivers/staging/gdm72xx/gdm_wimax.c | 815 ------------------------------------ drivers/staging/gdm72xx/gdm_wimax.h | 49 --- drivers/staging/gdm72xx/hci.h | 213 ---------- drivers/staging/gdm72xx/netlink_k.c | 156 ------- drivers/staging/gdm72xx/netlink_k.h | 25 -- drivers/staging/gdm72xx/sdio_boot.c | 158 ------- drivers/staging/gdm72xx/sdio_boot.h | 21 - drivers/staging/gdm72xx/usb_boot.c | 363 ---------------- drivers/staging/gdm72xx/usb_boot.h | 22 - drivers/staging/gdm72xx/usb_ids.h | 86 ---- drivers/staging/gdm72xx/wm_ioctl.h | 101 ----- 20 files changed, 4222 deletions(-) delete mode 100644 drivers/staging/gdm72xx/Kconfig delete mode 100644 drivers/staging/gdm72xx/Makefile delete mode 100644 drivers/staging/gdm72xx/TODO delete mode 100644 drivers/staging/gdm72xx/gdm_qos.c delete mode 100644 drivers/staging/gdm72xx/gdm_qos.h delete mode 100644 drivers/staging/gdm72xx/gdm_sdio.c delete mode 100644 drivers/staging/gdm72xx/gdm_sdio.h delete mode 100644 drivers/staging/gdm72xx/gdm_usb.c delete mode 100644 drivers/staging/gdm72xx/gdm_usb.h delete mode 100644 drivers/staging/gdm72xx/gdm_wimax.c delete mode 100644 drivers/staging/gdm72xx/gdm_wimax.h delete mode 100644 drivers/staging/gdm72xx/hci.h delete mode 100644 drivers/staging/gdm72xx/netlink_k.c delete mode 100644 drivers/staging/gdm72xx/netlink_k.h delete mode 100644 drivers/staging/gdm72xx/sdio_boot.c delete mode 100644 drivers/staging/gdm72xx/sdio_boot.h delete mode 100644 drivers/staging/gdm72xx/usb_boot.c delete mode 100644 drivers/staging/gdm72xx/usb_boot.h delete mode 100644 drivers/staging/gdm72xx/usb_ids.h delete mode 100644 drivers/staging/gdm72xx/wm_ioctl.h (limited to 'drivers/staging/gdm72xx') diff --git a/drivers/staging/gdm72xx/Kconfig b/drivers/staging/gdm72xx/Kconfig deleted file mode 100644 index bf11a7fbf..000000000 --- a/drivers/staging/gdm72xx/Kconfig +++ /dev/null @@ -1,63 +0,0 @@ -# -# GCT GDM72xx WiMAX driver configuration -# - -menuconfig WIMAX_GDM72XX - tristate "GCT GDM72xx WiMAX support" - depends on NET && (USB || MMC) - help - Support a WiMAX module based on the GCT GDM72xx WiMAX chip. - -if WIMAX_GDM72XX - -config WIMAX_GDM72XX_QOS - bool "Enable QoS support" - default n - help - Enable Quality of Service support based on the data protocol of - transmitting packets. - -config WIMAX_GDM72XX_K_MODE - bool "Enable K mode" - default n - help - Enable support for proprietary functions for KT (Korea Telecom). - -config WIMAX_GDM72XX_WIMAX2 - bool "Enable WiMAX2 support" - default n - help - Enable support for transmitting multiple packets (packet - aggregation) from the WiMAX module to the host processor. - -choice - prompt "Select interface" - -config WIMAX_GDM72XX_USB - bool "USB interface" - depends on (USB = y || USB = WIMAX_GDM72XX) - help - Select this option if the WiMAX module interfaces with the host - processor via USB. - -config WIMAX_GDM72XX_SDIO - bool "SDIO interface" - depends on (MMC = y || MMC = WIMAX_GDM72XX) - help - Select this option if the WiMAX module interfaces with the host - processor via SDIO. - -endchoice - -if WIMAX_GDM72XX_USB - -config WIMAX_GDM72XX_USB_PM - bool "Enable power management support" - depends on PM - help - Enable USB power management in order to reduce power consumption - while the interface is not in use. - -endif # WIMAX_GDM72XX_USB - -endif # WIMAX_GDM72XX diff --git a/drivers/staging/gdm72xx/Makefile b/drivers/staging/gdm72xx/Makefile deleted file mode 100644 index 35da7b90b..000000000 --- a/drivers/staging/gdm72xx/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_WIMAX_GDM72XX) := gdmwm.o - -gdmwm-y += gdm_wimax.o netlink_k.o -gdmwm-$(CONFIG_WIMAX_GDM72XX_QOS) += gdm_qos.o -gdmwm-$(CONFIG_WIMAX_GDM72XX_SDIO) += gdm_sdio.o sdio_boot.o -gdmwm-$(CONFIG_WIMAX_GDM72XX_USB) += gdm_usb.o usb_boot.o diff --git a/drivers/staging/gdm72xx/TODO b/drivers/staging/gdm72xx/TODO deleted file mode 100644 index 62d0cd622..000000000 --- a/drivers/staging/gdm72xx/TODO +++ /dev/null @@ -1,2 +0,0 @@ -TODO: -- Clean up coding style to meet kernel standard. diff --git a/drivers/staging/gdm72xx/gdm_qos.c b/drivers/staging/gdm72xx/gdm_qos.c deleted file mode 100644 index cad347a05..000000000 --- a/drivers/staging/gdm72xx/gdm_qos.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include - -#include -#include -#include - -#include "gdm_wimax.h" -#include "hci.h" -#include "gdm_qos.h" - -#define MAX_FREE_LIST_CNT 32 -static struct { - struct list_head head; - int cnt; - spinlock_t lock; -} qos_free_list; - -static void init_qos_entry_list(void) -{ - qos_free_list.cnt = 0; - INIT_LIST_HEAD(&qos_free_list.head); - spin_lock_init(&qos_free_list.lock); -} - -static void *alloc_qos_entry(void) -{ - struct qos_entry_s *entry; - unsigned long flags; - - spin_lock_irqsave(&qos_free_list.lock, flags); - if (qos_free_list.cnt) { - entry = list_entry(qos_free_list.head.prev, struct qos_entry_s, - list); - list_del(&entry->list); - qos_free_list.cnt--; - spin_unlock_irqrestore(&qos_free_list.lock, flags); - return entry; - } - spin_unlock_irqrestore(&qos_free_list.lock, flags); - - return kmalloc(sizeof(*entry), GFP_ATOMIC); -} - -static void free_qos_entry(void *entry) -{ - struct qos_entry_s *qentry = entry; - unsigned long flags; - - spin_lock_irqsave(&qos_free_list.lock, flags); - if (qos_free_list.cnt < MAX_FREE_LIST_CNT) { - list_add(&qentry->list, &qos_free_list.head); - qos_free_list.cnt++; - spin_unlock_irqrestore(&qos_free_list.lock, flags); - return; - } - spin_unlock_irqrestore(&qos_free_list.lock, flags); - - kfree(entry); -} - -static void free_qos_entry_list(struct list_head *free_list) -{ - struct qos_entry_s *entry, *n; - int total_free = 0; - - list_for_each_entry_safe(entry, n, free_list, list) { - list_del(&entry->list); - kfree(entry); - total_free++; - } - - pr_debug("%s: total_free_cnt=%d\n", __func__, total_free); -} - -void gdm_qos_init(void *nic_ptr) -{ - struct nic *nic = nic_ptr; - struct qos_cb_s *qcb = &nic->qos; - int i; - - for (i = 0; i < QOS_MAX; i++) { - INIT_LIST_HEAD(&qcb->qos_list[i]); - qcb->csr[i].qos_buf_count = 0; - qcb->csr[i].enabled = false; - } - - qcb->qos_list_cnt = 0; - qcb->qos_null_idx = QOS_MAX - 1; - qcb->qos_limit_size = 255; - - spin_lock_init(&qcb->qos_lock); - - init_qos_entry_list(); -} - -void gdm_qos_release_list(void *nic_ptr) -{ - struct nic *nic = nic_ptr; - struct qos_cb_s *qcb = &nic->qos; - unsigned long flags; - struct qos_entry_s *entry, *n; - struct list_head free_list; - int i; - - INIT_LIST_HEAD(&free_list); - - spin_lock_irqsave(&qcb->qos_lock, flags); - - for (i = 0; i < QOS_MAX; i++) { - qcb->csr[i].qos_buf_count = 0; - qcb->csr[i].enabled = false; - } - - qcb->qos_list_cnt = 0; - qcb->qos_null_idx = QOS_MAX - 1; - - for (i = 0; i < QOS_MAX; i++) { - list_for_each_entry_safe(entry, n, &qcb->qos_list[i], list) { - list_move_tail(&entry->list, &free_list); - } - } - spin_unlock_irqrestore(&qcb->qos_lock, flags); - free_qos_entry_list(&free_list); -} - -static int chk_ipv4_rule(struct gdm_wimax_csr_s *csr, u8 *stream, u8 *port) -{ - int i; - - if (csr->classifier_rule_en & IPTYPEOFSERVICE) { - if (((stream[1] & csr->ip2s_mask) < csr->ip2s_lo) || - ((stream[1] & csr->ip2s_mask) > csr->ip2s_hi)) - return 1; - } - - if (csr->classifier_rule_en & PROTOCOL) { - if (stream[9] != csr->protocol) - return 1; - } - - if (csr->classifier_rule_en & IPMASKEDSRCADDRESS) { - for (i = 0; i < 4; i++) { - if ((stream[12 + i] & csr->ipsrc_addrmask[i]) != - (csr->ipsrc_addr[i] & csr->ipsrc_addrmask[i])) - return 1; - } - } - - if (csr->classifier_rule_en & IPMASKEDDSTADDRESS) { - for (i = 0; i < 4; i++) { - if ((stream[16 + i] & csr->ipdst_addrmask[i]) != - (csr->ipdst_addr[i] & csr->ipdst_addrmask[i])) - return 1; - } - } - - if (csr->classifier_rule_en & PROTOCOLSRCPORTRANGE) { - i = ((port[0] << 8) & 0xff00) + port[1]; - if ((i < csr->srcport_lo) || (i > csr->srcport_hi)) - return 1; - } - - if (csr->classifier_rule_en & PROTOCOLDSTPORTRANGE) { - i = ((port[2] << 8) & 0xff00) + port[3]; - if ((i < csr->dstport_lo) || (i > csr->dstport_hi)) - return 1; - } - - return 0; -} - -static int get_qos_index(struct nic *nic, u8 *iph, u8 *tcpudph) -{ - int ip_ver, i; - struct qos_cb_s *qcb = &nic->qos; - - if (!iph || !tcpudph) - return -1; - - ip_ver = (iph[0] >> 4) & 0xf; - - if (ip_ver != 4) - return -1; - - for (i = 0; i < QOS_MAX; i++) { - if (!qcb->csr[i].enabled) - continue; - if (!qcb->csr[i].classifier_rule_en) - continue; - if (chk_ipv4_rule(&qcb->csr[i], iph, tcpudph) == 0) - return i; - } - - return -1; -} - -static void extract_qos_list(struct nic *nic, struct list_head *head) -{ - struct qos_cb_s *qcb = &nic->qos; - struct qos_entry_s *entry; - int i; - - INIT_LIST_HEAD(head); - - for (i = 0; i < QOS_MAX; i++) { - if (!qcb->csr[i].enabled) - continue; - if (qcb->csr[i].qos_buf_count >= qcb->qos_limit_size) - continue; - if (list_empty(&qcb->qos_list[i])) - continue; - - entry = list_entry(qcb->qos_list[i].prev, struct qos_entry_s, - list); - - list_move_tail(&entry->list, head); - qcb->csr[i].qos_buf_count++; - - if (!list_empty(&qcb->qos_list[i])) - netdev_warn(nic->netdev, "Index(%d) is piled!!\n", i); - } -} - -static void send_qos_list(struct nic *nic, struct list_head *head) -{ - struct qos_entry_s *entry, *n; - - list_for_each_entry_safe(entry, n, head, list) { - list_del(&entry->list); - gdm_wimax_send_tx(entry->skb, entry->dev); - free_qos_entry(entry); - } -} - -int gdm_qos_send_hci_pkt(struct sk_buff *skb, struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - int index; - struct qos_cb_s *qcb = &nic->qos; - unsigned long flags; - struct ethhdr *ethh = (struct ethhdr *)(skb->data + HCI_HEADER_SIZE); - struct iphdr *iph = (struct iphdr *)((char *)ethh + ETH_HLEN); - struct tcphdr *tcph; - struct qos_entry_s *entry = NULL; - struct list_head send_list; - int ret = 0; - - tcph = (struct tcphdr *)iph + iph->ihl*4; - - if (ethh->h_proto == cpu_to_be16(ETH_P_IP)) { - if (qcb->qos_list_cnt && !qos_free_list.cnt) { - entry = alloc_qos_entry(); - entry->skb = skb; - entry->dev = dev; - netdev_dbg(dev, "qcb->qos_list_cnt=%d\n", - qcb->qos_list_cnt); - } - - spin_lock_irqsave(&qcb->qos_lock, flags); - if (qcb->qos_list_cnt) { - index = get_qos_index(nic, (u8 *)iph, (u8 *)tcph); - if (index == -1) - index = qcb->qos_null_idx; - - if (!entry) { - entry = alloc_qos_entry(); - entry->skb = skb; - entry->dev = dev; - } - - list_add_tail(&entry->list, &qcb->qos_list[index]); - extract_qos_list(nic, &send_list); - spin_unlock_irqrestore(&qcb->qos_lock, flags); - send_qos_list(nic, &send_list); - goto out; - } - spin_unlock_irqrestore(&qcb->qos_lock, flags); - if (entry) - free_qos_entry(entry); - } - - ret = gdm_wimax_send_tx(skb, dev); -out: - return ret; -} - -static int get_csr(struct qos_cb_s *qcb, u32 sfid, int mode) -{ - int i; - - for (i = 0; i < qcb->qos_list_cnt; i++) { - if (qcb->csr[i].sfid == sfid) - return i; - } - - if (mode) { - for (i = 0; i < QOS_MAX; i++) { - if (!qcb->csr[i].enabled) { - qcb->csr[i].enabled = true; - qcb->qos_list_cnt++; - return i; - } - } - } - return -1; -} - -#define QOS_CHANGE_DEL 0xFC -#define QOS_ADD 0xFD -#define QOS_REPORT 0xFE - -void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size) -{ - struct nic *nic = nic_ptr; - int i, index, pos; - u32 sfid; - u8 sub_cmd_evt; - struct qos_cb_s *qcb = &nic->qos; - struct qos_entry_s *entry, *n; - struct list_head send_list; - struct list_head free_list; - unsigned long flags; - - sub_cmd_evt = (u8)buf[4]; - - if (sub_cmd_evt == QOS_REPORT) { - spin_lock_irqsave(&qcb->qos_lock, flags); - for (i = 0; i < qcb->qos_list_cnt; i++) { - sfid = ((buf[(i*5) + 6] << 24) & 0xff000000); - sfid += ((buf[(i*5) + 7] << 16) & 0xff0000); - sfid += ((buf[(i*5) + 8] << 8) & 0xff00); - sfid += (buf[(i*5) + 9]); - index = get_csr(qcb, sfid, 0); - if (index == -1) { - spin_unlock_irqrestore(&qcb->qos_lock, flags); - netdev_err(nic->netdev, "QoS ERROR: No SF\n"); - return; - } - qcb->csr[index].qos_buf_count = buf[(i*5) + 10]; - } - - extract_qos_list(nic, &send_list); - spin_unlock_irqrestore(&qcb->qos_lock, flags); - send_qos_list(nic, &send_list); - return; - } - - /* sub_cmd_evt == QOS_ADD || sub_cmd_evt == QOS_CHANG_DEL */ - pos = 6; - sfid = ((buf[pos++] << 24) & 0xff000000); - sfid += ((buf[pos++] << 16) & 0xff0000); - sfid += ((buf[pos++] << 8) & 0xff00); - sfid += (buf[pos++]); - - index = get_csr(qcb, sfid, 1); - if (index == -1) { - netdev_err(nic->netdev, - "QoS ERROR: csr Update Error / Wrong index (%d)\n", - index); - return; - } - - if (sub_cmd_evt == QOS_ADD) { - netdev_dbg(nic->netdev, "QOS_ADD SFID = 0x%x, index=%d\n", - sfid, index); - - spin_lock_irqsave(&qcb->qos_lock, flags); - qcb->csr[index].sfid = sfid; - qcb->csr[index].classifier_rule_en = ((buf[pos++] << 8) & 0xff00); - qcb->csr[index].classifier_rule_en += buf[pos++]; - if (qcb->csr[index].classifier_rule_en == 0) - qcb->qos_null_idx = index; - qcb->csr[index].ip2s_mask = buf[pos++]; - qcb->csr[index].ip2s_lo = buf[pos++]; - qcb->csr[index].ip2s_hi = buf[pos++]; - qcb->csr[index].protocol = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[0] = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[1] = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[2] = buf[pos++]; - qcb->csr[index].ipsrc_addrmask[3] = buf[pos++]; - qcb->csr[index].ipsrc_addr[0] = buf[pos++]; - qcb->csr[index].ipsrc_addr[1] = buf[pos++]; - qcb->csr[index].ipsrc_addr[2] = buf[pos++]; - qcb->csr[index].ipsrc_addr[3] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[0] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[1] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[2] = buf[pos++]; - qcb->csr[index].ipdst_addrmask[3] = buf[pos++]; - qcb->csr[index].ipdst_addr[0] = buf[pos++]; - qcb->csr[index].ipdst_addr[1] = buf[pos++]; - qcb->csr[index].ipdst_addr[2] = buf[pos++]; - qcb->csr[index].ipdst_addr[3] = buf[pos++]; - qcb->csr[index].srcport_lo = ((buf[pos++] << 8) & 0xff00); - qcb->csr[index].srcport_lo += buf[pos++]; - qcb->csr[index].srcport_hi = ((buf[pos++] << 8) & 0xff00); - qcb->csr[index].srcport_hi += buf[pos++]; - qcb->csr[index].dstport_lo = ((buf[pos++] << 8) & 0xff00); - qcb->csr[index].dstport_lo += buf[pos++]; - qcb->csr[index].dstport_hi = ((buf[pos++] << 8) & 0xff00); - qcb->csr[index].dstport_hi += buf[pos++]; - - qcb->qos_limit_size = 254 / qcb->qos_list_cnt; - spin_unlock_irqrestore(&qcb->qos_lock, flags); - } else if (sub_cmd_evt == QOS_CHANGE_DEL) { - netdev_dbg(nic->netdev, "QOS_CHANGE_DEL SFID = 0x%x, index=%d\n", - sfid, index); - - INIT_LIST_HEAD(&free_list); - - spin_lock_irqsave(&qcb->qos_lock, flags); - qcb->csr[index].enabled = false; - qcb->qos_list_cnt--; - qcb->qos_limit_size = 254 / qcb->qos_list_cnt; - - list_for_each_entry_safe(entry, n, &qcb->qos_list[index], - list) { - list_move_tail(&entry->list, &free_list); - } - spin_unlock_irqrestore(&qcb->qos_lock, flags); - free_qos_entry_list(&free_list); - } -} diff --git a/drivers/staging/gdm72xx/gdm_qos.h b/drivers/staging/gdm72xx/gdm_qos.h deleted file mode 100644 index bbc8aab33..000000000 --- a/drivers/staging/gdm72xx/gdm_qos.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_GDM_QOS_H__ -#define __GDM72XX_GDM_QOS_H__ - -#include -#include -#include - -#define QOS_MAX 16 -#define IPTYPEOFSERVICE 0x8000 -#define PROTOCOL 0x4000 -#define IPMASKEDSRCADDRESS 0x2000 -#define IPMASKEDDSTADDRESS 0x1000 -#define PROTOCOLSRCPORTRANGE 0x800 -#define PROTOCOLDSTPORTRANGE 0x400 -#define DSTMACADDR 0x200 -#define SRCMACADDR 0x100 -#define ETHERTYPE 0x80 -#define IEEE802_1DUSERPRIORITY 0x40 -#define IEEE802_1QVLANID 0x10 - -struct gdm_wimax_csr_s { - bool enabled; - u32 sfid; - u8 qos_buf_count; - u16 classifier_rule_en; - u8 ip2s_lo; - u8 ip2s_hi; - u8 ip2s_mask; - u8 protocol; - u8 ipsrc_addr[16]; - u8 ipsrc_addrmask[16]; - u8 ipdst_addr[16]; - u8 ipdst_addrmask[16]; - u16 srcport_lo; - u16 srcport_hi; - u16 dstport_lo; - u16 dstport_hi; -}; - -struct qos_entry_s { - struct list_head list; - struct sk_buff *skb; - struct net_device *dev; - -}; - -struct qos_cb_s { - struct list_head qos_list[QOS_MAX]; - int qos_list_cnt; - int qos_null_idx; - struct gdm_wimax_csr_s csr[QOS_MAX]; - spinlock_t qos_lock; - int qos_limit_size; -}; - -void gdm_qos_init(void *nic_ptr); -void gdm_qos_release_list(void *nic_ptr); -int gdm_qos_send_hci_pkt(struct sk_buff *skb, struct net_device *dev); -void gdm_recv_qos_hci_packet(void *nic_ptr, u8 *buf, int size); - -#endif /* __GDM72XX_GDM_QOS_H__ */ diff --git a/drivers/staging/gdm72xx/gdm_sdio.c b/drivers/staging/gdm72xx/gdm_sdio.c deleted file mode 100644 index 1f5a08772..000000000 --- a/drivers/staging/gdm72xx/gdm_sdio.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "gdm_sdio.h" -#include "gdm_wimax.h" -#include "sdio_boot.h" -#include "hci.h" - -#define TYPE_A_HEADER_SIZE 4 -#define TYPE_A_LOOKAHEAD_SIZE 16 - -#define MAX_NR_RX_BUF 4 - -#define SDU_TX_BUF_SIZE 2048 -#define TX_BUF_SIZE 2048 -#define TX_CHUNK_SIZE (2048 - TYPE_A_HEADER_SIZE) -#define RX_BUF_SIZE (25*1024) - -#define TX_HZ 2000 -#define TX_INTERVAL (NSEC_PER_SEC/TX_HZ) - -static struct sdio_tx *alloc_tx_struct(struct tx_cxt *tx) -{ - struct sdio_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC); - - if (!t) - return NULL; - - t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC); - if (!t->buf) { - kfree(t); - return NULL; - } - - t->tx_cxt = tx; - - return t; -} - -static void free_tx_struct(struct sdio_tx *t) -{ - if (t) { - kfree(t->buf); - kfree(t); - } -} - -static struct sdio_rx *alloc_rx_struct(struct rx_cxt *rx) -{ - struct sdio_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC); - - if (r) - r->rx_cxt = rx; - - return r; -} - -static void free_rx_struct(struct sdio_rx *r) -{ - kfree(r); -} - -/* Before this function is called, spin lock should be locked. */ -static struct sdio_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc) -{ - struct sdio_tx *t; - - if (list_empty(&tx->free_list)) - return NULL; - - t = list_entry(tx->free_list.prev, struct sdio_tx, list); - list_del(&t->list); - - *no_spc = list_empty(&tx->free_list) ? 1 : 0; - - return t; -} - -/* Before this function is called, spin lock should be locked. */ -static void put_tx_struct(struct tx_cxt *tx, struct sdio_tx *t) -{ - list_add_tail(&t->list, &tx->free_list); -} - -/* Before this function is called, spin lock should be locked. */ -static struct sdio_rx *get_rx_struct(struct rx_cxt *rx) -{ - struct sdio_rx *r; - - if (list_empty(&rx->free_list)) - return NULL; - - r = list_entry(rx->free_list.prev, struct sdio_rx, list); - list_del(&r->list); - - return r; -} - -/* Before this function is called, spin lock should be locked. */ -static void put_rx_struct(struct rx_cxt *rx, struct sdio_rx *r) -{ - list_add_tail(&r->list, &rx->free_list); -} - -static void release_sdio(struct sdiowm_dev *sdev) -{ - struct tx_cxt *tx = &sdev->tx; - struct rx_cxt *rx = &sdev->rx; - struct sdio_tx *t, *t_next; - struct sdio_rx *r, *r_next; - - kfree(tx->sdu_buf); - - list_for_each_entry_safe(t, t_next, &tx->free_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - list_for_each_entry_safe(t, t_next, &tx->hci_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - kfree(rx->rx_buf); - - list_for_each_entry_safe(r, r_next, &rx->free_list, list) { - list_del(&r->list); - free_rx_struct(r); - } - - list_for_each_entry_safe(r, r_next, &rx->req_list, list) { - list_del(&r->list); - free_rx_struct(r); - } -} - -static int init_sdio(struct sdiowm_dev *sdev) -{ - int ret = 0, i; - struct tx_cxt *tx = &sdev->tx; - struct rx_cxt *rx = &sdev->rx; - struct sdio_tx *t; - struct sdio_rx *r; - - INIT_LIST_HEAD(&tx->free_list); - INIT_LIST_HEAD(&tx->sdu_list); - INIT_LIST_HEAD(&tx->hci_list); - - spin_lock_init(&tx->lock); - - tx->sdu_buf = kmalloc(SDU_TX_BUF_SIZE, GFP_KERNEL); - if (!tx->sdu_buf) - goto fail; - - for (i = 0; i < MAX_NR_SDU_BUF; i++) { - t = alloc_tx_struct(tx); - if (!t) { - ret = -ENOMEM; - goto fail; - } - list_add(&t->list, &tx->free_list); - } - - INIT_LIST_HEAD(&rx->free_list); - INIT_LIST_HEAD(&rx->req_list); - - spin_lock_init(&rx->lock); - - for (i = 0; i < MAX_NR_RX_BUF; i++) { - r = alloc_rx_struct(rx); - if (!r) { - ret = -ENOMEM; - goto fail; - } - list_add(&r->list, &rx->free_list); - } - - rx->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); - if (!rx->rx_buf) - goto fail; - - return 0; - -fail: - release_sdio(sdev); - return ret; -} - -static void send_sdio_pkt(struct sdio_func *func, u8 *data, int len) -{ - int n, blocks, ret, remain; - - sdio_claim_host(func); - - blocks = len / func->cur_blksize; - n = blocks * func->cur_blksize; - if (blocks) { - ret = sdio_memcpy_toio(func, 0, data, n); - if (ret < 0) { - if (ret != -ENOMEDIUM) - dev_err(&func->dev, - "gdmwms: error: ret = %d\n", ret); - goto end_io; - } - } - - remain = len - n; - remain = (remain + 3) & ~3; - - if (remain) { - ret = sdio_memcpy_toio(func, 0, data + n, remain); - if (ret < 0) { - if (ret != -ENOMEDIUM) - dev_err(&func->dev, - "gdmwms: error: ret = %d\n", ret); - goto end_io; - } - } - -end_io: - sdio_release_host(func); -} - -static void send_sdu(struct sdio_func *func, struct tx_cxt *tx) -{ - struct list_head *l, *next; - struct hci_s *hci; - struct sdio_tx *t; - int pos, len, i, estlen, aggr_num = 0, aggr_len; - u8 *buf; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - - pos = TYPE_A_HEADER_SIZE + HCI_HEADER_SIZE; - list_for_each_entry(t, &tx->sdu_list, list) { - estlen = ((t->len + 3) & ~3) + 4; - if ((pos + estlen) > SDU_TX_BUF_SIZE) - break; - - aggr_num++; - memcpy(tx->sdu_buf + pos, t->buf, t->len); - memset(tx->sdu_buf + pos + t->len, 0, estlen - t->len); - pos += estlen; - } - aggr_len = pos; - - hci = (struct hci_s *)(tx->sdu_buf + TYPE_A_HEADER_SIZE); - hci->cmd_evt = cpu_to_be16(WIMAX_TX_SDU_AGGR); - hci->length = cpu_to_be16(aggr_len - TYPE_A_HEADER_SIZE - - HCI_HEADER_SIZE); - - spin_unlock_irqrestore(&tx->lock, flags); - - dev_dbg(&func->dev, "sdio_send: %*ph\n", aggr_len - TYPE_A_HEADER_SIZE, - tx->sdu_buf + TYPE_A_HEADER_SIZE); - - for (pos = TYPE_A_HEADER_SIZE; pos < aggr_len; pos += TX_CHUNK_SIZE) { - len = aggr_len - pos; - len = len > TX_CHUNK_SIZE ? TX_CHUNK_SIZE : len; - buf = tx->sdu_buf + pos - TYPE_A_HEADER_SIZE; - - buf[0] = len & 0xff; - buf[1] = (len >> 8) & 0xff; - buf[2] = (len >> 16) & 0xff; - buf[3] = (pos + len) >= aggr_len ? 0 : 1; - send_sdio_pkt(func, buf, len + TYPE_A_HEADER_SIZE); - } - - spin_lock_irqsave(&tx->lock, flags); - - for (l = tx->sdu_list.next, i = 0; i < aggr_num; i++, l = next) { - next = l->next; - t = list_entry(l, struct sdio_tx, list); - if (t->callback) - t->callback(t->cb_data); - - list_del(l); - put_tx_struct(t->tx_cxt, t); - } - - tx->sdu_stamp = ktime_get(); - spin_unlock_irqrestore(&tx->lock, flags); -} - -static void send_hci(struct sdio_func *func, struct tx_cxt *tx, - struct sdio_tx *t) -{ - unsigned long flags; - - dev_dbg(&func->dev, "sdio_send: %*ph\n", t->len - TYPE_A_HEADER_SIZE, - t->buf + TYPE_A_HEADER_SIZE); - - send_sdio_pkt(func, t->buf, t->len); - - spin_lock_irqsave(&tx->lock, flags); - if (t->callback) - t->callback(t->cb_data); - free_tx_struct(t); - spin_unlock_irqrestore(&tx->lock, flags); -} - -static void do_tx(struct work_struct *work) -{ - struct sdiowm_dev *sdev = container_of(work, struct sdiowm_dev, ws); - struct sdio_func *func = sdev->func; - struct tx_cxt *tx = &sdev->tx; - struct sdio_tx *t = NULL; - ktime_t now, before; - int is_sdu = 0; - long diff; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - if (!tx->can_send) { - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - - if (!list_empty(&tx->hci_list)) { - t = list_entry(tx->hci_list.next, struct sdio_tx, list); - list_del(&t->list); - is_sdu = 0; - } else if (!tx->stop_sdu_tx && !list_empty(&tx->sdu_list)) { - now = ktime_get(); - before = tx->sdu_stamp; - - diff = ktime_to_ns(ktime_sub(now, before)); - if (diff >= 0 && diff < TX_INTERVAL) { - schedule_work(&sdev->ws); - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - is_sdu = 1; - } - - if (!is_sdu && !t) { - spin_unlock_irqrestore(&tx->lock, flags); - return; - } - - tx->can_send = 0; - - spin_unlock_irqrestore(&tx->lock, flags); - - if (is_sdu) - send_sdu(func, tx); - else - send_hci(func, tx, t); -} - -static int gdm_sdio_send(void *priv_dev, void *data, int len, - void (*cb)(void *data), void *cb_data) -{ - struct sdiowm_dev *sdev = priv_dev; - struct tx_cxt *tx = &sdev->tx; - struct sdio_tx *t; - u8 *pkt = data; - int no_spc = 0; - u16 cmd_evt; - unsigned long flags; - - if (len > TX_BUF_SIZE - TYPE_A_HEADER_SIZE) - return -EINVAL; - - spin_lock_irqsave(&tx->lock, flags); - - cmd_evt = (pkt[0] << 8) | pkt[1]; - if (cmd_evt == WIMAX_TX_SDU) { - t = get_tx_struct(tx, &no_spc); - if (!t) { - /* This case must not happen. */ - spin_unlock_irqrestore(&tx->lock, flags); - return -ENOSPC; - } - list_add_tail(&t->list, &tx->sdu_list); - - memcpy(t->buf, data, len); - - t->len = len; - t->callback = cb; - t->cb_data = cb_data; - } else { - t = alloc_tx_struct(tx); - if (!t) { - spin_unlock_irqrestore(&tx->lock, flags); - return -ENOMEM; - } - list_add_tail(&t->list, &tx->hci_list); - - t->buf[0] = len & 0xff; - t->buf[1] = (len >> 8) & 0xff; - t->buf[2] = (len >> 16) & 0xff; - t->buf[3] = 2; - memcpy(t->buf + TYPE_A_HEADER_SIZE, data, len); - - t->len = len + TYPE_A_HEADER_SIZE; - t->callback = cb; - t->cb_data = cb_data; - } - - if (tx->can_send) - schedule_work(&sdev->ws); - - spin_unlock_irqrestore(&tx->lock, flags); - - if (no_spc) - return -ENOSPC; - - return 0; -} - -/* Handle the HCI, WIMAX_SDU_TX_FLOW. */ -static int control_sdu_tx_flow(struct sdiowm_dev *sdev, u8 *hci_data, int len) -{ - struct tx_cxt *tx = &sdev->tx; - u16 cmd_evt; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - - cmd_evt = (hci_data[0] << 8) | (hci_data[1]); - if (cmd_evt != WIMAX_SDU_TX_FLOW) - goto out; - - if (hci_data[4] == 0) { - dev_dbg(&sdev->func->dev, "WIMAX ==> STOP SDU TX\n"); - tx->stop_sdu_tx = 1; - } else if (hci_data[4] == 1) { - dev_dbg(&sdev->func->dev, "WIMAX ==> START SDU TX\n"); - tx->stop_sdu_tx = 0; - if (tx->can_send) - schedule_work(&sdev->ws); - /* If free buffer for sdu tx doesn't exist, then tx queue - * should not be woken. For this reason, don't pass the command, - * START_SDU_TX. - */ - if (list_empty(&tx->free_list)) - len = 0; - } - -out: - spin_unlock_irqrestore(&tx->lock, flags); - return len; -} - -static void gdm_sdio_irq(struct sdio_func *func) -{ - struct phy_dev *phy_dev = sdio_get_drvdata(func); - struct sdiowm_dev *sdev = phy_dev->priv_dev; - struct tx_cxt *tx = &sdev->tx; - struct rx_cxt *rx = &sdev->rx; - struct sdio_rx *r; - unsigned long flags; - u8 val, hdr[TYPE_A_LOOKAHEAD_SIZE], *buf; - u32 len, blocks, n; - int ret, remain; - - /* Check interrupt */ - val = sdio_readb(func, 0x13, &ret); - if (val & 0x01) - sdio_writeb(func, 0x01, 0x13, &ret); /* clear interrupt */ - else - return; - - ret = sdio_memcpy_fromio(func, hdr, 0x0, TYPE_A_LOOKAHEAD_SIZE); - if (ret) { - dev_err(&func->dev, - "Cannot read from function %d\n", func->num); - goto done; - } - - len = (hdr[2] << 16) | (hdr[1] << 8) | hdr[0]; - if (len > (RX_BUF_SIZE - TYPE_A_HEADER_SIZE)) { - dev_err(&func->dev, "Too big Type-A size: %d\n", len); - goto done; - } - - if (hdr[3] == 1) { /* Ack */ - u32 *ack_seq = (u32 *)&hdr[4]; - - spin_lock_irqsave(&tx->lock, flags); - tx->can_send = 1; - - if (!list_empty(&tx->sdu_list) || !list_empty(&tx->hci_list)) - schedule_work(&sdev->ws); - spin_unlock_irqrestore(&tx->lock, flags); - dev_dbg(&func->dev, "Ack... %0x\n", ntohl(*ack_seq)); - goto done; - } - - memcpy(rx->rx_buf, hdr + TYPE_A_HEADER_SIZE, - TYPE_A_LOOKAHEAD_SIZE - TYPE_A_HEADER_SIZE); - - buf = rx->rx_buf + TYPE_A_LOOKAHEAD_SIZE - TYPE_A_HEADER_SIZE; - remain = len - TYPE_A_LOOKAHEAD_SIZE + TYPE_A_HEADER_SIZE; - if (remain <= 0) - goto end_io; - - blocks = remain / func->cur_blksize; - - if (blocks) { - n = blocks * func->cur_blksize; - ret = sdio_memcpy_fromio(func, buf, 0x0, n); - if (ret) { - dev_err(&func->dev, - "Cannot read from function %d\n", func->num); - goto done; - } - buf += n; - remain -= n; - } - - if (remain) { - ret = sdio_memcpy_fromio(func, buf, 0x0, remain); - if (ret) { - dev_err(&func->dev, - "Cannot read from function %d\n", func->num); - goto done; - } - } - -end_io: - dev_dbg(&func->dev, "sdio_receive: %*ph\n", len, rx->rx_buf); - - len = control_sdu_tx_flow(sdev, rx->rx_buf, len); - - spin_lock_irqsave(&rx->lock, flags); - - if (!list_empty(&rx->req_list)) { - r = list_entry(rx->req_list.next, struct sdio_rx, list); - spin_unlock_irqrestore(&rx->lock, flags); - if (r->callback) - r->callback(r->cb_data, rx->rx_buf, len); - spin_lock_irqsave(&rx->lock, flags); - list_del(&r->list); - put_rx_struct(rx, r); - } - - spin_unlock_irqrestore(&rx->lock, flags); - -done: - sdio_writeb(func, 0x00, 0x10, &ret); /* PCRRT */ - if (!phy_dev->netdev) - register_wimax_device(phy_dev, &func->dev); -} - -static int gdm_sdio_receive(void *priv_dev, - void (*cb)(void *cb_data, void *data, int len), - void *cb_data) -{ - struct sdiowm_dev *sdev = priv_dev; - struct rx_cxt *rx = &sdev->rx; - struct sdio_rx *r; - unsigned long flags; - - spin_lock_irqsave(&rx->lock, flags); - r = get_rx_struct(rx); - if (!r) { - spin_unlock_irqrestore(&rx->lock, flags); - return -ENOMEM; - } - - r->callback = cb; - r->cb_data = cb_data; - - list_add_tail(&r->list, &rx->req_list); - spin_unlock_irqrestore(&rx->lock, flags); - - return 0; -} - -static int sdio_wimax_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - int ret; - struct phy_dev *phy_dev = NULL; - struct sdiowm_dev *sdev = NULL; - - dev_info(&func->dev, "Found GDM SDIO VID = 0x%04x PID = 0x%04x...\n", - func->vendor, func->device); - dev_info(&func->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION); - - sdio_claim_host(func); - sdio_enable_func(func); - sdio_claim_irq(func, gdm_sdio_irq); - - ret = sdio_boot(func); - if (ret) - return ret; - - phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL); - if (!phy_dev) { - ret = -ENOMEM; - goto out; - } - sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); - if (!sdev) { - ret = -ENOMEM; - goto out; - } - - phy_dev->priv_dev = (void *)sdev; - phy_dev->send_func = gdm_sdio_send; - phy_dev->rcv_func = gdm_sdio_receive; - - ret = init_sdio(sdev); - if (ret < 0) - goto out; - - sdev->func = func; - - sdio_writeb(func, 1, 0x14, &ret); /* Enable interrupt */ - sdio_release_host(func); - - INIT_WORK(&sdev->ws, do_tx); - - sdio_set_drvdata(func, phy_dev); -out: - if (ret) { - kfree(phy_dev); - kfree(sdev); - } - - return ret; -} - -static void sdio_wimax_remove(struct sdio_func *func) -{ - struct phy_dev *phy_dev = sdio_get_drvdata(func); - struct sdiowm_dev *sdev = phy_dev->priv_dev; - - cancel_work_sync(&sdev->ws); - if (phy_dev->netdev) - unregister_wimax_device(phy_dev); - sdio_claim_host(func); - sdio_release_irq(func); - sdio_disable_func(func); - sdio_release_host(func); - release_sdio(sdev); - - kfree(sdev); - kfree(phy_dev); -} - -static const struct sdio_device_id sdio_wimax_ids[] = { - { SDIO_DEVICE(0x0296, 0x5347) }, - {0} -}; - -MODULE_DEVICE_TABLE(sdio, sdio_wimax_ids); - -static struct sdio_driver sdio_wimax_driver = { - .probe = sdio_wimax_probe, - .remove = sdio_wimax_remove, - .name = "sdio_wimax", - .id_table = sdio_wimax_ids, -}; - -static int __init sdio_gdm_wimax_init(void) -{ - return sdio_register_driver(&sdio_wimax_driver); -} - -static void __exit sdio_gdm_wimax_exit(void) -{ - sdio_unregister_driver(&sdio_wimax_driver); -} - -module_init(sdio_gdm_wimax_init); -module_exit(sdio_gdm_wimax_exit); - -MODULE_VERSION(DRIVER_VERSION); -MODULE_DESCRIPTION("GCT WiMax SDIO Device Driver"); -MODULE_AUTHOR("Ethan Park"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gdm72xx/gdm_sdio.h b/drivers/staging/gdm72xx/gdm_sdio.h deleted file mode 100644 index aa7dad22a..000000000 --- a/drivers/staging/gdm72xx/gdm_sdio.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_GDM_SDIO_H__ -#define __GDM72XX_GDM_SDIO_H__ - -#include -#include - -#define MAX_NR_SDU_BUF 64 - -struct sdio_tx { - struct list_head list; - struct tx_cxt *tx_cxt; - u8 *buf; - int len; - void (*callback)(void *cb_data); - void *cb_data; -}; - -struct tx_cxt { - struct list_head free_list; - struct list_head sdu_list; - struct list_head hci_list; - ktime_t sdu_stamp; - u8 *sdu_buf; - spinlock_t lock; - int can_send; - int stop_sdu_tx; -}; - -struct sdio_rx { - struct list_head list; - struct rx_cxt *rx_cxt; - void (*callback)(void *cb_data, void *data, int len); - void *cb_data; -}; - -struct rx_cxt { - struct list_head free_list; - struct list_head req_list; - u8 *rx_buf; - spinlock_t lock; -}; - -struct sdiowm_dev { - struct sdio_func *func; - struct tx_cxt tx; - struct rx_cxt rx; - struct work_struct ws; -}; - -#endif /* __GDM72XX_GDM_SDIO_H__ */ diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c deleted file mode 100644 index 16e497d9d..000000000 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include - -#include "gdm_usb.h" -#include "gdm_wimax.h" -#include "usb_boot.h" -#include "hci.h" - -#include "usb_ids.h" - -MODULE_DEVICE_TABLE(usb, id_table); - -#define TX_BUF_SIZE 2048 - -#if defined(CONFIG_WIMAX_GDM72XX_WIMAX2) -#define RX_BUF_SIZE (128*1024) /* For packet aggregation */ -#else -#define RX_BUF_SIZE 2048 -#endif - -#define GDM7205_PADDING 256 - -#define DOWNLOAD_CONF_VALUE 0x21 - -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE - -static DECLARE_WAIT_QUEUE_HEAD(k_wait); -static LIST_HEAD(k_list); -static DEFINE_SPINLOCK(k_lock); -static int k_mode_stop; - -#define K_WAIT_TIME (2 * HZ / 100) - -#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ - -static struct usb_tx *alloc_tx_struct(struct tx_cxt *tx) -{ - struct usb_tx *t = kzalloc(sizeof(*t), GFP_ATOMIC); - - if (!t) - return NULL; - - t->urb = usb_alloc_urb(0, GFP_ATOMIC); - t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC); - if (!t->urb || !t->buf) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - return NULL; - } - - t->tx_cxt = tx; - - return t; -} - -static void free_tx_struct(struct usb_tx *t) -{ - if (t) { - usb_free_urb(t->urb); - kfree(t->buf); - kfree(t); - } -} - -static struct usb_rx *alloc_rx_struct(struct rx_cxt *rx) -{ - struct usb_rx *r = kzalloc(sizeof(*r), GFP_ATOMIC); - - if (!r) - return NULL; - - r->urb = usb_alloc_urb(0, GFP_ATOMIC); - r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC); - if (!r->urb || !r->buf) { - usb_free_urb(r->urb); - kfree(r->buf); - kfree(r); - return NULL; - } - - r->rx_cxt = rx; - return r; -} - -static void free_rx_struct(struct usb_rx *r) -{ - if (r) { - usb_free_urb(r->urb); - kfree(r->buf); - kfree(r); - } -} - -/* Before this function is called, spin lock should be locked. */ -static struct usb_tx *get_tx_struct(struct tx_cxt *tx, int *no_spc) -{ - struct usb_tx *t; - - if (list_empty(&tx->free_list)) { - *no_spc = 1; - return NULL; - } - - t = list_entry(tx->free_list.next, struct usb_tx, list); - list_del(&t->list); - - *no_spc = list_empty(&tx->free_list) ? 1 : 0; - - return t; -} - -/* Before this function is called, spin lock should be locked. */ -static void put_tx_struct(struct tx_cxt *tx, struct usb_tx *t) -{ - list_add_tail(&t->list, &tx->free_list); -} - -/* Before this function is called, spin lock should be locked. */ -static struct usb_rx *get_rx_struct(struct rx_cxt *rx) -{ - struct usb_rx *r; - - if (list_empty(&rx->free_list)) { - r = alloc_rx_struct(rx); - if (!r) - return NULL; - - list_add(&r->list, &rx->free_list); - } - - r = list_entry(rx->free_list.next, struct usb_rx, list); - list_move_tail(&r->list, &rx->used_list); - - return r; -} - -/* Before this function is called, spin lock should be locked. */ -static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r) -{ - list_move(&r->list, &rx->free_list); -} - -static void release_usb(struct usbwm_dev *udev) -{ - struct tx_cxt *tx = &udev->tx; - struct rx_cxt *rx = &udev->rx; - struct usb_tx *t, *t_next; - struct usb_rx *r, *r_next; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - - list_for_each_entry_safe(t, t_next, &tx->sdu_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - list_for_each_entry_safe(t, t_next, &tx->hci_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - list_for_each_entry_safe(t, t_next, &tx->free_list, list) { - list_del(&t->list); - free_tx_struct(t); - } - - spin_unlock_irqrestore(&tx->lock, flags); - - spin_lock_irqsave(&rx->lock, flags); - - list_for_each_entry_safe(r, r_next, &rx->free_list, list) { - list_del(&r->list); - free_rx_struct(r); - } - - list_for_each_entry_safe(r, r_next, &rx->used_list, list) { - list_del(&r->list); - free_rx_struct(r); - } - - spin_unlock_irqrestore(&rx->lock, flags); -} - -static int init_usb(struct usbwm_dev *udev) -{ - int ret = 0, i; - struct tx_cxt *tx = &udev->tx; - struct rx_cxt *rx = &udev->rx; - struct usb_tx *t; - struct usb_rx *r; - unsigned long flags; - - INIT_LIST_HEAD(&tx->free_list); - INIT_LIST_HEAD(&tx->sdu_list); - INIT_LIST_HEAD(&tx->hci_list); -#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE) - INIT_LIST_HEAD(&tx->pending_list); -#endif - - INIT_LIST_HEAD(&rx->free_list); - INIT_LIST_HEAD(&rx->used_list); - - spin_lock_init(&tx->lock); - spin_lock_init(&rx->lock); - - spin_lock_irqsave(&tx->lock, flags); - for (i = 0; i < MAX_NR_SDU_BUF; i++) { - t = alloc_tx_struct(tx); - if (!t) { - spin_unlock_irqrestore(&tx->lock, flags); - ret = -ENOMEM; - goto fail; - } - list_add(&t->list, &tx->free_list); - } - spin_unlock_irqrestore(&tx->lock, flags); - - r = alloc_rx_struct(rx); - if (!r) { - ret = -ENOMEM; - goto fail; - } - - spin_lock_irqsave(&rx->lock, flags); - list_add(&r->list, &rx->free_list); - spin_unlock_irqrestore(&rx->lock, flags); - return ret; - -fail: - release_usb(udev); - return ret; -} - -static void __gdm_usb_send_complete(struct urb *urb) -{ - struct usb_tx *t = urb->context; - struct tx_cxt *tx = t->tx_cxt; - u8 *pkt = t->buf; - u16 cmd_evt; - - /* Completion by usb_unlink_urb */ - if (urb->status == -ECONNRESET) - return; - - if (t->callback) - t->callback(t->cb_data); - - /* Delete from sdu list or hci list. */ - list_del(&t->list); - - cmd_evt = (pkt[0] << 8) | pkt[1]; - if (cmd_evt == WIMAX_TX_SDU) - put_tx_struct(tx, t); - else - free_tx_struct(t); -} - -static void gdm_usb_send_complete(struct urb *urb) -{ - struct usb_tx *t = urb->context; - struct tx_cxt *tx = t->tx_cxt; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - __gdm_usb_send_complete(urb); - spin_unlock_irqrestore(&tx->lock, flags); -} - -static int gdm_usb_send(void *priv_dev, void *data, int len, - void (*cb)(void *data), void *cb_data) -{ - struct usbwm_dev *udev = priv_dev; - struct usb_device *usbdev = udev->usbdev; - struct tx_cxt *tx = &udev->tx; - struct usb_tx *t; - int padding = udev->padding; - int no_spc = 0, ret; - u8 *pkt = data; - u16 cmd_evt; - unsigned long flags; -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE - unsigned long flags2; -#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ - - if (!udev->usbdev) { - dev_err(&usbdev->dev, "%s: No such device\n", __func__); - return -ENODEV; - } - - if (len > TX_BUF_SIZE - padding - 1) - return -EINVAL; - - spin_lock_irqsave(&tx->lock, flags); - - cmd_evt = (pkt[0] << 8) | pkt[1]; - if (cmd_evt == WIMAX_TX_SDU) { - t = get_tx_struct(tx, &no_spc); - if (!t) { - /* This case must not happen. */ - spin_unlock_irqrestore(&tx->lock, flags); - return -ENOSPC; - } - list_add_tail(&t->list, &tx->sdu_list); - } else { - t = alloc_tx_struct(tx); - if (!t) { - spin_unlock_irqrestore(&tx->lock, flags); - return -ENOMEM; - } - list_add_tail(&t->list, &tx->hci_list); - } - - memcpy(t->buf + padding, data, len); - t->callback = cb; - t->cb_data = cb_data; - - /* In some cases, USB Module of WiMax is blocked when data size is - * the multiple of 512. So, increment length by one in that case. - */ - if ((len % 512) == 0) - len++; - - usb_fill_bulk_urb(t->urb, usbdev, usb_sndbulkpipe(usbdev, 1), t->buf, - len + padding, gdm_usb_send_complete, t); - - dev_dbg(&usbdev->dev, "usb_send: %*ph\n", len + padding, t->buf); - -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM - if (usbdev->state & USB_STATE_SUSPENDED) { - list_add_tail(&t->p_list, &tx->pending_list); - schedule_work(&udev->pm_ws); - goto out; - } -#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ - -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE - if (udev->bw_switch) { - list_add_tail(&t->p_list, &tx->pending_list); - goto out; - } else if (cmd_evt == WIMAX_SCAN) { - struct rx_cxt *rx; - struct usb_rx *r; - - rx = &udev->rx; - - spin_lock_irqsave(&rx->lock, flags2); - list_for_each_entry(r, &rx->used_list, list) - usb_unlink_urb(r->urb); - spin_unlock_irqrestore(&rx->lock, flags2); - - udev->bw_switch = 1; - - spin_lock_irqsave(&k_lock, flags2); - list_add_tail(&udev->list, &k_list); - spin_unlock_irqrestore(&k_lock, flags2); - - wake_up(&k_wait); - } -#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ - - ret = usb_submit_urb(t->urb, GFP_ATOMIC); - if (ret) - goto send_fail; - -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM - usb_mark_last_busy(usbdev); -#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ - -#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE) -out: -#endif - spin_unlock_irqrestore(&tx->lock, flags); - - if (no_spc) - return -ENOSPC; - - return 0; - -send_fail: - t->callback = NULL; - __gdm_usb_send_complete(t->urb); - spin_unlock_irqrestore(&tx->lock, flags); - return ret; -} - -static void gdm_usb_rcv_complete(struct urb *urb) -{ - struct usb_rx *r = urb->context; - struct rx_cxt *rx = r->rx_cxt; - struct usbwm_dev *udev = container_of(r->rx_cxt, struct usbwm_dev, rx); - struct tx_cxt *tx = &udev->tx; - struct usb_tx *t; - u16 cmd_evt; - unsigned long flags, flags2; - struct usb_device *dev = urb->dev; - - /* Completion by usb_unlink_urb */ - if (urb->status == -ECONNRESET) - return; - - spin_lock_irqsave(&tx->lock, flags); - - if (!urb->status) { - cmd_evt = (r->buf[0] << 8) | (r->buf[1]); - - dev_dbg(&dev->dev, "usb_receive: %*ph\n", urb->actual_length, - r->buf); - - if (cmd_evt == WIMAX_SDU_TX_FLOW) { - if (r->buf[4] == 0) { - dev_dbg(&dev->dev, "WIMAX ==> STOP SDU TX\n"); - list_for_each_entry(t, &tx->sdu_list, list) - usb_unlink_urb(t->urb); - } else if (r->buf[4] == 1) { - dev_dbg(&dev->dev, "WIMAX ==> START SDU TX\n"); - list_for_each_entry(t, &tx->sdu_list, list) { - usb_submit_urb(t->urb, GFP_ATOMIC); - } - /* If free buffer for sdu tx doesn't - * exist, then tx queue should not be - * woken. For this reason, don't pass - * the command, START_SDU_TX. - */ - if (list_empty(&tx->free_list)) - urb->actual_length = 0; - } - } - } - - if (!urb->status && r->callback) - r->callback(r->cb_data, r->buf, urb->actual_length); - - spin_lock_irqsave(&rx->lock, flags2); - put_rx_struct(rx, r); - spin_unlock_irqrestore(&rx->lock, flags2); - - spin_unlock_irqrestore(&tx->lock, flags); - -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM - usb_mark_last_busy(dev); -#endif -} - -static int gdm_usb_receive(void *priv_dev, - void (*cb)(void *cb_data, void *data, int len), - void *cb_data) -{ - struct usbwm_dev *udev = priv_dev; - struct usb_device *usbdev = udev->usbdev; - struct rx_cxt *rx = &udev->rx; - struct usb_rx *r; - unsigned long flags; - - if (!udev->usbdev) { - dev_err(&usbdev->dev, "%s: No such device\n", __func__); - return -ENODEV; - } - - spin_lock_irqsave(&rx->lock, flags); - r = get_rx_struct(rx); - spin_unlock_irqrestore(&rx->lock, flags); - - if (!r) - return -ENOMEM; - - r->callback = cb; - r->cb_data = cb_data; - - usb_fill_bulk_urb(r->urb, usbdev, usb_rcvbulkpipe(usbdev, 0x82), r->buf, - RX_BUF_SIZE, gdm_usb_rcv_complete, r); - - return usb_submit_urb(r->urb, GFP_ATOMIC); -} - -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM -static void do_pm_control(struct work_struct *work) -{ - struct usbwm_dev *udev = container_of(work, struct usbwm_dev, pm_ws); - struct tx_cxt *tx = &udev->tx; - int ret; - unsigned long flags; - - ret = usb_autopm_get_interface(udev->intf); - if (!ret) - usb_autopm_put_interface(udev->intf); - - spin_lock_irqsave(&tx->lock, flags); - if (!(udev->usbdev->state & USB_STATE_SUSPENDED) && - (!list_empty(&tx->hci_list) || !list_empty(&tx->sdu_list))) { - struct usb_tx *t, *temp; - - list_for_each_entry_safe(t, temp, &tx->pending_list, p_list) { - list_del(&t->p_list); - ret = usb_submit_urb(t->urb, GFP_ATOMIC); - - if (ret) { - t->callback = NULL; - __gdm_usb_send_complete(t->urb); - } - } - } - spin_unlock_irqrestore(&tx->lock, flags); -} -#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ - -static int gdm_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int ret = 0; - u8 bConfigurationValue; - struct phy_dev *phy_dev = NULL; - struct usbwm_dev *udev = NULL; - u16 idVendor, idProduct, bcdDevice; - - struct usb_device *usbdev = interface_to_usbdev(intf); - - usb_get_dev(usbdev); - bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue; - - /*USB description is set up with Little-Endian*/ - idVendor = le16_to_cpu(usbdev->descriptor.idVendor); - idProduct = le16_to_cpu(usbdev->descriptor.idProduct); - bcdDevice = le16_to_cpu(usbdev->descriptor.bcdDevice); - - dev_info(&intf->dev, "Found GDM USB VID = 0x%04x PID = 0x%04x...\n", - idVendor, idProduct); - dev_info(&intf->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION); - - - if (idProduct == EMERGENCY_PID) { - ret = usb_emergency(usbdev); - goto out; - } - - /* Support for EEPROM bootloader */ - if (bConfigurationValue == DOWNLOAD_CONF_VALUE || - idProduct & B_DOWNLOAD) { - ret = usb_boot(usbdev, bcdDevice); - goto out; - } - - phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL); - if (!phy_dev) { - ret = -ENOMEM; - goto out; - } - udev = kzalloc(sizeof(*udev), GFP_KERNEL); - if (!udev) { - ret = -ENOMEM; - goto out; - } - - if (idProduct == 0x7205 || idProduct == 0x7206) - udev->padding = GDM7205_PADDING; - else - udev->padding = 0; - - phy_dev->priv_dev = (void *)udev; - phy_dev->send_func = gdm_usb_send; - phy_dev->rcv_func = gdm_usb_receive; - - ret = init_usb(udev); - if (ret < 0) - goto out; - - udev->usbdev = usbdev; - -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM - udev->intf = intf; - - intf->needs_remote_wakeup = 1; - device_init_wakeup(&intf->dev, 1); - - pm_runtime_set_autosuspend_delay(&usbdev->dev, 10 * 1000); /* msec */ - - INIT_WORK(&udev->pm_ws, do_pm_control); -#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ - - ret = register_wimax_device(phy_dev, &intf->dev); - if (ret) - release_usb(udev); - -out: - if (ret) { - kfree(phy_dev); - kfree(udev); - usb_put_dev(usbdev); - } else { - usb_set_intfdata(intf, phy_dev); - } - return ret; -} - -static void gdm_usb_disconnect(struct usb_interface *intf) -{ - u8 bConfigurationValue; - struct phy_dev *phy_dev; - struct usbwm_dev *udev; - u16 idProduct; - struct usb_device *usbdev = interface_to_usbdev(intf); - - bConfigurationValue = usbdev->actconfig->desc.bConfigurationValue; - phy_dev = usb_get_intfdata(intf); - - /*USB description is set up with Little-Endian*/ - idProduct = le16_to_cpu(usbdev->descriptor.idProduct); - - if (idProduct != EMERGENCY_PID && - bConfigurationValue != DOWNLOAD_CONF_VALUE && - (idProduct & B_DOWNLOAD) == 0) { - udev = phy_dev->priv_dev; - udev->usbdev = NULL; - - unregister_wimax_device(phy_dev); - release_usb(udev); - kfree(udev); - kfree(phy_dev); - } - - usb_put_dev(usbdev); -} - -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM -static int gdm_suspend(struct usb_interface *intf, pm_message_t pm_msg) -{ - struct phy_dev *phy_dev; - struct usbwm_dev *udev; - struct rx_cxt *rx; - struct usb_rx *r; - unsigned long flags; - - phy_dev = usb_get_intfdata(intf); - if (!phy_dev) - return 0; - - udev = phy_dev->priv_dev; - rx = &udev->rx; - - spin_lock_irqsave(&rx->lock, flags); - - list_for_each_entry(r, &rx->used_list, list) - usb_unlink_urb(r->urb); - - spin_unlock_irqrestore(&rx->lock, flags); - - return 0; -} - -static int gdm_resume(struct usb_interface *intf) -{ - struct phy_dev *phy_dev; - struct usbwm_dev *udev; - struct rx_cxt *rx; - struct usb_rx *r; - unsigned long flags; - - phy_dev = usb_get_intfdata(intf); - if (!phy_dev) - return 0; - - udev = phy_dev->priv_dev; - rx = &udev->rx; - - spin_lock_irqsave(&rx->lock, flags); - - list_for_each_entry(r, &rx->used_list, list) - usb_submit_urb(r->urb, GFP_ATOMIC); - - spin_unlock_irqrestore(&rx->lock, flags); - - return 0; -} - -#endif /* CONFIG_WIMAX_GDM72XX_USB_PM */ - -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE -static int k_mode_thread(void *arg) -{ - struct usbwm_dev *udev; - struct tx_cxt *tx; - struct rx_cxt *rx; - struct usb_tx *t, *temp; - struct usb_rx *r; - unsigned long flags, flags2, expire; - int ret; - - while (!k_mode_stop) { - spin_lock_irqsave(&k_lock, flags2); - while (!list_empty(&k_list)) { - udev = list_entry(k_list.next, struct usbwm_dev, list); - tx = &udev->tx; - rx = &udev->rx; - - list_del(&udev->list); - spin_unlock_irqrestore(&k_lock, flags2); - - expire = jiffies + K_WAIT_TIME; - while (time_before(jiffies, expire)) - schedule_timeout(K_WAIT_TIME); - - spin_lock_irqsave(&rx->lock, flags); - - list_for_each_entry(r, &rx->used_list, list) - usb_submit_urb(r->urb, GFP_ATOMIC); - - spin_unlock_irqrestore(&rx->lock, flags); - - spin_lock_irqsave(&tx->lock, flags); - - list_for_each_entry_safe(t, temp, &tx->pending_list, - p_list) { - list_del(&t->p_list); - ret = usb_submit_urb(t->urb, GFP_ATOMIC); - - if (ret) { - t->callback = NULL; - __gdm_usb_send_complete(t->urb); - } - } - - udev->bw_switch = 0; - spin_unlock_irqrestore(&tx->lock, flags); - - spin_lock_irqsave(&k_lock, flags2); - } - wait_event_interruptible_lock_irq(k_wait, - !list_empty(&k_list) || - k_mode_stop, k_lock); - spin_unlock_irqrestore(&k_lock, flags2); - } - return 0; -} -#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ - -static struct usb_driver gdm_usb_driver = { - .name = "gdm_wimax", - .probe = gdm_usb_probe, - .disconnect = gdm_usb_disconnect, - .id_table = id_table, -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM - .supports_autosuspend = 1, - .suspend = gdm_suspend, - .resume = gdm_resume, - .reset_resume = gdm_resume, -#endif -}; - -static int __init usb_gdm_wimax_init(void) -{ -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE - kthread_run(k_mode_thread, NULL, "k_mode_wimax"); -#endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ - return usb_register(&gdm_usb_driver); -} - -static void __exit usb_gdm_wimax_exit(void) -{ -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE - k_mode_stop = 1; - wake_up(&k_wait); -#endif - usb_deregister(&gdm_usb_driver); -} - -module_init(usb_gdm_wimax_init); -module_exit(usb_gdm_wimax_exit); - -MODULE_VERSION(DRIVER_VERSION); -MODULE_DESCRIPTION("GCT WiMax Device Driver"); -MODULE_AUTHOR("Ethan Park"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gdm72xx/gdm_usb.h b/drivers/staging/gdm72xx/gdm_usb.h deleted file mode 100644 index 8e58a25e7..000000000 --- a/drivers/staging/gdm72xx/gdm_usb.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_GDM_USB_H__ -#define __GDM72XX_GDM_USB_H__ - -#include -#include -#include - -#define B_DIFF_DL_DRV (1 << 4) -#define B_DOWNLOAD (1 << 5) -#define MAX_NR_SDU_BUF 64 - -struct usb_tx { - struct list_head list; -#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE) - struct list_head p_list; -#endif - struct tx_cxt *tx_cxt; - struct urb *urb; - u8 *buf; - void (*callback)(void *cb_data); - void *cb_data; -}; - -struct tx_cxt { - struct list_head free_list; - struct list_head sdu_list; - struct list_head hci_list; -#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE) - struct list_head pending_list; -#endif - spinlock_t lock; -}; - -struct usb_rx { - struct list_head list; - struct rx_cxt *rx_cxt; - struct urb *urb; - u8 *buf; - void (*callback)(void *cb_data, void *data, int len); - void *cb_data; -}; - -struct rx_cxt { - struct list_head free_list; - struct list_head used_list; - spinlock_t lock; -}; - -struct usbwm_dev { - struct usb_device *usbdev; -#ifdef CONFIG_WIMAX_GDM72XX_USB_PM - struct work_struct pm_ws; - - struct usb_interface *intf; -#endif -#ifdef CONFIG_WIMAX_GDM72XX_K_MODE - int bw_switch; - struct list_head list; -#endif - struct tx_cxt tx; - struct rx_cxt rx; - int padding; -}; - -#endif /* __GDM72XX_GDM_USB_H__ */ diff --git a/drivers/staging/gdm72xx/gdm_wimax.c b/drivers/staging/gdm72xx/gdm_wimax.c deleted file mode 100644 index ba03f9386..000000000 --- a/drivers/staging/gdm72xx/gdm_wimax.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -#include "gdm_wimax.h" -#include "hci.h" -#include "wm_ioctl.h" -#include "netlink_k.h" - -#define gdm_wimax_send(n, d, l) \ - (n->phy_dev->send_func)(n->phy_dev->priv_dev, d, l, NULL, NULL) -#define gdm_wimax_send_with_cb(n, d, l, c, b) \ - (n->phy_dev->send_func)(n->phy_dev->priv_dev, d, l, c, b) -#define gdm_wimax_rcv_with_cb(n, c, b) \ - (n->phy_dev->rcv_func)(n->phy_dev->priv_dev, c, b) - -#define EVT_MAX_SIZE 2048 - -struct evt_entry { - struct list_head list; - struct net_device *dev; - char evt_data[EVT_MAX_SIZE]; - int size; -}; - -static struct { - int ref_cnt; - struct sock *sock; - struct list_head evtq; - spinlock_t evt_lock; - struct list_head freeq; - struct work_struct ws; -} wm_event; - -static u8 gdm_wimax_macaddr[6] = {0x00, 0x0a, 0x3b, 0xf0, 0x01, 0x30}; - -static inline int gdm_wimax_header(struct sk_buff **pskb) -{ - u16 buf[HCI_HEADER_SIZE / sizeof(u16)]; - struct hci_s *hci = (struct hci_s *)buf; - struct sk_buff *skb = *pskb; - - if (unlikely(skb_headroom(skb) < HCI_HEADER_SIZE)) { - struct sk_buff *skb2; - - skb2 = skb_realloc_headroom(skb, HCI_HEADER_SIZE); - if (!skb2) - return -ENOMEM; - if (skb->sk) - skb_set_owner_w(skb2, skb->sk); - kfree_skb(skb); - skb = skb2; - } - - skb_push(skb, HCI_HEADER_SIZE); - hci->cmd_evt = cpu_to_be16(WIMAX_TX_SDU); - hci->length = cpu_to_be16(skb->len - HCI_HEADER_SIZE); - memcpy(skb->data, buf, HCI_HEADER_SIZE); - - *pskb = skb; - return 0; -} - -static inline struct evt_entry *alloc_event_entry(void) -{ - return kmalloc(sizeof(struct evt_entry), GFP_ATOMIC); -} - -static struct evt_entry *get_event_entry(void) -{ - struct evt_entry *e; - - if (list_empty(&wm_event.freeq)) { - e = alloc_event_entry(); - } else { - e = list_entry(wm_event.freeq.next, struct evt_entry, list); - list_del(&e->list); - } - - return e; -} - -static void put_event_entry(struct evt_entry *e) -{ - BUG_ON(!e); - - list_add_tail(&e->list, &wm_event.freeq); -} - -static void gdm_wimax_event_rcv(struct net_device *dev, u16 type, void *msg, - int len) -{ - struct nic *nic = netdev_priv(dev); - - u8 *buf = msg; - u16 hci_cmd = (buf[0]<<8) | buf[1]; - u16 hci_len = (buf[2]<<8) | buf[3]; - - netdev_dbg(dev, "H=>D: 0x%04x(%d)\n", hci_cmd, hci_len); - - gdm_wimax_send(nic, msg, len); -} - -static void __gdm_wimax_event_send(struct work_struct *work) -{ - int idx; - unsigned long flags; - struct evt_entry *e; - struct evt_entry *tmp; - - spin_lock_irqsave(&wm_event.evt_lock, flags); - - list_for_each_entry_safe(e, tmp, &wm_event.evtq, list) { - spin_unlock_irqrestore(&wm_event.evt_lock, flags); - - if (sscanf(e->dev->name, "wm%d", &idx) == 1) - netlink_send(wm_event.sock, idx, 0, e->evt_data, - e->size); - - spin_lock_irqsave(&wm_event.evt_lock, flags); - list_del(&e->list); - put_event_entry(e); - } - - spin_unlock_irqrestore(&wm_event.evt_lock, flags); -} - -static int gdm_wimax_event_init(void) -{ - if (!wm_event.ref_cnt) { - wm_event.sock = netlink_init(NETLINK_WIMAX, - gdm_wimax_event_rcv); - if (wm_event.sock) { - INIT_LIST_HEAD(&wm_event.evtq); - INIT_LIST_HEAD(&wm_event.freeq); - INIT_WORK(&wm_event.ws, __gdm_wimax_event_send); - spin_lock_init(&wm_event.evt_lock); - } - } - - if (wm_event.sock) { - wm_event.ref_cnt++; - return 0; - } - - pr_err("Creating WiMax Event netlink is failed\n"); - return -1; -} - -static void gdm_wimax_event_exit(void) -{ - if (wm_event.sock && --wm_event.ref_cnt == 0) { - struct evt_entry *e, *temp; - unsigned long flags; - - spin_lock_irqsave(&wm_event.evt_lock, flags); - - list_for_each_entry_safe(e, temp, &wm_event.evtq, list) { - list_del(&e->list); - kfree(e); - } - list_for_each_entry_safe(e, temp, &wm_event.freeq, list) { - list_del(&e->list); - kfree(e); - } - - spin_unlock_irqrestore(&wm_event.evt_lock, flags); - netlink_exit(wm_event.sock); - wm_event.sock = NULL; - } -} - -static int gdm_wimax_event_send(struct net_device *dev, char *buf, int size) -{ - struct evt_entry *e; - unsigned long flags; - - u16 hci_cmd = ((u8)buf[0]<<8) | (u8)buf[1]; - u16 hci_len = ((u8)buf[2]<<8) | (u8)buf[3]; - - netdev_dbg(dev, "D=>H: 0x%04x(%d)\n", hci_cmd, hci_len); - - spin_lock_irqsave(&wm_event.evt_lock, flags); - - e = get_event_entry(); - if (!e) { - netdev_err(dev, "%s: No memory for event\n", __func__); - spin_unlock_irqrestore(&wm_event.evt_lock, flags); - return -ENOMEM; - } - - e->dev = dev; - e->size = size; - memcpy(e->evt_data, buf, size); - - list_add_tail(&e->list, &wm_event.evtq); - spin_unlock_irqrestore(&wm_event.evt_lock, flags); - - schedule_work(&wm_event.ws); - - return 0; -} - -static void tx_complete(void *arg) -{ - struct nic *nic = arg; - - if (netif_queue_stopped(nic->netdev)) - netif_wake_queue(nic->netdev); -} - -int gdm_wimax_send_tx(struct sk_buff *skb, struct net_device *dev) -{ - int ret = 0; - struct nic *nic = netdev_priv(dev); - - ret = gdm_wimax_send_with_cb(nic, skb->data, skb->len, tx_complete, - nic); - if (ret == -ENOSPC) { - netif_stop_queue(dev); - ret = 0; - } - - if (ret) { - skb_pull(skb, HCI_HEADER_SIZE); - return ret; - } - - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len - HCI_HEADER_SIZE; - kfree_skb(skb); - return ret; -} - -static int gdm_wimax_tx(struct sk_buff *skb, struct net_device *dev) -{ - int ret = 0; - - ret = gdm_wimax_header(&skb); - if (ret < 0) { - skb_pull(skb, HCI_HEADER_SIZE); - return ret; - } - -#if defined(CONFIG_WIMAX_GDM72XX_QOS) - ret = gdm_qos_send_hci_pkt(skb, dev); -#else - ret = gdm_wimax_send_tx(skb, dev); -#endif - return ret; -} - -static int gdm_wimax_set_config(struct net_device *dev, struct ifmap *map) -{ - if (dev->flags & IFF_UP) - return -EBUSY; - - return 0; -} - -static void __gdm_wimax_set_mac_addr(struct net_device *dev, char *mac_addr) -{ - u16 hci_pkt_buf[32 / sizeof(u16)]; - struct hci_s *hci = (struct hci_s *)hci_pkt_buf; - struct nic *nic = netdev_priv(dev); - - /* Since dev is registered as a ethernet device, - * ether_setup has made dev->addr_len to be ETH_ALEN - */ - memcpy(dev->dev_addr, mac_addr, dev->addr_len); - - /* Let lower layer know of this change by sending - * SetInformation(MAC Address) - */ - hci->cmd_evt = cpu_to_be16(WIMAX_SET_INFO); - hci->length = cpu_to_be16(8); - hci->data[0] = 0; /* T */ - hci->data[1] = 6; /* L */ - memcpy(&hci->data[2], mac_addr, dev->addr_len); /* V */ - - gdm_wimax_send(nic, hci, HCI_HEADER_SIZE + 8); -} - -/* A driver function */ -static int gdm_wimax_set_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - __gdm_wimax_set_mac_addr(dev, addr->sa_data); - - return 0; -} - -static void gdm_wimax_ind_if_updown(struct net_device *dev, int if_up) -{ - u16 buf[32 / sizeof(u16)]; - struct hci_s *hci = (struct hci_s *)buf; - unsigned char up_down; - - up_down = if_up ? WIMAX_IF_UP : WIMAX_IF_DOWN; - - /* Indicate updating fsm */ - hci->cmd_evt = cpu_to_be16(WIMAX_IF_UPDOWN); - hci->length = cpu_to_be16(sizeof(up_down)); - hci->data[0] = up_down; - - gdm_wimax_event_send(dev, (char *)hci, HCI_HEADER_SIZE+sizeof(up_down)); -} - -static int gdm_wimax_open(struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - struct fsm_s *fsm = nic->sdk_data[SIOC_DATA_FSM].buf; - - netif_start_queue(dev); - - if (fsm && fsm->m_status != M_INIT) - gdm_wimax_ind_if_updown(dev, 1); - return 0; -} - -static int gdm_wimax_close(struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - struct fsm_s *fsm = nic->sdk_data[SIOC_DATA_FSM].buf; - - netif_stop_queue(dev); - - if (fsm && fsm->m_status != M_INIT) - gdm_wimax_ind_if_updown(dev, 0); - return 0; -} - -static void kdelete(void **buf) -{ - if (buf && *buf) { - kfree(*buf); - *buf = NULL; - } -} - -static int gdm_wimax_ioctl_get_data(struct udata_s *dst, struct data_s *src) -{ - int size; - - size = dst->size < src->size ? dst->size : src->size; - - dst->size = size; - if (src->size) { - if (!dst->buf) - return -EINVAL; - if (copy_to_user(dst->buf, src->buf, size)) - return -EFAULT; - } - return 0; -} - -static int gdm_wimax_ioctl_set_data(struct data_s *dst, struct udata_s *src) -{ - if (!src->size) { - dst->size = 0; - return 0; - } - - if (!src->buf) - return -EINVAL; - - if (!(dst->buf && dst->size == src->size)) { - kdelete(&dst->buf); - dst->buf = kmalloc(src->size, GFP_KERNEL); - if (!dst->buf) - return -ENOMEM; - } - - if (copy_from_user(dst->buf, src->buf, src->size)) { - kdelete(&dst->buf); - return -EFAULT; - } - dst->size = src->size; - return 0; -} - -static void gdm_wimax_cleanup_ioctl(struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - int i; - - for (i = 0; i < SIOC_DATA_MAX; i++) - kdelete(&nic->sdk_data[i].buf); -} - -static void gdm_wimax_ind_fsm_update(struct net_device *dev, struct fsm_s *fsm) -{ - u16 buf[32 / sizeof(u16)]; - struct hci_s *hci = (struct hci_s *)buf; - - /* Indicate updating fsm */ - hci->cmd_evt = cpu_to_be16(WIMAX_FSM_UPDATE); - hci->length = cpu_to_be16(sizeof(struct fsm_s)); - memcpy(&hci->data[0], fsm, sizeof(struct fsm_s)); - - gdm_wimax_event_send(dev, (char *)hci, - HCI_HEADER_SIZE + sizeof(struct fsm_s)); -} - -static void gdm_update_fsm(struct net_device *dev, struct fsm_s *new_fsm) -{ - struct nic *nic = netdev_priv(dev); - struct fsm_s *cur_fsm = - nic->sdk_data[SIOC_DATA_FSM].buf; - - if (!cur_fsm) - return; - - if (cur_fsm->m_status != new_fsm->m_status || - cur_fsm->c_status != new_fsm->c_status) { - if (new_fsm->m_status == M_CONNECTED) { - netif_carrier_on(dev); - } else if (cur_fsm->m_status == M_CONNECTED) { - netif_carrier_off(dev); - #if defined(CONFIG_WIMAX_GDM72XX_QOS) - gdm_qos_release_list(nic); - #endif - } - gdm_wimax_ind_fsm_update(dev, new_fsm); - } -} - -static int gdm_wimax_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct wm_req_s *req = (struct wm_req_s *)ifr; - struct nic *nic = netdev_priv(dev); - int ret; - struct fsm_s fsm_buf; - - if (cmd != SIOCWMIOCTL) - return -EOPNOTSUPP; - - switch (req->cmd) { - case SIOCG_DATA: - case SIOCS_DATA: - if (req->data_id >= SIOC_DATA_MAX) { - netdev_err(dev, "%s error: data-index(%d) is invalid!!\n", - __func__, req->data_id); - return -EOPNOTSUPP; - } - if (req->cmd == SIOCG_DATA) { - ret = gdm_wimax_ioctl_get_data( - &req->data, &nic->sdk_data[req->data_id]); - if (ret < 0) - return ret; - } else if (req->cmd == SIOCS_DATA) { - if (req->data_id == SIOC_DATA_FSM) { - /* NOTE: gdm_update_fsm should be called - * before gdm_wimax_ioctl_set_data is called. - */ - if (copy_from_user(&fsm_buf, req->data.buf, - sizeof(struct fsm_s))) - return -EFAULT; - - gdm_update_fsm(dev, &fsm_buf); - } - ret = gdm_wimax_ioctl_set_data( - &nic->sdk_data[req->data_id], &req->data); - if (ret < 0) - return ret; - } - break; - default: - netdev_err(dev, "%s: %x unknown ioctl\n", __func__, cmd); - return -EOPNOTSUPP; - } - - return 0; -} - -static void gdm_wimax_prepare_device(struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - u16 buf[32 / sizeof(u16)]; - struct hci_s *hci = (struct hci_s *)buf; - u16 len = 0; - u32 val = 0; - __be32 val_be32; - - /* GetInformation mac address */ - len = 0; - hci->cmd_evt = cpu_to_be16(WIMAX_GET_INFO); - hci->data[len++] = TLV_T(T_MAC_ADDRESS); - hci->length = cpu_to_be16(len); - gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len); - - val = T_CAPABILITY_WIMAX | T_CAPABILITY_MULTI_CS; - #if defined(CONFIG_WIMAX_GDM72XX_QOS) - val |= T_CAPABILITY_QOS; - #endif - #if defined(CONFIG_WIMAX_GDM72XX_WIMAX2) - val |= T_CAPABILITY_AGGREGATION; - #endif - - /* Set capability */ - len = 0; - hci->cmd_evt = cpu_to_be16(WIMAX_SET_INFO); - hci->data[len++] = TLV_T(T_CAPABILITY); - hci->data[len++] = TLV_L(T_CAPABILITY); - val_be32 = cpu_to_be32(val); - memcpy(&hci->data[len], &val_be32, TLV_L(T_CAPABILITY)); - len += TLV_L(T_CAPABILITY); - hci->length = cpu_to_be16(len); - gdm_wimax_send(nic, hci, HCI_HEADER_SIZE+len); - - netdev_info(dev, "GDM WiMax Set CAPABILITY: 0x%08X\n", val); -} - -static int gdm_wimax_hci_get_tlv(u8 *buf, u8 *T, u16 *L, u8 **V) -{ - #define __U82U16(b) ((u16)((u8 *)(b))[0] | ((u16)((u8 *)(b))[1] << 8)) - int next_pos; - - *T = buf[0]; - if (buf[1] == 0x82) { - *L = be16_to_cpu(__U82U16(&buf[2])); - next_pos = 1/*type*/+3/*len*/; - } else { - *L = buf[1]; - next_pos = 1/*type*/+1/*len*/; - } - *V = &buf[next_pos]; - - next_pos += *L/*length of val*/; - return next_pos; -} - -static int gdm_wimax_get_prepared_info(struct net_device *dev, char *buf, - int len) -{ - u8 T, *V; - u16 L; - u16 cmd_evt, cmd_len; - int pos = HCI_HEADER_SIZE; - - cmd_evt = be16_to_cpup((const __be16 *)&buf[0]); - cmd_len = be16_to_cpup((const __be16 *)&buf[2]); - - if (len < cmd_len + HCI_HEADER_SIZE) { - netdev_err(dev, "%s: invalid length [%d/%d]\n", __func__, - cmd_len + HCI_HEADER_SIZE, len); - return -1; - } - - if (cmd_evt == WIMAX_GET_INFO_RESULT) { - if (cmd_len < 2) { - netdev_err(dev, "%s: len is too short [%x/%d]\n", - __func__, cmd_evt, len); - return -1; - } - - pos += gdm_wimax_hci_get_tlv(&buf[pos], &T, &L, &V); - if (TLV_T(T_MAC_ADDRESS) == T) { - if (dev->addr_len != L) { - netdev_err(dev, - "%s Invalid information result T/L [%x/%d]\n", - __func__, T, L); - return -1; - } - netdev_info(dev, "MAC change [%pM]->[%pM]\n", - dev->dev_addr, V); - memcpy(dev->dev_addr, V, dev->addr_len); - return 1; - } - } - - gdm_wimax_event_send(dev, buf, len); - return 0; -} - -static void gdm_wimax_netif_rx(struct net_device *dev, char *buf, int len) -{ - struct sk_buff *skb; - int ret; - - skb = dev_alloc_skb(len + 2); - if (!skb) - return; - skb_reserve(skb, 2); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; - - memcpy(skb_put(skb, len), buf, len); - - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); /* what will happen? */ - - ret = in_interrupt() ? netif_rx(skb) : netif_rx_ni(skb); - if (ret == NET_RX_DROP) - netdev_err(dev, "%s skb dropped\n", __func__); -} - -static void gdm_wimax_transmit_aggr_pkt(struct net_device *dev, char *buf, - int len) -{ - #define HCI_PADDING_BYTE 4 - #define HCI_RESERVED_BYTE 4 - struct hci_s *hci; - int length; - - while (len > 0) { - hci = (struct hci_s *)buf; - - if (hci->cmd_evt != cpu_to_be16(WIMAX_RX_SDU)) { - netdev_err(dev, "Wrong cmd_evt(0x%04X)\n", - be16_to_cpu(hci->cmd_evt)); - break; - } - - length = be16_to_cpu(hci->length); - gdm_wimax_netif_rx(dev, hci->data, length); - - if (length & 0x3) { - /* Add padding size */ - length += HCI_PADDING_BYTE - (length & 0x3); - } - - length += HCI_HEADER_SIZE + HCI_RESERVED_BYTE; - len -= length; - buf += length; - } -} - -static void gdm_wimax_transmit_pkt(struct net_device *dev, char *buf, int len) -{ - #if defined(CONFIG_WIMAX_GDM72XX_QOS) - struct nic *nic = netdev_priv(dev); - #endif - u16 cmd_evt, cmd_len; - - /* This code is added for certain rx packet to be ignored. */ - if (len == 0) - return; - - cmd_evt = be16_to_cpup((const __be16 *)&buf[0]); - cmd_len = be16_to_cpup((const __be16 *)&buf[2]); - - if (len < cmd_len + HCI_HEADER_SIZE) { - if (len) - netdev_err(dev, "%s: invalid length [%d/%d]\n", - __func__, cmd_len + HCI_HEADER_SIZE, len); - return; - } - - switch (cmd_evt) { - case WIMAX_RX_SDU_AGGR: - gdm_wimax_transmit_aggr_pkt(dev, &buf[HCI_HEADER_SIZE], - cmd_len); - break; - case WIMAX_RX_SDU: - gdm_wimax_netif_rx(dev, &buf[HCI_HEADER_SIZE], cmd_len); - break; - #if defined(CONFIG_WIMAX_GDM72XX_QOS) - case WIMAX_EVT_MODEM_REPORT: - gdm_recv_qos_hci_packet(nic, buf, len); - break; - #endif - case WIMAX_SDU_TX_FLOW: - if (buf[4] == 0) { - if (!netif_queue_stopped(dev)) - netif_stop_queue(dev); - } else if (buf[4] == 1) { - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - } - break; - default: - gdm_wimax_event_send(dev, buf, len); - break; - } -} - -static void rx_complete(void *arg, void *data, int len) -{ - struct nic *nic = arg; - - gdm_wimax_transmit_pkt(nic->netdev, data, len); - gdm_wimax_rcv_with_cb(nic, rx_complete, nic); -} - -static void prepare_rx_complete(void *arg, void *data, int len) -{ - struct nic *nic = arg; - int ret; - - ret = gdm_wimax_get_prepared_info(nic->netdev, data, len); - if (ret == 1) { - gdm_wimax_rcv_with_cb(nic, rx_complete, nic); - } else { - if (ret < 0) - netdev_err(nic->netdev, - "get_prepared_info failed(%d)\n", ret); - gdm_wimax_rcv_with_cb(nic, prepare_rx_complete, nic); - } -} - -static void start_rx_proc(struct nic *nic) -{ - gdm_wimax_rcv_with_cb(nic, prepare_rx_complete, nic); -} - -static struct net_device_ops gdm_netdev_ops = { - .ndo_open = gdm_wimax_open, - .ndo_stop = gdm_wimax_close, - .ndo_set_config = gdm_wimax_set_config, - .ndo_start_xmit = gdm_wimax_tx, - .ndo_set_mac_address = gdm_wimax_set_mac_addr, - .ndo_do_ioctl = gdm_wimax_ioctl, -}; - -int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev) -{ - struct nic *nic = NULL; - struct net_device *dev; - int ret; - - dev = alloc_netdev(sizeof(*nic), "wm%d", NET_NAME_UNKNOWN, - ether_setup); - - if (!dev) { - pr_err("alloc_etherdev failed\n"); - return -ENOMEM; - } - - SET_NETDEV_DEV(dev, pdev); - dev->mtu = 1400; - dev->netdev_ops = &gdm_netdev_ops; - dev->flags &= ~IFF_MULTICAST; - memcpy(dev->dev_addr, gdm_wimax_macaddr, sizeof(gdm_wimax_macaddr)); - - nic = netdev_priv(dev); - nic->netdev = dev; - nic->phy_dev = phy_dev; - phy_dev->netdev = dev; - - /* event socket init */ - ret = gdm_wimax_event_init(); - if (ret < 0) { - pr_err("Cannot create event.\n"); - goto cleanup; - } - - ret = register_netdev(dev); - if (ret) - goto cleanup; - - netif_carrier_off(dev); - -#ifdef CONFIG_WIMAX_GDM72XX_QOS - gdm_qos_init(nic); -#endif - - start_rx_proc(nic); - - /* Prepare WiMax device */ - gdm_wimax_prepare_device(dev); - - return 0; - -cleanup: - pr_err("register_netdev failed\n"); - free_netdev(dev); - return ret; -} - -void unregister_wimax_device(struct phy_dev *phy_dev) -{ - struct nic *nic = netdev_priv(phy_dev->netdev); - struct fsm_s *fsm = nic->sdk_data[SIOC_DATA_FSM].buf; - - if (fsm) - fsm->m_status = M_INIT; - unregister_netdev(nic->netdev); - - gdm_wimax_event_exit(); - -#if defined(CONFIG_WIMAX_GDM72XX_QOS) - gdm_qos_release_list(nic); -#endif - - gdm_wimax_cleanup_ioctl(phy_dev->netdev); - - free_netdev(nic->netdev); -} diff --git a/drivers/staging/gdm72xx/gdm_wimax.h b/drivers/staging/gdm72xx/gdm_wimax.h deleted file mode 100644 index 3330cd798..000000000 --- a/drivers/staging/gdm72xx/gdm_wimax.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_GDM_WIMAX_H__ -#define __GDM72XX_GDM_WIMAX_H__ - -#include -#include -#include "wm_ioctl.h" -#if defined(CONFIG_WIMAX_GDM72XX_QOS) -#include "gdm_qos.h" -#endif - -#define DRIVER_VERSION "3.2.3" - -struct phy_dev { - void *priv_dev; - struct net_device *netdev; - int (*send_func)(void *priv_dev, void *data, int len, - void (*cb)(void *cb_data), void *cb_data); - int (*rcv_func)(void *priv_dev, - void (*cb)(void *cb_data, void *data, int len), - void *cb_data); -}; - -struct nic { - struct net_device *netdev; - struct phy_dev *phy_dev; - struct data_s sdk_data[SIOC_DATA_MAX]; -#if defined(CONFIG_WIMAX_GDM72XX_QOS) - struct qos_cb_s qos; -#endif -}; - -int register_wimax_device(struct phy_dev *phy_dev, struct device *pdev); -int gdm_wimax_send_tx(struct sk_buff *skb, struct net_device *dev); -void unregister_wimax_device(struct phy_dev *phy_dev); - -#endif /* __GDM72XX_GDM_WIMAX_H__ */ diff --git a/drivers/staging/gdm72xx/hci.h b/drivers/staging/gdm72xx/hci.h deleted file mode 100644 index 10a6bfa6e..000000000 --- a/drivers/staging/gdm72xx/hci.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_HCI_H__ -#define __GDM72XX_HCI_H__ - -#define HCI_HEADER_SIZE 4 -#define HCI_VALUE_OFFS (HCI_HEADER_SIZE) -#define HCI_MAX_PACKET 2048 -#define HCI_MAX_PARAM (HCI_MAX_PACKET-HCI_HEADER_SIZE) -#define HCI_MAX_TLV 32 - -/* CMD-EVT */ - -/* Category 0 */ -#define WIMAX_RESET 0x0000 -#define WIMAX_SET_INFO 0x0001 -#define WIMAX_GET_INFO 0x0002 -#define WIMAX_GET_INFO_RESULT 0x8003 -#define WIMAX_RADIO_OFF 0x0004 -#define WIMAX_RADIO_ON 0x0006 -#define WIMAX_WIMAX_RESET 0x0007 /* Is this still here */ - -/* Category 1 */ -#define WIMAX_NET_ENTRY 0x0100 -#define WIMAX_NET_DISCONN 0x0102 -#define WIMAX_ENTER_SLEEP 0x0103 -#define WIMAX_EXIT_SLEEP 0x0104 -#define WIMAX_ENTER_IDLE 0x0105 -#define WIMAX_EXIT_IDLE 0x0106 -#define WIMAX_MODE_CHANGE 0x8108 -#define WIMAX_HANDOVER 0x8109 /* obsolete */ -#define WIMAX_SCAN 0x010d -#define WIMAX_SCAN_COMPLETE 0x810e -#define WIMAX_SCAN_RESULT 0x810f -#define WIMAX_CONNECT 0x0110 -#define WIMAX_CONNECT_START 0x8111 -#define WIMAX_CONNECT_COMPLETE 0x8112 -#define WIMAX_ASSOC_START 0x8113 -#define WIMAX_ASSOC_COMPLETE 0x8114 -#define WIMAX_DISCONN_IND 0x8115 -#define WIMAX_ENTRY_IND 0x8116 -#define WIMAX_HO_START 0x8117 -#define WIMAX_HO_COMPLETE 0x8118 -#define WIMAX_RADIO_STATE_IND 0x8119 -#define WIMAX_IP_RENEW_IND 0x811a -#define WIMAX_DISCOVER_NSP 0x011d -#define WIMAX_DISCOVER_NSP_RESULT 0x811e -#define WIMAX_SDU_TX_FLOW 0x8125 - -/* Category 2 */ -#define WIMAX_TX_EAP 0x0200 -#define WIMAX_RX_EAP 0x8201 -#define WIMAX_TX_SDU 0x0202 -#define WIMAX_RX_SDU 0x8203 -#define WIMAX_RX_SDU_AGGR 0x8204 -#define WIMAX_TX_SDU_AGGR 0x0205 - -/* Category 3 */ -#define WIMAX_DM_CMD 0x030a -#define WIMAX_DM_RSP 0x830b - -#define WIMAX_CLI_CMD 0x030c -#define WIMAX_CLI_RSP 0x830d - -#define WIMAX_DL_IMAGE 0x0310 -#define WIMAX_DL_IMAGE_STATUS 0x8311 -#define WIMAX_UL_IMAGE 0x0312 -#define WIMAX_UL_IMAGE_RESULT 0x8313 -#define WIMAX_UL_IMAGE_STATUS 0x0314 -#define WIMAX_EVT_MODEM_REPORT 0x8325 - -/* Category 0xF */ -#define WIMAX_FSM_UPDATE 0x8F01 -#define WIMAX_IF_UPDOWN 0x8F02 -#define WIMAX_IF_UP 1 -#define WIMAX_IF_DOWN 2 - -/* WIMAX mode */ -#define W_NULL 0 -#define W_STANDBY 1 -#define W_OOZ 2 -#define W_AWAKE 3 -#define W_IDLE 4 -#define W_SLEEP 5 -#define W_WAIT 6 - -#define W_NET_ENTRY_RNG 0x80 -#define W_NET_ENTRY_SBC 0x81 -#define W_NET_ENTRY_PKM 0x82 -#define W_NET_ENTRY_REG 0x83 -#define W_NET_ENTRY_DSX 0x84 - -#define W_NET_ENTRY_RNG_FAIL 0x1100100 -#define W_NET_ENTRY_SBC_FAIL 0x1100200 -#define W_NET_ENTRY_PKM_FAIL 0x1102000 -#define W_NET_ENTRY_REG_FAIL 0x1103000 -#define W_NET_ENTRY_DSX_FAIL 0x1104000 - -/* Scan Type */ -#define W_SCAN_ALL_CHANNEL 0 -#define W_SCAN_ALL_SUBSCRIPTION 1 -#define W_SCAN_SPECIFIED_SUBSCRIPTION 2 - -/* TLV - * - * [31:31] indicates the type is composite. - * [30:16] is the length of the type. 0 length means length is variable. - * [15:0] is the actual type. - */ -#define TLV_L(x) (((x) >> 16) & 0xff) -#define TLV_T(x) ((x) & 0xff) -#define TLV_COMPOSITE(x) ((x) >> 31) - -/* GENERAL */ -#define T_MAC_ADDRESS (0x00 | (6 << 16)) -#define T_BSID (0x01 | (6 << 16)) -#define T_MSK (0x02 | (64 << 16)) -#define T_RSSI_THRSHLD (0x03 | (1 << 16)) -#define T_FREQUENCY (0x04 | (4 << 16)) -#define T_CONN_CS_TYPE (0x05 | (1 << 16)) -#define T_HOST_IP_VER (0x06 | (1 << 16)) -#define T_STBY_SCAN_INTERVAL (0x07 | (4 << 16)) -#define T_OOZ_SCAN_INTERVAL (0x08 | (4 << 16)) -#define T_IMEI (0x09 | (8 << 16)) -#define T_PID (0x0a | (12 << 16)) -#define T_CAPABILITY (0x1a | (4 << 16)) -#define T_RELEASE_NUMBER (0x1b | (4 << 16)) -#define T_DRIVER_REVISION (0x1c | (4 << 16)) -#define T_FW_REVISION (0x1d | (4 << 16)) -#define T_MAC_HW_REVISION (0x1e | (4 << 16)) -#define T_PHY_HW_REVISION (0x1f | (4 << 16)) - -/* HANDOVER */ -#define T_SCAN_INTERVAL (0x20 | (1 << 16)) -#define T_RSC_RETAIN_TIME (0x2f | (2 << 16)) - -/* SLEEP */ -#define T_TYPE1_ISW (0x40 | (1 << 16)) -#define T_SLP_START_TO (0x4a | (2 << 16)) - -/* IDLE */ -#define T_IDLE_MODE_TO (0x50 | (2 << 16)) -#define T_IDLE_START_TO (0x54 | (2 << 16)) - -/* MONITOR */ -#define T_RSSI (0x60 | (1 << 16)) -#define T_CINR (0x61 | (1 << 16)) -#define T_TX_POWER (0x6a | (1 << 16)) -#define T_CUR_FREQ (0x7f | (4 << 16)) - - -/* WIMAX */ -#define T_MAX_SUBSCRIPTION (0xa1 | (1 << 16)) -#define T_MAX_SF (0xa2 | (1 << 16)) -#define T_PHY_TYPE (0xa3 | (1 << 16)) -#define T_PKM (0xa4 | (1 << 16)) -#define T_AUTH_POLICY (0xa5 | (1 << 16)) -#define T_CS_TYPE (0xa6 | (2 << 16)) -#define T_VENDOR_NAME (0xa7 | (0 << 16)) -#define T_MOD_NAME (0xa8 | (0 << 16)) -#define T_PACKET_FILTER (0xa9 | (1 << 16)) -#define T_NSP_CHANGE_COUNT (0xaa | (4 << 16)) -#define T_RADIO_STATE (0xab | (1 << 16)) -#define T_URI_CONTACT_TYPE (0xac | (1 << 16)) -#define T_URI_TEXT (0xad | (0 << 16)) -#define T_URI (0xae | (0 << 16)) -#define T_ENABLE_AUTH (0xaf | (1 << 16)) -#define T_TIMEOUT (0xb0 | (2 << 16)) -#define T_RUN_MODE (0xb1 | (1 << 16)) -#define T_OMADMT_VER (0xb2 | (4 << 16)) -/* This is measured in seconds from 00:00:00 GMT January 1, 1970. */ -#define T_RTC_TIME (0xb3 | (4 << 16)) -#define T_CERT_STATUS (0xb4 | (4 << 16)) -#define T_CERT_MASK (0xb5 | (4 << 16)) -#define T_EMSK (0xb6 | (64 << 16)) - -/* Subscription TLV */ -#define T_SUBSCRIPTION_LIST (0xd1 | (0 << 16) | (1 << 31)) -#define T_H_NSPID (0xd2 | (3 << 16)) -#define T_NSP_NAME (0xd3 | (0 << 16)) -#define T_SUBSCRIPTION_NAME (0xd4 | (0 << 16)) -#define T_SUBSCRIPTION_FLAG (0xd5 | (2 << 16)) -#define T_V_NSPID (0xd6 | (3 << 16)) -#define T_NAP_ID (0xd7 | (3 << 16)) -#define T_PREAMBLES (0xd8 | (15 << 16)) -#define T_BW (0xd9 | (4 << 16)) -#define T_FFTSIZE (0xda | (4 << 16)) -#define T_DUPLEX_MODE (0xdb | (4 << 16)) - -/* T_CAPABILITY */ -#define T_CAPABILITY_MULTI_CS (1 << 0) -#define T_CAPABILITY_WIMAX (1 << 1) -#define T_CAPABILITY_QOS (1 << 2) -#define T_CAPABILITY_AGGREGATION (1 << 3) - -struct hci_s { - __be16 cmd_evt; - __be16 length; - u8 data[0]; -} __packed; - -#endif /* __GDM72XX_HCI_H__ */ diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c deleted file mode 100644 index f3cdaa6c4..000000000 --- a/drivers/staging/gdm72xx/netlink_k.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include "netlink_k.h" - -#if !defined(NLMSG_HDRLEN) -#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) -#endif - -#define ND_MAX_GROUP 30 -#define ND_IFINDEX_LEN sizeof(int) -#define ND_NLMSG_SPACE(len) (nlmsg_total_size(len) + ND_IFINDEX_LEN) -#define ND_NLMSG_DATA(nlh) \ - ((void *)((char *)nlmsg_data(nlh) + ND_IFINDEX_LEN)) -#define ND_NLMSG_S_LEN(len) (len+ND_IFINDEX_LEN) -#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len-ND_IFINDEX_LEN) -#define ND_NLMSG_IFIDX(nlh) nlmsg_data(nlh) -#define ND_MAX_MSG_LEN 8096 - -#if defined(DEFINE_MUTEX) -static DEFINE_MUTEX(netlink_mutex); -#else -static struct semaphore netlink_mutex; -#define mutex_lock(x) down(x) -#define mutex_unlock(x) up(x) -#endif - -static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len); - -static void netlink_rcv_cb(struct sk_buff *skb) -{ - struct nlmsghdr *nlh; - struct net_device *dev; - u32 mlen; - void *msg; - int ifindex; - - if (skb->len >= NLMSG_HDRLEN) { - nlh = (struct nlmsghdr *)skb->data; - - if (skb->len < nlh->nlmsg_len || - nlh->nlmsg_len > ND_MAX_MSG_LEN) { - netdev_err(skb->dev, "Invalid length (%d,%d)\n", - skb->len, nlh->nlmsg_len); - return; - } - - memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN); - msg = ND_NLMSG_DATA(nlh); - mlen = ND_NLMSG_R_LEN(nlh); - - if (rcv_cb) { - dev = dev_get_by_index(&init_net, ifindex); - if (dev) { - rcv_cb(dev, nlh->nlmsg_type, msg, mlen); - dev_put(dev); - } else - netdev_err(skb->dev, - "dev_get_by_index(%d) is not found.\n", - ifindex); - } else { - netdev_err(skb->dev, "Unregistered Callback\n"); - } - } -} - -static void netlink_rcv(struct sk_buff *skb) -{ - mutex_lock(&netlink_mutex); - netlink_rcv_cb(skb); - mutex_unlock(&netlink_mutex); -} - -struct sock *netlink_init(int unit, void (*cb)(struct net_device *dev, u16 type, - void *msg, int len)) -{ - struct sock *sock; - struct netlink_kernel_cfg cfg = { - .input = netlink_rcv, - }; - -#if !defined(DEFINE_MUTEX) - init_MUTEX(&netlink_mutex); -#endif - - sock = netlink_kernel_create(&init_net, unit, &cfg); - - if (sock) - rcv_cb = cb; - - return sock; -} - -void netlink_exit(struct sock *sock) -{ - netlink_kernel_release(sock); -} - -int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) -{ - static u32 seq; - struct sk_buff *skb = NULL; - struct nlmsghdr *nlh; - int ret = 0; - - if (group > ND_MAX_GROUP) { - pr_err("Group %d is invalid.\n", group); - pr_err("Valid group is 0 ~ %d.\n", ND_MAX_GROUP); - return -EINVAL; - } - - skb = nlmsg_new(len, GFP_ATOMIC); - if (!skb) { - pr_err("netlink_broadcast ret=%d\n", ret); - return -ENOMEM; - } - - seq++; - nlh = nlmsg_put(skb, 0, seq, type, len, 0); - if (!nlh) { - kfree_skb(skb); - return -EMSGSIZE; - } - memcpy(nlmsg_data(nlh), msg, len); - - NETLINK_CB(skb).portid = 0; - NETLINK_CB(skb).dst_group = 0; - - ret = netlink_broadcast(sock, skb, 0, group+1, GFP_ATOMIC); - - if (!ret) - return len; - if (ret != -ESRCH) { - pr_err("netlink_broadcast g=%d, t=%d, l=%d, r=%d\n", - group, type, len, ret); - } - ret = 0; - return ret; -} diff --git a/drivers/staging/gdm72xx/netlink_k.h b/drivers/staging/gdm72xx/netlink_k.h deleted file mode 100644 index 1fe7198d5..000000000 --- a/drivers/staging/gdm72xx/netlink_k.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_NETLINK_K_H__ -#define __GDM72XX_NETLINK_K_H__ - -#include -#include - -struct sock *netlink_init(int unit, void (*cb)(struct net_device *dev, u16 type, - void *msg, int len)); -void netlink_exit(struct sock *sock); -int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len); - -#endif /* __GDM72XX_NETLINK_K_H__ */ diff --git a/drivers/staging/gdm72xx/sdio_boot.c b/drivers/staging/gdm72xx/sdio_boot.c deleted file mode 100644 index de254277d..000000000 --- a/drivers/staging/gdm72xx/sdio_boot.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "gdm_sdio.h" -#include "sdio_boot.h" - -#define TYPE_A_HEADER_SIZE 4 -#define TYPE_A_LOOKAHEAD_SIZE 16 -#define YMEM0_SIZE 0x8000 /* 32kbytes */ -#define DOWNLOAD_SIZE (YMEM0_SIZE - TYPE_A_HEADER_SIZE) - -#define FW_DIR "gdm72xx/" -#define FW_KRN "/*(DEBLOBBED)*/" -#define FW_RFS "/*(DEBLOBBED)*/" - -static u8 *tx_buf; - -static int ack_ready(struct sdio_func *func) -{ - unsigned long wait = jiffies + HZ; - u8 val; - int ret; - - while (time_before(jiffies, wait)) { - val = sdio_readb(func, 0x13, &ret); - if (val & 0x01) - return 1; - schedule(); - } - - return 0; -} - -static int download_image(struct sdio_func *func, const char *img_name) -{ - int ret = 0, len, pno; - u8 *buf = tx_buf; - loff_t pos = 0; - int img_len; - const struct firmware *firm; - - ret = reject_firmware(&firm, img_name, &func->dev); - if (ret < 0) { - dev_err(&func->dev, - "requesting firmware %s failed with error %d\n", - img_name, ret); - return ret; - } - - buf = kmalloc(DOWNLOAD_SIZE + TYPE_A_HEADER_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - img_len = firm->size; - - if (img_len <= 0) { - ret = -1; - goto out; - } - - pno = 0; - while (img_len > 0) { - if (img_len > DOWNLOAD_SIZE) { - len = DOWNLOAD_SIZE; - buf[3] = 0; - } else { - len = img_len; /* the last packet */ - buf[3] = 2; - } - - buf[0] = len & 0xff; - buf[1] = (len >> 8) & 0xff; - buf[2] = (len >> 16) & 0xff; - - memcpy(buf+TYPE_A_HEADER_SIZE, firm->data + pos, len); - ret = sdio_memcpy_toio(func, 0, buf, len + TYPE_A_HEADER_SIZE); - if (ret < 0) { - dev_err(&func->dev, - "send image error: packet number = %d ret = %d\n", - pno, ret); - goto out; - } - - if (buf[3] == 2) /* The last packet */ - break; - if (!ack_ready(func)) { - ret = -EIO; - dev_err(&func->dev, "Ack is not ready.\n"); - goto out; - } - ret = sdio_memcpy_fromio(func, buf, 0, TYPE_A_LOOKAHEAD_SIZE); - if (ret < 0) { - dev_err(&func->dev, - "receive ack error: packet number = %d ret = %d\n", - pno, ret); - goto out; - } - sdio_writeb(func, 0x01, 0x13, &ret); - sdio_writeb(func, 0x00, 0x10, &ret); /* PCRRT */ - - img_len -= DOWNLOAD_SIZE; - pos += DOWNLOAD_SIZE; - pno++; - } - -out: - kfree(buf); - return ret; -} - -int sdio_boot(struct sdio_func *func) -{ - int ret; - const char *krn_name = FW_DIR FW_KRN; - const char *rfs_name = FW_DIR FW_RFS; - - tx_buf = kmalloc(YMEM0_SIZE, GFP_KERNEL); - if (!tx_buf) - return -ENOMEM; - - ret = download_image(func, krn_name); - if (ret) - goto restore_fs; - dev_info(&func->dev, "GCT: Kernel download success.\n"); - - ret = download_image(func, rfs_name); - if (ret) - goto restore_fs; - dev_info(&func->dev, "GCT: Filesystem download success.\n"); - -restore_fs: - kfree(tx_buf); - return ret; -} diff --git a/drivers/staging/gdm72xx/sdio_boot.h b/drivers/staging/gdm72xx/sdio_boot.h deleted file mode 100644 index e0800c6fe..000000000 --- a/drivers/staging/gdm72xx/sdio_boot.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_SDIO_BOOT_H__ -#define __GDM72XX_SDIO_BOOT_H__ - -struct sdio_func; - -int sdio_boot(struct sdio_func *func); - -#endif /* __GDM72XX_SDIO_BOOT_H__ */ diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c deleted file mode 100644 index 18c7f71af..000000000 --- a/drivers/staging/gdm72xx/usb_boot.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "gdm_usb.h" -#include "usb_boot.h" - -#define DN_KERNEL_MAGIC_NUMBER 0x10760001 -#define DN_ROOTFS_MAGIC_NUMBER 0x10760002 - -#define DOWNLOAD_SIZE 1024 - -#define MAX_IMG_CNT 16 -#define FW_DIR "gdm72xx/" -#define FW_UIMG "/*(DEBLOBBED)*/" -#define FW_KERN "zImage" -#define FW_FS "ramdisk.jffs2" - -struct dn_header { - __be32 magic_num; - __be32 file_size; -}; - -struct img_header { - u32 magic_code; - u32 count; - u32 len; - u32 offset[MAX_IMG_CNT]; - char hostname[32]; - char date[32]; -}; - -struct fw_info { - u32 id; - u32 len; - u32 kernel_len; - u32 rootfs_len; - u32 kernel_offset; - u32 rootfs_offset; - u32 fw_ver; - u32 mac_ver; - char hostname[32]; - char userid[16]; - char date[32]; - char user_desc[128]; -}; - -static void array_le32_to_cpu(u32 *arr, int num) -{ - int i; - - for (i = 0; i < num; i++, arr++) - le32_to_cpus(arr); -} - -static u8 *tx_buf; - -static int gdm_wibro_send(struct usb_device *usbdev, void *data, int len) -{ - int ret; - int actual; - - ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), data, len, - &actual, 1000); - - if (ret < 0) { - dev_err(&usbdev->dev, "Error : usb_bulk_msg ( result = %d )\n", - ret); - return ret; - } - return 0; -} - -static int gdm_wibro_recv(struct usb_device *usbdev, void *data, int len) -{ - int ret; - int actual; - - ret = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), data, len, - &actual, 5000); - - if (ret < 0) { - dev_err(&usbdev->dev, - "Error : usb_bulk_msg(recv) ( result = %d )\n", ret); - return ret; - } - return 0; -} - -static int download_image(struct usb_device *usbdev, - const struct firmware *firm, - loff_t pos, u32 img_len, u32 magic_num) -{ - struct dn_header h; - int ret = 0; - u32 size; - - size = ALIGN(img_len, DOWNLOAD_SIZE); - h.magic_num = cpu_to_be32(magic_num); - h.file_size = cpu_to_be32(size); - - ret = gdm_wibro_send(usbdev, &h, sizeof(h)); - if (ret < 0) - return ret; - - while (img_len > 0) { - if (img_len > DOWNLOAD_SIZE) - size = DOWNLOAD_SIZE; - else - size = img_len; /* the last chunk of data */ - - memcpy(tx_buf, firm->data + pos, size); - ret = gdm_wibro_send(usbdev, tx_buf, size); - - if (ret < 0) - return ret; - - img_len -= size; - pos += size; - } - - return ret; -} - -int usb_boot(struct usb_device *usbdev, u16 pid) -{ - int i, ret = 0; - struct img_header hdr; - struct fw_info fw_info; - loff_t pos = 0; - char *img_name = FW_DIR FW_UIMG; - const struct firmware *firm; - - ret = reject_firmware(&firm, img_name, &usbdev->dev); - if (ret < 0) { - dev_err(&usbdev->dev, - "requesting firmware %s failed with error %d\n", - img_name, ret); - return ret; - } - - tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL); - if (!tx_buf) { - release_firmware(firm); - return -ENOMEM; - } - - if (firm->size < sizeof(hdr)) { - dev_err(&usbdev->dev, "Cannot read the image info.\n"); - ret = -EIO; - goto out; - } - memcpy(&hdr, firm->data, sizeof(hdr)); - - array_le32_to_cpu((u32 *)&hdr, 19); - - if (hdr.count > MAX_IMG_CNT) { - dev_err(&usbdev->dev, "Too many images. %d\n", hdr.count); - ret = -EINVAL; - goto out; - } - - for (i = 0; i < hdr.count; i++) { - if (hdr.offset[i] > hdr.len) { - dev_err(&usbdev->dev, - "Invalid offset. Entry = %d Offset = 0x%08x Image length = 0x%08x\n", - i, hdr.offset[i], hdr.len); - ret = -EINVAL; - goto out; - } - - pos = hdr.offset[i]; - if (firm->size < sizeof(fw_info) + pos) { - dev_err(&usbdev->dev, "Cannot read the FW info.\n"); - ret = -EIO; - goto out; - } - memcpy(&fw_info, firm->data + pos, sizeof(fw_info)); - - array_le32_to_cpu((u32 *)&fw_info, 8); - - if ((fw_info.id & 0xffff) != pid) - continue; - - pos = hdr.offset[i] + fw_info.kernel_offset; - if (firm->size < fw_info.kernel_len + pos) { - dev_err(&usbdev->dev, "Kernel FW is too small.\n"); - goto out; - } - - ret = download_image(usbdev, firm, pos, fw_info.kernel_len, - DN_KERNEL_MAGIC_NUMBER); - if (ret < 0) - goto out; - dev_info(&usbdev->dev, "GCT: Kernel download success.\n"); - - pos = hdr.offset[i] + fw_info.rootfs_offset; - if (firm->size < fw_info.rootfs_len + pos) { - dev_err(&usbdev->dev, "Filesystem FW is too small.\n"); - goto out; - } - ret = download_image(usbdev, firm, pos, fw_info.rootfs_len, - DN_ROOTFS_MAGIC_NUMBER); - if (ret < 0) - goto out; - dev_info(&usbdev->dev, "GCT: Filesystem download success.\n"); - - break; - } - - if (i == hdr.count) { - dev_err(&usbdev->dev, "Firmware for gsk%x is not installed.\n", - pid); - ret = -EINVAL; - } -out: - release_firmware(firm); - kfree(tx_buf); - return ret; -} - -/*#define GDM7205_PADDING 256 */ -#define DOWNLOAD_CHUCK 2048 -#define KERNEL_TYPE_STRING "linux" -#define FS_TYPE_STRING "rootfs" - -static int em_wait_ack(struct usb_device *usbdev, int send_zlp) -{ - int ack; - int ret = -1; - - if (send_zlp) { - /*Send ZLP*/ - ret = gdm_wibro_send(usbdev, NULL, 0); - if (ret < 0) - goto out; - } - - /*Wait for ACK*/ - ret = gdm_wibro_recv(usbdev, &ack, sizeof(ack)); - if (ret < 0) - goto out; -out: - return ret; -} - -static int em_download_image(struct usb_device *usbdev, const char *img_name, - char *type_string) -{ - char *buf = NULL; - loff_t pos = 0; - int ret = 0; - int len; - int img_len; - const struct firmware *firm; - #if defined(GDM7205_PADDING) - const int pad_size = GDM7205_PADDING; - #else - const int pad_size = 0; - #endif - - ret = reject_firmware(&firm, img_name, &usbdev->dev); - if (ret < 0) { - dev_err(&usbdev->dev, - "requesting firmware %s failed with error %d\n", - img_name, ret); - return ret; - } - - buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL); - if (!buf) { - release_firmware(firm); - return -ENOMEM; - } - - strcpy(buf+pad_size, type_string); - ret = gdm_wibro_send(usbdev, buf, strlen(type_string)+pad_size); - if (ret < 0) - goto out; - - img_len = firm->size; - - if (img_len <= 0) { - ret = -1; - goto out; - } - - while (img_len > 0) { - if (img_len > DOWNLOAD_CHUCK) - len = DOWNLOAD_CHUCK; - else - len = img_len; /* the last chunk of data */ - - memcpy(buf+pad_size, firm->data + pos, len); - ret = gdm_wibro_send(usbdev, buf, len+pad_size); - - if (ret < 0) - goto out; - - img_len -= DOWNLOAD_CHUCK; - pos += DOWNLOAD_CHUCK; - - ret = em_wait_ack(usbdev, ((len+pad_size) % 512 == 0)); - if (ret < 0) - goto out; - } - - ret = em_wait_ack(usbdev, 1); - if (ret < 0) - goto out; - -out: - release_firmware(firm); - kfree(buf); - - return ret; -} - -static int em_fw_reset(struct usb_device *usbdev) -{ - /*Send ZLP*/ - return gdm_wibro_send(usbdev, NULL, 0); -} - -int usb_emergency(struct usb_device *usbdev) -{ - int ret; - const char *kern_name = FW_DIR FW_KERN; - const char *fs_name = FW_DIR FW_FS; - - ret = em_download_image(usbdev, kern_name, KERNEL_TYPE_STRING); - if (ret < 0) - return ret; - dev_err(&usbdev->dev, "GCT Emergency: Kernel download success.\n"); - - ret = em_download_image(usbdev, fs_name, FS_TYPE_STRING); - if (ret < 0) - return ret; - dev_info(&usbdev->dev, "GCT Emergency: Filesystem download success.\n"); - - ret = em_fw_reset(usbdev); - - return ret; -} diff --git a/drivers/staging/gdm72xx/usb_boot.h b/drivers/staging/gdm72xx/usb_boot.h deleted file mode 100644 index 5bf719037..000000000 --- a/drivers/staging/gdm72xx/usb_boot.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_USB_BOOT_H__ -#define __GDM72XX_USB_BOOT_H__ - -struct usb_device; - -int usb_boot(struct usb_device *usbdev, u16 pid); -int usb_emergency(struct usb_device *usbdev); - -#endif /* __GDM72XX_USB_BOOT_H__ */ diff --git a/drivers/staging/gdm72xx/usb_ids.h b/drivers/staging/gdm72xx/usb_ids.h deleted file mode 100644 index 7afb9ba5f..000000000 --- a/drivers/staging/gdm72xx/usb_ids.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_USB_IDS_H__ -#define __GDM72XX_USB_IDS_H__ - -/*You can replace vendor-ID as yours.*/ -#define GCT_VID 0x1076 - -/*You can replace product-ID as yours.*/ -#define GCT_PID1 0x7e00 -#define GCT_PID2 0x7f00 - -#define USB_DEVICE_ID_MATCH_DEVICE_INTERFACE \ - (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_CLASS) - -#define USB_DEVICE_INTF(vend, prod, intf) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_INTERFACE, \ - .idVendor = (vend), .idProduct = (prod), .bInterfaceClass = (intf) - -#define EMERGENCY_PID 0x720f -#define BL_PID_MASK 0xffc0 - -#define USB_DEVICE_BOOTLOADER(vid, pid) \ - {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD)} - -#define USB_DEVICE_BOOTLOADER_DRV(vid, pid) \ - {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD|B_DIFF_DL_DRV)} - -#define USB_DEVICE_CDC_DATA(vid, pid) \ - {USB_DEVICE_INTF((vid), (pid), USB_CLASS_CDC_DATA)} - -static const struct usb_device_id id_table[] = { - USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID1), - USB_DEVICE_BOOTLOADER_DRV(GCT_VID, GCT_PID1), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x1), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x2), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x3), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x4), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x5), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x6), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x7), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x8), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x9), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xa), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xb), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xc), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xd), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xe), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xf), - - USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID2), - USB_DEVICE_BOOTLOADER_DRV(GCT_VID, GCT_PID2), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x1), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x2), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x3), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x4), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x5), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x6), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x7), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x8), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x9), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xa), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xb), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xc), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xd), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xe), - USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xf), - - {USB_DEVICE(GCT_VID, EMERGENCY_PID)}, - { } -}; - -#endif /* __GDM72XX_USB_IDS_H__ */ diff --git a/drivers/staging/gdm72xx/wm_ioctl.h b/drivers/staging/gdm72xx/wm_ioctl.h deleted file mode 100644 index 631cb1d23..000000000 --- a/drivers/staging/gdm72xx/wm_ioctl.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __GDM72XX_WM_IOCTL_H__ -#define __GDM72XX_WM_IOCTL_H__ - -#if !defined(__KERNEL__) -#include -#endif - -#define NETLINK_WIMAX 31 - -#define SIOCWMIOCTL SIOCDEVPRIVATE - -#define SIOCG_DATA 0x8D10 -#define SIOCS_DATA 0x8D11 - -enum { - SIOC_DATA_FSM, - SIOC_DATA_NETLIST, - SIOC_DATA_CONNNSP, - SIOC_DATA_CONNCOMP, - SIOC_DATA_PROFILEID, - - SIOC_DATA_END -}; - -#define SIOC_DATA_MAX 16 - -/* FSM */ -enum { - M_INIT = 0, - M_OPEN_OFF, - M_OPEN_ON, - M_SCAN, - M_CONNECTING, - M_CONNECTED, - M_FSM_END, - - C_INIT = 0, - C_CONNSTART, - C_ASSOCSTART, - C_RNG, - C_SBC, - C_AUTH, - C_REG, - C_DSX, - C_ASSOCCOMPLETE, - C_CONNCOMPLETE, - C_FSM_END, - - D_INIT = 0, - D_READY, - D_LISTEN, - D_IPACQUISITION, - - END_FSM -}; - -struct fsm_s { - int m_status; /*main status*/ - int c_status; /*connection status*/ - int d_status; /*oma-dm status*/ -}; - -struct data_s { - int size; - void *buf; -}; - -struct udata_s { - int size; - void __user *buf; -}; - -struct wm_req_s { - union { - char ifrn_name[IFNAMSIZ]; - } ifr_ifrn; - unsigned short cmd; - unsigned short data_id; - struct udata_s data; - -/* NOTE: sizeof(struct wm_req_s) must be less than sizeof(struct ifreq). */ -}; - -#ifndef ifr_name -#define ifr_name ifr_ifrn.ifrn_name -#endif - -#endif /* __GDM72XX_WM_IOCTL_H__ */ -- cgit v1.2.3-54-g00ecf