Merge "ath10k: Add copy engine register MAP for wcn3990 wlan module"
This commit is contained in:
commit
71bbd5cfc9
4 changed files with 240 additions and 8 deletions
|
@ -266,7 +266,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
|
|||
*/
|
||||
int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void *per_transfer_context,
|
||||
u32 buffer,
|
||||
dma_addr_t buffer,
|
||||
unsigned int nbytes,
|
||||
unsigned int transfer_id,
|
||||
unsigned int flags)
|
||||
|
@ -349,7 +349,7 @@ void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe)
|
|||
|
||||
int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
|
||||
void *per_transfer_context,
|
||||
u32 buffer,
|
||||
dma_addr_t buffer,
|
||||
unsigned int nbytes,
|
||||
unsigned int transfer_id,
|
||||
unsigned int flags)
|
||||
|
@ -392,7 +392,8 @@ int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
|
|||
return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1);
|
||||
}
|
||||
|
||||
int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
||||
int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
|
||||
dma_addr_t paddr)
|
||||
{
|
||||
struct ath10k *ar = pipe->ar;
|
||||
struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
|
||||
|
@ -433,7 +434,8 @@ void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries)
|
|||
dest_ring->write_index = write_index;
|
||||
}
|
||||
|
||||
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
||||
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
|
||||
dma_addr_t paddr)
|
||||
{
|
||||
struct ath10k *ar = pipe->ar;
|
||||
int ret;
|
||||
|
|
|
@ -144,7 +144,7 @@ struct ce_attr;
|
|||
*/
|
||||
int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
|
||||
void *per_transfer_send_context,
|
||||
u32 buffer,
|
||||
dma_addr_t buffer,
|
||||
unsigned int nbytes,
|
||||
/* 14 bits */
|
||||
unsigned int transfer_id,
|
||||
|
@ -152,7 +152,7 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
|
|||
|
||||
int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void *per_transfer_context,
|
||||
u32 buffer,
|
||||
dma_addr_t buffer,
|
||||
unsigned int nbytes,
|
||||
unsigned int transfer_id,
|
||||
unsigned int flags);
|
||||
|
@ -164,8 +164,10 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
|
|||
/*==================Recv=======================*/
|
||||
|
||||
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
|
||||
int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
|
||||
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
|
||||
int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
|
||||
dma_addr_t paddr);
|
||||
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx,
|
||||
dma_addr_t paddr);
|
||||
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries);
|
||||
|
||||
/* recv flags */
|
||||
|
@ -263,6 +265,7 @@ struct ce_attr {
|
|||
void (*recv_cb)(struct ath10k_ce_pipe *);
|
||||
};
|
||||
|
||||
#ifndef CONFIG_ATH10K_SNOC
|
||||
#define SR_BA_ADDRESS 0x0000
|
||||
#define SR_SIZE_ADDRESS 0x0004
|
||||
#define DR_BA_ADDRESS 0x0008
|
||||
|
@ -383,6 +386,190 @@ struct ce_attr {
|
|||
#define DST_WATERMARK_HIGH_RESET 0
|
||||
#define DST_WATERMARK_ADDRESS 0x0050
|
||||
|
||||
#else
|
||||
#define WCN3990_CE0_SR_BA_LOW (0x00240000)
|
||||
#define WCN3990_CE1_SR_BA_LOW (0x00241000)
|
||||
#define WCN3990_CE2_SR_BA_LOW (0x00242000)
|
||||
#define WCN3990_CE3_SR_BA_LOW (0x00243000)
|
||||
#define WCN3990_CE4_SR_BA_LOW (0x00244000)
|
||||
#define WCN3990_CE5_SR_BA_LOW (0x00245000)
|
||||
#define WCN3990_CE6_SR_BA_LOW (0x00246000)
|
||||
#define WCN3990_CE7_SR_BA_LOW (0x00247000)
|
||||
#define WCN3990_CE8_SR_BA_LOW (0x00248000)
|
||||
#define WCN3990_CE9_SR_BA_LOW (0x00249000)
|
||||
#define WCN3990_CE10_SR_BA_LOW (0x0024A000)
|
||||
#define WCN3990_CE11_SR_BA_LOW (0x0024B000)
|
||||
#define WCN3990_CE0_DR_BA_LOW (0x0024000C)
|
||||
#define WNC3990_CE0_DR_SIZE (0x00240014)
|
||||
#define WCN3990_CE0_CE_CTRL1 (0x00240018)
|
||||
#define WCN3990_CE0_HOST_IE (0x0024002C)
|
||||
#define WCN3990_CE0_HOST_IS (0x00240030)
|
||||
#define WCN3990_CE0_MISC_IE (0x00240034)
|
||||
#define WCN3990_CE0_MISC_IS (0x00240038)
|
||||
#define WCN3990_CE0_SRC_WR_INDEX (0x0024003C)
|
||||
#define WCN3990_CE0_CURRENT_SRRI (0x00240044)
|
||||
#define WCN3990_CE0_CURRENT_DRRI (0x00240048)
|
||||
#define WCN3990_CE0_SRC_WATERMARK (0x0024004C)
|
||||
#define WCN3990_CE0_DST_WATERMARK (0x00240050)
|
||||
#define WCN3990_CE0_SR_SIZE (0x00240008)
|
||||
#define HOST_IE_COPY_COMPLETE_MASK (0x00000001)
|
||||
#define WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY 0x0024C000
|
||||
#define WCN3990_CE_WRAPPER_INDEX_BASE_LOW 0x0024C004
|
||||
#define WCN3990_CE_WRAPPER_INDEX_BASE_HIGH 0x0024C008
|
||||
#define CE_CTRL1_IDX_UPD_EN 0x00080000
|
||||
|
||||
#define WCN3990_CE_WRAPPER_BASE_ADDRESS \
|
||||
WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY
|
||||
#define WCN3990_CE0_BASE_ADDRESS \
|
||||
WCN3990_CE0_SR_BA_LOW
|
||||
#define WCN3990_CE1_BASE_ADDRESS \
|
||||
WCN3990_CE1_SR_BA_LOW
|
||||
#define WCN3990_CE2_BASE_ADDRESS \
|
||||
WCN3990_CE2_SR_BA_LOW
|
||||
#define WCN3990_CE3_BASE_ADDRESS \
|
||||
WCN3990_CE3_SR_BA_LOW
|
||||
#define WCN3990_CE4_BASE_ADDRESS \
|
||||
WCN3990_CE4_SR_BA_LOW
|
||||
#define WCN3990_CE5_BASE_ADDRESS \
|
||||
WCN3990_CE5_SR_BA_LOW
|
||||
#define WCN3990_CE6_BASE_ADDRESS \
|
||||
WCN3990_CE6_SR_BA_LOW
|
||||
#define WCN3990_CE7_BASE_ADDRESS \
|
||||
WCN3990_CE7_SR_BA_LOW
|
||||
#define WCN3990_CE8_BASE_ADDRESS \
|
||||
WCN3990_CE8_SR_BA_LOW
|
||||
#define WCN3990_CE9_BASE_ADDRESS \
|
||||
WCN3990_CE9_SR_BA_LOW
|
||||
#define WCN3990_CE10_BASE_ADDRESS \
|
||||
WCN3990_CE10_SR_BA_LOW
|
||||
#define WCN3990_CE11_BASE_ADDRESS \
|
||||
WCN3990_CE11_SR_BA_LOW
|
||||
|
||||
#define SR_BA_ADDRESS (WCN3990_CE0_SR_BA_LOW\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
#define SR_SIZE_ADDRESS (WCN3990_CE0_SR_SIZE \
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
#define DR_BA_ADDRESS (WCN3990_CE0_DR_BA_LOW\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
#define DR_SIZE_ADDRESS (WNC3990_CE0_DR_SIZE\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW \
|
||||
(WCN3990_CE_WRAPPER_INDEX_BASE_LOW - WCN3990_CE_WRAPPER_BASE_ADDRESS)
|
||||
|
||||
#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH \
|
||||
(WCN3990_CE_WRAPPER_INDEX_BASE_HIGH - WCN3990_CE_WRAPPER_BASE_ADDRESS)
|
||||
|
||||
#define CE_RRI_LOW (WCN3990_CE_WRAPPER_BASE_ADDRESS \
|
||||
+ WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW)
|
||||
|
||||
#define CE_RRI_HIGH (WCN3990_CE_WRAPPER_BASE_ADDRESS \
|
||||
+ WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH)
|
||||
|
||||
#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 18
|
||||
#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 18
|
||||
|
||||
#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00040000
|
||||
#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \
|
||||
(((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \
|
||||
CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK)
|
||||
|
||||
#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16
|
||||
#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16
|
||||
|
||||
#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00020000
|
||||
#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \
|
||||
(((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \
|
||||
CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB)
|
||||
#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \
|
||||
(((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \
|
||||
CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK)
|
||||
|
||||
#define CE_CTRL1_DMAX_LENGTH_MSB 0
|
||||
#define CE_CTRL1_DMAX_LENGTH_LSB 0
|
||||
|
||||
#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000FFFF
|
||||
#define CE_CTRL1_DMAX_LENGTH_GET(x) \
|
||||
(((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB)
|
||||
#define CE_CTRL1_DMAX_LENGTH_SET(x) \
|
||||
(((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK)
|
||||
|
||||
#define CE_CTRL1_ADDRESS (WCN3990_CE0_CE_CTRL1 \
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define HOST_IE_ADDRESS (WCN3990_CE0_HOST_IE\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010
|
||||
#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008
|
||||
#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004
|
||||
#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002
|
||||
#define HOST_IS_COPY_COMPLETE_MASK 0x00000001
|
||||
#define HOST_IS_ADDRESS (WCN3990_CE0_HOST_IS \
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
#define MISC_IE_ADDRESS (WCN3990_CE0_MISC_IE \
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define MISC_IS_AXI_ERR_MASK 0x00000100
|
||||
#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200
|
||||
#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100
|
||||
#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080
|
||||
#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040
|
||||
#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020
|
||||
#define MISC_IS_ADDRESS (WCN3990_CE0_MISC_IS \
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define SR_WR_INDEX_ADDRESS 0x3C
|
||||
#define DST_WR_INDEX_ADDRESS 0x40
|
||||
|
||||
#define CURRENT_SRRI_ADDRESS (WCN3990_CE0_CURRENT_SRRI\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
#define CURRENT_DRRI_ADDRESS (WCN3990_CE0_CURRENT_DRRI\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define SRC_WATERMARK_LOW_MSB 0
|
||||
#define SRC_WATERMARK_LOW_LSB 16
|
||||
|
||||
#define SRC_WATERMARK_LOW_MASK 0xffff0000
|
||||
#define SRC_WATERMARK_LOW_GET(x) \
|
||||
(((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB)
|
||||
#define SRC_WATERMARK_LOW_SET(x) \
|
||||
(((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)
|
||||
|
||||
#define SRC_WATERMARK_LOW_RESET 0
|
||||
#define SRC_WATERMARK_HIGH_MSB 15
|
||||
#define SRC_WATERMARK_HIGH_LSB 0
|
||||
#define SRC_WATERMARK_HIGH_MASK 0x0000ffff
|
||||
#define SRC_WATERMARK_HIGH_GET(x) \
|
||||
(((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB)
|
||||
#define SRC_WATERMARK_HIGH_SET(x) \
|
||||
(((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK)
|
||||
|
||||
#define SRC_WATERMARK_HIGH_RESET 0
|
||||
#define SRC_WATERMARK_ADDRESS (WCN3990_CE0_SRC_WATERMARK\
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define DST_WATERMARK_LOW_LSB 16
|
||||
#define DST_WATERMARK_LOW_MASK 0xffff0000
|
||||
#define DST_WATERMARK_LOW_SET(x) \
|
||||
(((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK)
|
||||
#define DST_WATERMARK_LOW_RESET 0
|
||||
#define DST_WATERMARK_HIGH_MSB 15
|
||||
#define DST_WATERMARK_HIGH_LSB 0
|
||||
#define DST_WATERMARK_HIGH_MASK 0x0000ffff
|
||||
#define DST_WATERMARK_HIGH_GET(x) \
|
||||
(((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB)
|
||||
#define DST_WATERMARK_HIGH_SET(x) \
|
||||
(((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK)
|
||||
#define DST_WATERMARK_HIGH_RESET 0
|
||||
#define DST_WATERMARK_ADDRESS (WCN3990_CE0_DST_WATERMARK \
|
||||
- WCN3990_CE0_BASE_ADDRESS)
|
||||
|
||||
#define BITS0_TO_31(val) ((uint32_t)((uint64_t)(val)\
|
||||
& (uint64_t)(0xFFFFFFFF)))
|
||||
#define BITS32_TO_35(val) ((uint32_t)(((uint64_t)(val)\
|
||||
& (uint64_t)(0xF00000000)) >> 32))
|
||||
#endif
|
||||
|
||||
static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
|
||||
{
|
||||
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
|
||||
|
|
|
@ -138,6 +138,32 @@ const struct ath10k_hw_regs qca4019_regs = {
|
|||
.pcie_intr_clr_address = 0x00000010,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_regs wcn3990_regs = {
|
||||
.rtc_soc_base_address = 0x00000000,
|
||||
.rtc_wmac_base_address = 0x00000000,
|
||||
.soc_core_base_address = 0x00000000,
|
||||
.ce_wrapper_base_address = 0x0024C000,
|
||||
.soc_global_reset_address = 0x00000008,
|
||||
.ce0_base_address = 0x00240000,
|
||||
.ce1_base_address = 0x00241000,
|
||||
.ce2_base_address = 0x00242000,
|
||||
.ce3_base_address = 0x00243000,
|
||||
.ce4_base_address = 0x00244000,
|
||||
.ce5_base_address = 0x00245000,
|
||||
.ce6_base_address = 0x00246000,
|
||||
.ce7_base_address = 0x00247000,
|
||||
.ce8_base_address = 0x00248000,
|
||||
.ce9_base_address = 0x00249000,
|
||||
.ce10_base_address = 0x0024A000,
|
||||
.ce11_base_address = 0x0024B000,
|
||||
.soc_chip_id_address = 0x000000f0,
|
||||
.soc_reset_control_si0_rst_mask = 0x00000001,
|
||||
.soc_reset_control_ce_rst_mask = 0x00000100,
|
||||
.ce_wrap_intr_sum_host_msi_lsb = 0x0000000c,
|
||||
.ce_wrap_intr_sum_host_msi_mask = 0x00fff000,
|
||||
.pcie_intr_fw_mask = 0x00100000,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca988x_values = {
|
||||
.rtc_state_val_on = 3,
|
||||
.ce_count = 8,
|
||||
|
@ -181,6 +207,15 @@ const struct ath10k_hw_values qca4019_values = {
|
|||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values wcn3990_values = {
|
||||
.rtc_state_val_on = 5,
|
||||
.ce_count = 12,
|
||||
.msi_assign_ce_max = 12,
|
||||
.num_target_ce_config_wlan = 12,
|
||||
.ce_desc_meta_data_mask = 0xFFF0,
|
||||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
|
||||
{
|
||||
|
|
|
@ -231,6 +231,7 @@ struct ath10k_hw_regs {
|
|||
u32 rtc_soc_base_address;
|
||||
u32 rtc_wmac_base_address;
|
||||
u32 soc_core_base_address;
|
||||
u32 soc_global_reset_address;
|
||||
u32 ce_wrapper_base_address;
|
||||
u32 ce0_base_address;
|
||||
u32 ce1_base_address;
|
||||
|
@ -240,6 +241,10 @@ struct ath10k_hw_regs {
|
|||
u32 ce5_base_address;
|
||||
u32 ce6_base_address;
|
||||
u32 ce7_base_address;
|
||||
u32 ce8_base_address;
|
||||
u32 ce9_base_address;
|
||||
u32 ce10_base_address;
|
||||
u32 ce11_base_address;
|
||||
u32 soc_reset_control_si0_rst_mask;
|
||||
u32 soc_reset_control_ce_rst_mask;
|
||||
u32 soc_chip_id_address;
|
||||
|
@ -257,6 +262,7 @@ extern const struct ath10k_hw_regs qca988x_regs;
|
|||
extern const struct ath10k_hw_regs qca6174_regs;
|
||||
extern const struct ath10k_hw_regs qca99x0_regs;
|
||||
extern const struct ath10k_hw_regs qca4019_regs;
|
||||
extern const struct ath10k_hw_regs wcn3990_regs;
|
||||
|
||||
struct ath10k_hw_values {
|
||||
u32 rtc_state_val_on;
|
||||
|
@ -272,6 +278,7 @@ extern const struct ath10k_hw_values qca6174_values;
|
|||
extern const struct ath10k_hw_values qca99x0_values;
|
||||
extern const struct ath10k_hw_values qca9888_values;
|
||||
extern const struct ath10k_hw_values qca4019_values;
|
||||
extern const struct ath10k_hw_values wcn3990_values;
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
|
||||
|
@ -284,6 +291,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
|||
#define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984)
|
||||
#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
|
||||
#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019)
|
||||
#define QCA_REV_WCN3990(ar) ((ar)->hw_rev == ATH10K_HW_WCN3990)
|
||||
|
||||
/* Known peculiarities:
|
||||
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
|
||||
|
|
Loading…
Add table
Reference in a new issue