···11+config RSI_91X22+ tristate "Redpine Signals Inc 91x WLAN driver support"33+ depends on MAC8021144+ ---help---55+ This option enabes support for RSI 1x1 devices.66+ Select M (recommended), if you have a RSI 1x1 wireless module.77+88+config RSI_DEBUGFS99+ bool "Redpine Signals Inc debug support"1010+ depends on RSI_91X1111+ default y1212+ ---help---1313+ Say Y, if you would like to enable debug support. This option1414+ creates debugfs entries1515+1616+config RSI_SDIO1717+ tristate "Redpine Signals SDIO bus support"1818+ depends on MMC && RSI_91X1919+ default m2020+ ---help---2121+ This option enables the SDIO bus support in rsi drivers.2222+ Select M (recommended), if you have a RSI 1x1 wireless module.2323+2424+config RSI_USB2525+ tristate "Redpine Signals USB bus support"2626+ depends on USB && RSI_91X2727+ default m2828+ ---help---2929+ This option enables the USB bus support in rsi drivers.3030+ Select M (recommended), if you have a RSI 1x1 wireless module.
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include "rsi_mgmt.h"1818+#include "rsi_common.h"1919+2020+/**2121+ * rsi_determine_min_weight_queue() - This function determines the queue with2222+ * the min weight.2323+ * @common: Pointer to the driver private structure.2424+ *2525+ * Return: q_num: Corresponding queue number.2626+ */2727+static u8 rsi_determine_min_weight_queue(struct rsi_common *common)2828+{2929+ struct wmm_qinfo *tx_qinfo = common->tx_qinfo;3030+ u32 q_len = 0;3131+ u8 ii = 0;3232+3333+ for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {3434+ q_len = skb_queue_len(&common->tx_queue[ii]);3535+ if ((tx_qinfo[ii].pkt_contended) && q_len) {3636+ common->min_weight = tx_qinfo[ii].weight;3737+ break;3838+ }3939+ }4040+ return ii;4141+}4242+4343+/**4444+ * rsi_recalculate_weights() - This function recalculates the weights4545+ * corresponding to each queue.4646+ * @common: Pointer to the driver private structure.4747+ *4848+ * Return: recontend_queue bool variable4949+ */5050+static bool rsi_recalculate_weights(struct rsi_common *common)5151+{5252+ struct wmm_qinfo *tx_qinfo = common->tx_qinfo;5353+ bool recontend_queue = false;5454+ u8 ii = 0;5555+ u32 q_len = 0;5656+5757+ for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {5858+ q_len = skb_queue_len(&common->tx_queue[ii]);5959+ /* Check for the need of contention */6060+ if (q_len) {6161+ if (tx_qinfo[ii].pkt_contended) {6262+ tx_qinfo[ii].weight =6363+ ((tx_qinfo[ii].weight > common->min_weight) ?6464+ tx_qinfo[ii].weight - common->min_weight : 0);6565+ } else {6666+ tx_qinfo[ii].pkt_contended = 1;6767+ tx_qinfo[ii].weight = tx_qinfo[ii].wme_params;6868+ recontend_queue = true;6969+ }7070+ } else { /* No packets so no contention */7171+ tx_qinfo[ii].weight = 0;7272+ tx_qinfo[ii].pkt_contended = 0;7373+ }7474+ }7575+7676+ return recontend_queue;7777+}7878+7979+/**8080+ * rsi_core_determine_hal_queue() - This function determines the queue from8181+ * which packet has to be dequeued.8282+ * @common: Pointer to the driver private structure.8383+ *8484+ * Return: q_num: Corresponding queue number on success.8585+ */8686+static u8 rsi_core_determine_hal_queue(struct rsi_common *common)8787+{8888+ bool recontend_queue = false;8989+ u32 q_len = 0;9090+ u8 q_num = INVALID_QUEUE;9191+ u8 ii, min = 0;9292+9393+ if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {9494+ if (!common->mgmt_q_block)9595+ q_num = MGMT_SOFT_Q;9696+ return q_num;9797+ }9898+9999+ if (common->pkt_cnt != 0) {100100+ --common->pkt_cnt;101101+ return common->selected_qnum;102102+ }103103+104104+get_queue_num:105105+ q_num = 0;106106+ recontend_queue = false;107107+108108+ q_num = rsi_determine_min_weight_queue(common);109109+ q_len = skb_queue_len(&common->tx_queue[ii]);110110+ ii = q_num;111111+112112+ /* Selecting the queue with least back off */113113+ for (; ii < NUM_EDCA_QUEUES; ii++) {114114+ if (((common->tx_qinfo[ii].pkt_contended) &&115115+ (common->tx_qinfo[ii].weight < min)) && q_len) {116116+ min = common->tx_qinfo[ii].weight;117117+ q_num = ii;118118+ }119119+ }120120+121121+ common->tx_qinfo[q_num].pkt_contended = 0;122122+ /* Adjust the back off values for all queues again */123123+ recontend_queue = rsi_recalculate_weights(common);124124+125125+ q_len = skb_queue_len(&common->tx_queue[q_num]);126126+ if (!q_len) {127127+ /* If any queues are freshly contended and the selected queue128128+ * doesn't have any packets129129+ * then get the queue number again with fresh values130130+ */131131+ if (recontend_queue)132132+ goto get_queue_num;133133+134134+ q_num = INVALID_QUEUE;135135+ return q_num;136136+ }137137+138138+ common->selected_qnum = q_num;139139+ q_len = skb_queue_len(&common->tx_queue[q_num]);140140+141141+ switch (common->selected_qnum) {142142+ case VO_Q:143143+ if (q_len > MAX_CONTINUOUS_VO_PKTS)144144+ common->pkt_cnt = (MAX_CONTINUOUS_VO_PKTS - 1);145145+ else146146+ common->pkt_cnt = --q_len;147147+ break;148148+149149+ case VI_Q:150150+ if (q_len > MAX_CONTINUOUS_VI_PKTS)151151+ common->pkt_cnt = (MAX_CONTINUOUS_VI_PKTS - 1);152152+ else153153+ common->pkt_cnt = --q_len;154154+155155+ break;156156+157157+ default:158158+ common->pkt_cnt = 0;159159+ break;160160+ }161161+162162+ return q_num;163163+}164164+165165+/**166166+ * rsi_core_queue_pkt() - This functions enqueues the packet to the queue167167+ * specified by the queue number.168168+ * @common: Pointer to the driver private structure.169169+ * @skb: Pointer to the socket buffer structure.170170+ *171171+ * Return: None.172172+ */173173+static void rsi_core_queue_pkt(struct rsi_common *common,174174+ struct sk_buff *skb)175175+{176176+ u8 q_num = skb->priority;177177+ if (q_num >= NUM_SOFT_QUEUES) {178178+ rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",179179+ __func__, q_num);180180+ dev_kfree_skb(skb);181181+ return;182182+ }183183+184184+ skb_queue_tail(&common->tx_queue[q_num], skb);185185+}186186+187187+/**188188+ * rsi_core_dequeue_pkt() - This functions dequeues the packet from the queue189189+ * specified by the queue number.190190+ * @common: Pointer to the driver private structure.191191+ * @q_num: Queue number.192192+ *193193+ * Return: Pointer to sk_buff structure.194194+ */195195+static struct sk_buff *rsi_core_dequeue_pkt(struct rsi_common *common,196196+ u8 q_num)197197+{198198+ if (q_num >= NUM_SOFT_QUEUES) {199199+ rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",200200+ __func__, q_num);201201+ return NULL;202202+ }203203+204204+ return skb_dequeue(&common->tx_queue[q_num]);205205+}206206+207207+/**208208+ * rsi_core_qos_processor() - This function is used to determine the wmm queue209209+ * based on the backoff procedure. Data packets are210210+ * dequeued from the selected hal queue and sent to211211+ * the below layers.212212+ * @common: Pointer to the driver private structure.213213+ *214214+ * Return: None.215215+ */216216+void rsi_core_qos_processor(struct rsi_common *common)217217+{218218+ struct rsi_hw *adapter = common->priv;219219+ struct sk_buff *skb;220220+ unsigned long tstamp_1, tstamp_2;221221+ u8 q_num;222222+ int status;223223+224224+ tstamp_1 = jiffies;225225+ while (1) {226226+ q_num = rsi_core_determine_hal_queue(common);227227+ rsi_dbg(DATA_TX_ZONE,228228+ "%s: Queue number = %d\n", __func__, q_num);229229+230230+ if (q_num == INVALID_QUEUE) {231231+ rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__);232232+ break;233233+ }234234+235235+ mutex_lock(&common->tx_rxlock);236236+237237+ status = adapter->check_hw_queue_status(adapter, q_num);238238+ if ((status <= 0)) {239239+ mutex_unlock(&common->tx_rxlock);240240+ break;241241+ }242242+243243+ if ((q_num < MGMT_SOFT_Q) &&244244+ ((skb_queue_len(&common->tx_queue[q_num])) <=245245+ MIN_DATA_QUEUE_WATER_MARK)) {246246+ if (ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))247247+ ieee80211_wake_queue(adapter->hw,248248+ WME_AC(q_num));249249+ }250250+251251+ skb = rsi_core_dequeue_pkt(common, q_num);252252+ if (skb == NULL) {253253+ mutex_unlock(&common->tx_rxlock);254254+ break;255255+ }256256+257257+ if (q_num == MGMT_SOFT_Q)258258+ status = rsi_send_mgmt_pkt(common, skb);259259+ else260260+ status = rsi_send_data_pkt(common, skb);261261+262262+ if (status) {263263+ mutex_unlock(&common->tx_rxlock);264264+ break;265265+ }266266+267267+ common->tx_stats.total_tx_pkt_send[q_num]++;268268+269269+ tstamp_2 = jiffies;270270+ mutex_unlock(&common->tx_rxlock);271271+272272+ if (tstamp_2 > tstamp_1 + (300 * HZ / 1000))273273+ schedule();274274+ }275275+}276276+277277+/**278278+ * rsi_core_xmit() - This function transmits the packets received from mac80211279279+ * @common: Pointer to the driver private structure.280280+ * @skb: Pointer to the socket buffer structure.281281+ *282282+ * Return: None.283283+ */284284+void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)285285+{286286+ struct rsi_hw *adapter = common->priv;287287+ struct ieee80211_tx_info *info;288288+ struct skb_info *tx_params;289289+ struct ieee80211_hdr *tmp_hdr = NULL;290290+ u8 q_num, tid = 0;291291+292292+ if ((!skb) || (!skb->len)) {293293+ rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n",294294+ __func__);295295+ goto xmit_fail;296296+ }297297+ info = IEEE80211_SKB_CB(skb);298298+ tx_params = (struct skb_info *)info->driver_data;299299+ tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];300300+301301+ if (common->fsm_state != FSM_MAC_INIT_DONE) {302302+ rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);303303+ goto xmit_fail;304304+ }305305+306306+ if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) ||307307+ (ieee80211_is_ctl(tmp_hdr->frame_control))) {308308+ q_num = MGMT_SOFT_Q;309309+ skb->priority = q_num;310310+ } else {311311+ if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {312312+ tid = (skb->data[24] & IEEE80211_QOS_TID);313313+ skb->priority = TID_TO_WME_AC(tid);314314+ } else {315315+ tid = IEEE80211_NONQOS_TID;316316+ skb->priority = BE_Q;317317+ }318318+ q_num = skb->priority;319319+ tx_params->tid = tid;320320+ tx_params->sta_id = 0;321321+ }322322+323323+ if ((q_num != MGMT_SOFT_Q) &&324324+ ((skb_queue_len(&common->tx_queue[q_num]) + 1) >=325325+ DATA_QUEUE_WATER_MARK)) {326326+ if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))327327+ ieee80211_stop_queue(adapter->hw, WME_AC(q_num));328328+ rsi_set_event(&common->tx_thread.event);329329+ goto xmit_fail;330330+ }331331+332332+ rsi_core_queue_pkt(common, skb);333333+ rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thead <===\n", __func__);334334+ rsi_set_event(&common->tx_thread.event);335335+336336+ return;337337+338338+xmit_fail:339339+ rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__);340340+ /* Dropping pkt here */341341+ ieee80211_free_txskb(common->priv->hw, skb);342342+}
+339
drivers/net/wireless/rsi/rsi_91x_debugfs.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include "rsi_debugfs.h"1818+#include "rsi_sdio.h"1919+2020+/**2121+ * rsi_sdio_stats_read() - This function returns the sdio status of the driver.2222+ * @seq: Pointer to the sequence file structure.2323+ * @data: Pointer to the data.2424+ *2525+ * Return: 0 on success, -1 on failure.2626+ */2727+static int rsi_sdio_stats_read(struct seq_file *seq, void *data)2828+{2929+ struct rsi_common *common = seq->private;3030+ struct rsi_hw *adapter = common->priv;3131+ struct rsi_91x_sdiodev *dev =3232+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;3333+3434+ seq_printf(seq, "total_sdio_interrupts: %d\n",3535+ dev->rx_info.sdio_int_counter);3636+ seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n",3737+ dev->rx_info.total_sdio_msdu_pending_intr);3838+ seq_printf(seq, "sdio_buff_full_count : %d\n",3939+ dev->rx_info.buf_full_counter);4040+ seq_printf(seq, "sdio_buf_semi_full_count %d\n",4141+ dev->rx_info.buf_semi_full_counter);4242+ seq_printf(seq, "sdio_unknown_intr_count: %d\n",4343+ dev->rx_info.total_sdio_unknown_intr);4444+ /* RX Path Stats */4545+ seq_printf(seq, "BUFFER FULL STATUS : %d\n",4646+ dev->rx_info.buffer_full);4747+ seq_printf(seq, "SEMI BUFFER FULL STATUS : %d\n",4848+ dev->rx_info.semi_buffer_full);4949+ seq_printf(seq, "MGMT BUFFER FULL STATUS : %d\n",5050+ dev->rx_info.mgmt_buffer_full);5151+ seq_printf(seq, "BUFFER FULL COUNTER : %d\n",5252+ dev->rx_info.buf_full_counter);5353+ seq_printf(seq, "BUFFER SEMI FULL COUNTER : %d\n",5454+ dev->rx_info.buf_semi_full_counter);5555+ seq_printf(seq, "MGMT BUFFER FULL COUNTER : %d\n",5656+ dev->rx_info.mgmt_buf_full_counter);5757+5858+ return 0;5959+}6060+6161+/**6262+ * rsi_sdio_stats_open() - This funtion calls single open function of seq_file6363+ * to open file and read contents from it.6464+ * @inode: Pointer to the inode structure.6565+ * @file: Pointer to the file structure.6666+ *6767+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.6868+ */6969+static int rsi_sdio_stats_open(struct inode *inode,7070+ struct file *file)7171+{7272+ return single_open(file, rsi_sdio_stats_read, inode->i_private);7373+}7474+7575+/**7676+ * rsi_version_read() - This function gives driver and firmware version number.7777+ * @seq: Pointer to the sequence file structure.7878+ * @data: Pointer to the data.7979+ *8080+ * Return: 0 on success, -1 on failure.8181+ */8282+static int rsi_version_read(struct seq_file *seq, void *data)8383+{8484+ struct rsi_common *common = seq->private;8585+8686+ common->driver_ver.major = 0;8787+ common->driver_ver.minor = 1;8888+ common->driver_ver.release_num = 0;8989+ common->driver_ver.patch_num = 0;9090+ seq_printf(seq, "Driver : %x.%d.%d.%d\nLMAC : %d.%d.%d.%d\n",9191+ common->driver_ver.major,9292+ common->driver_ver.minor,9393+ common->driver_ver.release_num,9494+ common->driver_ver.patch_num,9595+ common->fw_ver.major,9696+ common->fw_ver.minor,9797+ common->fw_ver.release_num,9898+ common->fw_ver.patch_num);9999+ return 0;100100+}101101+102102+/**103103+ * rsi_version_open() - This funtion calls single open function of seq_file to104104+ * open file and read contents from it.105105+ * @inode: Pointer to the inode structure.106106+ * @file: Pointer to the file structure.107107+ *108108+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.109109+ */110110+static int rsi_version_open(struct inode *inode,111111+ struct file *file)112112+{113113+ return single_open(file, rsi_version_read, inode->i_private);114114+}115115+116116+/**117117+ * rsi_stats_read() - This function return the status of the driver.118118+ * @seq: Pointer to the sequence file structure.119119+ * @data: Pointer to the data.120120+ *121121+ * Return: 0 on success, -1 on failure.122122+ */123123+static int rsi_stats_read(struct seq_file *seq, void *data)124124+{125125+ struct rsi_common *common = seq->private;126126+127127+ unsigned char fsm_state[][32] = {128128+ "FSM_CARD_NOT_READY",129129+ "FSM_BOOT_PARAMS_SENT",130130+ "FSM_EEPROM_READ_MAC_ADDR",131131+ "FSM_RESET_MAC_SENT",132132+ "FSM_RADIO_CAPS_SENT",133133+ "FSM_BB_RF_PROG_SENT",134134+ "FSM_MAC_INIT_DONE"135135+ };136136+ seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n");137137+ seq_puts(seq, "DRIVER_FSM_STATE: ");138138+139139+ if (common->fsm_state <= FSM_MAC_INIT_DONE)140140+ seq_printf(seq, "%s", fsm_state[common->fsm_state]);141141+142142+ seq_printf(seq, "(%d)\n\n", common->fsm_state);143143+144144+ /* Mgmt TX Path Stats */145145+ seq_printf(seq, "total_mgmt_pkt_send : %d\n",146146+ common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);147147+ seq_printf(seq, "total_mgmt_pkt_queued : %d\n",148148+ skb_queue_len(&common->tx_queue[4]));149149+ seq_printf(seq, "total_mgmt_pkt_freed : %d\n",150150+ common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);151151+152152+ /* Data TX Path Stats */153153+ seq_printf(seq, "total_data_vo_pkt_send: %8d\t",154154+ common->tx_stats.total_tx_pkt_send[VO_Q]);155155+ seq_printf(seq, "total_data_vo_pkt_queued: %8d\t",156156+ skb_queue_len(&common->tx_queue[0]));157157+ seq_printf(seq, "total_vo_pkt_freed: %8d\n",158158+ common->tx_stats.total_tx_pkt_freed[VO_Q]);159159+ seq_printf(seq, "total_data_vi_pkt_send: %8d\t",160160+ common->tx_stats.total_tx_pkt_send[VI_Q]);161161+ seq_printf(seq, "total_data_vi_pkt_queued: %8d\t",162162+ skb_queue_len(&common->tx_queue[1]));163163+ seq_printf(seq, "total_vi_pkt_freed: %8d\n",164164+ common->tx_stats.total_tx_pkt_freed[VI_Q]);165165+ seq_printf(seq, "total_data_be_pkt_send: %8d\t",166166+ common->tx_stats.total_tx_pkt_send[BE_Q]);167167+ seq_printf(seq, "total_data_be_pkt_queued: %8d\t",168168+ skb_queue_len(&common->tx_queue[2]));169169+ seq_printf(seq, "total_be_pkt_freed: %8d\n",170170+ common->tx_stats.total_tx_pkt_freed[BE_Q]);171171+ seq_printf(seq, "total_data_bk_pkt_send: %8d\t",172172+ common->tx_stats.total_tx_pkt_send[BK_Q]);173173+ seq_printf(seq, "total_data_bk_pkt_queued: %8d\t",174174+ skb_queue_len(&common->tx_queue[3]));175175+ seq_printf(seq, "total_bk_pkt_freed: %8d\n",176176+ common->tx_stats.total_tx_pkt_freed[BK_Q]);177177+178178+ seq_puts(seq, "\n");179179+ return 0;180180+}181181+182182+/**183183+ * rsi_stats_open() - This funtion calls single open function of seq_file to184184+ * open file and read contents from it.185185+ * @inode: Pointer to the inode structure.186186+ * @file: Pointer to the file structure.187187+ *188188+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.189189+ */190190+static int rsi_stats_open(struct inode *inode,191191+ struct file *file)192192+{193193+ return single_open(file, rsi_stats_read, inode->i_private);194194+}195195+196196+/**197197+ * rsi_debug_zone_read() - This function display the currently enabled debug zones.198198+ * @seq: Pointer to the sequence file structure.199199+ * @data: Pointer to the data.200200+ *201201+ * Return: 0 on success, -1 on failure.202202+ */203203+static int rsi_debug_zone_read(struct seq_file *seq, void *data)204204+{205205+ rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled);206206+ seq_printf(seq, "The zones available are %#x\n",207207+ rsi_zone_enabled);208208+ return 0;209209+}210210+211211+/**212212+ * rsi_debug_read() - This funtion calls single open function of seq_file to213213+ * open file and read contents from it.214214+ * @inode: Pointer to the inode structure.215215+ * @file: Pointer to the file structure.216216+ *217217+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.218218+ */219219+static int rsi_debug_read(struct inode *inode,220220+ struct file *file)221221+{222222+ return single_open(file, rsi_debug_zone_read, inode->i_private);223223+}224224+225225+/**226226+ * rsi_debug_zone_write() - This function writes into hal queues as per user227227+ * requirement.228228+ * @filp: Pointer to the file structure.229229+ * @buff: Pointer to the character buffer.230230+ * @len: Length of the data to be written into buffer.231231+ * @data: Pointer to the data.232232+ *233233+ * Return: len: Number of bytes read.234234+ */235235+static ssize_t rsi_debug_zone_write(struct file *filp,236236+ const char __user *buff,237237+ size_t len,238238+ loff_t *data)239239+{240240+ unsigned long dbg_zone;241241+ int ret;242242+243243+ if (!len)244244+ return 0;245245+246246+ ret = kstrtoul_from_user(buff, len, 16, &dbg_zone);247247+248248+ if (ret)249249+ return ret;250250+251251+ rsi_zone_enabled = dbg_zone;252252+ return len;253253+}254254+255255+#define FOPS(fopen) { \256256+ .owner = THIS_MODULE, \257257+ .open = (fopen), \258258+ .read = seq_read, \259259+ .llseek = seq_lseek, \260260+}261261+262262+#define FOPS_RW(fopen, fwrite) { \263263+ .owner = THIS_MODULE, \264264+ .open = (fopen), \265265+ .read = seq_read, \266266+ .llseek = seq_lseek, \267267+ .write = (fwrite), \268268+}269269+270270+static const struct rsi_dbg_files dev_debugfs_files[] = {271271+ {"version", 0644, FOPS(rsi_version_open),},272272+ {"stats", 0644, FOPS(rsi_stats_open),},273273+ {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),},274274+ {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),},275275+};276276+277277+/**278278+ * rsi_init_dbgfs() - This function initializes the dbgfs entry.279279+ * @adapter: Pointer to the adapter structure.280280+ *281281+ * Return: 0 on success, -1 on failure.282282+ */283283+int rsi_init_dbgfs(struct rsi_hw *adapter)284284+{285285+ struct rsi_common *common = adapter->priv;286286+ struct rsi_debugfs *dev_dbgfs;287287+ char devdir[6];288288+ int ii;289289+ const struct rsi_dbg_files *files;290290+291291+ dev_dbgfs = kzalloc(sizeof(*dev_dbgfs), GFP_KERNEL);292292+ adapter->dfsentry = dev_dbgfs;293293+294294+ snprintf(devdir, sizeof(devdir), "%s",295295+ wiphy_name(adapter->hw->wiphy));296296+ dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL);297297+298298+ if (IS_ERR(dev_dbgfs->subdir)) {299299+ if (dev_dbgfs->subdir == ERR_PTR(-ENODEV))300300+ rsi_dbg(ERR_ZONE,301301+ "%s:Debugfs has not been mounted\n", __func__);302302+ else303303+ rsi_dbg(ERR_ZONE, "debugfs:%s not created\n", devdir);304304+305305+ adapter->dfsentry = NULL;306306+ kfree(dev_dbgfs);307307+ return (int)PTR_ERR(dev_dbgfs->subdir);308308+ } else {309309+ for (ii = 0; ii < adapter->num_debugfs_entries; ii++) {310310+ files = &dev_debugfs_files[ii];311311+ dev_dbgfs->rsi_files[ii] =312312+ debugfs_create_file(files->name,313313+ files->perms,314314+ dev_dbgfs->subdir,315315+ common,316316+ &files->fops);317317+ }318318+ }319319+ return 0;320320+}321321+EXPORT_SYMBOL_GPL(rsi_init_dbgfs);322322+323323+/**324324+ * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries325325+ * in the reverse order of creation.326326+ * @adapter: Pointer to the adapter structure.327327+ *328328+ * Return: None.329329+ */330330+void rsi_remove_dbgfs(struct rsi_hw *adapter)331331+{332332+ struct rsi_debugfs *dev_dbgfs = adapter->dfsentry;333333+334334+ if (!dev_dbgfs)335335+ return;336336+337337+ debugfs_remove_recursive(dev_dbgfs->subdir);338338+}339339+EXPORT_SYMBOL_GPL(rsi_remove_dbgfs);
+1008
drivers/net/wireless/rsi/rsi_91x_mac80211.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include <linux/etherdevice.h>1818+#include "rsi_debugfs.h"1919+#include "rsi_mgmt.h"2020+#include "rsi_common.h"2121+2222+static const struct ieee80211_channel rsi_2ghz_channels[] = {2323+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412,2424+ .hw_value = 1 }, /* Channel 1 */2525+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417,2626+ .hw_value = 2 }, /* Channel 2 */2727+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422,2828+ .hw_value = 3 }, /* Channel 3 */2929+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427,3030+ .hw_value = 4 }, /* Channel 4 */3131+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432,3232+ .hw_value = 5 }, /* Channel 5 */3333+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437,3434+ .hw_value = 6 }, /* Channel 6 */3535+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442,3636+ .hw_value = 7 }, /* Channel 7 */3737+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447,3838+ .hw_value = 8 }, /* Channel 8 */3939+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452,4040+ .hw_value = 9 }, /* Channel 9 */4141+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457,4242+ .hw_value = 10 }, /* Channel 10 */4343+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462,4444+ .hw_value = 11 }, /* Channel 11 */4545+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467,4646+ .hw_value = 12 }, /* Channel 12 */4747+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472,4848+ .hw_value = 13 }, /* Channel 13 */4949+ { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484,5050+ .hw_value = 14 }, /* Channel 14 */5151+};5252+5353+static const struct ieee80211_channel rsi_5ghz_channels[] = {5454+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180,5555+ .hw_value = 36, }, /* Channel 36 */5656+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200,5757+ .hw_value = 40, }, /* Channel 40 */5858+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220,5959+ .hw_value = 44, }, /* Channel 44 */6060+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240,6161+ .hw_value = 48, }, /* Channel 48 */6262+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5260,6363+ .hw_value = 52, }, /* Channel 52 */6464+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5280,6565+ .hw_value = 56, }, /* Channel 56 */6666+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5300,6767+ .hw_value = 60, }, /* Channel 60 */6868+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5320,6969+ .hw_value = 64, }, /* Channel 64 */7070+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5500,7171+ .hw_value = 100, }, /* Channel 100 */7272+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5520,7373+ .hw_value = 104, }, /* Channel 104 */7474+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5540,7575+ .hw_value = 108, }, /* Channel 108 */7676+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5560,7777+ .hw_value = 112, }, /* Channel 112 */7878+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5580,7979+ .hw_value = 116, }, /* Channel 116 */8080+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5600,8181+ .hw_value = 120, }, /* Channel 120 */8282+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5620,8383+ .hw_value = 124, }, /* Channel 124 */8484+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5640,8585+ .hw_value = 128, }, /* Channel 128 */8686+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5660,8787+ .hw_value = 132, }, /* Channel 132 */8888+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5680,8989+ .hw_value = 136, }, /* Channel 136 */9090+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5700,9191+ .hw_value = 140, }, /* Channel 140 */9292+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5745,9393+ .hw_value = 149, }, /* Channel 149 */9494+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5765,9595+ .hw_value = 153, }, /* Channel 153 */9696+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5785,9797+ .hw_value = 157, }, /* Channel 157 */9898+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5805,9999+ .hw_value = 161, }, /* Channel 161 */100100+ { .band = IEEE80211_BAND_5GHZ, .center_freq = 5825,101101+ .hw_value = 165, }, /* Channel 165 */102102+};103103+104104+struct ieee80211_rate rsi_rates[12] = {105105+ { .bitrate = STD_RATE_01 * 5, .hw_value = RSI_RATE_1 },106106+ { .bitrate = STD_RATE_02 * 5, .hw_value = RSI_RATE_2 },107107+ { .bitrate = STD_RATE_5_5 * 5, .hw_value = RSI_RATE_5_5 },108108+ { .bitrate = STD_RATE_11 * 5, .hw_value = RSI_RATE_11 },109109+ { .bitrate = STD_RATE_06 * 5, .hw_value = RSI_RATE_6 },110110+ { .bitrate = STD_RATE_09 * 5, .hw_value = RSI_RATE_9 },111111+ { .bitrate = STD_RATE_12 * 5, .hw_value = RSI_RATE_12 },112112+ { .bitrate = STD_RATE_18 * 5, .hw_value = RSI_RATE_18 },113113+ { .bitrate = STD_RATE_24 * 5, .hw_value = RSI_RATE_24 },114114+ { .bitrate = STD_RATE_36 * 5, .hw_value = RSI_RATE_36 },115115+ { .bitrate = STD_RATE_48 * 5, .hw_value = RSI_RATE_48 },116116+ { .bitrate = STD_RATE_54 * 5, .hw_value = RSI_RATE_54 },117117+};118118+119119+const u16 rsi_mcsrates[8] = {120120+ RSI_RATE_MCS0, RSI_RATE_MCS1, RSI_RATE_MCS2, RSI_RATE_MCS3,121121+ RSI_RATE_MCS4, RSI_RATE_MCS5, RSI_RATE_MCS6, RSI_RATE_MCS7122122+};123123+124124+/**125125+ * rsi_is_cipher_wep() - This function determines if the cipher is WEP or not.126126+ * @common: Pointer to the driver private structure.127127+ *128128+ * Return: If cipher type is WEP, a value of 1 is returned, else 0.129129+ */130130+131131+bool rsi_is_cipher_wep(struct rsi_common *common)132132+{133133+ if (((common->secinfo.gtk_cipher == WLAN_CIPHER_SUITE_WEP104) ||134134+ (common->secinfo.gtk_cipher == WLAN_CIPHER_SUITE_WEP40)) &&135135+ (!common->secinfo.ptk_cipher))136136+ return true;137137+ else138138+ return false;139139+}140140+141141+/**142142+ * rsi_register_rates_channels() - This function registers channels and rates.143143+ * @adapter: Pointer to the adapter structure.144144+ * @band: Operating band to be set.145145+ *146146+ * Return: None.147147+ */148148+static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)149149+{150150+ struct ieee80211_supported_band *sbands = &adapter->sbands[band];151151+ void *channels = NULL;152152+153153+ if (band == IEEE80211_BAND_2GHZ) {154154+ channels = kmalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL);155155+ memcpy(channels,156156+ rsi_2ghz_channels,157157+ sizeof(rsi_2ghz_channels));158158+ sbands->band = IEEE80211_BAND_2GHZ;159159+ sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels);160160+ sbands->bitrates = rsi_rates;161161+ sbands->n_bitrates = ARRAY_SIZE(rsi_rates);162162+ } else {163163+ channels = kmalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL);164164+ memcpy(channels,165165+ rsi_5ghz_channels,166166+ sizeof(rsi_5ghz_channels));167167+ sbands->band = IEEE80211_BAND_5GHZ;168168+ sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels);169169+ sbands->bitrates = &rsi_rates[4];170170+ sbands->n_bitrates = ARRAY_SIZE(rsi_rates) - 4;171171+ }172172+173173+ sbands->channels = channels;174174+175175+ memset(&sbands->ht_cap, 0, sizeof(struct ieee80211_sta_ht_cap));176176+ sbands->ht_cap.ht_supported = true;177177+ sbands->ht_cap.cap = (IEEE80211_HT_CAP_SUP_WIDTH_20_40 |178178+ IEEE80211_HT_CAP_SGI_20 |179179+ IEEE80211_HT_CAP_SGI_40);180180+ sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;181181+ sbands->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;182182+ sbands->ht_cap.mcs.rx_mask[0] = 0xff;183183+ sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;184184+ /* sbands->ht_cap.mcs.rx_highest = 0x82; */185185+}186186+187187+/**188188+ * rsi_mac80211_attach() - This function is used to de-initialize the189189+ * Mac80211 stack.190190+ * @adapter: Pointer to the adapter structure.191191+ *192192+ * Return: None.193193+ */194194+void rsi_mac80211_detach(struct rsi_hw *adapter)195195+{196196+ struct ieee80211_hw *hw = adapter->hw;197197+198198+ if (hw) {199199+ ieee80211_stop_queues(hw);200200+ ieee80211_unregister_hw(hw);201201+ ieee80211_free_hw(hw);202202+ }203203+204204+ rsi_remove_dbgfs(adapter);205205+}206206+EXPORT_SYMBOL_GPL(rsi_mac80211_detach);207207+208208+/**209209+ * rsi_indicate_tx_status() - This function indicates the transmit status.210210+ * @adapter: Pointer to the adapter structure.211211+ * @skb: Pointer to the socket buffer structure.212212+ * @status: Status213213+ *214214+ * Return: None.215215+ */216216+void rsi_indicate_tx_status(struct rsi_hw *adapter,217217+ struct sk_buff *skb,218218+ int status)219219+{220220+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);221221+222222+ memset(info->driver_data, 0, IEEE80211_TX_INFO_DRIVER_DATA_SIZE);223223+224224+ if (!status)225225+ info->flags |= IEEE80211_TX_STAT_ACK;226226+227227+ ieee80211_tx_status_irqsafe(adapter->hw, skb);228228+}229229+230230+/**231231+ * rsi_mac80211_tx() - This is the handler that 802.11 module calls for each232232+ * transmitted frame.SKB contains the buffer starting233233+ * from the IEEE 802.11 header.234234+ * @hw: Pointer to the ieee80211_hw structure.235235+ * @control: Pointer to the ieee80211_tx_control structure236236+ * @skb: Pointer to the socket buffer structure.237237+ *238238+ * Return: None239239+ */240240+static void rsi_mac80211_tx(struct ieee80211_hw *hw,241241+ struct ieee80211_tx_control *control,242242+ struct sk_buff *skb)243243+{244244+ struct rsi_hw *adapter = hw->priv;245245+ struct rsi_common *common = adapter->priv;246246+247247+ rsi_core_xmit(common, skb);248248+}249249+250250+/**251251+ * rsi_mac80211_start() - This is first handler that 802.11 module calls, since252252+ * the driver init is complete by then, just253253+ * returns success.254254+ * @hw: Pointer to the ieee80211_hw structure.255255+ *256256+ * Return: 0 as success.257257+ */258258+static int rsi_mac80211_start(struct ieee80211_hw *hw)259259+{260260+ struct rsi_hw *adapter = hw->priv;261261+ struct rsi_common *common = adapter->priv;262262+263263+ mutex_lock(&common->mutex);264264+ common->iface_down = false;265265+ mutex_unlock(&common->mutex);266266+267267+ return 0;268268+}269269+270270+/**271271+ * rsi_mac80211_stop() - This is the last handler that 802.11 module calls.272272+ * @hw: Pointer to the ieee80211_hw structure.273273+ *274274+ * Return: None.275275+ */276276+static void rsi_mac80211_stop(struct ieee80211_hw *hw)277277+{278278+ struct rsi_hw *adapter = hw->priv;279279+ struct rsi_common *common = adapter->priv;280280+281281+ mutex_lock(&common->mutex);282282+ common->iface_down = true;283283+ mutex_unlock(&common->mutex);284284+}285285+286286+/**287287+ * rsi_mac80211_add_interface() - This function is called when a netdevice288288+ * attached to the hardware is enabled.289289+ * @hw: Pointer to the ieee80211_hw structure.290290+ * @vif: Pointer to the ieee80211_vif structure.291291+ *292292+ * Return: ret: 0 on success, negative error code on failure.293293+ */294294+static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,295295+ struct ieee80211_vif *vif)296296+{297297+ struct rsi_hw *adapter = hw->priv;298298+ struct rsi_common *common = adapter->priv;299299+ int ret = -EOPNOTSUPP;300300+301301+ mutex_lock(&common->mutex);302302+ switch (vif->type) {303303+ case NL80211_IFTYPE_STATION:304304+ if (!adapter->sc_nvifs) {305305+ ++adapter->sc_nvifs;306306+ adapter->vifs[0] = vif;307307+ ret = rsi_set_vap_capabilities(common, STA_OPMODE);308308+ }309309+ break;310310+ default:311311+ rsi_dbg(ERR_ZONE,312312+ "%s: Interface type %d not supported\n", __func__,313313+ vif->type);314314+ }315315+ mutex_unlock(&common->mutex);316316+317317+ return ret;318318+}319319+320320+/**321321+ * rsi_mac80211_remove_interface() - This function notifies driver that an322322+ * interface is going down.323323+ * @hw: Pointer to the ieee80211_hw structure.324324+ * @vif: Pointer to the ieee80211_vif structure.325325+ *326326+ * Return: None.327327+ */328328+static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,329329+ struct ieee80211_vif *vif)330330+{331331+ struct rsi_hw *adapter = hw->priv;332332+ struct rsi_common *common = adapter->priv;333333+334334+ mutex_lock(&common->mutex);335335+ if (vif->type == NL80211_IFTYPE_STATION)336336+ adapter->sc_nvifs--;337337+338338+ if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))339339+ adapter->vifs[0] = NULL;340340+ mutex_unlock(&common->mutex);341341+}342342+343343+/**344344+ * rsi_mac80211_config() - This function is a handler for configuration345345+ * requests. The stack calls this function to346346+ * change hardware configuration, e.g., channel.347347+ * @hw: Pointer to the ieee80211_hw structure.348348+ * @changed: Changed flags set.349349+ *350350+ * Return: 0 on success, negative error code on failure.351351+ */352352+static int rsi_mac80211_config(struct ieee80211_hw *hw,353353+ u32 changed)354354+{355355+ struct rsi_hw *adapter = hw->priv;356356+ struct rsi_common *common = adapter->priv;357357+ int status = -EOPNOTSUPP;358358+359359+ mutex_lock(&common->mutex);360360+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {361361+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;362362+ u16 channel = curchan->hw_value;363363+364364+ rsi_dbg(INFO_ZONE,365365+ "%s: Set channel: %d MHz type: %d channel_no %d\n",366366+ __func__, curchan->center_freq,367367+ curchan->flags, channel);368368+ common->band = curchan->band;369369+ status = rsi_set_channel(adapter->priv, channel);370370+ }371371+ mutex_unlock(&common->mutex);372372+373373+ return status;374374+}375375+376376+/**377377+ * rsi_get_connected_channel() - This function is used to get the current378378+ * connected channel number.379379+ * @adapter: Pointer to the adapter structure.380380+ *381381+ * Return: Current connected AP's channel number is returned.382382+ */383383+u16 rsi_get_connected_channel(struct rsi_hw *adapter)384384+{385385+ struct ieee80211_vif *vif = adapter->vifs[0];386386+ if (vif) {387387+ struct ieee80211_bss_conf *bss = &vif->bss_conf;388388+ struct ieee80211_channel *channel = bss->chandef.chan;389389+ return channel->hw_value;390390+ }391391+392392+ return 0;393393+}394394+395395+/**396396+ * rsi_mac80211_bss_info_changed() - This function is a handler for config397397+ * requests related to BSS parameters that398398+ * may vary during BSS's lifespan.399399+ * @hw: Pointer to the ieee80211_hw structure.400400+ * @vif: Pointer to the ieee80211_vif structure.401401+ * @bss_conf: Pointer to the ieee80211_bss_conf structure.402402+ * @changed: Changed flags set.403403+ *404404+ * Return: None.405405+ */406406+static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,407407+ struct ieee80211_vif *vif,408408+ struct ieee80211_bss_conf *bss_conf,409409+ u32 changed)410410+{411411+ struct rsi_hw *adapter = hw->priv;412412+ struct rsi_common *common = adapter->priv;413413+414414+ mutex_lock(&common->mutex);415415+ if (changed & BSS_CHANGED_ASSOC) {416416+ rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n",417417+ __func__, bss_conf->assoc);418418+ rsi_inform_bss_status(common,419419+ bss_conf->assoc,420420+ bss_conf->bssid,421421+ bss_conf->qos,422422+ bss_conf->aid);423423+ }424424+ mutex_unlock(&common->mutex);425425+}426426+427427+/**428428+ * rsi_mac80211_conf_filter() - This function configure the device's RX filter.429429+ * @hw: Pointer to the ieee80211_hw structure.430430+ * @changed: Changed flags set.431431+ * @total_flags: Total initial flags set.432432+ * @multicast: Multicast.433433+ *434434+ * Return: None.435435+ */436436+static void rsi_mac80211_conf_filter(struct ieee80211_hw *hw,437437+ u32 changed_flags,438438+ u32 *total_flags,439439+ u64 multicast)440440+{441441+ /* Not doing much here as of now */442442+ *total_flags &= RSI_SUPP_FILTERS;443443+}444444+445445+/**446446+ * rsi_mac80211_conf_tx() - This function configures TX queue parameters447447+ * (EDCF (aifs, cw_min, cw_max), bursting)448448+ * for a hardware TX queue.449449+ * @hw: Pointer to the ieee80211_hw structure450450+ * @vif: Pointer to the ieee80211_vif structure.451451+ * @queue: Queue number.452452+ * @params: Pointer to ieee80211_tx_queue_params structure.453453+ *454454+ * Return: 0 on success, negative error code on failure.455455+ */456456+static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw,457457+ struct ieee80211_vif *vif, u16 queue,458458+ const struct ieee80211_tx_queue_params *params)459459+{460460+ struct rsi_hw *adapter = hw->priv;461461+ struct rsi_common *common = adapter->priv;462462+ u8 idx = 0;463463+464464+ if (queue >= IEEE80211_NUM_ACS)465465+ return 0;466466+467467+ rsi_dbg(INFO_ZONE,468468+ "%s: Conf queue %d, aifs: %d, cwmin: %d cwmax: %d, txop: %d\n",469469+ __func__, queue, params->aifs,470470+ params->cw_min, params->cw_max, params->txop);471471+472472+ mutex_lock(&common->mutex);473473+ /* Map into the way the f/w expects */474474+ switch (queue) {475475+ case IEEE80211_AC_VO:476476+ idx = VO_Q;477477+ break;478478+ case IEEE80211_AC_VI:479479+ idx = VI_Q;480480+ break;481481+ case IEEE80211_AC_BE:482482+ idx = BE_Q;483483+ break;484484+ case IEEE80211_AC_BK:485485+ idx = BK_Q;486486+ break;487487+ default:488488+ idx = BE_Q;489489+ break;490490+ }491491+492492+ memcpy(&common->edca_params[idx],493493+ params,494494+ sizeof(struct ieee80211_tx_queue_params));495495+ mutex_unlock(&common->mutex);496496+497497+ return 0;498498+}499499+500500+/**501501+ * rsi_hal_key_config() - This function loads the keys into the firmware.502502+ * @hw: Pointer to the ieee80211_hw structure.503503+ * @vif: Pointer to the ieee80211_vif structure.504504+ * @key: Pointer to the ieee80211_key_conf structure.505505+ *506506+ * Return: status: 0 on success, -1 on failure.507507+ */508508+static int rsi_hal_key_config(struct ieee80211_hw *hw,509509+ struct ieee80211_vif *vif,510510+ struct ieee80211_key_conf *key)511511+{512512+ struct rsi_hw *adapter = hw->priv;513513+ int status;514514+ u8 key_type;515515+516516+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)517517+ key_type = RSI_PAIRWISE_KEY;518518+ else519519+ key_type = RSI_GROUP_KEY;520520+521521+ rsi_dbg(ERR_ZONE, "%s: Cipher 0x%x key_type: %d key_len: %d\n",522522+ __func__, key->cipher, key_type, key->keylen);523523+524524+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) ||525525+ (key->cipher == WLAN_CIPHER_SUITE_WEP40)) {526526+ status = rsi_hal_load_key(adapter->priv,527527+ key->key,528528+ key->keylen,529529+ RSI_PAIRWISE_KEY,530530+ key->keyidx,531531+ key->cipher);532532+ if (status)533533+ return status;534534+ }535535+ return rsi_hal_load_key(adapter->priv,536536+ key->key,537537+ key->keylen,538538+ key_type,539539+ key->keyidx,540540+ key->cipher);541541+}542542+543543+/**544544+ * rsi_mac80211_set_key() - This function sets type of key to be loaded.545545+ * @hw: Pointer to the ieee80211_hw structure.546546+ * @cmd: enum set_key_cmd.547547+ * @vif: Pointer to the ieee80211_vif structure.548548+ * @sta: Pointer to the ieee80211_sta structure.549549+ * @key: Pointer to the ieee80211_key_conf structure.550550+ *551551+ * Return: status: 0 on success, negative error code on failure.552552+ */553553+static int rsi_mac80211_set_key(struct ieee80211_hw *hw,554554+ enum set_key_cmd cmd,555555+ struct ieee80211_vif *vif,556556+ struct ieee80211_sta *sta,557557+ struct ieee80211_key_conf *key)558558+{559559+ struct rsi_hw *adapter = hw->priv;560560+ struct rsi_common *common = adapter->priv;561561+ struct security_info *secinfo = &common->secinfo;562562+ int status;563563+564564+ mutex_lock(&common->mutex);565565+ switch (cmd) {566566+ case SET_KEY:567567+ secinfo->security_enable = true;568568+ status = rsi_hal_key_config(hw, vif, key);569569+ if (status) {570570+ mutex_unlock(&common->mutex);571571+ return status;572572+ }573573+574574+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)575575+ secinfo->ptk_cipher = key->cipher;576576+ else577577+ secinfo->gtk_cipher = key->cipher;578578+579579+ key->hw_key_idx = key->keyidx;580580+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;581581+582582+ rsi_dbg(ERR_ZONE, "%s: RSI set_key\n", __func__);583583+ break;584584+585585+ case DISABLE_KEY:586586+ secinfo->security_enable = false;587587+ rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);588588+ memset(key, 0, sizeof(struct ieee80211_key_conf));589589+ status = rsi_hal_key_config(hw, vif, key);590590+ break;591591+592592+ default:593593+ status = -EOPNOTSUPP;594594+ break;595595+ }596596+597597+ mutex_unlock(&common->mutex);598598+ return status;599599+}600600+601601+/**602602+ * rsi_mac80211_ampdu_action() - This function selects the AMPDU action for603603+ * the corresponding mlme_action flag and604604+ * informs the f/w regarding this.605605+ * @hw: Pointer to the ieee80211_hw structure.606606+ * @vif: Pointer to the ieee80211_vif structure.607607+ * @action: ieee80211_ampdu_mlme_action enum.608608+ * @sta: Pointer to the ieee80211_sta structure.609609+ * @tid: Traffic identifier.610610+ * @ssn: Pointer to ssn value.611611+ * @buf_size: Buffer size (for kernel version > 2.6.38).612612+ *613613+ * Return: status: 0 on success, negative error code on failure.614614+ */615615+static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,616616+ struct ieee80211_vif *vif,617617+ enum ieee80211_ampdu_mlme_action action,618618+ struct ieee80211_sta *sta,619619+ unsigned short tid,620620+ unsigned short *ssn,621621+ unsigned char buf_size)622622+{623623+ int status = -EOPNOTSUPP;624624+ struct rsi_hw *adapter = hw->priv;625625+ struct rsi_common *common = adapter->priv;626626+ u16 seq_no = 0;627627+ u8 ii = 0;628628+629629+ for (ii = 0; ii < RSI_MAX_VIFS; ii++) {630630+ if (vif == adapter->vifs[ii])631631+ break;632632+ }633633+634634+ mutex_lock(&common->mutex);635635+ rsi_dbg(INFO_ZONE, "%s: AMPDU action %d called\n", __func__, action);636636+ if (ssn != NULL)637637+ seq_no = *ssn;638638+639639+ switch (action) {640640+ case IEEE80211_AMPDU_RX_START:641641+ status = rsi_send_aggregation_params_frame(common,642642+ tid,643643+ seq_no,644644+ buf_size,645645+ STA_RX_ADDBA_DONE);646646+ break;647647+648648+ case IEEE80211_AMPDU_RX_STOP:649649+ status = rsi_send_aggregation_params_frame(common,650650+ tid,651651+ 0,652652+ buf_size,653653+ STA_RX_DELBA);654654+ break;655655+656656+ case IEEE80211_AMPDU_TX_START:657657+ common->vif_info[ii].seq_start = seq_no;658658+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);659659+ break;660660+661661+ case IEEE80211_AMPDU_TX_STOP_CONT:662662+ case IEEE80211_AMPDU_TX_STOP_FLUSH:663663+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:664664+ status = rsi_send_aggregation_params_frame(common,665665+ tid,666666+ seq_no,667667+ buf_size,668668+ STA_TX_DELBA);669669+ if (!status)670670+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);671671+ break;672672+673673+ case IEEE80211_AMPDU_TX_OPERATIONAL:674674+ status = rsi_send_aggregation_params_frame(common,675675+ tid,676676+ common->vif_info[ii]677677+ .seq_start,678678+ buf_size,679679+ STA_TX_ADDBA_DONE);680680+ break;681681+682682+ default:683683+ rsi_dbg(ERR_ZONE, "%s: Uknown AMPDU action\n", __func__);684684+ break;685685+ }686686+687687+ mutex_unlock(&common->mutex);688688+ return status;689689+}690690+691691+/**692692+ * rsi_mac80211_set_rts_threshold() - This function sets rts threshold value.693693+ * @hw: Pointer to the ieee80211_hw structure.694694+ * @value: Rts threshold value.695695+ *696696+ * Return: 0 on success.697697+ */698698+static int rsi_mac80211_set_rts_threshold(struct ieee80211_hw *hw,699699+ u32 value)700700+{701701+ struct rsi_hw *adapter = hw->priv;702702+ struct rsi_common *common = adapter->priv;703703+704704+ mutex_lock(&common->mutex);705705+ common->rts_threshold = value;706706+ mutex_unlock(&common->mutex);707707+708708+ return 0;709709+}710710+711711+/**712712+ * rsi_mac80211_set_rate_mask() - This function sets bitrate_mask to be used.713713+ * @hw: Pointer to the ieee80211_hw structure714714+ * @vif: Pointer to the ieee80211_vif structure.715715+ * @mask: Pointer to the cfg80211_bitrate_mask structure.716716+ *717717+ * Return: 0 on success.718718+ */719719+static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw,720720+ struct ieee80211_vif *vif,721721+ const struct cfg80211_bitrate_mask *mask)722722+{723723+ struct rsi_hw *adapter = hw->priv;724724+ struct rsi_common *common = adapter->priv;725725+726726+ mutex_lock(&common->mutex);727727+728728+ common->fixedrate_mask[IEEE80211_BAND_2GHZ] = 0;729729+730730+ if (mask->control[IEEE80211_BAND_2GHZ].legacy == 0xfff) {731731+ common->fixedrate_mask[IEEE80211_BAND_2GHZ] =732732+ (mask->control[IEEE80211_BAND_2GHZ].ht_mcs[0] << 12);733733+ } else {734734+ common->fixedrate_mask[IEEE80211_BAND_2GHZ] =735735+ mask->control[IEEE80211_BAND_2GHZ].legacy;736736+ }737737+ mutex_unlock(&common->mutex);738738+739739+ return 0;740740+}741741+742742+/**743743+ * rsi_fill_rx_status() - This function fills rx status in744744+ * ieee80211_rx_status structure.745745+ * @hw: Pointer to the ieee80211_hw structure.746746+ * @skb: Pointer to the socket buffer structure.747747+ * @common: Pointer to the driver private structure.748748+ * @rxs: Pointer to the ieee80211_rx_status structure.749749+ *750750+ * Return: None.751751+ */752752+static void rsi_fill_rx_status(struct ieee80211_hw *hw,753753+ struct sk_buff *skb,754754+ struct rsi_common *common,755755+ struct ieee80211_rx_status *rxs)756756+{757757+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);758758+ struct skb_info *rx_params = (struct skb_info *)info->driver_data;759759+ struct ieee80211_hdr *hdr;760760+ char rssi = rx_params->rssi;761761+ u8 hdrlen = 0;762762+ u8 channel = rx_params->channel;763763+ s32 freq;764764+765765+ hdr = ((struct ieee80211_hdr *)(skb->data));766766+ hdrlen = ieee80211_hdrlen(hdr->frame_control);767767+768768+ memset(info, 0, sizeof(struct ieee80211_tx_info));769769+770770+ rxs->signal = -(rssi);771771+772772+ if (channel <= 14)773773+ rxs->band = IEEE80211_BAND_2GHZ;774774+ else775775+ rxs->band = IEEE80211_BAND_5GHZ;776776+777777+ freq = ieee80211_channel_to_frequency(channel, rxs->band);778778+779779+ if (freq)780780+ rxs->freq = freq;781781+782782+ if (ieee80211_has_protected(hdr->frame_control)) {783783+ if (rsi_is_cipher_wep(common)) {784784+ memmove(skb->data + 4, skb->data, hdrlen);785785+ skb_pull(skb, 4);786786+ } else {787787+ memmove(skb->data + 8, skb->data, hdrlen);788788+ skb_pull(skb, 8);789789+ rxs->flag |= RX_FLAG_MMIC_STRIPPED;790790+ }791791+ rxs->flag |= RX_FLAG_DECRYPTED;792792+ rxs->flag |= RX_FLAG_IV_STRIPPED;793793+ }794794+}795795+796796+/**797797+ * rsi_indicate_pkt_to_os() - This function sends recieved packet to mac80211.798798+ * @common: Pointer to the driver private structure.799799+ * @skb: Pointer to the socket buffer structure.800800+ *801801+ * Return: None.802802+ */803803+void rsi_indicate_pkt_to_os(struct rsi_common *common,804804+ struct sk_buff *skb)805805+{806806+ struct rsi_hw *adapter = common->priv;807807+ struct ieee80211_hw *hw = adapter->hw;808808+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);809809+810810+ if ((common->iface_down) || (!adapter->sc_nvifs)) {811811+ dev_kfree_skb(skb);812812+ return;813813+ }814814+815815+ /* filling in the ieee80211_rx_status flags */816816+ rsi_fill_rx_status(hw, skb, common, rx_status);817817+818818+ ieee80211_rx_irqsafe(hw, skb);819819+}820820+821821+static void rsi_set_min_rate(struct ieee80211_hw *hw,822822+ struct ieee80211_sta *sta,823823+ struct rsi_common *common)824824+{825825+ u8 band = hw->conf.chandef.chan->band;826826+ u8 ii;827827+ u32 rate_bitmap;828828+ bool matched = false;829829+830830+ common->bitrate_mask[band] = sta->supp_rates[band];831831+832832+ rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]);833833+834834+ if (rate_bitmap & 0xfff) {835835+ /* Find out the min rate */836836+ for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {837837+ if (rate_bitmap & BIT(ii)) {838838+ common->min_rate = rsi_rates[ii].hw_value;839839+ matched = true;840840+ break;841841+ }842842+ }843843+ }844844+845845+ common->vif_info[0].is_ht = sta->ht_cap.ht_supported;846846+847847+ if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) {848848+ for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) {849849+ if ((rate_bitmap >> 12) & BIT(ii)) {850850+ common->min_rate = rsi_mcsrates[ii];851851+ matched = true;852852+ break;853853+ }854854+ }855855+ }856856+857857+ if (!matched)858858+ common->min_rate = 0xffff;859859+}860860+861861+/**862862+ * rsi_mac80211_sta_add() - This function notifies driver about a peer getting863863+ * connected.864864+ * @hw: pointer to the ieee80211_hw structure.865865+ * @vif: Pointer to the ieee80211_vif structure.866866+ * @sta: Pointer to the ieee80211_sta structure.867867+ *868868+ * Return: 0 on success, -1 on failure.869869+ */870870+static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,871871+ struct ieee80211_vif *vif,872872+ struct ieee80211_sta *sta)873873+{874874+ struct rsi_hw *adapter = hw->priv;875875+ struct rsi_common *common = adapter->priv;876876+877877+ mutex_lock(&common->mutex);878878+879879+ rsi_set_min_rate(hw, sta, common);880880+881881+ if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||882882+ (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) {883883+ common->vif_info[0].sgi = true;884884+ }885885+886886+ if (sta->ht_cap.ht_supported)887887+ ieee80211_start_tx_ba_session(sta, 0, 0);888888+889889+ mutex_unlock(&common->mutex);890890+891891+ return 0;892892+}893893+894894+/**895895+ * rsi_mac80211_sta_remove() - This function notifies driver about a peer896896+ * getting disconnected.897897+ * @hw: Pointer to the ieee80211_hw structure.898898+ * @vif: Pointer to the ieee80211_vif structure.899899+ * @sta: Pointer to the ieee80211_sta structure.900900+ *901901+ * Return: 0 on success, -1 on failure.902902+ */903903+static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,904904+ struct ieee80211_vif *vif,905905+ struct ieee80211_sta *sta)906906+{907907+ struct rsi_hw *adapter = hw->priv;908908+ struct rsi_common *common = adapter->priv;909909+910910+ mutex_lock(&common->mutex);911911+ /* Resetting all the fields to default values */912912+ common->bitrate_mask[IEEE80211_BAND_2GHZ] = 0;913913+ common->bitrate_mask[IEEE80211_BAND_5GHZ] = 0;914914+ common->min_rate = 0xffff;915915+ common->vif_info[0].is_ht = false;916916+ common->vif_info[0].sgi = false;917917+ common->vif_info[0].seq_start = 0;918918+ common->secinfo.ptk_cipher = 0;919919+ common->secinfo.gtk_cipher = 0;920920+ mutex_unlock(&common->mutex);921921+922922+ return 0;923923+}924924+925925+static struct ieee80211_ops mac80211_ops = {926926+ .tx = rsi_mac80211_tx,927927+ .start = rsi_mac80211_start,928928+ .stop = rsi_mac80211_stop,929929+ .add_interface = rsi_mac80211_add_interface,930930+ .remove_interface = rsi_mac80211_remove_interface,931931+ .config = rsi_mac80211_config,932932+ .bss_info_changed = rsi_mac80211_bss_info_changed,933933+ .conf_tx = rsi_mac80211_conf_tx,934934+ .configure_filter = rsi_mac80211_conf_filter,935935+ .set_key = rsi_mac80211_set_key,936936+ .set_rts_threshold = rsi_mac80211_set_rts_threshold,937937+ .set_bitrate_mask = rsi_mac80211_set_rate_mask,938938+ .ampdu_action = rsi_mac80211_ampdu_action,939939+ .sta_add = rsi_mac80211_sta_add,940940+ .sta_remove = rsi_mac80211_sta_remove,941941+};942942+943943+/**944944+ * rsi_mac80211_attach() - This function is used to initialize Mac80211 stack.945945+ * @common: Pointer to the driver private structure.946946+ *947947+ * Return: 0 on success, -1 on failure.948948+ */949949+int rsi_mac80211_attach(struct rsi_common *common)950950+{951951+ int status = 0;952952+ struct ieee80211_hw *hw = NULL;953953+ struct wiphy *wiphy = NULL;954954+ struct rsi_hw *adapter = common->priv;955955+ u8 addr_mask[ETH_ALEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x3};956956+957957+ rsi_dbg(INIT_ZONE, "%s: Performing mac80211 attach\n", __func__);958958+959959+ hw = ieee80211_alloc_hw(sizeof(struct rsi_hw), &mac80211_ops);960960+ if (!hw) {961961+ rsi_dbg(ERR_ZONE, "%s: ieee80211 hw alloc failed\n", __func__);962962+ return -ENOMEM;963963+ }964964+965965+ wiphy = hw->wiphy;966966+967967+ SET_IEEE80211_DEV(hw, adapter->device);968968+969969+ hw->priv = adapter;970970+ adapter->hw = hw;971971+972972+ hw->flags = IEEE80211_HW_SIGNAL_DBM |973973+ IEEE80211_HW_HAS_RATE_CONTROL |974974+ IEEE80211_HW_AMPDU_AGGREGATION |975975+ 0;976976+977977+ hw->queues = MAX_HW_QUEUES;978978+ hw->extra_tx_headroom = RSI_NEEDED_HEADROOM;979979+980980+ hw->max_rates = 1;981981+ hw->max_rate_tries = MAX_RETRIES;982982+983983+ hw->max_tx_aggregation_subframes = 6;984984+ rsi_register_rates_channels(adapter, IEEE80211_BAND_2GHZ);985985+ hw->rate_control_algorithm = "AARF";986986+987987+ SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);988988+ ether_addr_copy(hw->wiphy->addr_mask, addr_mask);989989+990990+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);991991+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;992992+ wiphy->retry_short = RETRY_SHORT;993993+ wiphy->retry_long = RETRY_LONG;994994+ wiphy->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;995995+ wiphy->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;996996+ wiphy->flags = 0;997997+998998+ wiphy->available_antennas_rx = 1;999999+ wiphy->available_antennas_tx = 1;10001000+ wiphy->bands[IEEE80211_BAND_2GHZ] =10011001+ &adapter->sbands[IEEE80211_BAND_2GHZ];10021002+10031003+ status = ieee80211_register_hw(hw);10041004+ if (status)10051005+ return status;10061006+10071007+ return rsi_init_dbgfs(adapter);10081008+}
+270
drivers/net/wireless/rsi/rsi_91x_main.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include <linux/module.h>1818+#include <linux/firmware.h>1919+#include "rsi_mgmt.h"2020+#include "rsi_common.h"2121+2222+u32 rsi_zone_enabled = /* INFO_ZONE |2323+ INIT_ZONE |2424+ MGMT_TX_ZONE |2525+ MGMT_RX_ZONE |2626+ DATA_TX_ZONE |2727+ DATA_RX_ZONE |2828+ FSM_ZONE |2929+ ISR_ZONE | */3030+ ERR_ZONE |3131+ 0;3232+EXPORT_SYMBOL_GPL(rsi_zone_enabled);3333+3434+/**3535+ * rsi_prepare_skb() - This function prepares the skb.3636+ * @common: Pointer to the driver private structure.3737+ * @buffer: Pointer to the packet data.3838+ * @pkt_len: Length of the packet.3939+ * @extended_desc: Extended descriptor.4040+ *4141+ * Return: Successfully skb.4242+ */4343+static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,4444+ u8 *buffer,4545+ u32 pkt_len,4646+ u8 extended_desc)4747+{4848+ struct ieee80211_tx_info *info;4949+ struct skb_info *rx_params;5050+ struct sk_buff *skb = NULL;5151+ u8 payload_offset;5252+5353+ if (WARN(!pkt_len, "%s: Dummy pkt received", __func__))5454+ return NULL;5555+5656+ if (pkt_len > (RSI_RCV_BUFFER_LEN * 4)) {5757+ rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n",5858+ __func__, pkt_len);5959+ pkt_len = RSI_RCV_BUFFER_LEN * 4;6060+ }6161+6262+ pkt_len -= extended_desc;6363+ skb = dev_alloc_skb(pkt_len + FRAME_DESC_SZ);6464+ if (skb == NULL)6565+ return NULL;6666+6767+ payload_offset = (extended_desc + FRAME_DESC_SZ);6868+ skb_put(skb, pkt_len);6969+ memcpy((skb->data), (buffer + payload_offset), skb->len);7070+7171+ info = IEEE80211_SKB_CB(skb);7272+ rx_params = (struct skb_info *)info->driver_data;7373+ rx_params->rssi = rsi_get_rssi(buffer);7474+ rx_params->channel = rsi_get_connected_channel(common->priv);7575+7676+ return skb;7777+}7878+7979+/**8080+ * rsi_read_pkt() - This function reads frames from the card.8181+ * @common: Pointer to the driver private structure.8282+ * @rcv_pkt_len: Received pkt length. In case of USB it is 0.8383+ *8484+ * Return: 0 on success, -1 on failure.8585+ */8686+int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len)8787+{8888+ u8 *frame_desc = NULL, extended_desc = 0;8989+ u32 index, length = 0, queueno = 0;9090+ u16 actual_length = 0, offset;9191+ struct sk_buff *skb = NULL;9292+9393+ index = 0;9494+ do {9595+ frame_desc = &common->rx_data_pkt[index];9696+ actual_length = *(u16 *)&frame_desc[0];9797+ offset = *(u16 *)&frame_desc[2];9898+9999+ queueno = rsi_get_queueno(frame_desc, offset);100100+ length = rsi_get_length(frame_desc, offset);101101+ extended_desc = rsi_get_extended_desc(frame_desc, offset);102102+103103+ switch (queueno) {104104+ case RSI_WIFI_DATA_Q:105105+ skb = rsi_prepare_skb(common,106106+ (frame_desc + offset),107107+ length,108108+ extended_desc);109109+ if (skb == NULL)110110+ goto fail;111111+112112+ rsi_indicate_pkt_to_os(common, skb);113113+ break;114114+115115+ case RSI_WIFI_MGMT_Q:116116+ rsi_mgmt_pkt_recv(common, (frame_desc + offset));117117+ break;118118+119119+ default:120120+ rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n",121121+ __func__, queueno);122122+ goto fail;123123+ }124124+125125+ index += actual_length;126126+ rcv_pkt_len -= actual_length;127127+ } while (rcv_pkt_len > 0);128128+129129+ return 0;130130+fail:131131+ return -EINVAL;132132+}133133+EXPORT_SYMBOL_GPL(rsi_read_pkt);134134+135135+/**136136+ * rsi_tx_scheduler_thread() - This function is a kernel thread to send the137137+ * packets to the device.138138+ * @common: Pointer to the driver private structure.139139+ *140140+ * Return: None.141141+ */142142+static void rsi_tx_scheduler_thread(struct rsi_common *common)143143+{144144+ struct rsi_hw *adapter = common->priv;145145+ u32 timeout = EVENT_WAIT_FOREVER;146146+147147+ do {148148+ if (adapter->determine_event_timeout)149149+ timeout = adapter->determine_event_timeout(adapter);150150+ rsi_wait_event(&common->tx_thread.event, timeout);151151+ rsi_reset_event(&common->tx_thread.event);152152+153153+ if (common->init_done)154154+ rsi_core_qos_processor(common);155155+ } while (atomic_read(&common->tx_thread.thread_done) == 0);156156+ complete_and_exit(&common->tx_thread.completion, 0);157157+}158158+159159+/**160160+ * rsi_91x_init() - This function initializes os interface operations.161161+ * @void: Void.162162+ *163163+ * Return: Pointer to the adapter structure on success, NULL on failure .164164+ */165165+struct rsi_hw *rsi_91x_init(void)166166+{167167+ struct rsi_hw *adapter = NULL;168168+ struct rsi_common *common = NULL;169169+ u8 ii = 0;170170+171171+ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);172172+ if (!adapter)173173+ return NULL;174174+175175+ adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL);176176+ if (adapter->priv == NULL) {177177+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of memory\n",178178+ __func__);179179+ kfree(adapter);180180+ return NULL;181181+ } else {182182+ common = adapter->priv;183183+ common->priv = adapter;184184+ }185185+186186+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)187187+ skb_queue_head_init(&common->tx_queue[ii]);188188+189189+ rsi_init_event(&common->tx_thread.event);190190+ mutex_init(&common->mutex);191191+ mutex_init(&common->tx_rxlock);192192+193193+ if (rsi_create_kthread(common,194194+ &common->tx_thread,195195+ rsi_tx_scheduler_thread,196196+ "Tx-Thread")) {197197+ rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);198198+ goto err;199199+ }200200+201201+ common->init_done = true;202202+ return adapter;203203+204204+err:205205+ kfree(common);206206+ kfree(adapter);207207+ return NULL;208208+}209209+EXPORT_SYMBOL_GPL(rsi_91x_init);210210+211211+/**212212+ * rsi_91x_deinit() - This function de-intializes os intf operations.213213+ * @adapter: Pointer to the adapter structure.214214+ *215215+ * Return: None.216216+ */217217+void rsi_91x_deinit(struct rsi_hw *adapter)218218+{219219+ struct rsi_common *common = adapter->priv;220220+ u8 ii;221221+222222+ rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__);223223+224224+ rsi_kill_thread(&common->tx_thread);225225+226226+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)227227+ skb_queue_purge(&common->tx_queue[ii]);228228+229229+ common->init_done = false;230230+231231+ kfree(common);232232+ kfree(adapter->rsi_dev);233233+ kfree(adapter);234234+}235235+EXPORT_SYMBOL_GPL(rsi_91x_deinit);236236+237237+/**238238+ * rsi_91x_hal_module_init() - This function is invoked when the module is239239+ * loaded into the kernel.240240+ * It registers the client driver.241241+ * @void: Void.242242+ *243243+ * Return: 0 on success, -1 on failure.244244+ */245245+static int rsi_91x_hal_module_init(void)246246+{247247+ rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__);248248+ return 0;249249+}250250+251251+/**252252+ * rsi_91x_hal_module_exit() - This function is called at the time of253253+ * removing/unloading the module.254254+ * It unregisters the client driver.255255+ * @void: Void.256256+ *257257+ * Return: None.258258+ */259259+static void rsi_91x_hal_module_exit(void)260260+{261261+ rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__);262262+}263263+264264+module_init(rsi_91x_hal_module_init);265265+module_exit(rsi_91x_hal_module_exit);266266+MODULE_AUTHOR("Redpine Signals Inc");267267+MODULE_DESCRIPTION("Station driver for RSI 91x devices");268268+MODULE_SUPPORTED_DEVICE("RSI-91x");269269+MODULE_VERSION("0.1");270270+MODULE_LICENSE("Dual BSD/GPL");
+1302
drivers/net/wireless/rsi/rsi_91x_mgmt.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include <linux/etherdevice.h>1818+#include "rsi_mgmt.h"1919+#include "rsi_common.h"2020+2121+static struct bootup_params boot_params_20 = {2222+ .magic_number = cpu_to_le16(0x5aa5),2323+ .crystal_good_time = 0x0,2424+ .valid = cpu_to_le32(VALID_20),2525+ .reserved_for_valids = 0x0,2626+ .bootup_mode_info = 0x0,2727+ .digital_loop_back_params = 0x0,2828+ .rtls_timestamp_en = 0x0,2929+ .host_spi_intr_cfg = 0x0,3030+ .device_clk_info = {{3131+ .pll_config_g = {3232+ .tapll_info_g = {3333+ .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)|3434+ (TA_PLL_M_VAL_20)),3535+ .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20),3636+ },3737+ .pll960_info_g = {3838+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)|3939+ (PLL960_N_VAL_20)),4040+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),4141+ .pll_reg_3 = 0x0,4242+ },4343+ .afepll_info_g = {4444+ .pll_reg = cpu_to_le16(0x9f0),4545+ }4646+ },4747+ .switch_clk_g = {4848+ .switch_clk_info = cpu_to_le16(BIT(3)),4949+ .bbp_lmac_clk_reg_val = cpu_to_le16(0x121),5050+ .umac_clock_reg_config = 0x0,5151+ .qspi_uart_clock_reg_config = 0x05252+ }5353+ },5454+ {5555+ .pll_config_g = {5656+ .tapll_info_g = {5757+ .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)|5858+ (TA_PLL_M_VAL_20)),5959+ .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20),6060+ },6161+ .pll960_info_g = {6262+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)|6363+ (PLL960_N_VAL_20)),6464+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),6565+ .pll_reg_3 = 0x0,6666+ },6767+ .afepll_info_g = {6868+ .pll_reg = cpu_to_le16(0x9f0),6969+ }7070+ },7171+ .switch_clk_g = {7272+ .switch_clk_info = 0x0,7373+ .bbp_lmac_clk_reg_val = 0x0,7474+ .umac_clock_reg_config = 0x0,7575+ .qspi_uart_clock_reg_config = 0x07676+ }7777+ },7878+ {7979+ .pll_config_g = {8080+ .tapll_info_g = {8181+ .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_20 << 8)|8282+ (TA_PLL_M_VAL_20)),8383+ .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_20),8484+ },8585+ .pll960_info_g = {8686+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8)|8787+ (PLL960_N_VAL_20)),8888+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),8989+ .pll_reg_3 = 0x0,9090+ },9191+ .afepll_info_g = {9292+ .pll_reg = cpu_to_le16(0x9f0),9393+ }9494+ },9595+ .switch_clk_g = {9696+ .switch_clk_info = 0x0,9797+ .bbp_lmac_clk_reg_val = 0x0,9898+ .umac_clock_reg_config = 0x0,9999+ .qspi_uart_clock_reg_config = 0x0100100+ }101101+ } },102102+ .buckboost_wakeup_cnt = 0x0,103103+ .pmu_wakeup_wait = 0x0,104104+ .shutdown_wait_time = 0x0,105105+ .pmu_slp_clkout_sel = 0x0,106106+ .wdt_prog_value = 0x0,107107+ .wdt_soc_rst_delay = 0x0,108108+ .dcdc_operation_mode = 0x0,109109+ .soc_reset_wait_cnt = 0x0110110+};111111+112112+static struct bootup_params boot_params_40 = {113113+ .magic_number = cpu_to_le16(0x5aa5),114114+ .crystal_good_time = 0x0,115115+ .valid = cpu_to_le32(VALID_40),116116+ .reserved_for_valids = 0x0,117117+ .bootup_mode_info = 0x0,118118+ .digital_loop_back_params = 0x0,119119+ .rtls_timestamp_en = 0x0,120120+ .host_spi_intr_cfg = 0x0,121121+ .device_clk_info = {{122122+ .pll_config_g = {123123+ .tapll_info_g = {124124+ .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)|125125+ (TA_PLL_M_VAL_40)),126126+ .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40),127127+ },128128+ .pll960_info_g = {129129+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)|130130+ (PLL960_N_VAL_40)),131131+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),132132+ .pll_reg_3 = 0x0,133133+ },134134+ .afepll_info_g = {135135+ .pll_reg = cpu_to_le16(0x9f0),136136+ }137137+ },138138+ .switch_clk_g = {139139+ .switch_clk_info = cpu_to_le16(0x09),140140+ .bbp_lmac_clk_reg_val = cpu_to_le16(0x1121),141141+ .umac_clock_reg_config = cpu_to_le16(0x48),142142+ .qspi_uart_clock_reg_config = 0x0143143+ }144144+ },145145+ {146146+ .pll_config_g = {147147+ .tapll_info_g = {148148+ .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)|149149+ (TA_PLL_M_VAL_40)),150150+ .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40),151151+ },152152+ .pll960_info_g = {153153+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)|154154+ (PLL960_N_VAL_40)),155155+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),156156+ .pll_reg_3 = 0x0,157157+ },158158+ .afepll_info_g = {159159+ .pll_reg = cpu_to_le16(0x9f0),160160+ }161161+ },162162+ .switch_clk_g = {163163+ .switch_clk_info = 0x0,164164+ .bbp_lmac_clk_reg_val = 0x0,165165+ .umac_clock_reg_config = 0x0,166166+ .qspi_uart_clock_reg_config = 0x0167167+ }168168+ },169169+ {170170+ .pll_config_g = {171171+ .tapll_info_g = {172172+ .pll_reg_1 = cpu_to_le16((TA_PLL_N_VAL_40 << 8)|173173+ (TA_PLL_M_VAL_40)),174174+ .pll_reg_2 = cpu_to_le16(TA_PLL_P_VAL_40),175175+ },176176+ .pll960_info_g = {177177+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8)|178178+ (PLL960_N_VAL_40)),179179+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),180180+ .pll_reg_3 = 0x0,181181+ },182182+ .afepll_info_g = {183183+ .pll_reg = cpu_to_le16(0x9f0),184184+ }185185+ },186186+ .switch_clk_g = {187187+ .switch_clk_info = 0x0,188188+ .bbp_lmac_clk_reg_val = 0x0,189189+ .umac_clock_reg_config = 0x0,190190+ .qspi_uart_clock_reg_config = 0x0191191+ }192192+ } },193193+ .buckboost_wakeup_cnt = 0x0,194194+ .pmu_wakeup_wait = 0x0,195195+ .shutdown_wait_time = 0x0,196196+ .pmu_slp_clkout_sel = 0x0,197197+ .wdt_prog_value = 0x0,198198+ .wdt_soc_rst_delay = 0x0,199199+ .dcdc_operation_mode = 0x0,200200+ .soc_reset_wait_cnt = 0x0201201+};202202+203203+static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};204204+205205+/**206206+ * rsi_set_default_parameters() - This function sets default parameters.207207+ * @common: Pointer to the driver private structure.208208+ *209209+ * Return: none210210+ */211211+static void rsi_set_default_parameters(struct rsi_common *common)212212+{213213+ common->band = IEEE80211_BAND_2GHZ;214214+ common->channel_width = BW_20MHZ;215215+ common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;216216+ common->channel = 1;217217+ common->min_rate = 0xffff;218218+ common->fsm_state = FSM_CARD_NOT_READY;219219+ common->iface_down = true;220220+}221221+222222+/**223223+ * rsi_set_contention_vals() - This function sets the contention values for the224224+ * backoff procedure.225225+ * @common: Pointer to the driver private structure.226226+ *227227+ * Return: None.228228+ */229229+static void rsi_set_contention_vals(struct rsi_common *common)230230+{231231+ u8 ii = 0;232232+233233+ for (; ii < NUM_EDCA_QUEUES; ii++) {234234+ common->tx_qinfo[ii].wme_params =235235+ (((common->edca_params[ii].cw_min / 2) +236236+ (common->edca_params[ii].aifs)) *237237+ WMM_SHORT_SLOT_TIME + SIFS_DURATION);238238+ common->tx_qinfo[ii].weight = common->tx_qinfo[ii].wme_params;239239+ common->tx_qinfo[ii].pkt_contended = 0;240240+ }241241+}242242+243243+/**244244+ * rsi_send_internal_mgmt_frame() - This function sends management frames to245245+ * firmware.Also schedules packet to queue246246+ * for transmission.247247+ * @common: Pointer to the driver private structure.248248+ * @skb: Pointer to the socket buffer structure.249249+ *250250+ * Return: 0 on success, -1 on failure.251251+ */252252+static int rsi_send_internal_mgmt_frame(struct rsi_common *common,253253+ struct sk_buff *skb)254254+{255255+ struct skb_info *tx_params;256256+257257+ if (skb == NULL) {258258+ rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);259259+ return -ENOMEM;260260+ }261261+ tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data;262262+ tx_params->flags |= INTERNAL_MGMT_PKT;263263+ skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb);264264+ rsi_set_event(&common->tx_thread.event);265265+ return 0;266266+}267267+268268+/**269269+ * rsi_load_radio_caps() - This function is used to send radio capabilities270270+ * values to firmware.271271+ * @common: Pointer to the driver private structure.272272+ *273273+ * Return: 0 on success, corresponding negative error code on failure.274274+ */275275+static int rsi_load_radio_caps(struct rsi_common *common)276276+{277277+ struct rsi_radio_caps *radio_caps;278278+ struct rsi_hw *adapter = common->priv;279279+ struct ieee80211_hw *hw = adapter->hw;280280+ u16 inx = 0;281281+ u8 ii;282282+ u8 radio_id = 0;283283+ u16 gc[20] = {0xf0, 0xf0, 0xf0, 0xf0,284284+ 0xf0, 0xf0, 0xf0, 0xf0,285285+ 0xf0, 0xf0, 0xf0, 0xf0,286286+ 0xf0, 0xf0, 0xf0, 0xf0,287287+ 0xf0, 0xf0, 0xf0, 0xf0};288288+ struct ieee80211_conf *conf = &hw->conf;289289+ struct sk_buff *skb;290290+291291+ rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__);292292+293293+ skb = dev_alloc_skb(sizeof(struct rsi_radio_caps));294294+295295+ if (!skb) {296296+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",297297+ __func__);298298+ return -ENOMEM;299299+ }300300+301301+ memset(skb->data, 0, sizeof(struct rsi_radio_caps));302302+ radio_caps = (struct rsi_radio_caps *)skb->data;303303+304304+ radio_caps->desc_word[1] = cpu_to_le16(RADIO_CAPABILITIES);305305+ radio_caps->desc_word[4] = cpu_to_le16(RSI_RF_TYPE << 8);306306+307307+ if (common->channel_width == BW_40MHZ) {308308+ radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ);309309+ radio_caps->desc_word[7] |= cpu_to_le16(RSI_ENABLE_40MHZ);310310+ if (common->channel_width) {311311+ radio_caps->desc_word[5] =312312+ cpu_to_le16(common->channel_width << 12);313313+ radio_caps->desc_word[5] |= cpu_to_le16(FULL40M_ENABLE);314314+ }315315+316316+ if (conf_is_ht40_minus(conf)) {317317+ radio_caps->desc_word[5] = 0;318318+ radio_caps->desc_word[5] |=319319+ cpu_to_le16(LOWER_20_ENABLE);320320+ radio_caps->desc_word[5] |=321321+ cpu_to_le16(LOWER_20_ENABLE >> 12);322322+ }323323+324324+ if (conf_is_ht40_plus(conf)) {325325+ radio_caps->desc_word[5] = 0;326326+ radio_caps->desc_word[5] |=327327+ cpu_to_le16(UPPER_20_ENABLE);328328+ radio_caps->desc_word[5] |=329329+ cpu_to_le16(UPPER_20_ENABLE >> 12);330330+ }331331+ }332332+333333+ radio_caps->desc_word[7] |= cpu_to_le16(radio_id << 8);334334+335335+ for (ii = 0; ii < MAX_HW_QUEUES; ii++) {336336+ radio_caps->qos_params[ii].cont_win_min_q = cpu_to_le16(3);337337+ radio_caps->qos_params[ii].cont_win_max_q = cpu_to_le16(0x3f);338338+ radio_caps->qos_params[ii].aifsn_val_q = cpu_to_le16(2);339339+ radio_caps->qos_params[ii].txop_q = 0;340340+ }341341+342342+ for (ii = 0; ii < MAX_HW_QUEUES - 4; ii++) {343343+ radio_caps->qos_params[ii].cont_win_min_q =344344+ cpu_to_le16(common->edca_params[ii].cw_min);345345+ radio_caps->qos_params[ii].cont_win_max_q =346346+ cpu_to_le16(common->edca_params[ii].cw_max);347347+ radio_caps->qos_params[ii].aifsn_val_q =348348+ cpu_to_le16((common->edca_params[ii].aifs) << 8);349349+ radio_caps->qos_params[ii].txop_q =350350+ cpu_to_le16(common->edca_params[ii].txop);351351+ }352352+353353+ memcpy(&common->rate_pwr[0], &gc[0], 40);354354+ for (ii = 0; ii < 20; ii++)355355+ radio_caps->gcpd_per_rate[inx++] =356356+ cpu_to_le16(common->rate_pwr[ii] & 0x00FF);357357+358358+ radio_caps->desc_word[0] = cpu_to_le16((sizeof(struct rsi_radio_caps) -359359+ FRAME_DESC_SZ) |360360+ (RSI_WIFI_MGMT_Q << 12));361361+362362+363363+ skb_put(skb, (sizeof(struct rsi_radio_caps)));364364+365365+ return rsi_send_internal_mgmt_frame(common, skb);366366+}367367+368368+/**369369+ * rsi_mgmt_pkt_to_core() - This function is the entry point for Mgmt module.370370+ * @common: Pointer to the driver private structure.371371+ * @msg: Pointer to received packet.372372+ * @msg_len: Length of the recieved packet.373373+ * @type: Type of recieved packet.374374+ *375375+ * Return: 0 on success, -1 on failure.376376+ */377377+static int rsi_mgmt_pkt_to_core(struct rsi_common *common,378378+ u8 *msg,379379+ s32 msg_len,380380+ u8 type)381381+{382382+ struct rsi_hw *adapter = common->priv;383383+ struct ieee80211_tx_info *info;384384+ struct skb_info *rx_params;385385+ u8 pad_bytes = msg[4];386386+ u8 pkt_recv;387387+ struct sk_buff *skb;388388+ char *buffer;389389+390390+ if (type == RX_DOT11_MGMT) {391391+ if (!adapter->sc_nvifs)392392+ return -ENOLINK;393393+394394+ msg_len -= pad_bytes;395395+ if ((msg_len <= 0) || (!msg)) {396396+ rsi_dbg(MGMT_RX_ZONE, "Invalid rx msg of len = %d\n",397397+ __func__, msg_len);398398+ return -EINVAL;399399+ }400400+401401+ skb = dev_alloc_skb(msg_len);402402+ if (!skb) {403403+ rsi_dbg(ERR_ZONE, "%s: Failed to allocate skb\n",404404+ __func__);405405+ return -ENOMEM;406406+ }407407+408408+ buffer = skb_put(skb, msg_len);409409+410410+ memcpy(buffer,411411+ (u8 *)(msg + FRAME_DESC_SZ + pad_bytes),412412+ msg_len);413413+414414+ pkt_recv = buffer[0];415415+416416+ info = IEEE80211_SKB_CB(skb);417417+ rx_params = (struct skb_info *)info->driver_data;418418+ rx_params->rssi = rsi_get_rssi(msg);419419+ rx_params->channel = rsi_get_channel(msg);420420+ rsi_indicate_pkt_to_os(common, skb);421421+ } else {422422+ rsi_dbg(MGMT_TX_ZONE, "%s: Internal Packet\n", __func__);423423+ }424424+425425+ return 0;426426+}427427+428428+/**429429+ * rsi_hal_send_sta_notify_frame() - This function sends the station notify430430+ * frame to firmware.431431+ * @common: Pointer to the driver private structure.432432+ * @opmode: Operating mode of device.433433+ * @notify_event: Notification about station connection.434434+ * @bssid: bssid.435435+ * @qos_enable: Qos is enabled.436436+ * @aid: Aid (unique for all STA).437437+ *438438+ * Return: status: 0 on success, corresponding negative error code on failure.439439+ */440440+static int rsi_hal_send_sta_notify_frame(struct rsi_common *common,441441+ u8 opmode,442442+ u8 notify_event,443443+ const unsigned char *bssid,444444+ u8 qos_enable,445445+ u16 aid)446446+{447447+ struct sk_buff *skb = NULL;448448+ struct rsi_peer_notify *peer_notify;449449+ u16 vap_id = 0;450450+ int status;451451+452452+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending sta notify frame\n", __func__);453453+454454+ skb = dev_alloc_skb(sizeof(struct rsi_peer_notify));455455+456456+ if (!skb) {457457+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",458458+ __func__);459459+ return -ENOMEM;460460+ }461461+462462+ memset(skb->data, 0, sizeof(struct rsi_peer_notify));463463+ peer_notify = (struct rsi_peer_notify *)skb->data;464464+465465+ peer_notify->command = cpu_to_le16(opmode << 1);466466+467467+ switch (notify_event) {468468+ case STA_CONNECTED:469469+ peer_notify->command |= cpu_to_le16(RSI_ADD_PEER);470470+ break;471471+ case STA_DISCONNECTED:472472+ peer_notify->command |= cpu_to_le16(RSI_DELETE_PEER);473473+ break;474474+ default:475475+ break;476476+ }477477+478478+ peer_notify->command |= cpu_to_le16((aid & 0xfff) << 4);479479+ ether_addr_copy(peer_notify->mac_addr, bssid);480480+481481+ peer_notify->sta_flags = cpu_to_le32((qos_enable) ? 1 : 0);482482+483483+ peer_notify->desc_word[0] =484484+ cpu_to_le16((sizeof(struct rsi_peer_notify) - FRAME_DESC_SZ) |485485+ (RSI_WIFI_MGMT_Q << 12));486486+ peer_notify->desc_word[1] = cpu_to_le16(PEER_NOTIFY);487487+ peer_notify->desc_word[7] |= cpu_to_le16(vap_id << 8);488488+489489+ skb_put(skb, sizeof(struct rsi_peer_notify));490490+491491+ status = rsi_send_internal_mgmt_frame(common, skb);492492+493493+ if (!status && qos_enable) {494494+ rsi_set_contention_vals(common);495495+ status = rsi_load_radio_caps(common);496496+ }497497+ return status;498498+}499499+500500+/**501501+ * rsi_send_aggregation_params_frame() - This function sends the ampdu502502+ * indication frame to firmware.503503+ * @common: Pointer to the driver private structure.504504+ * @tid: traffic identifier.505505+ * @ssn: ssn.506506+ * @buf_size: buffer size.507507+ * @event: notification about station connection.508508+ *509509+ * Return: 0 on success, corresponding negative error code on failure.510510+ */511511+int rsi_send_aggregation_params_frame(struct rsi_common *common,512512+ u16 tid,513513+ u16 ssn,514514+ u8 buf_size,515515+ u8 event)516516+{517517+ struct sk_buff *skb = NULL;518518+ struct rsi_mac_frame *mgmt_frame;519519+ u8 peer_id = 0;520520+521521+ skb = dev_alloc_skb(FRAME_DESC_SZ);522522+523523+ if (!skb) {524524+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",525525+ __func__);526526+ return -ENOMEM;527527+ }528528+529529+ memset(skb->data, 0, FRAME_DESC_SZ);530530+ mgmt_frame = (struct rsi_mac_frame *)skb->data;531531+532532+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending AMPDU indication frame\n", __func__);533533+534534+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);535535+ mgmt_frame->desc_word[1] = cpu_to_le16(AMPDU_IND);536536+537537+ if (event == STA_TX_ADDBA_DONE) {538538+ mgmt_frame->desc_word[4] = cpu_to_le16(ssn);539539+ mgmt_frame->desc_word[5] = cpu_to_le16(buf_size);540540+ mgmt_frame->desc_word[7] =541541+ cpu_to_le16((tid | (START_AMPDU_AGGR << 4) | (peer_id << 8)));542542+ } else if (event == STA_RX_ADDBA_DONE) {543543+ mgmt_frame->desc_word[4] = cpu_to_le16(ssn);544544+ mgmt_frame->desc_word[7] = cpu_to_le16(tid |545545+ (START_AMPDU_AGGR << 4) |546546+ (RX_BA_INDICATION << 5) |547547+ (peer_id << 8));548548+ } else if (event == STA_TX_DELBA) {549549+ mgmt_frame->desc_word[7] = cpu_to_le16(tid |550550+ (STOP_AMPDU_AGGR << 4) |551551+ (peer_id << 8));552552+ } else if (event == STA_RX_DELBA) {553553+ mgmt_frame->desc_word[7] = cpu_to_le16(tid |554554+ (STOP_AMPDU_AGGR << 4) |555555+ (RX_BA_INDICATION << 5) |556556+ (peer_id << 8));557557+ }558558+559559+ skb_put(skb, FRAME_DESC_SZ);560560+561561+ return rsi_send_internal_mgmt_frame(common, skb);562562+}563563+564564+/**565565+ * rsi_program_bb_rf() - This function starts base band and RF programming.566566+ * This is called after initial configurations are done.567567+ * @common: Pointer to the driver private structure.568568+ *569569+ * Return: 0 on success, corresponding negative error code on failure.570570+ */571571+static int rsi_program_bb_rf(struct rsi_common *common)572572+{573573+ struct sk_buff *skb;574574+ struct rsi_mac_frame *mgmt_frame;575575+576576+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending program BB/RF frame\n", __func__);577577+578578+ skb = dev_alloc_skb(FRAME_DESC_SZ);579579+ if (!skb) {580580+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",581581+ __func__);582582+ return -ENOMEM;583583+ }584584+585585+ memset(skb->data, 0, FRAME_DESC_SZ);586586+ mgmt_frame = (struct rsi_mac_frame *)skb->data;587587+588588+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);589589+ mgmt_frame->desc_word[1] = cpu_to_le16(BBP_PROG_IN_TA);590590+ mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint << 8);591591+592592+ if (common->rf_reset) {593593+ mgmt_frame->desc_word[7] = cpu_to_le16(RF_RESET_ENABLE);594594+ rsi_dbg(MGMT_TX_ZONE, "%s: ===> RF RESET REQUEST SENT <===\n",595595+ __func__);596596+ common->rf_reset = 0;597597+ }598598+ common->bb_rf_prog_count = 1;599599+ mgmt_frame->desc_word[7] |= cpu_to_le16(PUT_BBP_RESET |600600+ BBP_REG_WRITE | (RSI_RF_TYPE << 4));601601+ skb_put(skb, FRAME_DESC_SZ);602602+603603+ return rsi_send_internal_mgmt_frame(common, skb);604604+}605605+606606+/**607607+ * rsi_set_vap_capabilities() - This function send vap capability to firmware.608608+ * @common: Pointer to the driver private structure.609609+ * @opmode: Operating mode of device.610610+ *611611+ * Return: 0 on success, corresponding negative error code on failure.612612+ */613613+int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode)614614+{615615+ struct sk_buff *skb = NULL;616616+ struct rsi_vap_caps *vap_caps;617617+ u16 vap_id = 0;618618+619619+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending VAP capabilities frame\n", __func__);620620+621621+ skb = dev_alloc_skb(sizeof(struct rsi_vap_caps));622622+ if (!skb) {623623+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",624624+ __func__);625625+ return -ENOMEM;626626+ }627627+628628+ memset(skb->data, 0, sizeof(struct rsi_vap_caps));629629+ vap_caps = (struct rsi_vap_caps *)skb->data;630630+631631+ vap_caps->desc_word[0] = cpu_to_le16((sizeof(struct rsi_vap_caps) -632632+ FRAME_DESC_SZ) |633633+ (RSI_WIFI_MGMT_Q << 12));634634+ vap_caps->desc_word[1] = cpu_to_le16(VAP_CAPABILITIES);635635+ vap_caps->desc_word[4] = cpu_to_le16(mode |636636+ (common->channel_width << 8));637637+ vap_caps->desc_word[7] = cpu_to_le16((vap_id << 8) |638638+ (common->mac_id << 4) |639639+ common->radio_id);640640+641641+ memcpy(vap_caps->mac_addr, common->mac_addr, IEEE80211_ADDR_LEN);642642+ vap_caps->keep_alive_period = cpu_to_le16(90);643643+ vap_caps->frag_threshold = cpu_to_le16(IEEE80211_MAX_FRAG_THRESHOLD);644644+645645+ vap_caps->rts_threshold = cpu_to_le16(common->rts_threshold);646646+ vap_caps->default_mgmt_rate = 0;647647+ if (conf_is_ht40(&common->priv->hw->conf)) {648648+ vap_caps->default_ctrl_rate =649649+ cpu_to_le32(RSI_RATE_6 | FULL40M_ENABLE << 16);650650+ } else {651651+ vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6);652652+ }653653+ vap_caps->default_data_rate = 0;654654+ vap_caps->beacon_interval = cpu_to_le16(200);655655+ vap_caps->dtim_period = cpu_to_le16(4);656656+657657+ skb_put(skb, sizeof(*vap_caps));658658+659659+ return rsi_send_internal_mgmt_frame(common, skb);660660+}661661+662662+/**663663+ * rsi_hal_load_key() - This function is used to load keys within the firmware.664664+ * @common: Pointer to the driver private structure.665665+ * @data: Pointer to the key data.666666+ * @key_len: Key length to be loaded.667667+ * @key_type: Type of key: GROUP/PAIRWISE.668668+ * @key_id: Key index.669669+ * @cipher: Type of cipher used.670670+ *671671+ * Return: 0 on success, -1 on failure.672672+ */673673+int rsi_hal_load_key(struct rsi_common *common,674674+ u8 *data,675675+ u16 key_len,676676+ u8 key_type,677677+ u8 key_id,678678+ u32 cipher)679679+{680680+ struct sk_buff *skb = NULL;681681+ struct rsi_set_key *set_key;682682+ u16 key_descriptor = 0;683683+684684+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending load key frame\n", __func__);685685+686686+ skb = dev_alloc_skb(sizeof(struct rsi_set_key));687687+ if (!skb) {688688+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",689689+ __func__);690690+ return -ENOMEM;691691+ }692692+693693+ memset(skb->data, 0, sizeof(struct rsi_set_key));694694+ set_key = (struct rsi_set_key *)skb->data;695695+696696+ if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||697697+ (cipher == WLAN_CIPHER_SUITE_WEP104)) {698698+ key_len += 1;699699+ key_descriptor |= BIT(2);700700+ if (key_len >= 13)701701+ key_descriptor |= BIT(3);702702+ } else if (cipher != KEY_TYPE_CLEAR) {703703+ key_descriptor |= BIT(4);704704+ if (key_type == RSI_PAIRWISE_KEY)705705+ key_id = 0;706706+ if (cipher == WLAN_CIPHER_SUITE_TKIP)707707+ key_descriptor |= BIT(5);708708+ }709709+ key_descriptor |= (key_type | BIT(13) | (key_id << 14));710710+711711+ set_key->desc_word[0] = cpu_to_le16((sizeof(struct rsi_set_key) -712712+ FRAME_DESC_SZ) |713713+ (RSI_WIFI_MGMT_Q << 12));714714+ set_key->desc_word[1] = cpu_to_le16(SET_KEY_REQ);715715+ set_key->desc_word[4] = cpu_to_le16(key_descriptor);716716+717717+ if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||718718+ (cipher == WLAN_CIPHER_SUITE_WEP104)) {719719+ memcpy(&set_key->key[key_id][1],720720+ data,721721+ key_len * 2);722722+ } else {723723+ memcpy(&set_key->key[0][0], data, key_len);724724+ }725725+726726+ memcpy(set_key->tx_mic_key, &data[16], 8);727727+ memcpy(set_key->rx_mic_key, &data[24], 8);728728+729729+ skb_put(skb, sizeof(struct rsi_set_key));730730+731731+ return rsi_send_internal_mgmt_frame(common, skb);732732+}733733+734734+/*735735+ * rsi_load_bootup_params() - This function send bootup params to the firmware.736736+ * @common: Pointer to the driver private structure.737737+ *738738+ * Return: 0 on success, corresponding error code on failure.739739+ */740740+static u8 rsi_load_bootup_params(struct rsi_common *common)741741+{742742+ struct sk_buff *skb;743743+ struct rsi_boot_params *boot_params;744744+745745+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__);746746+ skb = dev_alloc_skb(sizeof(struct rsi_boot_params));747747+ if (!skb) {748748+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",749749+ __func__);750750+ return -ENOMEM;751751+ }752752+753753+ memset(skb->data, 0, sizeof(struct rsi_boot_params));754754+ boot_params = (struct rsi_boot_params *)skb->data;755755+756756+ rsi_dbg(MGMT_TX_ZONE, "%s:\n", __func__);757757+758758+ if (common->channel_width == BW_40MHZ) {759759+ memcpy(&boot_params->bootup_params,760760+ &boot_params_40,761761+ sizeof(struct bootup_params));762762+ rsi_dbg(MGMT_TX_ZONE, "%s: Packet 40MHZ <=== %d\n", __func__,763763+ UMAC_CLK_40BW);764764+ boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40BW);765765+ } else {766766+ memcpy(&boot_params->bootup_params,767767+ &boot_params_20,768768+ sizeof(struct bootup_params));769769+ if (boot_params_20.valid != cpu_to_le32(VALID_20)) {770770+ boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_20BW);771771+ rsi_dbg(MGMT_TX_ZONE,772772+ "%s: Packet 20MHZ <=== %d\n", __func__,773773+ UMAC_CLK_20BW);774774+ } else {775775+ boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40MHZ);776776+ rsi_dbg(MGMT_TX_ZONE,777777+ "%s: Packet 20MHZ <=== %d\n", __func__,778778+ UMAC_CLK_40MHZ);779779+ }780780+ }781781+782782+ /**783783+ * Bit{0:11} indicates length of the Packet784784+ * Bit{12:15} indicates host queue number785785+ */786786+ boot_params->desc_word[0] = cpu_to_le16(sizeof(struct bootup_params) |787787+ (RSI_WIFI_MGMT_Q << 12));788788+ boot_params->desc_word[1] = cpu_to_le16(BOOTUP_PARAMS_REQUEST);789789+790790+ skb_put(skb, sizeof(struct rsi_boot_params));791791+792792+ return rsi_send_internal_mgmt_frame(common, skb);793793+}794794+795795+/**796796+ * rsi_send_reset_mac() - This function prepares reset MAC request and sends an797797+ * internal management frame to indicate it to firmware.798798+ * @common: Pointer to the driver private structure.799799+ *800800+ * Return: 0 on success, corresponding error code on failure.801801+ */802802+static int rsi_send_reset_mac(struct rsi_common *common)803803+{804804+ struct sk_buff *skb;805805+ struct rsi_mac_frame *mgmt_frame;806806+807807+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending reset MAC frame\n", __func__);808808+809809+ skb = dev_alloc_skb(FRAME_DESC_SZ);810810+ if (!skb) {811811+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",812812+ __func__);813813+ return -ENOMEM;814814+ }815815+816816+ memset(skb->data, 0, FRAME_DESC_SZ);817817+ mgmt_frame = (struct rsi_mac_frame *)skb->data;818818+819819+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);820820+ mgmt_frame->desc_word[1] = cpu_to_le16(RESET_MAC_REQ);821821+ mgmt_frame->desc_word[4] = cpu_to_le16(RETRY_COUNT << 8);822822+823823+ skb_put(skb, FRAME_DESC_SZ);824824+825825+ return rsi_send_internal_mgmt_frame(common, skb);826826+}827827+828828+/**829829+ * rsi_set_channel() - This function programs the channel.830830+ * @common: Pointer to the driver private structure.831831+ * @channel: Channel value to be set.832832+ *833833+ * Return: 0 on success, corresponding error code on failure.834834+ */835835+int rsi_set_channel(struct rsi_common *common, u16 channel)836836+{837837+ struct sk_buff *skb = NULL;838838+ struct rsi_mac_frame *mgmt_frame;839839+840840+ rsi_dbg(MGMT_TX_ZONE,841841+ "%s: Sending scan req frame\n", __func__);842842+843843+ skb = dev_alloc_skb(FRAME_DESC_SZ);844844+ if (!skb) {845845+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",846846+ __func__);847847+ return -ENOMEM;848848+ }849849+850850+ memset(skb->data, 0, FRAME_DESC_SZ);851851+ mgmt_frame = (struct rsi_mac_frame *)skb->data;852852+853853+ if (common->band == IEEE80211_BAND_5GHZ) {854854+ if ((channel >= 36) && (channel <= 64))855855+ channel = ((channel - 32) / 4);856856+ else if ((channel > 64) && (channel <= 140))857857+ channel = ((channel - 102) / 4) + 8;858858+ else if (channel >= 149)859859+ channel = ((channel - 151) / 4) + 18;860860+ else861861+ return -EINVAL;862862+ } else {863863+ if (channel > 14) {864864+ rsi_dbg(ERR_ZONE, "%s: Invalid chno %d, band = %d\n",865865+ __func__, channel, common->band);866866+ return -EINVAL;867867+ }868868+ }869869+870870+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);871871+ mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST);872872+ mgmt_frame->desc_word[4] = cpu_to_le16(channel);873873+874874+ mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET |875875+ BBP_REG_WRITE |876876+ (RSI_RF_TYPE << 4));877877+878878+ mgmt_frame->desc_word[5] = cpu_to_le16(0x01);879879+880880+ if (common->channel_width == BW_40MHZ)881881+ mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8);882882+883883+ common->channel = channel;884884+885885+ skb_put(skb, FRAME_DESC_SZ);886886+887887+ return rsi_send_internal_mgmt_frame(common, skb);888888+}889889+890890+/**891891+ * rsi_compare() - This function is used to compare two integers892892+ * @a: pointer to the first integer893893+ * @b: pointer to the second integer894894+ *895895+ * Return: 0 if both are equal, -1 if the first is smaller, else 1896896+ */897897+static int rsi_compare(const void *a, const void *b)898898+{899899+ u16 _a = *(const u16 *)(a);900900+ u16 _b = *(const u16 *)(b);901901+902902+ if (_a > _b)903903+ return -1;904904+905905+ if (_a < _b)906906+ return 1;907907+908908+ return 0;909909+}910910+911911+/**912912+ * rsi_map_rates() - This function is used to map selected rates to hw rates.913913+ * @rate: The standard rate to be mapped.914914+ * @offset: Offset that will be returned.915915+ *916916+ * Return: 0 if it is a mcs rate, else 1917917+ */918918+static bool rsi_map_rates(u16 rate, int *offset)919919+{920920+ int kk;921921+ for (kk = 0; kk < ARRAY_SIZE(rsi_mcsrates); kk++) {922922+ if (rate == mcs[kk]) {923923+ *offset = kk;924924+ return false;925925+ }926926+ }927927+928928+ for (kk = 0; kk < ARRAY_SIZE(rsi_rates); kk++) {929929+ if (rate == rsi_rates[kk].bitrate / 5) {930930+ *offset = kk;931931+ break;932932+ }933933+ }934934+ return true;935935+}936936+937937+/**938938+ * rsi_send_auto_rate_request() - This function is to set rates for connection939939+ * and send autorate request to firmware.940940+ * @common: Pointer to the driver private structure.941941+ *942942+ * Return: 0 on success, corresponding error code on failure.943943+ */944944+static int rsi_send_auto_rate_request(struct rsi_common *common)945945+{946946+ struct sk_buff *skb;947947+ struct rsi_auto_rate *auto_rate;948948+ int ii = 0, jj = 0, kk = 0;949949+ struct ieee80211_hw *hw = common->priv->hw;950950+ u8 band = hw->conf.chandef.chan->band;951951+ u8 num_supported_rates = 0;952952+ u8 rate_offset = 0;953953+ u32 rate_bitmap = common->bitrate_mask[band];954954+955955+ u16 *selected_rates, min_rate;956956+957957+ skb = dev_alloc_skb(sizeof(struct rsi_auto_rate));958958+ if (!skb) {959959+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",960960+ __func__);961961+ return -ENOMEM;962962+ }963963+964964+ selected_rates = kmalloc(2 * RSI_TBL_SZ, GFP_KERNEL);965965+ if (!selected_rates) {966966+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",967967+ __func__);968968+ return -ENOMEM;969969+ }970970+971971+ memset(skb->data, 0, sizeof(struct rsi_auto_rate));972972+ memset(selected_rates, 0, 2 * RSI_TBL_SZ);973973+974974+ auto_rate = (struct rsi_auto_rate *)skb->data;975975+976976+ auto_rate->aarf_rssi = cpu_to_le16(((u16)3 << 6) | (u16)(18 & 0x3f));977977+ auto_rate->collision_tolerance = cpu_to_le16(3);978978+ auto_rate->failure_limit = cpu_to_le16(3);979979+ auto_rate->initial_boundary = cpu_to_le16(3);980980+ auto_rate->max_threshold_limt = cpu_to_le16(27);981981+982982+ auto_rate->desc_word[1] = cpu_to_le16(AUTO_RATE_IND);983983+984984+ if (common->channel_width == BW_40MHZ)985985+ auto_rate->desc_word[7] |= cpu_to_le16(1);986986+987987+ if (band == IEEE80211_BAND_2GHZ)988988+ min_rate = STD_RATE_01;989989+ else990990+ min_rate = STD_RATE_06;991991+992992+ for (ii = 0, jj = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {993993+ if (rate_bitmap & BIT(ii)) {994994+ selected_rates[jj++] = (rsi_rates[ii].bitrate / 5);995995+ rate_offset++;996996+ }997997+ }998998+ num_supported_rates = jj;999999+10001000+ if (common->vif_info[0].is_ht) {10011001+ for (ii = 0; ii < ARRAY_SIZE(mcs); ii++)10021002+ selected_rates[jj++] = mcs[ii];10031003+ num_supported_rates += ARRAY_SIZE(mcs);10041004+ rate_offset += ARRAY_SIZE(mcs);10051005+ }10061006+10071007+ if (rate_offset < (RSI_TBL_SZ / 2) - 1) {10081008+ for (ii = jj; ii < (RSI_TBL_SZ / 2); ii++) {10091009+ selected_rates[jj++] = min_rate;10101010+ rate_offset++;10111011+ }10121012+ }10131013+10141014+ sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL);10151015+10161016+ /* mapping the rates to RSI rates */10171017+ for (ii = 0; ii < jj; ii++) {10181018+ if (rsi_map_rates(selected_rates[ii], &kk)) {10191019+ auto_rate->supported_rates[ii] =10201020+ cpu_to_le16(rsi_rates[kk].hw_value);10211021+ } else {10221022+ auto_rate->supported_rates[ii] =10231023+ cpu_to_le16(rsi_mcsrates[kk]);10241024+ }10251025+ }10261026+10271027+ /* loading HT rates in the bottom half of the auto rate table */10281028+ if (common->vif_info[0].is_ht) {10291029+ if (common->vif_info[0].sgi)10301030+ auto_rate->supported_rates[rate_offset++] =10311031+ cpu_to_le16(RSI_RATE_MCS7_SG);10321032+10331033+ for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1;10341034+ ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) {10351035+ if (common->vif_info[0].sgi)10361036+ auto_rate->supported_rates[ii++] =10371037+ cpu_to_le16(rsi_mcsrates[kk] | BIT(9));10381038+ auto_rate->supported_rates[ii] =10391039+ cpu_to_le16(rsi_mcsrates[kk--]);10401040+ }10411041+10421042+ for (; ii < RSI_TBL_SZ; ii++) {10431043+ auto_rate->supported_rates[ii] =10441044+ cpu_to_le16(rsi_mcsrates[0]);10451045+ }10461046+ }10471047+10481048+ auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2);10491049+ auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2);10501050+ auto_rate->desc_word[7] |= cpu_to_le16(0 << 8);10511051+ num_supported_rates *= 2;10521052+10531053+ auto_rate->desc_word[0] = cpu_to_le16((sizeof(*auto_rate) -10541054+ FRAME_DESC_SZ) |10551055+ (RSI_WIFI_MGMT_Q << 12));10561056+10571057+ skb_put(skb,10581058+ sizeof(struct rsi_auto_rate));10591059+ kfree(selected_rates);10601060+10611061+ return rsi_send_internal_mgmt_frame(common, skb);10621062+}10631063+10641064+/**10651065+ * rsi_inform_bss_status() - This function informs about bss status with the10661066+ * help of sta notify params by sending an internal10671067+ * management frame to firmware.10681068+ * @common: Pointer to the driver private structure.10691069+ * @status: Bss status type.10701070+ * @bssid: Bssid.10711071+ * @qos_enable: Qos is enabled.10721072+ * @aid: Aid (unique for all STAs).10731073+ *10741074+ * Return: None.10751075+ */10761076+void rsi_inform_bss_status(struct rsi_common *common,10771077+ u8 status,10781078+ const unsigned char *bssid,10791079+ u8 qos_enable,10801080+ u16 aid)10811081+{10821082+ if (status) {10831083+ rsi_hal_send_sta_notify_frame(common,10841084+ NL80211_IFTYPE_STATION,10851085+ STA_CONNECTED,10861086+ bssid,10871087+ qos_enable,10881088+ aid);10891089+ if (common->min_rate == 0xffff)10901090+ rsi_send_auto_rate_request(common);10911091+ } else {10921092+ rsi_hal_send_sta_notify_frame(common,10931093+ NL80211_IFTYPE_STATION,10941094+ STA_DISCONNECTED,10951095+ bssid,10961096+ qos_enable,10971097+ aid);10981098+ }10991099+}11001100+11011101+/**11021102+ * rsi_eeprom_read() - This function sends a frame to read the mac address11031103+ * from the eeprom.11041104+ * @common: Pointer to the driver private structure.11051105+ *11061106+ * Return: 0 on success, -1 on failure.11071107+ */11081108+static int rsi_eeprom_read(struct rsi_common *common)11091109+{11101110+ struct rsi_mac_frame *mgmt_frame;11111111+ struct sk_buff *skb;11121112+11131113+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending EEPROM read req frame\n", __func__);11141114+11151115+ skb = dev_alloc_skb(FRAME_DESC_SZ);11161116+ if (!skb) {11171117+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",11181118+ __func__);11191119+ return -ENOMEM;11201120+ }11211121+11221122+ memset(skb->data, 0, FRAME_DESC_SZ);11231123+ mgmt_frame = (struct rsi_mac_frame *)skb->data;11241124+11251125+ /* FrameType */11261126+ mgmt_frame->desc_word[1] = cpu_to_le16(EEPROM_READ_TYPE);11271127+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);11281128+ /* Number of bytes to read */11291129+ mgmt_frame->desc_word[3] = cpu_to_le16(ETH_ALEN +11301130+ WLAN_MAC_MAGIC_WORD_LEN +11311131+ WLAN_HOST_MODE_LEN +11321132+ WLAN_FW_VERSION_LEN);11331133+ /* Address to read */11341134+ mgmt_frame->desc_word[4] = cpu_to_le16(WLAN_MAC_EEPROM_ADDR);11351135+11361136+ skb_put(skb, FRAME_DESC_SZ);11371137+11381138+ return rsi_send_internal_mgmt_frame(common, skb);11391139+}11401140+11411141+/**11421142+ * rsi_handle_ta_confirm_type() - This function handles the confirm frames.11431143+ * @common: Pointer to the driver private structure.11441144+ * @msg: Pointer to received packet.11451145+ *11461146+ * Return: 0 on success, -1 on failure.11471147+ */11481148+static int rsi_handle_ta_confirm_type(struct rsi_common *common,11491149+ u8 *msg)11501150+{11511151+ u8 sub_type = (msg[15] & 0xff);11521152+11531153+ switch (sub_type) {11541154+ case BOOTUP_PARAMS_REQUEST:11551155+ rsi_dbg(FSM_ZONE, "%s: Boot up params confirm received\n",11561156+ __func__);11571157+ if (common->fsm_state == FSM_BOOT_PARAMS_SENT) {11581158+ if (rsi_eeprom_read(common)) {11591159+ common->fsm_state = FSM_CARD_NOT_READY;11601160+ goto out;11611161+ } else {11621162+ common->fsm_state = FSM_EEPROM_READ_MAC_ADDR;11631163+ }11641164+ } else {11651165+ rsi_dbg(ERR_ZONE,11661166+ "%s: Received bootup params cfm in %d state\n",11671167+ __func__, common->fsm_state);11681168+ return 0;11691169+ }11701170+ break;11711171+11721172+ case EEPROM_READ_TYPE:11731173+ if (common->fsm_state == FSM_EEPROM_READ_MAC_ADDR) {11741174+ if (msg[16] == MAGIC_WORD) {11751175+ u8 offset = (FRAME_DESC_SZ + WLAN_HOST_MODE_LEN11761176+ + WLAN_MAC_MAGIC_WORD_LEN);11771177+ memcpy(common->mac_addr,11781178+ &msg[offset],11791179+ ETH_ALEN);11801180+ memcpy(&common->fw_ver,11811181+ &msg[offset + ETH_ALEN],11821182+ sizeof(struct version_info));11831183+11841184+ } else {11851185+ common->fsm_state = FSM_CARD_NOT_READY;11861186+ break;11871187+ }11881188+ if (rsi_send_reset_mac(common))11891189+ goto out;11901190+ else11911191+ common->fsm_state = FSM_RESET_MAC_SENT;11921192+ } else {11931193+ rsi_dbg(ERR_ZONE,11941194+ "%s: Received eeprom mac addr in %d state\n",11951195+ __func__, common->fsm_state);11961196+ return 0;11971197+ }11981198+ break;11991199+12001200+ case RESET_MAC_REQ:12011201+ if (common->fsm_state == FSM_RESET_MAC_SENT) {12021202+ rsi_dbg(FSM_ZONE, "%s: Reset MAC cfm received\n",12031203+ __func__);12041204+12051205+ if (rsi_load_radio_caps(common))12061206+ goto out;12071207+ else12081208+ common->fsm_state = FSM_RADIO_CAPS_SENT;12091209+ } else {12101210+ rsi_dbg(ERR_ZONE,12111211+ "%s: Received reset mac cfm in %d state\n",12121212+ __func__, common->fsm_state);12131213+ return 0;12141214+ }12151215+ break;12161216+12171217+ case RADIO_CAPABILITIES:12181218+ if (common->fsm_state == FSM_RADIO_CAPS_SENT) {12191219+ common->rf_reset = 1;12201220+ if (rsi_program_bb_rf(common)) {12211221+ goto out;12221222+ } else {12231223+ common->fsm_state = FSM_BB_RF_PROG_SENT;12241224+ rsi_dbg(FSM_ZONE, "%s: Radio cap cfm received\n",12251225+ __func__);12261226+ }12271227+ } else {12281228+ rsi_dbg(ERR_ZONE,12291229+ "%s: Received radio caps cfm in %d state\n",12301230+ __func__, common->fsm_state);12311231+ return 0;12321232+ }12331233+ break;12341234+12351235+ case BB_PROG_VALUES_REQUEST:12361236+ case RF_PROG_VALUES_REQUEST:12371237+ case BBP_PROG_IN_TA:12381238+ rsi_dbg(FSM_ZONE, "%s: BB/RF cfm received\n", __func__);12391239+ if (common->fsm_state == FSM_BB_RF_PROG_SENT) {12401240+ common->bb_rf_prog_count--;12411241+ if (!common->bb_rf_prog_count) {12421242+ common->fsm_state = FSM_MAC_INIT_DONE;12431243+ return rsi_mac80211_attach(common);12441244+ }12451245+ } else {12461246+ goto out;12471247+ }12481248+ break;12491249+12501250+ default:12511251+ rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n",12521252+ __func__);12531253+ break;12541254+ }12551255+ return 0;12561256+out:12571257+ rsi_dbg(ERR_ZONE, "%s: Unable to send pkt/Invalid frame received\n",12581258+ __func__);12591259+ return -EINVAL;12601260+}12611261+12621262+/**12631263+ * rsi_mgmt_pkt_recv() - This function processes the management packets12641264+ * recieved from the hardware.12651265+ * @common: Pointer to the driver private structure.12661266+ * @msg: Pointer to the received packet.12671267+ *12681268+ * Return: 0 on success, -1 on failure.12691269+ */12701270+int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)12711271+{12721272+ s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff);12731273+ u16 msg_type = (msg[2]);12741274+12751275+ rsi_dbg(FSM_ZONE, "%s: Msg Len: %d, Msg Type: %4x\n",12761276+ __func__, msg_len, msg_type);12771277+12781278+ if (msg_type == TA_CONFIRM_TYPE) {12791279+ return rsi_handle_ta_confirm_type(common, msg);12801280+ } else if (msg_type == CARD_READY_IND) {12811281+ rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n",12821282+ __func__);12831283+ if (common->fsm_state == FSM_CARD_NOT_READY) {12841284+ rsi_set_default_parameters(common);12851285+12861286+ if (rsi_load_bootup_params(common))12871287+ return -ENOMEM;12881288+ else12891289+ common->fsm_state = FSM_BOOT_PARAMS_SENT;12901290+ } else {12911291+ return -EINVAL;12921292+ }12931293+ } else if (msg_type == TX_STATUS_IND) {12941294+ if (msg[15] == PROBEREQ_CONFIRM)12951295+ common->mgmt_q_block = false;12961296+ rsi_dbg(FSM_ZONE, "%s: Probe confirm received\n",12971297+ __func__);12981298+ } else {12991299+ return rsi_mgmt_pkt_to_core(common, msg, msg_len, msg_type);13001300+ }13011301+ return 0;13021302+}
+196
drivers/net/wireless/rsi/rsi_91x_pkt.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#include "rsi_mgmt.h"1818+1919+/**2020+ * rsi_send_data_pkt() - This function sends the recieved data packet from2121+ * driver to device.2222+ * @common: Pointer to the driver private structure.2323+ * @skb: Pointer to the socket buffer structure.2424+ *2525+ * Return: status: 0 on success, -1 on failure.2626+ */2727+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)2828+{2929+ struct rsi_hw *adapter = common->priv;3030+ struct ieee80211_hdr *tmp_hdr = NULL;3131+ struct ieee80211_tx_info *info;3232+ struct skb_info *tx_params;3333+ struct ieee80211_bss_conf *bss = NULL;3434+ int status = -EINVAL;3535+ u8 ieee80211_size = MIN_802_11_HDR_LEN;3636+ u8 extnd_size = 0;3737+ __le16 *frame_desc;3838+ u16 seq_num = 0;3939+4040+ info = IEEE80211_SKB_CB(skb);4141+ bss = &info->control.vif->bss_conf;4242+ tx_params = (struct skb_info *)info->driver_data;4343+4444+ if (!bss->assoc)4545+ goto err;4646+4747+ tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];4848+ seq_num = (le16_to_cpu(tmp_hdr->seq_ctrl) >> 4);4949+5050+ extnd_size = ((uintptr_t)skb->data & 0x3);5151+5252+ if ((FRAME_DESC_SZ + extnd_size) > skb_headroom(skb)) {5353+ rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);5454+ status = -ENOSPC;5555+ goto err;5656+ }5757+5858+ skb_push(skb, (FRAME_DESC_SZ + extnd_size));5959+ frame_desc = (__le16 *)&skb->data[0];6060+ memset((u8 *)frame_desc, 0, FRAME_DESC_SZ);6161+6262+ if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {6363+ ieee80211_size += 2;6464+ frame_desc[6] |= cpu_to_le16(BIT(12));6565+ }6666+6767+ if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&6868+ (common->secinfo.security_enable)) {6969+ if (rsi_is_cipher_wep(common))7070+ ieee80211_size += 4;7171+ else7272+ ieee80211_size += 8;7373+ frame_desc[6] |= cpu_to_le16(BIT(15));7474+ }7575+7676+ frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |7777+ (RSI_WIFI_DATA_Q << 12));7878+ frame_desc[2] = cpu_to_le16((extnd_size) | (ieee80211_size) << 8);7979+8080+ if (common->min_rate != 0xffff) {8181+ /* Send fixed rate */8282+ frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);8383+ frame_desc[4] = cpu_to_le16(common->min_rate);8484+ }8585+8686+ frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);8787+ frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |8888+ (skb->priority & 0xf) |8989+ (tx_params->sta_id << 8));9090+9191+ status = adapter->host_intf_write_pkt(common->priv,9292+ skb->data,9393+ skb->len);9494+ if (status)9595+ rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n",9696+ __func__);9797+9898+err:9999+ ++common->tx_stats.total_tx_pkt_freed[skb->priority];100100+ rsi_indicate_tx_status(common->priv, skb, status);101101+ return status;102102+}103103+104104+/**105105+ * rsi_send_mgmt_pkt() - This functions sends the received management packet106106+ * from driver to device.107107+ * @common: Pointer to the driver private structure.108108+ * @skb: Pointer to the socket buffer structure.109109+ *110110+ * Return: status: 0 on success, -1 on failure.111111+ */112112+int rsi_send_mgmt_pkt(struct rsi_common *common,113113+ struct sk_buff *skb)114114+{115115+ struct rsi_hw *adapter = common->priv;116116+ struct ieee80211_hdr *wh = NULL;117117+ struct ieee80211_tx_info *info;118118+ struct ieee80211_bss_conf *bss = NULL;119119+ struct skb_info *tx_params;120120+ int status = -E2BIG;121121+ __le16 *msg = NULL;122122+ u8 extnd_size = 0;123123+ u8 vap_id = 0;124124+125125+ info = IEEE80211_SKB_CB(skb);126126+ tx_params = (struct skb_info *)info->driver_data;127127+ extnd_size = ((uintptr_t)skb->data & 0x3);128128+129129+ if (tx_params->flags & INTERNAL_MGMT_PKT) {130130+ if ((extnd_size) > skb_headroom(skb)) {131131+ rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);132132+ dev_kfree_skb(skb);133133+ return -ENOSPC;134134+ }135135+ skb_push(skb, extnd_size);136136+ skb->data[extnd_size + 4] = extnd_size;137137+ status = adapter->host_intf_write_pkt(common->priv,138138+ (u8 *)skb->data,139139+ skb->len);140140+ if (status) {141141+ rsi_dbg(ERR_ZONE,142142+ "%s: Failed to write the packet\n", __func__);143143+ }144144+ dev_kfree_skb(skb);145145+ return status;146146+ }147147+148148+ bss = &info->control.vif->bss_conf;149149+ wh = (struct ieee80211_hdr *)&skb->data[0];150150+151151+ if (FRAME_DESC_SZ > skb_headroom(skb))152152+ goto err;153153+154154+ skb_push(skb, FRAME_DESC_SZ);155155+ memset(skb->data, 0, FRAME_DESC_SZ);156156+ msg = (__le16 *)skb->data;157157+158158+ if (skb->len > MAX_MGMT_PKT_SIZE) {159159+ rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);160160+ goto err;161161+ }162162+163163+ msg[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |164164+ (RSI_WIFI_MGMT_Q << 12));165165+ msg[1] = cpu_to_le16(TX_DOT11_MGMT);166166+ msg[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8);167167+ msg[3] = cpu_to_le16(RATE_INFO_ENABLE);168168+ msg[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);169169+170170+ if (wh->addr1[0] & BIT(0))171171+ msg[3] |= cpu_to_le16(RSI_BROADCAST_PKT);172172+173173+ if (common->band == IEEE80211_BAND_2GHZ)174174+ msg[4] = cpu_to_le16(RSI_11B_MODE);175175+ else176176+ msg[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);177177+178178+ /* Indicate to firmware to give cfm */179179+ if ((skb->data[16] == IEEE80211_STYPE_PROBE_REQ) && (!bss->assoc)) {180180+ msg[1] |= cpu_to_le16(BIT(10));181181+ msg[7] = cpu_to_le16(PROBEREQ_CONFIRM);182182+ common->mgmt_q_block = true;183183+ }184184+185185+ msg[7] |= cpu_to_le16(vap_id << 8);186186+187187+ status = adapter->host_intf_write_pkt(common->priv,188188+ (u8 *)msg,189189+ skb->len);190190+ if (status)191191+ rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);192192+193193+err:194194+ rsi_indicate_tx_status(common->priv, skb, status);195195+ return status;196196+}
+850
drivers/net/wireless/rsi/rsi_91x_sdio.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ *1616+ */1717+1818+#include <linux/module.h>1919+#include "rsi_sdio.h"2020+#include "rsi_common.h"2121+2222+/**2323+ * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.2424+ * @rw: Read/write2525+ * @func: function number2626+ * @raw: indicates whether to perform read after write2727+ * @address: address to which to read/write2828+ * @writedata: data to write2929+ *3030+ * Return: argument3131+ */3232+static u32 rsi_sdio_set_cmd52_arg(bool rw,3333+ u8 func,3434+ u8 raw,3535+ u32 address,3636+ u8 writedata)3737+{3838+ return ((rw & 1) << 31) | ((func & 0x7) << 28) |3939+ ((raw & 1) << 27) | (1 << 26) |4040+ ((address & 0x1FFFF) << 9) | (1 << 8) |4141+ (writedata & 0xFF);4242+}4343+4444+/**4545+ * rsi_cmd52writebyte() - This function issues cmd52 byte write onto the card.4646+ * @card: Pointer to the mmc_card.4747+ * @address: Address to write.4848+ * @byte: Data to write.4949+ *5050+ * Return: Write status.5151+ */5252+static int rsi_cmd52writebyte(struct mmc_card *card,5353+ u32 address,5454+ u8 byte)5555+{5656+ struct mmc_command io_cmd;5757+ u32 arg;5858+5959+ memset(&io_cmd, 0, sizeof(io_cmd));6060+ arg = rsi_sdio_set_cmd52_arg(1, 0, 0, address, byte);6161+ io_cmd.opcode = SD_IO_RW_DIRECT;6262+ io_cmd.arg = arg;6363+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;6464+6565+ return mmc_wait_for_cmd(card->host, &io_cmd, 0);6666+}6767+6868+/**6969+ * rsi_cmd52readbyte() - This function issues cmd52 byte read onto the card.7070+ * @card: Pointer to the mmc_card.7171+ * @address: Address to read from.7272+ * @byte: Variable to store read value.7373+ *7474+ * Return: Read status.7575+ */7676+static int rsi_cmd52readbyte(struct mmc_card *card,7777+ u32 address,7878+ u8 *byte)7979+{8080+ struct mmc_command io_cmd;8181+ u32 arg;8282+ int err;8383+8484+ memset(&io_cmd, 0, sizeof(io_cmd));8585+ arg = rsi_sdio_set_cmd52_arg(0, 0, 0, address, 0);8686+ io_cmd.opcode = SD_IO_RW_DIRECT;8787+ io_cmd.arg = arg;8888+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;8989+9090+ err = mmc_wait_for_cmd(card->host, &io_cmd, 0);9191+ if ((!err) && (byte))9292+ *byte = io_cmd.resp[0] & 0xFF;9393+ return err;9494+}9595+9696+/**9797+ * rsi_issue_sdiocommand() - This function issues sdio commands.9898+ * @func: Pointer to the sdio_func structure.9999+ * @opcode: Opcode value.100100+ * @arg: Arguments to pass.101101+ * @flags: Flags which are set.102102+ * @resp: Pointer to store response.103103+ *104104+ * Return: err: command status as 0 or -1.105105+ */106106+static int rsi_issue_sdiocommand(struct sdio_func *func,107107+ u32 opcode,108108+ u32 arg,109109+ u32 flags,110110+ u32 *resp)111111+{112112+ struct mmc_command cmd;113113+ struct mmc_host *host;114114+ int err;115115+116116+ host = func->card->host;117117+118118+ memset(&cmd, 0, sizeof(struct mmc_command));119119+ cmd.opcode = opcode;120120+ cmd.arg = arg;121121+ cmd.flags = flags;122122+ err = mmc_wait_for_cmd(host, &cmd, 3);123123+124124+ if ((!err) && (resp))125125+ *resp = cmd.resp[0];126126+127127+ return err;128128+}129129+130130+/**131131+ * rsi_handle_interrupt() - This function is called upon the occurence132132+ * of an interrupt.133133+ * @function: Pointer to the sdio_func structure.134134+ *135135+ * Return: None.136136+ */137137+static void rsi_handle_interrupt(struct sdio_func *function)138138+{139139+ struct rsi_hw *adapter = sdio_get_drvdata(function);140140+141141+ sdio_release_host(function);142142+ rsi_interrupt_handler(adapter);143143+ sdio_claim_host(function);144144+}145145+146146+/**147147+ * rsi_reset_card() - This function resets and re-initializes the card.148148+ * @pfunction: Pointer to the sdio_func structure.149149+ *150150+ * Return: None.151151+ */152152+static void rsi_reset_card(struct sdio_func *pfunction)153153+{154154+ int ret = 0;155155+ int err;156156+ struct mmc_card *card = pfunction->card;157157+ struct mmc_host *host = card->host;158158+ s32 bit = (fls(host->ocr_avail) - 1);159159+ u8 cmd52_resp;160160+ u32 clock, resp, i;161161+ u16 rca;162162+163163+ /* Reset 9110 chip */164164+ ret = rsi_cmd52writebyte(pfunction->card,165165+ SDIO_CCCR_ABORT,166166+ (1 << 3));167167+168168+ /* Card will not send any response as it is getting reset immediately169169+ * Hence expect a timeout status from host controller170170+ */171171+ if (ret != -ETIMEDOUT)172172+ rsi_dbg(ERR_ZONE, "%s: Reset failed : %d\n", __func__, ret);173173+174174+ /* Wait for few milli seconds to get rid of residue charges if any */175175+ msleep(20);176176+177177+ /* Initialize the SDIO card */178178+ host->ios.vdd = bit;179179+ host->ios.chip_select = MMC_CS_DONTCARE;180180+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;181181+ host->ios.power_mode = MMC_POWER_UP;182182+ host->ios.bus_width = MMC_BUS_WIDTH_1;183183+ host->ios.timing = MMC_TIMING_LEGACY;184184+ host->ops->set_ios(host, &host->ios);185185+186186+ /*187187+ * This delay should be sufficient to allow the power supply188188+ * to reach the minimum voltage.189189+ */190190+ msleep(20);191191+192192+ host->ios.clock = host->f_min;193193+ host->ios.power_mode = MMC_POWER_ON;194194+ host->ops->set_ios(host, &host->ios);195195+196196+ /*197197+ * This delay must be at least 74 clock sizes, or 1 ms, or the198198+ * time required to reach a stable voltage.199199+ */200200+ msleep(20);201201+202202+ /* Issue CMD0. Goto idle state */203203+ host->ios.chip_select = MMC_CS_HIGH;204204+ host->ops->set_ios(host, &host->ios);205205+ msleep(20);206206+ err = rsi_issue_sdiocommand(pfunction,207207+ MMC_GO_IDLE_STATE,208208+ 0,209209+ (MMC_RSP_NONE | MMC_CMD_BC),210210+ NULL);211211+ host->ios.chip_select = MMC_CS_DONTCARE;212212+ host->ops->set_ios(host, &host->ios);213213+ msleep(20);214214+ host->use_spi_crc = 0;215215+216216+ if (err)217217+ rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);218218+219219+ if (!host->ocr_avail) {220220+ /* Issue CMD5, arg = 0 */221221+ err = rsi_issue_sdiocommand(pfunction,222222+ SD_IO_SEND_OP_COND,223223+ 0,224224+ (MMC_RSP_R4 | MMC_CMD_BCR),225225+ &resp);226226+ if (err)227227+ rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",228228+ __func__, err);229229+ host->ocr_avail = resp;230230+ }231231+232232+ /* Issue CMD5, arg = ocr. Wait till card is ready */233233+ for (i = 0; i < 100; i++) {234234+ err = rsi_issue_sdiocommand(pfunction,235235+ SD_IO_SEND_OP_COND,236236+ host->ocr_avail,237237+ (MMC_RSP_R4 | MMC_CMD_BCR),238238+ &resp);239239+ if (err) {240240+ rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",241241+ __func__, err);242242+ break;243243+ }244244+245245+ if (resp & MMC_CARD_BUSY)246246+ break;247247+ msleep(20);248248+ }249249+250250+ if ((i == 100) || (err)) {251251+ rsi_dbg(ERR_ZONE, "%s: card in not ready : %d %d\n",252252+ __func__, i, err);253253+ return;254254+ }255255+256256+ /* Issue CMD3, get RCA */257257+ err = rsi_issue_sdiocommand(pfunction,258258+ SD_SEND_RELATIVE_ADDR,259259+ 0,260260+ (MMC_RSP_R6 | MMC_CMD_BCR),261261+ &resp);262262+ if (err) {263263+ rsi_dbg(ERR_ZONE, "%s: CMD3 failed : %d\n", __func__, err);264264+ return;265265+ }266266+ rca = resp >> 16;267267+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;268268+ host->ops->set_ios(host, &host->ios);269269+270270+ /* Issue CMD7, select card */271271+ err = rsi_issue_sdiocommand(pfunction,272272+ MMC_SELECT_CARD,273273+ (rca << 16),274274+ (MMC_RSP_R1 | MMC_CMD_AC),275275+ NULL);276276+ if (err) {277277+ rsi_dbg(ERR_ZONE, "%s: CMD7 failed : %d\n", __func__, err);278278+ return;279279+ }280280+281281+ /* Enable high speed */282282+ if (card->host->caps & MMC_CAP_SD_HIGHSPEED) {283283+ rsi_dbg(ERR_ZONE, "%s: Set high speed mode\n", __func__);284284+ err = rsi_cmd52readbyte(card, SDIO_CCCR_SPEED, &cmd52_resp);285285+ if (err) {286286+ rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",287287+ __func__, err);288288+ card->state &= ~MMC_STATE_HIGHSPEED;289289+ } else {290290+ err = rsi_cmd52writebyte(card,291291+ SDIO_CCCR_SPEED,292292+ (cmd52_resp | SDIO_SPEED_EHS));293293+ if (err) {294294+ rsi_dbg(ERR_ZONE,295295+ "%s: CCR speed regwrite failed %d\n",296296+ __func__, err);297297+ return;298298+ }299299+ mmc_card_set_highspeed(card);300300+ host->ios.timing = MMC_TIMING_SD_HS;301301+ host->ops->set_ios(host, &host->ios);302302+ }303303+ }304304+305305+ /* Set clock */306306+ if (mmc_card_highspeed(card))307307+ clock = 50000000;308308+ else309309+ clock = card->cis.max_dtr;310310+311311+ if (clock > host->f_max)312312+ clock = host->f_max;313313+314314+ host->ios.clock = clock;315315+ host->ops->set_ios(host, &host->ios);316316+317317+ if (card->host->caps & MMC_CAP_4_BIT_DATA) {318318+ /* CMD52: Set bus width & disable card detect resistor */319319+ err = rsi_cmd52writebyte(card,320320+ SDIO_CCCR_IF,321321+ (SDIO_BUS_CD_DISABLE |322322+ SDIO_BUS_WIDTH_4BIT));323323+ if (err) {324324+ rsi_dbg(ERR_ZONE, "%s: Set bus mode failed : %d\n",325325+ __func__, err);326326+ return;327327+ }328328+ host->ios.bus_width = MMC_BUS_WIDTH_4;329329+ host->ops->set_ios(host, &host->ios);330330+ }331331+}332332+333333+/**334334+ * rsi_setclock() - This function sets the clock frequency.335335+ * @adapter: Pointer to the adapter structure.336336+ * @freq: Clock frequency.337337+ *338338+ * Return: None.339339+ */340340+static void rsi_setclock(struct rsi_hw *adapter, u32 freq)341341+{342342+ struct rsi_91x_sdiodev *dev =343343+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;344344+ struct mmc_host *host = dev->pfunction->card->host;345345+ u32 clock;346346+347347+ clock = freq * 1000;348348+ if (clock > host->f_max)349349+ clock = host->f_max;350350+ host->ios.clock = clock;351351+ host->ops->set_ios(host, &host->ios);352352+}353353+354354+/**355355+ * rsi_setblocklength() - This function sets the host block length.356356+ * @adapter: Pointer to the adapter structure.357357+ * @length: Block length to be set.358358+ *359359+ * Return: status: 0 on success, -1 on failure.360360+ */361361+static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)362362+{363363+ struct rsi_91x_sdiodev *dev =364364+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;365365+ int status;366366+ rsi_dbg(INIT_ZONE, "%s: Setting the block length\n", __func__);367367+368368+ status = sdio_set_block_size(dev->pfunction, length);369369+ dev->pfunction->max_blksize = 256;370370+371371+ rsi_dbg(INFO_ZONE,372372+ "%s: Operational blk length is %d\n", __func__, length);373373+ return status;374374+}375375+376376+/**377377+ * rsi_setupcard() - This function queries and sets the card's features.378378+ * @adapter: Pointer to the adapter structure.379379+ *380380+ * Return: status: 0 on success, -1 on failure.381381+ */382382+static int rsi_setupcard(struct rsi_hw *adapter)383383+{384384+ struct rsi_91x_sdiodev *dev =385385+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;386386+ int status = 0;387387+388388+ rsi_setclock(adapter, 50000);389389+390390+ dev->tx_blk_size = 256;391391+ status = rsi_setblocklength(adapter, dev->tx_blk_size);392392+ if (status)393393+ rsi_dbg(ERR_ZONE,394394+ "%s: Unable to set block length\n", __func__);395395+ return status;396396+}397397+398398+/**399399+ * rsi_sdio_read_register() - This function reads one byte of information400400+ * from a register.401401+ * @adapter: Pointer to the adapter structure.402402+ * @addr: Address of the register.403403+ * @data: Pointer to the data that stores the data read.404404+ *405405+ * Return: 0 on success, -1 on failure.406406+ */407407+int rsi_sdio_read_register(struct rsi_hw *adapter,408408+ u32 addr,409409+ u8 *data)410410+{411411+ struct rsi_91x_sdiodev *dev =412412+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;413413+ u8 fun_num = 0;414414+ int status;415415+416416+ sdio_claim_host(dev->pfunction);417417+418418+ if (fun_num == 0)419419+ *data = sdio_f0_readb(dev->pfunction, addr, &status);420420+ else421421+ *data = sdio_readb(dev->pfunction, addr, &status);422422+423423+ sdio_release_host(dev->pfunction);424424+425425+ return status;426426+}427427+428428+/**429429+ * rsi_sdio_write_register() - This function writes one byte of information430430+ * into a register.431431+ * @adapter: Pointer to the adapter structure.432432+ * @function: Function Number.433433+ * @addr: Address of the register.434434+ * @data: Pointer to the data tha has to be written.435435+ *436436+ * Return: 0 on success, -1 on failure.437437+ */438438+int rsi_sdio_write_register(struct rsi_hw *adapter,439439+ u8 function,440440+ u32 addr,441441+ u8 *data)442442+{443443+ struct rsi_91x_sdiodev *dev =444444+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;445445+ int status = 0;446446+447447+ sdio_claim_host(dev->pfunction);448448+449449+ if (function == 0)450450+ sdio_f0_writeb(dev->pfunction, *data, addr, &status);451451+ else452452+ sdio_writeb(dev->pfunction, *data, addr, &status);453453+454454+ sdio_release_host(dev->pfunction);455455+456456+ return status;457457+}458458+459459+/**460460+ * rsi_sdio_ack_intr() - This function acks the interrupt received.461461+ * @adapter: Pointer to the adapter structure.462462+ * @int_bit: Interrupt bit to write into register.463463+ *464464+ * Return: None.465465+ */466466+void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)467467+{468468+ int status;469469+ status = rsi_sdio_write_register(adapter,470470+ 1,471471+ (SDIO_FUN1_INTR_CLR_REG |472472+ RSI_SD_REQUEST_MASTER),473473+ &int_bit);474474+ if (status)475475+ rsi_dbg(ERR_ZONE, "%s: unable to send ack\n", __func__);476476+}477477+478478+479479+480480+/**481481+ * rsi_sdio_read_register_multiple() - This function read multiple bytes of482482+ * information from the SD card.483483+ * @adapter: Pointer to the adapter structure.484484+ * @addr: Address of the register.485485+ * @count: Number of multiple bytes to be read.486486+ * @data: Pointer to the read data.487487+ *488488+ * Return: 0 on success, -1 on failure.489489+ */490490+static int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,491491+ u32 addr,492492+ u32 count,493493+ u8 *data)494494+{495495+ struct rsi_91x_sdiodev *dev =496496+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;497497+ u32 status;498498+499499+ sdio_claim_host(dev->pfunction);500500+501501+ status = sdio_readsb(dev->pfunction, data, addr, count);502502+503503+ sdio_release_host(dev->pfunction);504504+505505+ if (status != 0)506506+ rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 read failed\n", __func__);507507+ return status;508508+}509509+510510+/**511511+ * rsi_sdio_write_register_multiple() - This function writes multiple bytes of512512+ * information to the SD card.513513+ * @adapter: Pointer to the adapter structure.514514+ * @addr: Address of the register.515515+ * @data: Pointer to the data that has to be written.516516+ * @count: Number of multiple bytes to be written.517517+ *518518+ * Return: 0 on success, -1 on failure.519519+ */520520+int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,521521+ u32 addr,522522+ u8 *data,523523+ u32 count)524524+{525525+ struct rsi_91x_sdiodev *dev =526526+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;527527+ int status;528528+529529+ if (dev->write_fail > 1) {530530+ rsi_dbg(ERR_ZONE, "%s: Stopping card writes\n", __func__);531531+ return 0;532532+ } else if (dev->write_fail == 1) {533533+ /**534534+ * Assuming it is a CRC failure, we want to allow another535535+ * card write536536+ */537537+ rsi_dbg(ERR_ZONE, "%s: Continue card writes\n", __func__);538538+ dev->write_fail++;539539+ }540540+541541+ sdio_claim_host(dev->pfunction);542542+543543+ status = sdio_writesb(dev->pfunction, addr, data, count);544544+545545+ sdio_release_host(dev->pfunction);546546+547547+ if (status) {548548+ rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 write failed %d\n",549549+ __func__, status);550550+ dev->write_fail = 2;551551+ } else {552552+ memcpy(dev->prev_desc, data, FRAME_DESC_SZ);553553+ }554554+ return status;555555+}556556+557557+/**558558+ * rsi_sdio_host_intf_write_pkt() - This function writes the packet to device.559559+ * @adapter: Pointer to the adapter structure.560560+ * @pkt: Pointer to the data to be written on to the device.561561+ * @len: length of the data to be written on to the device.562562+ *563563+ * Return: 0 on success, -1 on failure.564564+ */565565+static int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter,566566+ u8 *pkt,567567+ u32 len)568568+{569569+ struct rsi_91x_sdiodev *dev =570570+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;571571+ u32 block_size = dev->tx_blk_size;572572+ u32 num_blocks, address, length;573573+ u32 queueno;574574+ int status;575575+576576+ queueno = ((pkt[1] >> 4) & 0xf);577577+578578+ num_blocks = len / block_size;579579+580580+ if (len % block_size)581581+ num_blocks++;582582+583583+ address = (num_blocks * block_size | (queueno << 12));584584+ length = num_blocks * block_size;585585+586586+ status = rsi_sdio_write_register_multiple(adapter,587587+ address,588588+ (u8 *)pkt,589589+ length);590590+ if (status)591591+ rsi_dbg(ERR_ZONE, "%s: Unable to write onto the card: %d\n",592592+ __func__, status);593593+ rsi_dbg(DATA_TX_ZONE, "%s: Successfully written onto card\n", __func__);594594+ return status;595595+}596596+597597+/**598598+ * rsi_sdio_host_intf_read_pkt() - This function reads the packet599599+ from the device.600600+ * @adapter: Pointer to the adapter data structure.601601+ * @pkt: Pointer to the packet data to be read from the the device.602602+ * @length: Length of the data to be read from the device.603603+ *604604+ * Return: 0 on success, -1 on failure.605605+ */606606+int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,607607+ u8 *pkt,608608+ u32 length)609609+{610610+ int status = -EINVAL;611611+612612+ if (!length) {613613+ rsi_dbg(ERR_ZONE, "%s: Pkt size is zero\n", __func__);614614+ return status;615615+ }616616+617617+ status = rsi_sdio_read_register_multiple(adapter,618618+ length,619619+ length, /*num of bytes*/620620+ (u8 *)pkt);621621+622622+ if (status)623623+ rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,624624+ status);625625+ return status;626626+}627627+628628+/**629629+ * rsi_init_sdio_interface() - This function does init specific to SDIO.630630+ *631631+ * @adapter: Pointer to the adapter data structure.632632+ * @pkt: Pointer to the packet data to be read from the the device.633633+ *634634+ * Return: 0 on success, -1 on failure.635635+ */636636+637637+static int rsi_init_sdio_interface(struct rsi_hw *adapter,638638+ struct sdio_func *pfunction)639639+{640640+ struct rsi_91x_sdiodev *rsi_91x_dev;641641+ int status = -ENOMEM;642642+643643+ rsi_91x_dev = kzalloc(sizeof(*rsi_91x_dev), GFP_KERNEL);644644+ if (!rsi_91x_dev)645645+ return status;646646+647647+ adapter->rsi_dev = rsi_91x_dev;648648+649649+ sdio_claim_host(pfunction);650650+651651+ pfunction->enable_timeout = 100;652652+ status = sdio_enable_func(pfunction);653653+ if (status) {654654+ rsi_dbg(ERR_ZONE, "%s: Failed to enable interface\n", __func__);655655+ sdio_release_host(pfunction);656656+ return status;657657+ }658658+659659+ rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);660660+661661+ rsi_91x_dev->pfunction = pfunction;662662+ adapter->device = &pfunction->dev;663663+664664+ sdio_set_drvdata(pfunction, adapter);665665+666666+ status = rsi_setupcard(adapter);667667+ if (status) {668668+ rsi_dbg(ERR_ZONE, "%s: Failed to setup card\n", __func__);669669+ goto fail;670670+ }671671+672672+ rsi_dbg(INIT_ZONE, "%s: Setup card succesfully\n", __func__);673673+674674+ status = rsi_init_sdio_slave_regs(adapter);675675+ if (status) {676676+ rsi_dbg(ERR_ZONE, "%s: Failed to init slave regs\n", __func__);677677+ goto fail;678678+ }679679+ sdio_release_host(pfunction);680680+681681+ adapter->host_intf_write_pkt = rsi_sdio_host_intf_write_pkt;682682+ adapter->host_intf_read_pkt = rsi_sdio_host_intf_read_pkt;683683+ adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;684684+ adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;685685+686686+#ifdef CONFIG_RSI_DEBUGFS687687+ adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES;688688+#endif689689+ return status;690690+fail:691691+ sdio_disable_func(pfunction);692692+ sdio_release_host(pfunction);693693+ return status;694694+}695695+696696+/**697697+ * rsi_probe() - This function is called by kernel when the driver provided698698+ * Vendor and device IDs are matched. All the initialization699699+ * work is done here.700700+ * @pfunction: Pointer to the sdio_func structure.701701+ * @id: Pointer to sdio_device_id structure.702702+ *703703+ * Return: 0 on success, 1 on failure.704704+ */705705+static int rsi_probe(struct sdio_func *pfunction,706706+ const struct sdio_device_id *id)707707+{708708+ struct rsi_hw *adapter;709709+710710+ rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);711711+712712+ adapter = rsi_91x_init();713713+ if (!adapter) {714714+ rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",715715+ __func__);716716+ return 1;717717+ }718718+719719+ if (rsi_init_sdio_interface(adapter, pfunction)) {720720+ rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",721721+ __func__);722722+ goto fail;723723+ }724724+725725+ if (rsi_sdio_device_init(adapter->priv)) {726726+ rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);727727+ sdio_claim_host(pfunction);728728+ sdio_disable_func(pfunction);729729+ sdio_release_host(pfunction);730730+ goto fail;731731+ }732732+733733+ sdio_claim_host(pfunction);734734+ if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {735735+ rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);736736+ sdio_release_host(pfunction);737737+ goto fail;738738+ }739739+740740+ sdio_release_host(pfunction);741741+ rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);742742+743743+ return 0;744744+fail:745745+ rsi_91x_deinit(adapter);746746+ rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);747747+ return 1;748748+}749749+750750+/**751751+ * rsi_disconnect() - This function performs the reverse of the probe function.752752+ * @pfunction: Pointer to the sdio_func structure.753753+ *754754+ * Return: void.755755+ */756756+static void rsi_disconnect(struct sdio_func *pfunction)757757+{758758+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);759759+ struct rsi_91x_sdiodev *dev =760760+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;761761+762762+ if (!adapter)763763+ return;764764+765765+ dev->write_fail = 2;766766+ rsi_mac80211_detach(adapter);767767+768768+ sdio_claim_host(pfunction);769769+ sdio_release_irq(pfunction);770770+ sdio_disable_func(pfunction);771771+ rsi_91x_deinit(adapter);772772+ /* Resetting to take care of the case, where-in driver is re-loaded */773773+ rsi_reset_card(pfunction);774774+ sdio_release_host(pfunction);775775+}776776+777777+#ifdef CONFIG_PM778778+static int rsi_suspend(struct device *dev)779779+{780780+ /* Not yet implemented */781781+ return -ENOSYS;782782+}783783+784784+static int rsi_resume(struct device *dev)785785+{786786+ /* Not yet implemented */787787+ return -ENOSYS;788788+}789789+790790+static const struct dev_pm_ops rsi_pm_ops = {791791+ .suspend = rsi_suspend,792792+ .resume = rsi_resume,793793+};794794+#endif795795+796796+static const struct sdio_device_id rsi_dev_table[] = {797797+ { SDIO_DEVICE(0x303, 0x100) },798798+ { SDIO_DEVICE(0x041B, 0x0301) },799799+ { SDIO_DEVICE(0x041B, 0x0201) },800800+ { SDIO_DEVICE(0x041B, 0x9330) },801801+ { /* Blank */},802802+};803803+804804+static struct sdio_driver rsi_driver = {805805+ .name = "RSI-SDIO WLAN",806806+ .probe = rsi_probe,807807+ .remove = rsi_disconnect,808808+ .id_table = rsi_dev_table,809809+#ifdef CONFIG_PM810810+ .drv = {811811+ .pm = &rsi_pm_ops,812812+ }813813+#endif814814+};815815+816816+/**817817+ * rsi_module_init() - This function registers the sdio module.818818+ * @void: Void.819819+ *820820+ * Return: 0 on success.821821+ */822822+static int rsi_module_init(void)823823+{824824+ sdio_register_driver(&rsi_driver);825825+ rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);826826+ return 0;827827+}828828+829829+/**830830+ * rsi_module_exit() - This function unregisters the sdio module.831831+ * @void: Void.832832+ *833833+ * Return: None.834834+ */835835+static void rsi_module_exit(void)836836+{837837+ sdio_unregister_driver(&rsi_driver);838838+ rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);839839+}840840+841841+module_init(rsi_module_init);842842+module_exit(rsi_module_exit);843843+844844+MODULE_AUTHOR("Redpine Signals Inc");845845+MODULE_DESCRIPTION("Common SDIO layer for RSI drivers");846846+MODULE_SUPPORTED_DEVICE("RSI-91x");847847+MODULE_DEVICE_TABLE(sdio, rsi_dev_table);848848+MODULE_FIRMWARE(FIRMWARE_RSI9113);849849+MODULE_VERSION("0.1");850850+MODULE_LICENSE("Dual BSD/GPL");
+566
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ *1616+ */1717+1818+#include <linux/firmware.h>1919+#include "rsi_sdio.h"2020+#include "rsi_common.h"2121+2222+/**2323+ * rsi_sdio_master_access_msword() - This function sets the AHB master access2424+ * MS word in the SDIO slave registers.2525+ * @adapter: Pointer to the adapter structure.2626+ * @ms_word: ms word need to be initialized.2727+ *2828+ * Return: status: 0 on success, -1 on failure.2929+ */3030+static int rsi_sdio_master_access_msword(struct rsi_hw *adapter,3131+ u16 ms_word)3232+{3333+ u8 byte;3434+ u8 function = 0;3535+ int status = 0;3636+3737+ byte = (u8)(ms_word & 0x00FF);3838+3939+ rsi_dbg(INIT_ZONE,4040+ "%s: MASTER_ACCESS_MSBYTE:0x%x\n", __func__, byte);4141+4242+ status = rsi_sdio_write_register(adapter,4343+ function,4444+ SDIO_MASTER_ACCESS_MSBYTE,4545+ &byte);4646+ if (status) {4747+ rsi_dbg(ERR_ZONE,4848+ "%s: fail to access MASTER_ACCESS_MSBYTE\n",4949+ __func__);5050+ return -1;5151+ }5252+5353+ byte = (u8)(ms_word >> 8);5454+5555+ rsi_dbg(INIT_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte);5656+ status = rsi_sdio_write_register(adapter,5757+ function,5858+ SDIO_MASTER_ACCESS_LSBYTE,5959+ &byte);6060+ return status;6161+}6262+6363+/**6464+ * rsi_copy_to_card() - This function includes the actual funtionality of6565+ * copying the TA firmware to the card.Basically this6666+ * function includes opening the TA file,reading the6767+ * TA file and writing their values in blocks of data.6868+ * @common: Pointer to the driver private structure.6969+ * @fw: Pointer to the firmware value to be written.7070+ * @len: length of firmware file.7171+ * @num_blocks: Number of blocks to be written to the card.7272+ *7373+ * Return: 0 on success and -1 on failure.7474+ */7575+static int rsi_copy_to_card(struct rsi_common *common,7676+ const u8 *fw,7777+ u32 len,7878+ u32 num_blocks)7979+{8080+ struct rsi_hw *adapter = common->priv;8181+ struct rsi_91x_sdiodev *dev =8282+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;8383+ u32 indx, ii;8484+ u32 block_size = dev->tx_blk_size;8585+ u32 lsb_address;8686+ __le32 data[] = { TA_HOLD_THREAD_VALUE, TA_SOFT_RST_CLR,8787+ TA_PC_ZERO, TA_RELEASE_THREAD_VALUE };8888+ u32 address[] = { TA_HOLD_THREAD_REG, TA_SOFT_RESET_REG,8989+ TA_TH0_PC_REG, TA_RELEASE_THREAD_REG };9090+ u32 base_address;9191+ u16 msb_address;9292+9393+ base_address = TA_LOAD_ADDRESS;9494+ msb_address = base_address >> 16;9595+9696+ for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {9797+ lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);9898+ if (rsi_sdio_write_register_multiple(adapter,9999+ lsb_address,100100+ (u8 *)(fw + indx),101101+ block_size)) {102102+ rsi_dbg(ERR_ZONE,103103+ "%s: Unable to load %s blk\n", __func__,104104+ FIRMWARE_RSI9113);105105+ return -1;106106+ }107107+ rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);108108+ base_address += block_size;109109+ if ((base_address >> 16) != msb_address) {110110+ msb_address += 1;111111+ if (rsi_sdio_master_access_msword(adapter,112112+ msb_address)) {113113+ rsi_dbg(ERR_ZONE,114114+ "%s: Unable to set ms word reg\n",115115+ __func__);116116+ return -1;117117+ }118118+ }119119+ }120120+121121+ if (len % block_size) {122122+ lsb_address = ((u16) base_address | RSI_SD_REQUEST_MASTER);123123+ if (rsi_sdio_write_register_multiple(adapter,124124+ lsb_address,125125+ (u8 *)(fw + indx),126126+ len % block_size)) {127127+ rsi_dbg(ERR_ZONE,128128+ "%s: Unable to load f/w\n", __func__);129129+ return -1;130130+ }131131+ }132132+ rsi_dbg(INIT_ZONE,133133+ "%s: Succesfully loaded TA instructions\n", __func__);134134+135135+ if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {136136+ rsi_dbg(ERR_ZONE,137137+ "%s: Unable to set ms word to common reg\n",138138+ __func__);139139+ return -1;140140+ }141141+142142+ for (ii = 0; ii < ARRAY_SIZE(data); ii++) {143143+ /* Bringing TA out of reset */144144+ if (rsi_sdio_write_register_multiple(adapter,145145+ (address[ii] |146146+ RSI_SD_REQUEST_MASTER),147147+ (u8 *)&data[ii],148148+ 4)) {149149+ rsi_dbg(ERR_ZONE,150150+ "%s: Unable to hold TA threads\n", __func__);151151+ return -1;152152+ }153153+ }154154+155155+ rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);156156+ return 0;157157+}158158+159159+/**160160+ * rsi_load_ta_instructions() - This function includes the actual funtionality161161+ * of loading the TA firmware.This function also162162+ * includes opening the TA file,reading the TA163163+ * file and writing their value in blocks of data.164164+ * @common: Pointer to the driver private structure.165165+ *166166+ * Return: status: 0 on success, -1 on failure.167167+ */168168+static int rsi_load_ta_instructions(struct rsi_common *common)169169+{170170+ struct rsi_hw *adapter = common->priv;171171+ struct rsi_91x_sdiodev *dev =172172+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;173173+ u32 len;174174+ u32 num_blocks;175175+ const u8 *fw;176176+ const struct firmware *fw_entry = NULL;177177+ u32 block_size = dev->tx_blk_size;178178+ int status = 0;179179+ u32 base_address;180180+ u16 msb_address;181181+182182+ if (rsi_sdio_master_access_msword(adapter, TA_BASE_ADDR)) {183183+ rsi_dbg(ERR_ZONE,184184+ "%s: Unable to set ms word to common reg\n",185185+ __func__);186186+ return -1;187187+ }188188+ base_address = TA_LOAD_ADDRESS;189189+ msb_address = (base_address >> 16);190190+191191+ if (rsi_sdio_master_access_msword(adapter, msb_address)) {192192+ rsi_dbg(ERR_ZONE,193193+ "%s: Unable to set ms word reg\n", __func__);194194+ return -1;195195+ }196196+197197+ status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);198198+ if (status < 0) {199199+ rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",200200+ __func__, FIRMWARE_RSI9113);201201+ return status;202202+ }203203+204204+ fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);205205+ len = fw_entry->size;206206+207207+ if (len % 4)208208+ len += (4 - (len % 4));209209+210210+ num_blocks = (len / block_size);211211+212212+ rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);213213+ rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);214214+215215+ status = rsi_copy_to_card(common, fw, len, num_blocks);216216+ release_firmware(fw_entry);217217+ return status;218218+}219219+220220+/**221221+ * rsi_process_pkt() - This Function reads rx_blocks register and figures out222222+ * the size of the rx pkt.223223+ * @common: Pointer to the driver private structure.224224+ *225225+ * Return: 0 on success, -1 on failure.226226+ */227227+static int rsi_process_pkt(struct rsi_common *common)228228+{229229+ struct rsi_hw *adapter = common->priv;230230+ u8 num_blks = 0;231231+ u32 rcv_pkt_len = 0;232232+ int status = 0;233233+234234+ status = rsi_sdio_read_register(adapter,235235+ SDIO_RX_NUM_BLOCKS_REG,236236+ &num_blks);237237+238238+ if (status) {239239+ rsi_dbg(ERR_ZONE,240240+ "%s: Failed to read pkt length from the card:\n",241241+ __func__);242242+ return status;243243+ }244244+ rcv_pkt_len = (num_blks * 256);245245+246246+ common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL);247247+ if (!common->rx_data_pkt) {248248+ rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n",249249+ __func__);250250+ return -1;251251+ }252252+253253+ status = rsi_sdio_host_intf_read_pkt(adapter,254254+ common->rx_data_pkt,255255+ rcv_pkt_len);256256+ if (status) {257257+ rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",258258+ __func__);259259+ goto fail;260260+ }261261+262262+ status = rsi_read_pkt(common, rcv_pkt_len);263263+ kfree(common->rx_data_pkt);264264+ return status;265265+266266+fail:267267+ kfree(common->rx_data_pkt);268268+ return -1;269269+}270270+271271+/**272272+ * rsi_init_sdio_slave_regs() - This function does the actual initialization273273+ * of SDBUS slave registers.274274+ * @adapter: Pointer to the adapter structure.275275+ *276276+ * Return: status: 0 on success, -1 on failure.277277+ */278278+int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)279279+{280280+ struct rsi_91x_sdiodev *dev =281281+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;282282+ u8 function = 0;283283+ u8 byte;284284+ int status = 0;285285+286286+ if (dev->next_read_delay) {287287+ byte = dev->next_read_delay;288288+ status = rsi_sdio_write_register(adapter,289289+ function,290290+ SDIO_NXT_RD_DELAY2,291291+ &byte);292292+ if (status) {293293+ rsi_dbg(ERR_ZONE,294294+ "%s: Failed to write SDIO_NXT_RD_DELAY2\n",295295+ __func__);296296+ return -1;297297+ }298298+ }299299+300300+ if (dev->sdio_high_speed_enable) {301301+ rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__);302302+ byte = 0x3;303303+304304+ status = rsi_sdio_write_register(adapter,305305+ function,306306+ SDIO_REG_HIGH_SPEED,307307+ &byte);308308+ if (status) {309309+ rsi_dbg(ERR_ZONE,310310+ "%s: Failed to enable SDIO high speed\n",311311+ __func__);312312+ return -1;313313+ }314314+ }315315+316316+ /* This tells SDIO FIFO when to start read to host */317317+ rsi_dbg(INIT_ZONE, "%s: Initialzing SDIO read start level\n", __func__);318318+ byte = 0x24;319319+320320+ status = rsi_sdio_write_register(adapter,321321+ function,322322+ SDIO_READ_START_LVL,323323+ &byte);324324+ if (status) {325325+ rsi_dbg(ERR_ZONE,326326+ "%s: Failed to write SDIO_READ_START_LVL\n", __func__);327327+ return -1;328328+ }329329+330330+ rsi_dbg(INIT_ZONE, "%s: Initialzing FIFO ctrl registers\n", __func__);331331+ byte = (128 - 32);332332+333333+ status = rsi_sdio_write_register(adapter,334334+ function,335335+ SDIO_READ_FIFO_CTL,336336+ &byte);337337+ if (status) {338338+ rsi_dbg(ERR_ZONE,339339+ "%s: Failed to write SDIO_READ_FIFO_CTL\n", __func__);340340+ return -1;341341+ }342342+343343+ byte = 32;344344+ status = rsi_sdio_write_register(adapter,345345+ function,346346+ SDIO_WRITE_FIFO_CTL,347347+ &byte);348348+ if (status) {349349+ rsi_dbg(ERR_ZONE,350350+ "%s: Failed to write SDIO_WRITE_FIFO_CTL\n", __func__);351351+ return -1;352352+ }353353+354354+ return 0;355355+}356356+357357+/**358358+ * rsi_interrupt_handler() - This function read and process SDIO interrupts.359359+ * @adapter: Pointer to the adapter structure.360360+ *361361+ * Return: None.362362+ */363363+void rsi_interrupt_handler(struct rsi_hw *adapter)364364+{365365+ struct rsi_common *common = adapter->priv;366366+ struct rsi_91x_sdiodev *dev =367367+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;368368+ int status;369369+ enum sdio_interrupt_type isr_type;370370+ u8 isr_status = 0;371371+ u8 fw_status = 0;372372+373373+ dev->rx_info.sdio_int_counter++;374374+375375+ do {376376+ mutex_lock(&common->tx_rxlock);377377+ status = rsi_sdio_read_register(common->priv,378378+ RSI_FN1_INT_REGISTER,379379+ &isr_status);380380+ if (status) {381381+ rsi_dbg(ERR_ZONE,382382+ "%s: Failed to Read Intr Status Register\n",383383+ __func__);384384+ mutex_unlock(&common->tx_rxlock);385385+ return;386386+ }387387+388388+ if (isr_status == 0) {389389+ rsi_set_event(&common->tx_thread.event);390390+ dev->rx_info.sdio_intr_status_zero++;391391+ mutex_unlock(&common->tx_rxlock);392392+ return;393393+ }394394+395395+ rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",396396+ __func__, isr_status, (1 << MSDU_PKT_PENDING),397397+ (1 << FW_ASSERT_IND));398398+399399+ do {400400+ RSI_GET_SDIO_INTERRUPT_TYPE(isr_status, isr_type);401401+402402+ switch (isr_type) {403403+ case BUFFER_AVAILABLE:404404+ dev->rx_info.watch_bufferfull_count = 0;405405+ dev->rx_info.buffer_full = false;406406+ dev->rx_info.mgmt_buffer_full = false;407407+ rsi_sdio_ack_intr(common->priv,408408+ (1 << PKT_BUFF_AVAILABLE));409409+ rsi_set_event((&common->tx_thread.event));410410+ rsi_dbg(ISR_ZONE,411411+ "%s: ==> BUFFER_AVILABLE <==\n",412412+ __func__);413413+ dev->rx_info.buf_avilable_counter++;414414+ break;415415+416416+ case FIRMWARE_ASSERT_IND:417417+ rsi_dbg(ERR_ZONE,418418+ "%s: ==> FIRMWARE Assert <==\n",419419+ __func__);420420+ status = rsi_sdio_read_register(common->priv,421421+ SDIO_FW_STATUS_REG,422422+ &fw_status);423423+ if (status) {424424+ rsi_dbg(ERR_ZONE,425425+ "%s: Failed to read f/w reg\n",426426+ __func__);427427+ } else {428428+ rsi_dbg(ERR_ZONE,429429+ "%s: Firmware Status is 0x%x\n",430430+ __func__ , fw_status);431431+ rsi_sdio_ack_intr(common->priv,432432+ (1 << FW_ASSERT_IND));433433+ }434434+435435+ common->fsm_state = FSM_CARD_NOT_READY;436436+ break;437437+438438+ case MSDU_PACKET_PENDING:439439+ rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");440440+ dev->rx_info.total_sdio_msdu_pending_intr++;441441+442442+ status = rsi_process_pkt(common);443443+ if (status) {444444+ rsi_dbg(ERR_ZONE,445445+ "%s: Failed to read pkt\n",446446+ __func__);447447+ mutex_unlock(&common->tx_rxlock);448448+ return;449449+ }450450+ break;451451+ default:452452+ rsi_sdio_ack_intr(common->priv, isr_status);453453+ dev->rx_info.total_sdio_unknown_intr++;454454+ isr_status = 0;455455+ rsi_dbg(ISR_ZONE,456456+ "Unknown Interrupt %x\n",457457+ isr_status);458458+ break;459459+ }460460+ isr_status ^= BIT(isr_type - 1);461461+ } while (isr_status);462462+ mutex_unlock(&common->tx_rxlock);463463+ } while (1);464464+}465465+466466+/**467467+ * rsi_device_init() - This Function Initializes The HAL.468468+ * @common: Pointer to the driver private structure.469469+ *470470+ * Return: 0 on success, -1 on failure.471471+ */472472+int rsi_sdio_device_init(struct rsi_common *common)473473+{474474+ if (rsi_load_ta_instructions(common))475475+ return -1;476476+477477+ if (rsi_sdio_master_access_msword(common->priv, MISC_CFG_BASE_ADDR)) {478478+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n",479479+ __func__);480480+ return -1;481481+ }482482+ rsi_dbg(INIT_ZONE,483483+ "%s: Setting ms word to 0x41050000\n", __func__);484484+485485+ return 0;486486+}487487+488488+/**489489+ * rsi_sdio_read_buffer_status_register() - This function is used to the read490490+ * buffer status register and set491491+ * relevant fields in492492+ * rsi_91x_sdiodev struct.493493+ * @adapter: Pointer to the driver hw structure.494494+ * @q_num: The Q number whose status is to be found.495495+ *496496+ * Return: status: -1 on failure or else queue full/stop is indicated.497497+ */498498+int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)499499+{500500+ struct rsi_common *common = adapter->priv;501501+ struct rsi_91x_sdiodev *dev =502502+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;503503+ u8 buf_status = 0;504504+ int status = 0;505505+506506+ status = rsi_sdio_read_register(common->priv,507507+ RSI_DEVICE_BUFFER_STATUS_REGISTER,508508+ &buf_status);509509+510510+ if (status) {511511+ rsi_dbg(ERR_ZONE,512512+ "%s: Failed to read status register\n", __func__);513513+ return -1;514514+ }515515+516516+ if (buf_status & (BIT(PKT_MGMT_BUFF_FULL))) {517517+ if (!dev->rx_info.mgmt_buffer_full)518518+ dev->rx_info.mgmt_buf_full_counter++;519519+ dev->rx_info.mgmt_buffer_full = true;520520+ } else {521521+ dev->rx_info.mgmt_buffer_full = false;522522+ }523523+524524+ if (buf_status & (BIT(PKT_BUFF_FULL))) {525525+ if (!dev->rx_info.buffer_full)526526+ dev->rx_info.buf_full_counter++;527527+ dev->rx_info.buffer_full = true;528528+ } else {529529+ dev->rx_info.buffer_full = false;530530+ }531531+532532+ if (buf_status & (BIT(PKT_BUFF_SEMI_FULL))) {533533+ if (!dev->rx_info.semi_buffer_full)534534+ dev->rx_info.buf_semi_full_counter++;535535+ dev->rx_info.semi_buffer_full = true;536536+ } else {537537+ dev->rx_info.semi_buffer_full = false;538538+ }539539+540540+ if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))541541+ return QUEUE_FULL;542542+543543+ if (dev->rx_info.buffer_full)544544+ return QUEUE_FULL;545545+546546+ return QUEUE_NOT_FULL;547547+}548548+549549+/**550550+ * rsi_sdio_determine_event_timeout() - This Function determines the event551551+ * timeout duration.552552+ * @adapter: Pointer to the adapter structure.553553+ *554554+ * Return: timeout duration is returned.555555+ */556556+int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter)557557+{558558+ struct rsi_91x_sdiodev *dev =559559+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;560560+561561+ /* Once buffer full is seen, event timeout to occur every 2 msecs */562562+ if (dev->rx_info.buffer_full)563563+ return 2;564564+565565+ return EVENT_WAIT_FOREVER;566566+}
+575
drivers/net/wireless/rsi/rsi_91x_usb.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ *1616+ */1717+1818+#include <linux/module.h>1919+#include "rsi_usb.h"2020+2121+/**2222+ * rsi_usb_card_write() - This function writes to the USB Card.2323+ * @adapter: Pointer to the adapter structure.2424+ * @buf: Pointer to the buffer from where the data has to be taken.2525+ * @len: Length to be written.2626+ * @endpoint: Type of endpoint.2727+ *2828+ * Return: status: 0 on success, -1 on failure.2929+ */3030+static int rsi_usb_card_write(struct rsi_hw *adapter,3131+ void *buf,3232+ u16 len,3333+ u8 endpoint)3434+{3535+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;3636+ int status;3737+ s32 transfer;3838+3939+ status = usb_bulk_msg(dev->usbdev,4040+ usb_sndbulkpipe(dev->usbdev,4141+ dev->bulkout_endpoint_addr[endpoint - 1]),4242+ buf,4343+ len,4444+ &transfer,4545+ HZ * 5);4646+4747+ if (status < 0) {4848+ rsi_dbg(ERR_ZONE,4949+ "Card write failed with error code :%10d\n", status);5050+ dev->write_fail = 1;5151+ }5252+ return status;5353+}5454+5555+/**5656+ * rsi_write_multiple() - This function writes multiple bytes of information5757+ * to the USB card.5858+ * @adapter: Pointer to the adapter structure.5959+ * @addr: Address of the register.6060+ * @data: Pointer to the data that has to be written.6161+ * @count: Number of multiple bytes to be written.6262+ *6363+ * Return: 0 on success, -1 on failure.6464+ */6565+static int rsi_write_multiple(struct rsi_hw *adapter,6666+ u8 endpoint,6767+ u8 *data,6868+ u32 count)6969+{7070+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;7171+ u8 *seg = dev->tx_buffer;7272+7373+ if (dev->write_fail)7474+ return 0;7575+7676+ if (endpoint == MGMT_EP) {7777+ memset(seg, 0, RSI_USB_TX_HEAD_ROOM);7878+ memcpy(seg + RSI_USB_TX_HEAD_ROOM, data, count);7979+ } else {8080+ seg = ((u8 *)data - RSI_USB_TX_HEAD_ROOM);8181+ }8282+8383+ return rsi_usb_card_write(adapter,8484+ seg,8585+ count + RSI_USB_TX_HEAD_ROOM,8686+ endpoint);8787+}8888+8989+/**9090+ * rsi_find_bulk_in_and_out_endpoints() - This function initializes the bulk9191+ * endpoints to the device.9292+ * @interface: Pointer to the USB interface structure.9393+ * @adapter: Pointer to the adapter structure.9494+ *9595+ * Return: ret_val: 0 on success, -ENOMEM on failure.9696+ */9797+static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,9898+ struct rsi_hw *adapter)9999+{100100+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;101101+ struct usb_host_interface *iface_desc;102102+ struct usb_endpoint_descriptor *endpoint;103103+ __le16 buffer_size;104104+ int ii, bep_found = 0;105105+106106+ iface_desc = &(interface->altsetting[0]);107107+108108+ for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) {109109+ endpoint = &(iface_desc->endpoint[ii].desc);110110+111111+ if ((!(dev->bulkin_endpoint_addr)) &&112112+ (endpoint->bEndpointAddress & USB_DIR_IN) &&113113+ ((endpoint->bmAttributes &114114+ USB_ENDPOINT_XFERTYPE_MASK) ==115115+ USB_ENDPOINT_XFER_BULK)) {116116+ buffer_size = endpoint->wMaxPacketSize;117117+ dev->bulkin_size = buffer_size;118118+ dev->bulkin_endpoint_addr =119119+ endpoint->bEndpointAddress;120120+ }121121+122122+ if (!dev->bulkout_endpoint_addr[bep_found] &&123123+ !(endpoint->bEndpointAddress & USB_DIR_IN) &&124124+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==125125+ USB_ENDPOINT_XFER_BULK)) {126126+ dev->bulkout_endpoint_addr[bep_found] =127127+ endpoint->bEndpointAddress;128128+ buffer_size = endpoint->wMaxPacketSize;129129+ dev->bulkout_size[bep_found] = buffer_size;130130+ bep_found++;131131+ }132132+133133+ if (bep_found >= MAX_BULK_EP)134134+ break;135135+ }136136+137137+ if (!(dev->bulkin_endpoint_addr) &&138138+ (dev->bulkout_endpoint_addr[0]))139139+ return -EINVAL;140140+141141+ return 0;142142+}143143+144144+/* rsi_usb_reg_read() - This function reads data from given register address.145145+ * @usbdev: Pointer to the usb_device structure.146146+ * @reg: Address of the register to be read.147147+ * @value: Value to be read.148148+ * @len: length of data to be read.149149+ *150150+ * Return: status: 0 on success, -1 on failure.151151+ */152152+static int rsi_usb_reg_read(struct usb_device *usbdev,153153+ u32 reg,154154+ u16 *value,155155+ u16 len)156156+{157157+ u8 temp_buf[4];158158+ int status = 0;159159+160160+ status = usb_control_msg(usbdev,161161+ usb_rcvctrlpipe(usbdev, 0),162162+ USB_VENDOR_REGISTER_READ,163163+ USB_TYPE_VENDOR,164164+ ((reg & 0xffff0000) >> 16), (reg & 0xffff),165165+ (void *)temp_buf,166166+ len,167167+ HZ * 5);168168+169169+ *value = (temp_buf[0] | (temp_buf[1] << 8));170170+ if (status < 0) {171171+ rsi_dbg(ERR_ZONE,172172+ "%s: Reg read failed with error code :%d\n",173173+ __func__, status);174174+ }175175+ return status;176176+}177177+178178+/**179179+ * rsi_usb_reg_write() - This function writes the given data into the given180180+ * register address.181181+ * @usbdev: Pointer to the usb_device structure.182182+ * @reg: Address of the register.183183+ * @value: Value to write.184184+ * @len: Length of data to be written.185185+ *186186+ * Return: status: 0 on success, -1 on failure.187187+ */188188+static int rsi_usb_reg_write(struct usb_device *usbdev,189189+ u32 reg,190190+ u16 value,191191+ u16 len)192192+{193193+ u8 usb_reg_buf[4];194194+ int status = 0;195195+196196+ usb_reg_buf[0] = (value & 0x00ff);197197+ usb_reg_buf[1] = (value & 0xff00) >> 8;198198+ usb_reg_buf[2] = 0x0;199199+ usb_reg_buf[3] = 0x0;200200+201201+ status = usb_control_msg(usbdev,202202+ usb_sndctrlpipe(usbdev, 0),203203+ USB_VENDOR_REGISTER_WRITE,204204+ USB_TYPE_VENDOR,205205+ ((reg & 0xffff0000) >> 16),206206+ (reg & 0xffff),207207+ (void *)usb_reg_buf,208208+ len,209209+ HZ * 5);210210+ if (status < 0) {211211+ rsi_dbg(ERR_ZONE,212212+ "%s: Reg write failed with error code :%d\n",213213+ __func__, status);214214+ }215215+ return status;216216+}217217+218218+/**219219+ * rsi_rx_done_handler() - This function is called when a packet is received220220+ * from USB stack. This is callback to recieve done.221221+ * @urb: Received URB.222222+ *223223+ * Return: None.224224+ */225225+static void rsi_rx_done_handler(struct urb *urb)226226+{227227+ struct rsi_hw *adapter = urb->context;228228+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;229229+230230+ if (urb->status)231231+ return;232232+233233+ rsi_set_event(&dev->rx_thread.event);234234+}235235+236236+/**237237+ * rsi_rx_urb_submit() - This function submits the given URB to the USB stack.238238+ * @adapter: Pointer to the adapter structure.239239+ *240240+ * Return: 0 on success, -1 on failure.241241+ */242242+static int rsi_rx_urb_submit(struct rsi_hw *adapter)243243+{244244+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;245245+ struct urb *urb = dev->rx_usb_urb[0];246246+ int status;247247+248248+ usb_fill_bulk_urb(urb,249249+ dev->usbdev,250250+ usb_rcvbulkpipe(dev->usbdev,251251+ dev->bulkin_endpoint_addr),252252+ urb->transfer_buffer,253253+ 3000,254254+ rsi_rx_done_handler,255255+ adapter);256256+257257+ status = usb_submit_urb(urb, GFP_KERNEL);258258+ if (status)259259+ rsi_dbg(ERR_ZONE, "%s: Failed in urb submission\n", __func__);260260+261261+ return status;262262+}263263+264264+/**265265+ * rsi_usb_write_register_multiple() - This function writes multiple bytes of266266+ * information to multiple registers.267267+ * @adapter: Pointer to the adapter structure.268268+ * @addr: Address of the register.269269+ * @data: Pointer to the data that has to be written.270270+ * @count: Number of multiple bytes to be written on to the registers.271271+ *272272+ * Return: status: 0 on success, -1 on failure.273273+ */274274+int rsi_usb_write_register_multiple(struct rsi_hw *adapter,275275+ u32 addr,276276+ u8 *data,277277+ u32 count)278278+{279279+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;280280+ u8 *buf;281281+ u8 transfer;282282+ int status = 0;283283+284284+ buf = kzalloc(4096, GFP_KERNEL);285285+ if (!buf)286286+ return -ENOMEM;287287+288288+ while (count) {289289+ transfer = min_t(int, count, 4096);290290+ memcpy(buf, data, transfer);291291+ status = usb_control_msg(dev->usbdev,292292+ usb_sndctrlpipe(dev->usbdev, 0),293293+ USB_VENDOR_REGISTER_WRITE,294294+ USB_TYPE_VENDOR,295295+ ((addr & 0xffff0000) >> 16),296296+ (addr & 0xffff),297297+ (void *)buf,298298+ transfer,299299+ HZ * 5);300300+ if (status < 0) {301301+ rsi_dbg(ERR_ZONE,302302+ "Reg write failed with error code :%d\n",303303+ status);304304+ } else {305305+ count -= transfer;306306+ data += transfer;307307+ addr += transfer;308308+ }309309+ }310310+311311+ kfree(buf);312312+ return 0;313313+}314314+315315+/**316316+ *rsi_usb_host_intf_write_pkt() - This function writes the packet to the317317+ * USB card.318318+ * @adapter: Pointer to the adapter structure.319319+ * @pkt: Pointer to the data to be written on to the card.320320+ * @len: Length of the data to be written on to the card.321321+ *322322+ * Return: 0 on success, -1 on failure.323323+ */324324+static int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,325325+ u8 *pkt,326326+ u32 len)327327+{328328+ u32 queueno = ((pkt[1] >> 4) & 0xf);329329+ u8 endpoint;330330+331331+ endpoint = ((queueno == RSI_WIFI_MGMT_Q) ? MGMT_EP : DATA_EP);332332+333333+ return rsi_write_multiple(adapter,334334+ endpoint,335335+ (u8 *)pkt,336336+ len);337337+}338338+339339+/**340340+ * rsi_deinit_usb_interface() - This function deinitializes the usb interface.341341+ * @adapter: Pointer to the adapter structure.342342+ *343343+ * Return: None.344344+ */345345+static void rsi_deinit_usb_interface(struct rsi_hw *adapter)346346+{347347+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;348348+349349+ rsi_kill_thread(&dev->rx_thread);350350+ kfree(adapter->priv->rx_data_pkt);351351+ kfree(dev->tx_buffer);352352+}353353+354354+/**355355+ * rsi_init_usb_interface() - This function initializes the usb interface.356356+ * @adapter: Pointer to the adapter structure.357357+ * @pfunction: Pointer to USB interface structure.358358+ *359359+ * Return: 0 on success, -1 on failure.360360+ */361361+static int rsi_init_usb_interface(struct rsi_hw *adapter,362362+ struct usb_interface *pfunction)363363+{364364+ struct rsi_91x_usbdev *rsi_dev;365365+ struct rsi_common *common = adapter->priv;366366+ int status;367367+368368+ rsi_dev = kzalloc(sizeof(*rsi_dev), GFP_KERNEL);369369+ if (!rsi_dev)370370+ return -ENOMEM;371371+372372+ adapter->rsi_dev = rsi_dev;373373+ rsi_dev->usbdev = interface_to_usbdev(pfunction);374374+375375+ if (rsi_find_bulk_in_and_out_endpoints(pfunction, adapter))376376+ return -EINVAL;377377+378378+ adapter->device = &pfunction->dev;379379+ usb_set_intfdata(pfunction, adapter);380380+381381+ common->rx_data_pkt = kmalloc(2048, GFP_KERNEL);382382+ if (!common->rx_data_pkt) {383383+ rsi_dbg(ERR_ZONE, "%s: Failed to allocate memory\n",384384+ __func__);385385+ return -ENOMEM;386386+ }387387+388388+ rsi_dev->tx_buffer = kmalloc(2048, GFP_ATOMIC);389389+ rsi_dev->rx_usb_urb[0] = usb_alloc_urb(0, GFP_KERNEL);390390+ rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;391391+ rsi_dev->tx_blk_size = 252;392392+393393+ /* Initializing function callbacks */394394+ adapter->rx_urb_submit = rsi_rx_urb_submit;395395+ adapter->host_intf_write_pkt = rsi_usb_host_intf_write_pkt;396396+ adapter->check_hw_queue_status = rsi_usb_check_queue_status;397397+ adapter->determine_event_timeout = rsi_usb_event_timeout;398398+399399+ rsi_init_event(&rsi_dev->rx_thread.event);400400+ status = rsi_create_kthread(common, &rsi_dev->rx_thread,401401+ rsi_usb_rx_thread, "RX-Thread");402402+ if (status) {403403+ rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);404404+ goto fail;405405+ }406406+407407+#ifdef CONFIG_RSI_DEBUGFS408408+ /* In USB, one less than the MAX_DEBUGFS_ENTRIES entries is required */409409+ adapter->num_debugfs_entries = (MAX_DEBUGFS_ENTRIES - 1);410410+#endif411411+412412+ rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);413413+ return 0;414414+415415+fail:416416+ kfree(rsi_dev->tx_buffer);417417+ kfree(common->rx_data_pkt);418418+ return status;419419+}420420+421421+/**422422+ * rsi_probe() - This function is called by kernel when the driver provided423423+ * Vendor and device IDs are matched. All the initialization424424+ * work is done here.425425+ * @pfunction: Pointer to the USB interface structure.426426+ * @id: Pointer to the usb_device_id structure.427427+ *428428+ * Return: 0 on success, -1 on failure.429429+ */430430+static int rsi_probe(struct usb_interface *pfunction,431431+ const struct usb_device_id *id)432432+{433433+ struct rsi_hw *adapter;434434+ struct rsi_91x_usbdev *dev;435435+ u16 fw_status;436436+437437+ rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);438438+439439+ adapter = rsi_91x_init();440440+ if (!adapter) {441441+ rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",442442+ __func__);443443+ return 1;444444+ }445445+446446+ if (rsi_init_usb_interface(adapter, pfunction)) {447447+ rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n",448448+ __func__);449449+ goto err;450450+ }451451+452452+ rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__);453453+454454+ dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;455455+456456+ if (rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2) < 0)457457+ goto err1;458458+ else459459+ fw_status &= 1;460460+461461+ if (!fw_status) {462462+ if (rsi_usb_device_init(adapter->priv)) {463463+ rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",464464+ __func__);465465+ goto err1;466466+ }467467+468468+ if (rsi_usb_reg_write(dev->usbdev,469469+ USB_INTERNAL_REG_1,470470+ RSI_USB_READY_MAGIC_NUM, 1) < 0)471471+ goto err1;472472+ rsi_dbg(INIT_ZONE, "%s: Performed device init\n", __func__);473473+ }474474+475475+ if (rsi_rx_urb_submit(adapter))476476+ goto err1;477477+478478+ return 0;479479+err1:480480+ rsi_deinit_usb_interface(adapter);481481+err:482482+ rsi_91x_deinit(adapter);483483+ rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);484484+ return 1;485485+}486486+487487+/**488488+ * rsi_disconnect() - This function performs the reverse of the probe function,489489+ * it deintialize the driver structure.490490+ * @pfunction: Pointer to the USB interface structure.491491+ *492492+ * Return: None.493493+ */494494+static void rsi_disconnect(struct usb_interface *pfunction)495495+{496496+ struct rsi_hw *adapter = usb_get_intfdata(pfunction);497497+498498+ if (!adapter)499499+ return;500500+501501+ rsi_mac80211_detach(adapter);502502+ rsi_deinit_usb_interface(adapter);503503+ rsi_91x_deinit(adapter);504504+505505+ rsi_dbg(INFO_ZONE, "%s: Deinitialization completed\n", __func__);506506+}507507+508508+#ifdef CONFIG_PM509509+static int rsi_suspend(struct usb_interface *intf, pm_message_t message)510510+{511511+ /* Not yet implemented */512512+ return -ENOSYS;513513+}514514+515515+static int rsi_resume(struct usb_interface *intf)516516+{517517+ /* Not yet implemented */518518+ return -ENOSYS;519519+}520520+#endif521521+522522+static const struct usb_device_id rsi_dev_table[] = {523523+ { USB_DEVICE(0x0303, 0x0100) },524524+ { USB_DEVICE(0x041B, 0x0301) },525525+ { USB_DEVICE(0x041B, 0x0201) },526526+ { USB_DEVICE(0x041B, 0x9330) },527527+ { /* Blank */},528528+};529529+530530+static struct usb_driver rsi_driver = {531531+ .name = "RSI-USB WLAN",532532+ .probe = rsi_probe,533533+ .disconnect = rsi_disconnect,534534+ .id_table = rsi_dev_table,535535+#ifdef CONFIG_PM536536+ .suspend = rsi_suspend,537537+ .resume = rsi_resume,538538+#endif539539+};540540+541541+/**542542+ * rsi_module_init() - This function registers the client driver.543543+ * @void: Void.544544+ *545545+ * Return: 0 on success.546546+ */547547+static int rsi_module_init(void)548548+{549549+ usb_register(&rsi_driver);550550+ rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);551551+ return 0;552552+}553553+554554+/**555555+ * rsi_module_exit() - This function unregisters the client driver.556556+ * @void: Void.557557+ *558558+ * Return: None.559559+ */560560+static void rsi_module_exit(void)561561+{562562+ usb_deregister(&rsi_driver);563563+ rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);564564+}565565+566566+module_init(rsi_module_init);567567+module_exit(rsi_module_exit);568568+569569+MODULE_AUTHOR("Redpine Signals Inc");570570+MODULE_DESCRIPTION("Common USB layer for RSI drivers");571571+MODULE_SUPPORTED_DEVICE("RSI-91x");572572+MODULE_DEVICE_TABLE(usb, rsi_dev_table);573573+MODULE_FIRMWARE(FIRMWARE_RSI9113);574574+MODULE_VERSION("0.1");575575+MODULE_LICENSE("Dual BSD/GPL");
+177
drivers/net/wireless/rsi/rsi_91x_usb_ops.c
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ *1616+ */1717+1818+#include <linux/firmware.h>1919+#include "rsi_usb.h"2020+2121+/**2222+ * rsi_copy_to_card() - This function includes the actual funtionality of2323+ * copying the TA firmware to the card.Basically this2424+ * function includes opening the TA file,reading the TA2525+ * file and writing their values in blocks of data.2626+ * @common: Pointer to the driver private structure.2727+ * @fw: Pointer to the firmware value to be written.2828+ * @len: length of firmware file.2929+ * @num_blocks: Number of blocks to be written to the card.3030+ *3131+ * Return: 0 on success and -1 on failure.3232+ */3333+static int rsi_copy_to_card(struct rsi_common *common,3434+ const u8 *fw,3535+ u32 len,3636+ u32 num_blocks)3737+{3838+ struct rsi_hw *adapter = common->priv;3939+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;4040+ u32 indx, ii;4141+ u32 block_size = dev->tx_blk_size;4242+ u32 lsb_address;4343+ u32 base_address;4444+4545+ base_address = TA_LOAD_ADDRESS;4646+4747+ for (indx = 0, ii = 0; ii < num_blocks; ii++, indx += block_size) {4848+ lsb_address = base_address;4949+ if (rsi_usb_write_register_multiple(adapter,5050+ lsb_address,5151+ (u8 *)(fw + indx),5252+ block_size)) {5353+ rsi_dbg(ERR_ZONE,5454+ "%s: Unable to load %s blk\n", __func__,5555+ FIRMWARE_RSI9113);5656+ return -EIO;5757+ }5858+ rsi_dbg(INIT_ZONE, "%s: loading block: %d\n", __func__, ii);5959+ base_address += block_size;6060+ }6161+6262+ if (len % block_size) {6363+ lsb_address = base_address;6464+ if (rsi_usb_write_register_multiple(adapter,6565+ lsb_address,6666+ (u8 *)(fw + indx),6767+ len % block_size)) {6868+ rsi_dbg(ERR_ZONE,6969+ "%s: Unable to load %s blk\n", __func__,7070+ FIRMWARE_RSI9113);7171+ return -EIO;7272+ }7373+ }7474+ rsi_dbg(INIT_ZONE,7575+ "%s: Succesfully loaded %s instructions\n", __func__,7676+ FIRMWARE_RSI9113);7777+7878+ rsi_dbg(INIT_ZONE, "%s: loaded firmware\n", __func__);7979+ return 0;8080+}8181+8282+/**8383+ * rsi_usb_rx_thread() - This is a kernel thread to receive the packets from8484+ * the USB device.8585+ * @common: Pointer to the driver private structure.8686+ *8787+ * Return: None.8888+ */8989+void rsi_usb_rx_thread(struct rsi_common *common)9090+{9191+ struct rsi_hw *adapter = common->priv;9292+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;9393+ int status;9494+9595+ do {9696+ rsi_wait_event(&dev->rx_thread.event, EVENT_WAIT_FOREVER);9797+9898+ if (atomic_read(&dev->rx_thread.thread_done))9999+ goto out;100100+101101+ mutex_lock(&common->tx_rxlock);102102+ status = rsi_read_pkt(common, 0);103103+ if (status) {104104+ rsi_dbg(ERR_ZONE, "%s: Failed To read data", __func__);105105+ mutex_unlock(&common->tx_rxlock);106106+ return;107107+ }108108+ mutex_unlock(&common->tx_rxlock);109109+ rsi_reset_event(&dev->rx_thread.event);110110+ if (adapter->rx_urb_submit(adapter)) {111111+ rsi_dbg(ERR_ZONE,112112+ "%s: Failed in urb submission", __func__);113113+ return;114114+ }115115+ } while (1);116116+117117+out:118118+ rsi_dbg(INFO_ZONE, "%s: Terminated thread\n", __func__);119119+ complete_and_exit(&dev->rx_thread.completion, 0);120120+}121121+122122+123123+/**124124+ * rsi_load_ta_instructions() - This function includes the actual funtionality125125+ * of loading the TA firmware.This function also126126+ * includes opening the TA file,reading the TA127127+ * file and writing their value in blocks of data.128128+ * @common: Pointer to the driver private structure.129129+ *130130+ * Return: status: 0 on success, -1 on failure.131131+ */132132+static int rsi_load_ta_instructions(struct rsi_common *common)133133+{134134+ struct rsi_hw *adapter = common->priv;135135+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;136136+ const struct firmware *fw_entry = NULL;137137+ u32 block_size = dev->tx_blk_size;138138+ const u8 *fw;139139+ u32 num_blocks, len;140140+ int status = 0;141141+142142+ status = request_firmware(&fw_entry, FIRMWARE_RSI9113, adapter->device);143143+ if (status < 0) {144144+ rsi_dbg(ERR_ZONE, "%s Firmware file %s not found\n",145145+ __func__, FIRMWARE_RSI9113);146146+ return status;147147+ }148148+149149+ fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);150150+ len = fw_entry->size;151151+152152+ if (len % 4)153153+ len += (4 - (len % 4));154154+155155+ num_blocks = (len / block_size);156156+157157+ rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);158158+ rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);159159+160160+ status = rsi_copy_to_card(common, fw, len, num_blocks);161161+ release_firmware(fw_entry);162162+ return status;163163+}164164+165165+/**166166+ * rsi_device_init() - This Function Initializes The HAL.167167+ * @common: Pointer to the driver private structure.168168+ *169169+ * Return: 0 on success, -1 on failure.170170+ */171171+int rsi_usb_device_init(struct rsi_common *common)172172+{173173+ if (rsi_load_ta_instructions(common))174174+ return -EIO;175175+176176+ return 0;177177+ }
+126
drivers/net/wireless/rsi/rsi_boot_params.h
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#ifndef __RSI_BOOTPARAMS_HEADER_H__1818+#define __RSI_BOOTPARAMS_HEADER_H__1919+2020+#define CRYSTAL_GOOD_TIME BIT(0)2121+#define BOOTUP_MODE_INFO BIT(1)2222+#define WIFI_TAPLL_CONFIGS BIT(5)2323+#define WIFI_PLL960_CONFIGS BIT(6)2424+#define WIFI_AFEPLL_CONFIGS BIT(7)2525+#define WIFI_SWITCH_CLK_CONFIGS BIT(8)2626+2727+#define TA_PLL_M_VAL_20 82828+#define TA_PLL_N_VAL_20 12929+#define TA_PLL_P_VAL_20 43030+3131+#define PLL960_M_VAL_20 0x143232+#define PLL960_N_VAL_20 03333+#define PLL960_P_VAL_20 53434+3535+#define UMAC_CLK_40MHZ 403636+3737+#define TA_PLL_M_VAL_40 463838+#define TA_PLL_N_VAL_40 33939+#define TA_PLL_P_VAL_40 34040+4141+#define PLL960_M_VAL_40 0x144242+#define PLL960_N_VAL_40 04343+#define PLL960_P_VAL_40 54444+4545+#define UMAC_CLK_20BW \4646+ (((TA_PLL_M_VAL_20 + 1) * 40) / \4747+ ((TA_PLL_N_VAL_20 + 1) * (TA_PLL_P_VAL_20 + 1)))4848+#define VALID_20 \4949+ (WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS)5050+#define UMAC_CLK_40BW \5151+ (((TA_PLL_M_VAL_40 + 1) * 40) / \5252+ ((TA_PLL_N_VAL_40 + 1) * (TA_PLL_P_VAL_40 + 1)))5353+#define VALID_40 \5454+ (WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS | \5555+ WIFI_TAPLL_CONFIGS | CRYSTAL_GOOD_TIME | BOOTUP_MODE_INFO)5656+5757+/* structure to store configs related to TAPLL programming */5858+struct tapll_info {5959+ __le16 pll_reg_1;6060+ __le16 pll_reg_2;6161+} __packed;6262+6363+/* structure to store configs related to PLL960 programming */6464+struct pll960_info {6565+ __le16 pll_reg_1;6666+ __le16 pll_reg_2;6767+ __le16 pll_reg_3;6868+} __packed;6969+7070+/* structure to store configs related to AFEPLL programming */7171+struct afepll_info {7272+ __le16 pll_reg;7373+} __packed;7474+7575+/* structure to store configs related to pll configs */7676+struct pll_config {7777+ struct tapll_info tapll_info_g;7878+ struct pll960_info pll960_info_g;7979+ struct afepll_info afepll_info_g;8080+} __packed;8181+8282+/* structure to store configs related to UMAC clk programming */8383+struct switch_clk {8484+ __le16 switch_clk_info;8585+ /* If switch_bbp_lmac_clk_reg is set then this value will be programmed8686+ * into reg8787+ */8888+ __le16 bbp_lmac_clk_reg_val;8989+ /* if switch_umac_clk is set then this value will be programmed */9090+ __le16 umac_clock_reg_config;9191+ /* if switch_qspi_clk is set then this value will be programmed */9292+ __le16 qspi_uart_clock_reg_config;9393+} __packed;9494+9595+struct device_clk_info {9696+ struct pll_config pll_config_g;9797+ struct switch_clk switch_clk_g;9898+} __packed;9999+100100+struct bootup_params {101101+ __le16 magic_number;102102+ __le16 crystal_good_time;103103+ __le32 valid;104104+ __le32 reserved_for_valids;105105+ __le16 bootup_mode_info;106106+ /* configuration used for digital loop back */107107+ __le16 digital_loop_back_params;108108+ __le16 rtls_timestamp_en;109109+ __le16 host_spi_intr_cfg;110110+ struct device_clk_info device_clk_info[3];111111+ /* ulp buckboost wait time */112112+ __le32 buckboost_wakeup_cnt;113113+ /* pmu wakeup wait time & WDT EN info */114114+ __le16 pmu_wakeup_wait;115115+ u8 shutdown_wait_time;116116+ /* Sleep clock source selection */117117+ u8 pmu_slp_clkout_sel;118118+ /* WDT programming values */119119+ __le32 wdt_prog_value;120120+ /* WDT soc reset delay */121121+ __le32 wdt_soc_rst_delay;122122+ /* dcdc modes configs */123123+ __le32 dcdc_operation_mode;124124+ __le32 soc_reset_wait_cnt;125125+} __packed;126126+#endif
+87
drivers/net/wireless/rsi/rsi_common.h
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#ifndef __RSI_COMMON_H__1818+#define __RSI_COMMON_H__1919+2020+#include <linux/kthread.h>2121+2222+#define EVENT_WAIT_FOREVER 02323+#define TA_LOAD_ADDRESS 0x002424+#define FIRMWARE_RSI9113 "rsi_91x.fw"2525+#define QUEUE_NOT_FULL 12626+#define QUEUE_FULL 02727+2828+static inline int rsi_init_event(struct rsi_event *pevent)2929+{3030+ atomic_set(&pevent->event_condition, 1);3131+ init_waitqueue_head(&pevent->event_queue);3232+ return 0;3333+}3434+3535+static inline int rsi_wait_event(struct rsi_event *event, u32 timeout)3636+{3737+ int status = 0;3838+3939+ if (!timeout)4040+ status = wait_event_interruptible(event->event_queue,4141+ (atomic_read(&event->event_condition) == 0));4242+ else4343+ status = wait_event_interruptible_timeout(event->event_queue,4444+ (atomic_read(&event->event_condition) == 0),4545+ timeout);4646+ return status;4747+}4848+4949+static inline void rsi_set_event(struct rsi_event *event)5050+{5151+ atomic_set(&event->event_condition, 0);5252+ wake_up_interruptible(&event->event_queue);5353+}5454+5555+static inline void rsi_reset_event(struct rsi_event *event)5656+{5757+ atomic_set(&event->event_condition, 1);5858+}5959+6060+static inline int rsi_create_kthread(struct rsi_common *common,6161+ struct rsi_thread *thread,6262+ void *func_ptr,6363+ u8 *name)6464+{6565+ init_completion(&thread->completion);6666+ thread->task = kthread_run(func_ptr, common, name);6767+ if (IS_ERR(thread->task))6868+ return (int)PTR_ERR(thread->task);6969+7070+ return 0;7171+}7272+7373+static inline int rsi_kill_thread(struct rsi_thread *handle)7474+{7575+ atomic_inc(&handle->thread_done);7676+ rsi_set_event(&handle->event);7777+7878+ wait_for_completion(&handle->completion);7979+ return kthread_stop(handle->task);8080+}8181+8282+void rsi_mac80211_detach(struct rsi_hw *hw);8383+u16 rsi_get_connected_channel(struct rsi_hw *adapter);8484+struct rsi_hw *rsi_91x_init(void);8585+void rsi_91x_deinit(struct rsi_hw *adapter);8686+int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len);8787+#endif
+48
drivers/net/wireless/rsi/rsi_debugfs.h
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#ifndef __RSI_DEBUGFS_H__1818+#define __RSI_DEBUGFS_H__1919+2020+#include "rsi_main.h"2121+#include <linux/debugfs.h>2222+2323+#ifndef CONFIG_RSI_DEBUGFS2424+static inline int rsi_init_dbgfs(struct rsi_hw *adapter)2525+{2626+ return 0;2727+}2828+2929+static inline void rsi_remove_dbgfs(struct rsi_hw *adapter)3030+{3131+ return;3232+}3333+#else3434+struct rsi_dbg_files {3535+ const char *name;3636+ umode_t perms;3737+ const struct file_operations fops;3838+};3939+4040+struct rsi_debugfs {4141+ struct dentry *subdir;4242+ struct rsi_dbg_ops *dfs_get_ops;4343+ struct dentry *rsi_files[MAX_DEBUGFS_ENTRIES];4444+};4545+int rsi_init_dbgfs(struct rsi_hw *adapter);4646+void rsi_remove_dbgfs(struct rsi_hw *adapter);4747+#endif4848+#endif
+232
drivers/net/wireless/rsi/rsi_main.h
···11+/**22+ * Copyright (c) 2014 Redpine Signals Inc.33+ *44+ * Permission to use, copy, modify, and/or distribute this software for any55+ * purpose with or without fee is hereby granted, provided that the above66+ * copyright notice and this permission notice appear in all copies.77+ *88+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES99+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1010+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1111+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1212+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1313+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1414+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1515+ */1616+1717+#ifndef __RSI_MAIN_H__1818+#define __RSI_MAIN_H__1919+2020+#include <linux/string.h>2121+#include <linux/skbuff.h>2222+#include <net/mac80211.h>2323+2424+#define ERR_ZONE BIT(0) /* For Error Msgs */2525+#define INFO_ZONE BIT(1) /* For General Status Msgs */2626+#define INIT_ZONE BIT(2) /* For Driver Init Seq Msgs */2727+#define MGMT_TX_ZONE BIT(3) /* For TX Mgmt Path Msgs */2828+#define MGMT_RX_ZONE BIT(4) /* For RX Mgmt Path Msgs */2929+#define DATA_TX_ZONE BIT(5) /* For TX Data Path Msgs */3030+#define DATA_RX_ZONE BIT(6) /* For RX Data Path Msgs */3131+#define FSM_ZONE BIT(7) /* For State Machine Msgs */3232+#define ISR_ZONE BIT(8) /* For Interrupt Msgs */3333+3434+#define FSM_CARD_NOT_READY 03535+#define FSM_BOOT_PARAMS_SENT 13636+#define FSM_EEPROM_READ_MAC_ADDR 23737+#define FSM_RESET_MAC_SENT 33838+#define FSM_RADIO_CAPS_SENT 43939+#define FSM_BB_RF_PROG_SENT 54040+#define FSM_MAC_INIT_DONE 64141+4242+extern u32 rsi_zone_enabled;4343+4444+static inline void rsi_dbg(u32 zone, const char *fmt, ...)4545+{4646+ struct va_format vaf;4747+ va_list args;4848+4949+ va_start(args, fmt);5050+5151+ vaf.fmt = fmt;5252+ vaf.va = &args;5353+5454+ if (zone & rsi_zone_enabled)5555+ pr_info("%pV", &vaf);5656+ va_end(args);5757+}5858+5959+#define RSI_MAX_VIFS 16060+#define NUM_EDCA_QUEUES 46161+#define IEEE80211_ADDR_LEN 66262+#define FRAME_DESC_SZ 166363+#define MIN_802_11_HDR_LEN 246464+6565+#define DATA_QUEUE_WATER_MARK 4006666+#define MIN_DATA_QUEUE_WATER_MARK 3006767+#define MULTICAST_WATER_MARK 2006868+#define MAC_80211_HDR_FRAME_CONTROL 06969+#define WME_NUM_AC 47070+#define NUM_SOFT_QUEUES 57171+#define MAX_HW_QUEUES 87272+#define INVALID_QUEUE 0xff7373+#define MAX_CONTINUOUS_VO_PKTS 87474+#define MAX_CONTINUOUS_VI_PKTS 47575+7676+/* Queue information */7777+#define RSI_WIFI_MGMT_Q 0x47878+#define RSI_WIFI_DATA_Q 0x57979+#define IEEE80211_MGMT_FRAME 0x008080+#define IEEE80211_CTL_FRAME 0x048181+8282+#define IEEE80211_QOS_TID 0x0f8383+#define IEEE80211_NONQOS_TID 168484+8585+#define MAX_DEBUGFS_ENTRIES 48686+8787+#define TID_TO_WME_AC(_tid) ( \8888+ ((_tid) == 0 || (_tid) == 3) ? BE_Q : \8989+ ((_tid) < 3) ? BK_Q : \9090+ ((_tid) < 6) ? VI_Q : \9191+ VO_Q)9292+9393+#define WME_AC(_q) ( \9494+ ((_q) == BK_Q) ? IEEE80211_AC_BK : \9595+ ((_q) == BE_Q) ? IEEE80211_AC_BE : \9696+ ((_q) == VI_Q) ? IEEE80211_AC_VI : \9797+ IEEE80211_AC_VO)9898+9999+struct version_info {100100+ u16 major;101101+ u16 minor;102102+ u16 release_num;103103+ u16 patch_num;104104+} __packed;105105+106106+struct skb_info {107107+ s8 rssi;108108+ u32 flags;109109+ u16 channel;110110+ s8 tid;111111+ s8 sta_id;112112+};113113+114114+enum edca_queue {115115+ BK_Q,116116+ BE_Q,117117+ VI_Q,118118+ VO_Q,119119+ MGMT_SOFT_Q120120+};121121+122122+struct security_info {123123+ bool security_enable;124124+ u32 ptk_cipher;125125+ u32 gtk_cipher;126126+};127127+128128+struct wmm_qinfo {129129+ s32 weight;130130+ s32 wme_params;131131+ s32 pkt_contended;132132+};133133+134134+struct transmit_q_stats {135135+ u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 1];136136+ u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 1];137137+};138138+139139+struct vif_priv {140140+ bool is_ht;141141+ bool sgi;142142+ u16 seq_start;143143+};144144+145145+struct rsi_event {146146+ atomic_t event_condition;147147+ wait_queue_head_t event_queue;148148+};149149+150150+struct rsi_thread {151151+ void (*thread_function)(void *);152152+ struct completion completion;153153+ struct task_struct *task;154154+ struct rsi_event event;155155+ atomic_t thread_done;156156+};157157+158158+struct rsi_hw;159159+160160+struct rsi_common {161161+ struct rsi_hw *priv;162162+ struct vif_priv vif_info[RSI_MAX_VIFS];163163+164164+ bool mgmt_q_block;165165+ struct version_info driver_ver;166166+ struct version_info fw_ver;167167+168168+ struct rsi_thread tx_thread;169169+ struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 1];170170+ /* Mutex declaration */171171+ struct mutex mutex;172172+ /* Mutex used between tx/rx threads */173173+ struct mutex tx_rxlock;174174+ u8 endpoint;175175+176176+ /* Channel/band related */177177+ u8 band;178178+ u8 channel_width;179179+180180+ u16 rts_threshold;181181+ u16 bitrate_mask[2];182182+ u32 fixedrate_mask[2];183183+184184+ u8 rf_reset;185185+ struct transmit_q_stats tx_stats;186186+ struct security_info secinfo;187187+ struct wmm_qinfo tx_qinfo[NUM_EDCA_QUEUES];188188+ struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];189189+ u8 mac_addr[IEEE80211_ADDR_LEN];190190+191191+ /* state related */192192+ u32 fsm_state;193193+ bool init_done;194194+ u8 bb_rf_prog_count;195195+ bool iface_down;196196+197197+ /* Generic */198198+ u8 channel;199199+ u8 *rx_data_pkt;200200+ u8 mac_id;201201+ u8 radio_id;202202+ u16 rate_pwr[20];203203+ u16 min_rate;204204+205205+ /* WMM algo related */206206+ u8 selected_qnum;207207+ u32 pkt_cnt;208208+ u8 min_weight;209209+};210210+211211+struct rsi_hw {212212+ struct rsi_common *priv;213213+ struct ieee80211_hw *hw;214214+ struct ieee80211_vif *vifs[RSI_MAX_VIFS];215215+ struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];216216+ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];217217+218218+ struct device *device;219219+ u8 sc_nvifs;220220+221221+#ifdef CONFIG_RSI_DEBUGFS222222+ struct rsi_debugfs *dfsentry;223223+ u8 num_debugfs_entries;224224+#endif225225+ void *rsi_dev;226226+ int (*host_intf_read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);227227+ int (*host_intf_write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);228228+ int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);229229+ int (*rx_urb_submit)(struct rsi_hw *adapter);230230+ int (*determine_event_timeout)(struct rsi_hw *adapter);231231+};232232+#endif
···11+/**22+ * @section LICENSE33+ * Copyright (c) 2014 Redpine Signals Inc.44+ *55+ * Permission to use, copy, modify, and/or distribute this software for any66+ * purpose with or without fee is hereby granted, provided that the above77+ * copyright notice and this permission notice appear in all copies.88+ *99+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES1010+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1111+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1212+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1313+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1414+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1515+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1616+ *1717+ */1818+1919+#ifndef __RSI_SDIO_INTF__2020+#define __RSI_SDIO_INTF__2121+2222+#include <linux/mmc/card.h>2323+#include <linux/mmc/mmc.h>2424+#include <linux/mmc/host.h>2525+#include <linux/mmc/sdio_func.h>2626+#include <linux/mmc/sdio.h>2727+#include <linux/mmc/sd.h>2828+#include <linux/mmc/sdio_ids.h>2929+#include "rsi_main.h"3030+3131+enum sdio_interrupt_type {3232+ BUFFER_FULL = 0x0,3333+ BUFFER_AVAILABLE = 0x1,3434+ FIRMWARE_ASSERT_IND = 0x3,3535+ MSDU_PACKET_PENDING = 0x4,3636+ UNKNOWN_INT = 0XE3737+};3838+3939+/* Buffer status register related info */4040+#define PKT_BUFF_SEMI_FULL 04141+#define PKT_BUFF_FULL 14242+#define PKT_MGMT_BUFF_FULL 24343+#define MSDU_PKT_PENDING 34444+/* Interrupt Bit Related Macros */4545+#define PKT_BUFF_AVAILABLE 04646+#define FW_ASSERT_IND 24747+4848+#define RSI_DEVICE_BUFFER_STATUS_REGISTER 0xf34949+#define RSI_FN1_INT_REGISTER 0xf95050+#define RSI_SD_REQUEST_MASTER 0x100005151+5252+/* FOR SD CARD ONLY */5353+#define SDIO_RX_NUM_BLOCKS_REG 0x000F15454+#define SDIO_FW_STATUS_REG 0x000F25555+#define SDIO_NXT_RD_DELAY2 0x000F55656+#define SDIO_MASTER_ACCESS_MSBYTE 0x000FA5757+#define SDIO_MASTER_ACCESS_LSBYTE 0x000FB5858+#define SDIO_READ_START_LVL 0x000FC5959+#define SDIO_READ_FIFO_CTL 0x000FD6060+#define SDIO_WRITE_FIFO_CTL 0x000FE6161+#define SDIO_FUN1_INTR_CLR_REG 0x00086262+#define SDIO_REG_HIGH_SPEED 0x00136363+6464+#define RSI_GET_SDIO_INTERRUPT_TYPE(_I, TYPE) \6565+ { \6666+ TYPE = \6767+ (_I & (1 << PKT_BUFF_AVAILABLE)) ? \6868+ BUFFER_AVAILABLE : \6969+ (_I & (1 << MSDU_PKT_PENDING)) ? \7070+ MSDU_PACKET_PENDING : \7171+ (_I & (1 << FW_ASSERT_IND)) ? \7272+ FIRMWARE_ASSERT_IND : UNKNOWN_INT; \7373+ }7474+7575+/* common registers in SDIO function1 */7676+#define TA_SOFT_RESET_REG 0x00047777+#define TA_TH0_PC_REG 0x04007878+#define TA_HOLD_THREAD_REG 0x08447979+#define TA_RELEASE_THREAD_REG 0x08488080+8181+#define TA_SOFT_RST_CLR 08282+#define TA_SOFT_RST_SET BIT(0)8383+#define TA_PC_ZERO 08484+#define TA_HOLD_THREAD_VALUE cpu_to_le32(0xF)8585+#define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF)8686+#define TA_BASE_ADDR 0x22008787+#define MISC_CFG_BASE_ADDR 0x41508888+8989+struct receive_info {9090+ bool buffer_full;9191+ bool semi_buffer_full;9292+ bool mgmt_buffer_full;9393+ u32 mgmt_buf_full_counter;9494+ u32 buf_semi_full_counter;9595+ u8 watch_bufferfull_count;9696+ u32 sdio_intr_status_zero;9797+ u32 sdio_int_counter;9898+ u32 total_sdio_msdu_pending_intr;9999+ u32 total_sdio_unknown_intr;100100+ u32 buf_full_counter;101101+ u32 buf_avilable_counter;102102+};103103+104104+struct rsi_91x_sdiodev {105105+ struct sdio_func *pfunction;106106+ struct task_struct *in_sdio_litefi_irq;107107+ struct receive_info rx_info;108108+ u32 next_read_delay;109109+ u32 sdio_high_speed_enable;110110+ u8 sdio_clock_speed;111111+ u32 cardcapability;112112+ u8 prev_desc[16];113113+ u32 tx_blk_size;114114+ u8 write_fail;115115+};116116+117117+void rsi_interrupt_handler(struct rsi_hw *adapter);118118+int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);119119+int rsi_sdio_device_init(struct rsi_common *common);120120+int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);121121+int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);122122+int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,123123+ u32 addr, u8 *data);124124+int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,125125+ u8 *data, u32 count);126126+void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);127127+int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);128128+int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);129129+#endif
+68
drivers/net/wireless/rsi/rsi_usb.h
···11+/**22+ * @section LICENSE33+ * Copyright (c) 2014 Redpine Signals Inc.44+ *55+ * Permission to use, copy, modify, and/or distribute this software for any66+ * purpose with or without fee is hereby granted, provided that the above77+ * copyright notice and this permission notice appear in all copies.88+ *99+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES1010+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF1111+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR1212+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES1313+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN1414+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF1515+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.1616+ */1717+1818+#ifndef __RSI_USB_INTF__1919+#define __RSI_USB_INTF__2020+2121+#include <linux/usb.h>2222+#include "rsi_main.h"2323+#include "rsi_common.h"2424+2525+#define USB_INTERNAL_REG_1 0x250002626+#define RSI_USB_READY_MAGIC_NUM 0xab2727+#define FW_STATUS_REG 0x410500122828+2929+#define USB_VENDOR_REGISTER_READ 0x153030+#define USB_VENDOR_REGISTER_WRITE 0x163131+#define RSI_USB_TX_HEAD_ROOM 1283232+3333+#define MAX_RX_URBS 13434+#define MAX_BULK_EP 83535+#define MGMT_EP 13636+#define DATA_EP 23737+3838+struct rsi_91x_usbdev {3939+ struct rsi_thread rx_thread;4040+ u8 endpoint;4141+ struct usb_device *usbdev;4242+ struct usb_interface *pfunction;4343+ struct urb *rx_usb_urb[MAX_RX_URBS];4444+ u8 *tx_buffer;4545+ __le16 bulkin_size;4646+ u8 bulkin_endpoint_addr;4747+ __le16 bulkout_size[MAX_BULK_EP];4848+ u8 bulkout_endpoint_addr[MAX_BULK_EP];4949+ u32 tx_blk_size;5050+ u8 write_fail;5151+};5252+5353+static inline int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num)5454+{5555+ /* In USB, there isn't any need to check the queue status */5656+ return QUEUE_NOT_FULL;5757+}5858+5959+static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)6060+{6161+ return EVENT_WAIT_FOREVER;6262+}6363+6464+int rsi_usb_device_init(struct rsi_common *common);6565+int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,6666+ u8 *data, u32 count);6767+void rsi_usb_rx_thread(struct rsi_common *common);6868+#endif