Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | /*
* Wireless Host Controller (WHC) private header.
*
* Copyright (C) 2007 Cambridge Silicon Radio Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __WHCD_H
#define __WHCD_H
#include <linux/uwb/whci.h>
#include <linux/uwb/umc.h>
#include <linux/workqueue.h>
#include "whci-hc.h"
/* Generic command timeout. */
#define WHC_GENCMD_TIMEOUT_MS 100
struct whc_dbg;
struct whc {
struct wusbhc wusbhc;
struct umc_dev *umc;
resource_size_t base_phys;
void __iomem *base;
int irq;
u8 n_devices;
u8 n_keys;
u8 n_mmc_ies;
u64 *pz_list;
struct dn_buf_entry *dn_buf;
struct di_buf_entry *di_buf;
dma_addr_t pz_list_dma;
dma_addr_t dn_buf_dma;
dma_addr_t di_buf_dma;
spinlock_t lock;
struct mutex mutex;
void * gen_cmd_buf;
dma_addr_t gen_cmd_buf_dma;
wait_queue_head_t cmd_wq;
struct workqueue_struct *workqueue;
struct work_struct dn_work;
struct dma_pool *qset_pool;
struct list_head async_list;
struct list_head async_removed_list;
wait_queue_head_t async_list_wq;
struct work_struct async_work;
struct list_head periodic_list[5];
struct list_head periodic_removed_list;
wait_queue_head_t periodic_list_wq;
struct work_struct periodic_work;
struct whc_dbg *dbg;
};
#define wusbhc_to_whc(w) (container_of((w), struct whc, wusbhc))
/**
* struct whc_std - a software TD.
* @urb: the URB this sTD is for.
* @offset: start of the URB's data for this TD.
* @len: the length of data in the associated TD.
* @ntds_remaining: number of TDs (starting from this one) in this transfer.
*
* @bounce_buf: a bounce buffer if the std was from an urb with a sg
* list that could not be mapped to qTDs directly.
* @bounce_sg: the first scatterlist element bounce_buf is for.
* @bounce_offset: the offset into bounce_sg for the start of bounce_buf.
*
* Queued URBs may require more TDs than are available in a qset so we
* use a list of these "software TDs" (sTDs) to hold per-TD data.
*/
struct whc_std {
struct urb *urb;
size_t len;
int ntds_remaining;
struct whc_qtd *qtd;
struct list_head list_node;
int num_pointers;
dma_addr_t dma_addr;
struct whc_page_list_entry *pl_virt;
void *bounce_buf;
struct scatterlist *bounce_sg;
unsigned bounce_offset;
};
/**
* struct whc_urb - per URB host controller structure.
* @urb: the URB this struct is for.
* @qset: the qset associated to the URB.
* @dequeue_work: the work to remove the URB when dequeued.
* @is_async: the URB belongs to async sheduler or not.
* @status: the status to be returned when calling wusbhc_giveback_urb.
*/
struct whc_urb {
struct urb *urb;
struct whc_qset *qset;
struct work_struct dequeue_work;
bool is_async;
int status;
};
/**
* whc_std_last - is this sTD the URB's last?
* @std: the sTD to check.
*/
static inline bool whc_std_last(struct whc_std *std)
{
return std->ntds_remaining <= 1;
}
enum whc_update {
WHC_UPDATE_ADDED = 0x01,
WHC_UPDATE_REMOVED = 0x02,
WHC_UPDATE_UPDATED = 0x04,
};
/* init.c */
int whc_init(struct whc *whc);
void whc_clean_up(struct whc *whc);
/* hw.c */
void whc_write_wusbcmd(struct whc *whc, u32 mask, u32 val);
int whc_do_gencmd(struct whc *whc, u32 cmd, u32 params, void *addr, size_t len);
void whc_hw_error(struct whc *whc, const char *reason);
/* wusb.c */
int whc_wusbhc_start(struct wusbhc *wusbhc);
void whc_wusbhc_stop(struct wusbhc *wusbhc, int delay);
int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
u8 handle, struct wuie_hdr *wuie);
int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle);
int whc_bwa_set(struct wusbhc *wusbhc, s8 stream_index, const struct uwb_mas_bm *mas_bm);
int whc_dev_info_set(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev);
int whc_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots);
int whc_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid,
const void *ptk, size_t key_size);
int whc_set_gtk(struct wusbhc *wusbhc, u32 tkid,
const void *gtk, size_t key_size);
int whc_set_cluster_id(struct whc *whc, u8 bcid);
/* int.c */
irqreturn_t whc_int_handler(struct usb_hcd *hcd);
void whc_dn_work(struct work_struct *work);
/* asl.c */
void asl_start(struct whc *whc);
void asl_stop(struct whc *whc);
int asl_init(struct whc *whc);
void asl_clean_up(struct whc *whc);
int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags);
int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status);
void asl_qset_delete(struct whc *whc, struct whc_qset *qset);
void scan_async_work(struct work_struct *work);
/* pzl.c */
int pzl_init(struct whc *whc);
void pzl_clean_up(struct whc *whc);
void pzl_start(struct whc *whc);
void pzl_stop(struct whc *whc);
int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags);
int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status);
void pzl_qset_delete(struct whc *whc, struct whc_qset *qset);
void scan_periodic_work(struct work_struct *work);
/* qset.c */
struct whc_qset *qset_alloc(struct whc *whc, gfp_t mem_flags);
void qset_free(struct whc *whc, struct whc_qset *qset);
struct whc_qset *get_qset(struct whc *whc, struct urb *urb, gfp_t mem_flags);
void qset_delete(struct whc *whc, struct whc_qset *qset);
void qset_clear(struct whc *whc, struct whc_qset *qset);
void qset_reset(struct whc *whc, struct whc_qset *qset);
int qset_add_urb(struct whc *whc, struct whc_qset *qset, struct urb *urb,
gfp_t mem_flags);
void qset_free_std(struct whc *whc, struct whc_std *std);
void qset_remove_urb(struct whc *whc, struct whc_qset *qset,
struct urb *urb, int status);
void process_halted_qtd(struct whc *whc, struct whc_qset *qset,
struct whc_qtd *qtd);
void process_inactive_qtd(struct whc *whc, struct whc_qset *qset,
struct whc_qtd *qtd);
enum whc_update qset_add_qtds(struct whc *whc, struct whc_qset *qset);
void qset_remove_complete(struct whc *whc, struct whc_qset *qset);
void pzl_update(struct whc *whc, uint32_t wusbcmd);
void asl_update(struct whc *whc, uint32_t wusbcmd);
/* debug.c */
void whc_dbg_init(struct whc *whc);
void whc_dbg_clean_up(struct whc *whc);
#endif /* #ifndef __WHCD_H */
|