162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * O(1) TX queue with built-in allocator for ST-Ericsson CW1200 drivers 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2010, ST-Ericsson 662306a36Sopenharmony_ci * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef CW1200_QUEUE_H_INCLUDED 1062306a36Sopenharmony_ci#define CW1200_QUEUE_H_INCLUDED 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* private */ struct cw1200_queue_item; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* extern */ struct sk_buff; 1562306a36Sopenharmony_ci/* extern */ struct wsm_tx; 1662306a36Sopenharmony_ci/* extern */ struct cw1200_common; 1762306a36Sopenharmony_ci/* extern */ struct ieee80211_tx_queue_stats; 1862306a36Sopenharmony_ci/* extern */ struct cw1200_txpriv; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* forward */ struct cw1200_queue_stats; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_citypedef void (*cw1200_queue_skb_dtor_t)(struct cw1200_common *priv, 2362306a36Sopenharmony_ci struct sk_buff *skb, 2462306a36Sopenharmony_ci const struct cw1200_txpriv *txpriv); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct cw1200_queue { 2762306a36Sopenharmony_ci struct cw1200_queue_stats *stats; 2862306a36Sopenharmony_ci size_t capacity; 2962306a36Sopenharmony_ci size_t num_queued; 3062306a36Sopenharmony_ci size_t num_pending; 3162306a36Sopenharmony_ci size_t num_sent; 3262306a36Sopenharmony_ci struct cw1200_queue_item *pool; 3362306a36Sopenharmony_ci struct list_head queue; 3462306a36Sopenharmony_ci struct list_head free_pool; 3562306a36Sopenharmony_ci struct list_head pending; 3662306a36Sopenharmony_ci int tx_locked_cnt; 3762306a36Sopenharmony_ci int *link_map_cache; 3862306a36Sopenharmony_ci bool overfull; 3962306a36Sopenharmony_ci spinlock_t lock; /* Protect queue entry */ 4062306a36Sopenharmony_ci u8 queue_id; 4162306a36Sopenharmony_ci u8 generation; 4262306a36Sopenharmony_ci struct timer_list gc; 4362306a36Sopenharmony_ci unsigned long ttl; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct cw1200_queue_stats { 4762306a36Sopenharmony_ci spinlock_t lock; /* Protect stats entry */ 4862306a36Sopenharmony_ci int *link_map_cache; 4962306a36Sopenharmony_ci int num_queued; 5062306a36Sopenharmony_ci size_t map_capacity; 5162306a36Sopenharmony_ci wait_queue_head_t wait_link_id_empty; 5262306a36Sopenharmony_ci cw1200_queue_skb_dtor_t skb_dtor; 5362306a36Sopenharmony_ci struct cw1200_common *priv; 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistruct cw1200_txpriv { 5762306a36Sopenharmony_ci u8 link_id; 5862306a36Sopenharmony_ci u8 raw_link_id; 5962306a36Sopenharmony_ci u8 tid; 6062306a36Sopenharmony_ci u8 rate_id; 6162306a36Sopenharmony_ci u8 offset; 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciint cw1200_queue_stats_init(struct cw1200_queue_stats *stats, 6562306a36Sopenharmony_ci size_t map_capacity, 6662306a36Sopenharmony_ci cw1200_queue_skb_dtor_t skb_dtor, 6762306a36Sopenharmony_ci struct cw1200_common *priv); 6862306a36Sopenharmony_ciint cw1200_queue_init(struct cw1200_queue *queue, 6962306a36Sopenharmony_ci struct cw1200_queue_stats *stats, 7062306a36Sopenharmony_ci u8 queue_id, 7162306a36Sopenharmony_ci size_t capacity, 7262306a36Sopenharmony_ci unsigned long ttl); 7362306a36Sopenharmony_ciint cw1200_queue_clear(struct cw1200_queue *queue); 7462306a36Sopenharmony_civoid cw1200_queue_stats_deinit(struct cw1200_queue_stats *stats); 7562306a36Sopenharmony_civoid cw1200_queue_deinit(struct cw1200_queue *queue); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cisize_t cw1200_queue_get_num_queued(struct cw1200_queue *queue, 7862306a36Sopenharmony_ci u32 link_id_map); 7962306a36Sopenharmony_ciint cw1200_queue_put(struct cw1200_queue *queue, 8062306a36Sopenharmony_ci struct sk_buff *skb, 8162306a36Sopenharmony_ci struct cw1200_txpriv *txpriv); 8262306a36Sopenharmony_ciint cw1200_queue_get(struct cw1200_queue *queue, 8362306a36Sopenharmony_ci u32 link_id_map, 8462306a36Sopenharmony_ci struct wsm_tx **tx, 8562306a36Sopenharmony_ci struct ieee80211_tx_info **tx_info, 8662306a36Sopenharmony_ci const struct cw1200_txpriv **txpriv); 8762306a36Sopenharmony_ciint cw1200_queue_requeue(struct cw1200_queue *queue, u32 packet_id); 8862306a36Sopenharmony_ciint cw1200_queue_requeue_all(struct cw1200_queue *queue); 8962306a36Sopenharmony_ciint cw1200_queue_remove(struct cw1200_queue *queue, 9062306a36Sopenharmony_ci u32 packet_id); 9162306a36Sopenharmony_ciint cw1200_queue_get_skb(struct cw1200_queue *queue, u32 packet_id, 9262306a36Sopenharmony_ci struct sk_buff **skb, 9362306a36Sopenharmony_ci const struct cw1200_txpriv **txpriv); 9462306a36Sopenharmony_civoid cw1200_queue_lock(struct cw1200_queue *queue); 9562306a36Sopenharmony_civoid cw1200_queue_unlock(struct cw1200_queue *queue); 9662306a36Sopenharmony_cibool cw1200_queue_get_xmit_timestamp(struct cw1200_queue *queue, 9762306a36Sopenharmony_ci unsigned long *timestamp, 9862306a36Sopenharmony_ci u32 pending_frame_id); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cibool cw1200_queue_stats_is_empty(struct cw1200_queue_stats *stats, 10162306a36Sopenharmony_ci u32 link_id_map); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic inline u8 cw1200_queue_get_queue_id(u32 packet_id) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci return (packet_id >> 16) & 0xFF; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic inline u8 cw1200_queue_get_generation(u32 packet_id) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci return (packet_id >> 8) & 0xFF; 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#endif /* CW1200_QUEUE_H_INCLUDED */ 114