Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iwl-trans.h
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * This file is provided under a dual BSD/GPLv2 license. When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * GPL LICENSE SUMMARY
7  *
8  * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of version 2 of the GNU General Public License as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22  * USA
23  *
24  * The full GNU General Public License is included in this distribution
25  * in the file called LICENSE.GPL.
26  *
27  * Contact Information:
28  * Intel Linux Wireless <[email protected]>
29  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30  *
31  * BSD LICENSE
32  *
33  * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
34  * All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  *
40  * * Redistributions of source code must retain the above copyright
41  * notice, this list of conditions and the following disclaimer.
42  * * Redistributions in binary form must reproduce the above copyright
43  * notice, this list of conditions and the following disclaimer in
44  * the documentation and/or other materials provided with the
45  * distribution.
46  * * Neither the name Intel Corporation nor the names of its
47  * contributors may be used to endorse or promote products derived
48  * from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61  *
62  *****************************************************************************/
63 #ifndef __iwl_trans_h__
64 #define __iwl_trans_h__
65 
66 #include <linux/ieee80211.h>
67 #include <linux/mm.h> /* for page_address */
68 
69 #include "iwl-debug.h"
70 #include "iwl-config.h"
71 #include "iwl-fw.h"
72 
116 #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
117 #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
118 #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
119 #define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
120 #define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
121 #define SEQ_TO_INDEX(s) ((s) & 0xff)
122 #define INDEX_TO_SEQ(i) ((i) & 0xff)
123 #define SEQ_RX_FRAME cpu_to_le16(0x8000)
124 
132  u8 cmd; /* Command ID: REPLY_RXON, etc. */
133  u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
134  /*
135  * The driver sets up the sequence number to values of its choosing.
136  * uCode does not use this value, but passes it back to the driver
137  * when sending the response to each driver-originated command, so
138  * the driver can match the response to the command. Since the values
139  * don't get used by uCode, the driver may set up an arbitrary format.
140  *
141  * There is one exception: uCode sets bit 15 when it originates
142  * the response/notification, i.e. when the response/notification
143  * is not a direct response to a command sent by the driver. For
144  * example, uCode issues REPLY_RX when it sends a received frame
145  * to the driver; it is not a direct response to any driver command.
146  *
147  * The Linux driver uses the following format:
148  *
149  * 0:7 tfd index - position within TX queue
150  * 8:12 TX queue id
151  * 13:14 reserved
152  * 15 unsolicited RX or uCode-originated notification
153  */
155 } __packed;
156 
157 /* iwl_cmd_header flags value */
158 #define IWL_CMD_FAILED_MSK 0x40
159 
160 
161 #define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
162 #define FH_RSCSR_FRAME_INVALID 0x55550000
163 #define FH_RSCSR_FRAME_ALIGN 0x40
164 
166  /*
167  * The first 4 bytes of the RX frame header contain both the RX frame
168  * size and some flags.
169  * Bit fields:
170  * 31: flag flush RB request
171  * 30: flag ignore TC (terminal counter) request
172  * 29: flag fast IRQ request
173  * 28-14: Reserved
174  * 13-00: RX frame size
175  */
178  u8 data[];
179 } __packed;
180 
195 enum CMD_MODE {
196  CMD_SYNC = 0,
201 };
202 
203 #define DEF_CMD_PAYLOAD_SIZE 320
204 
213  struct iwl_cmd_header hdr; /* uCode API */
215 } __packed;
216 
217 #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
218 
219 #define IWL_MAX_CMD_TFDS 2
220 
232 };
233 
248 struct iwl_host_cmd {
249  const void *data[IWL_MAX_CMD_TFDS];
251  unsigned long _rx_page_addr;
254 
259 };
260 
261 static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
262 {
264 }
265 
267  struct page *_page;
268  int _offset;
270  unsigned int truesize;
271 };
272 
273 static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
274 {
275  return (void *)((unsigned long)page_address(r->_page) + r->_offset);
276 }
277 
278 static inline int rxb_offset(struct iwl_rx_cmd_buffer *r)
279 {
280  return r->_offset;
281 }
282 
283 static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
284 {
285  r->_page_stolen = true;
286  get_page(r->_page);
287  return r->_page;
288 }
289 
290 #define MAX_NO_RECLAIM_CMDS 6
291 
292 #define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
293 
294 /*
295  * Maximum number of HW queues the transport layer
296  * currently supports
297  */
298 #define IWL_MAX_HW_QUEUES 32
299 #define IWL_INVALID_STATION 255
300 #define IWL_MAX_TID_COUNT 8
301 #define IWL_FRAME_LIMIT 64
302 
324 
329 
332  const char **command_names;
333 };
334 
335 struct iwl_trans;
336 
384 
386  void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
387  int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
390 
392 
393  int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
394 
395  int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
396  struct iwl_device_cmd *dev_cmd, int queue);
397  void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
398  struct sk_buff_head *skbs);
399 
400  void (*txq_enable)(struct iwl_trans *trans, int queue, int fifo,
401  int sta_id, int tid, int frame_limit, u16 ssn);
403 
404  int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
406 #ifdef CONFIG_PM_SLEEP
407  int (*suspend)(struct iwl_trans *trans);
408  int (*resume)(struct iwl_trans *trans);
409 #endif
410  void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
411  void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
412  u32 (*read32)(struct iwl_trans *trans, u32 ofs);
414  const struct iwl_trans_config *trans_cfg);
415  void (*set_pmi)(struct iwl_trans *trans, bool state);
416 };
417 
427 };
428 
448 struct iwl_trans {
449  const struct iwl_trans_ops *ops;
451  const struct iwl_cfg *cfg;
454 
455  struct device *dev;
458  char hw_id_str[52];
459 
461 
463 
464  /* The following fields are internal only */
468 
469  struct dentry *dbgfs_dir;
470 
471  /* pointer to trans specific struct */
472  /*Ensure that this pointer will always be aligned to sizeof pointer */
473  char trans_specific[0] __aligned(sizeof(void *));
474 };
475 
476 static inline void iwl_trans_configure(struct iwl_trans *trans,
477  const struct iwl_trans_config *trans_cfg)
478 {
479  /*
480  * only set the op_mode for the moment. Later on, this function will do
481  * more
482  */
483  trans->op_mode = trans_cfg->op_mode;
484 
485  trans->ops->configure(trans, trans_cfg);
486 }
487 
488 static inline int iwl_trans_start_hw(struct iwl_trans *trans)
489 {
490  might_sleep();
491 
492  return trans->ops->start_hw(trans);
493 }
494 
495 static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
496  bool op_mode_leaving)
497 {
498  might_sleep();
499 
500  trans->ops->stop_hw(trans, op_mode_leaving);
501 
502  trans->state = IWL_TRANS_NO_FW;
503 }
504 
505 static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
506 {
507  might_sleep();
508 
509  trans->state = IWL_TRANS_FW_ALIVE;
510 
511  trans->ops->fw_alive(trans);
512 }
513 
514 static inline int iwl_trans_start_fw(struct iwl_trans *trans,
515  const struct fw_img *fw)
516 {
517  might_sleep();
518 
519  return trans->ops->start_fw(trans, fw);
520 }
521 
522 static inline void iwl_trans_stop_device(struct iwl_trans *trans)
523 {
524  might_sleep();
525 
526  trans->ops->stop_device(trans);
527 
528  trans->state = IWL_TRANS_NO_FW;
529 }
530 
531 static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
532 {
533  might_sleep();
534  trans->ops->wowlan_suspend(trans);
535 }
536 
537 static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
538  struct iwl_host_cmd *cmd)
539 {
541  "%s bad state = %d", __func__, trans->state);
542 
543  return trans->ops->send_cmd(trans, cmd);
544 }
545 
546 static inline struct iwl_device_cmd *
547 iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
548 {
549  u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
550 
551  if (unlikely(dev_cmd_ptr == NULL))
552  return NULL;
553 
554  return (struct iwl_device_cmd *)
555  (dev_cmd_ptr + trans->dev_cmd_headroom);
556 }
557 
558 static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
559  struct iwl_device_cmd *dev_cmd)
560 {
561  u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom;
562 
563  kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr);
564 }
565 
566 static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
567  struct iwl_device_cmd *dev_cmd, int queue)
568 {
570  "%s bad state = %d", __func__, trans->state);
571 
572  return trans->ops->tx(trans, skb, dev_cmd, queue);
573 }
574 
575 static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
576  int ssn, struct sk_buff_head *skbs)
577 {
579  "%s bad state = %d", __func__, trans->state);
580 
581  trans->ops->reclaim(trans, queue, ssn, skbs);
582 }
583 
584 static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue)
585 {
587  "%s bad state = %d", __func__, trans->state);
588 
589  trans->ops->txq_disable(trans, queue);
590 }
591 
592 static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
593  int fifo, int sta_id, int tid,
594  int frame_limit, u16 ssn)
595 {
596  might_sleep();
597 
599  "%s bad state = %d", __func__, trans->state);
600 
601  trans->ops->txq_enable(trans, queue, fifo, sta_id, tid,
602  frame_limit, ssn);
603 }
604 
605 static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
606  int fifo)
607 {
608  iwl_trans_txq_enable(trans, queue, fifo, IWL_INVALID_STATION,
610 }
611 
612 static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
613 {
615  "%s bad state = %d", __func__, trans->state);
616 
617  return trans->ops->wait_tx_queue_empty(trans);
618 }
619 
620 static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
621  struct dentry *dir)
622 {
623  return trans->ops->dbgfs_register(trans, dir);
624 }
625 
626 #ifdef CONFIG_PM_SLEEP
627 static inline int iwl_trans_suspend(struct iwl_trans *trans)
628 {
629  return trans->ops->suspend(trans);
630 }
631 
632 static inline int iwl_trans_resume(struct iwl_trans *trans)
633 {
634  return trans->ops->resume(trans);
635 }
636 #endif
637 
638 static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
639 {
640  trans->ops->write8(trans, ofs, val);
641 }
642 
643 static inline void iwl_trans_write32(struct iwl_trans *trans, u32 ofs, u32 val)
644 {
645  trans->ops->write32(trans, ofs, val);
646 }
647 
648 static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
649 {
650  return trans->ops->read32(trans, ofs);
651 }
652 
653 static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
654 {
655  trans->ops->set_pmi(trans, state);
656 }
657 
658 /*****************************************************
659 * driver (transport) register/unregister functions
660 ******************************************************/
662 void iwl_pci_unregister_driver(void);
663 
664 #endif /* __iwl_trans_h__ */