From ebf256e36754fc5c4a259bb28f3c0a081eb70467 Mon Sep 17 00:00:00 2001 From: Keyur Patel Date: Sun, 14 Jul 2019 13:27:06 -0400 Subject: staging: most: Delete an error message for a failed memory allocation The kfifo_alloc() failure generates enough information and doesn't need to be accompanied by another error statement. Signed-off-by: Keyur Patel Link: https://lore.kernel.org/r/20190714172708.5067-1-iamkeyur96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/cdev/cdev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index d0cc0b746107..724d098aeef0 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -463,10 +463,8 @@ static int comp_probe(struct most_interface *iface, int channel_id, spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); - if (retval) { - pr_info("failed to alloc channel kfifo"); + if (retval) goto err_del_cdev_and_free_channel; - } init_waitqueue_head(&c->wq); mutex_init(&c->io_mutex); spin_lock_irqsave(&ch_list_lock, cl_flags); -- cgit v1.2.3-59-g8ed1b From baacd53a3b72d1dc74a340d16b8cf560dfe24717 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 5 Jul 2019 18:41:31 +0530 Subject: staging: greybus: Replace function gb_i2c_device_setup() Remove function gb_i2c_device_setup as all it does is call gb_i2c_functionality_operation. Rename gb_i2c_functionality_operation to gb_i2c_device_setup to maintain compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190705131131.27354-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/i2c.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 7bb85a75d3b1..b2522043a1a4 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -31,7 +31,14 @@ static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality) return gb_i2c_functionality; /* All bits the same for now */ } -static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev) +/* + * Do initial setup of the i2c device. This includes verifying we + * can support it (based on the protocol version it advertises). + * If that's OK, we get and cached its functionality bits. + * + * Note: gb_i2c_dev->connection is assumed to have been valid. + */ +static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) { struct gb_i2c_functionality_response response; u32 functionality; @@ -235,19 +242,6 @@ static const struct i2c_algorithm gb_i2c_algorithm = { .functionality = gb_i2c_functionality, }; -/* - * Do initial setup of the i2c device. This includes verifying we - * can support it (based on the protocol version it advertises). - * If that's OK, we get and cached its functionality bits. - * - * Note: gb_i2c_dev->connection is assumed to have been valid. - */ -static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) -{ - /* Assume the functionality never changes, just get it once */ - return gb_i2c_functionality_operation(gb_i2c_dev); -} - static int gb_i2c_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) { -- cgit v1.2.3-59-g8ed1b From e1928327353d5ddd00b7d4d46f46961ea5c2dc34 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 4 Jul 2019 14:30:31 +0100 Subject: staging: greybus: remove redundant assignment to variable is_empty The variable is_empty is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Vaibhav Agarwal Reviewed-by: Mark Greer Link: https://lore.kernel.org/r/20190704133031.28809-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/audio_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c index c2a4af4c1d06..9b19ea9d3fa1 100644 --- a/drivers/staging/greybus/audio_manager.c +++ b/drivers/staging/greybus/audio_manager.c @@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(gb_audio_manager_remove); void gb_audio_manager_remove_all(void) { struct gb_audio_manager_module *module, *next; - int is_empty = 1; + int is_empty; down_write(&modules_rwsem); -- cgit v1.2.3-59-g8ed1b From e82a9a17d49c52a5ea96589a0ee738d3fef33323 Mon Sep 17 00:00:00 2001 From: Pratik Shinde Date: Mon, 15 Jul 2019 17:51:27 +0530 Subject: staging: erofs:converting all 'unsigned' to 'unsigned int' Fixed checkpatch warnings: converting all 'unsigned' to 'unsigned int' Signed-off-by: Pratik Shinde Reviewed-by: Gao Xiang Link: https://lore.kernel.org/r/20190715122127.13733-1-pratikshinde320@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 7 ++++--- drivers/staging/erofs/unzip_pagevec.h | 11 ++++++----- drivers/staging/erofs/unzip_vle.h | 8 ++++---- drivers/staging/erofs/xattr.h | 17 +++++++++-------- 4 files changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 963cc1b8b896..0ebc294120c2 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -359,8 +359,8 @@ struct erofs_vnode { unsigned char inode_isize; unsigned short xattr_isize; - unsigned xattr_shared_count; - unsigned *xattr_shared_xattrs; + unsigned int xattr_shared_count; + unsigned int *xattr_shared_xattrs; union { erofs_blk_t raw_blkaddr; @@ -510,7 +510,8 @@ erofs_grab_bio(struct super_block *sb, return bio; } -static inline void __submit_bio(struct bio *bio, unsigned op, unsigned op_flags) +static inline void __submit_bio(struct bio *bio, unsigned int op, + unsigned int op_flags) { bio_set_op_attrs(bio, op, op_flags); submit_bio(bio); diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/unzip_pagevec.h index 7af0ba8d8495..e65dbca93ae8 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/drivers/staging/erofs/unzip_pagevec.h @@ -54,9 +54,9 @@ static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, static inline struct page * z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, - unsigned nr) + unsigned int nr) { - unsigned index; + unsigned int index; /* keep away from occupied pages */ if (ctor->next) @@ -64,7 +64,7 @@ z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, for (index = 0; index < nr; ++index) { const erofs_vtptr_t t = ctor->pages[index]; - const unsigned tags = tagptr_unfold_tags(t); + const unsigned int tags = tagptr_unfold_tags(t); if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) return tagptr_unfold_ptr(t); @@ -91,8 +91,9 @@ z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, } static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, - unsigned nr, - erofs_vtptr_t *pages, unsigned i) + unsigned int nr, + erofs_vtptr_t *pages, + unsigned int i) { ctor->nr = nr; ctor->curr = ctor->next = NULL; diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h index ab509d75aefd..df91ad149439 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/drivers/staging/erofs/unzip_vle.h @@ -34,7 +34,7 @@ struct z_erofs_vle_work { unsigned short nr_pages; /* L: queued pages in pagevec[] */ - unsigned vcnt; + unsigned int vcnt; union { /* L: pagevec */ @@ -124,7 +124,7 @@ union z_erofs_onlinepage_converter { unsigned long *v; }; -static inline unsigned z_erofs_onlinepage_index(struct page *page) +static inline unsigned int z_erofs_onlinepage_index(struct page *page) { union z_erofs_onlinepage_converter u; @@ -164,7 +164,7 @@ repeat: } v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | - ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned)down); + ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); if (cmpxchg(p, o, v) != o) goto repeat; } @@ -172,7 +172,7 @@ repeat: static inline void z_erofs_onlinepage_endio(struct page *page) { union z_erofs_onlinepage_converter u; - unsigned v; + unsigned int v; DBG_BUGON(!PagePrivate(page)); u.v = &page_private(page); diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 35ba5ac2139a..3990805dfc6c 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -20,14 +20,14 @@ /* Attribute not found */ #define ENOATTR ENODATA -static inline unsigned inlinexattr_header_size(struct inode *inode) +static inline unsigned int inlinexattr_header_size(struct inode *inode) { return sizeof(struct erofs_xattr_ibody_header) + sizeof(u32) * EROFS_V(inode)->xattr_shared_count; } -static inline erofs_blk_t -xattrblock_addr(struct erofs_sb_info *sbi, unsigned xattr_id) +static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi, + unsigned int xattr_id) { #ifdef CONFIG_EROFS_FS_XATTR return sbi->xattr_blkaddr + @@ -37,8 +37,8 @@ xattrblock_addr(struct erofs_sb_info *sbi, unsigned xattr_id) #endif } -static inline unsigned -xattrblock_offset(struct erofs_sb_info *sbi, unsigned xattr_id) +static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, + unsigned int xattr_id) { return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; } @@ -49,7 +49,7 @@ extern const struct xattr_handler erofs_xattr_trusted_handler; extern const struct xattr_handler erofs_xattr_security_handler; #endif -static inline const struct xattr_handler *erofs_xattr_handler(unsigned index) +static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) { static const struct xattr_handler *xattr_handler_map[] = { [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, @@ -63,8 +63,9 @@ static const struct xattr_handler *xattr_handler_map[] = { [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, #endif }; - return index && index < ARRAY_SIZE(xattr_handler_map) ? - xattr_handler_map[index] : NULL; + + return idx && idx < ARRAY_SIZE(xattr_handler_map) ? + xattr_handler_map[idx] : NULL; } #ifdef CONFIG_EROFS_FS_XATTR -- cgit v1.2.3-59-g8ed1b From 2ac3b368f40f31fccad2377939a66e6986b54976 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:42:47 +0530 Subject: staging: erofs: Remove function erofs_kill_sb() Remove function erofs_kill_sb as all it does is call kill_block_super. Modify references to the former to point to the latter. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Reviewed-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190712071247.2357-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 54494412eba4..3e2a65ba1945 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -554,16 +554,11 @@ static struct dentry *erofs_mount( &priv, erofs_fill_super); } -static void erofs_kill_sb(struct super_block *sb) -{ - kill_block_super(sb); -} - static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", .mount = erofs_mount, - .kill_sb = erofs_kill_sb, + .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("erofs"); -- cgit v1.2.3-59-g8ed1b From d327ace0f301c6c203c0ed1aa5da823ab6fef5f6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 5 Jul 2019 09:25:54 +0100 Subject: staging: rtl8712: remove redundant assignment to variable res The variable res is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190705082554.15588-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 307b0e292976..dac79e6dcdcb 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -739,7 +739,7 @@ static void dump_xframe(struct _adapter *padapter, int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) { - int res = _SUCCESS; + int res; res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); pxmitframe->pkt = NULL; -- cgit v1.2.3-59-g8ed1b From 8826a1985f96d402a66e25fe6eab09144b4d8003 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 8 Jul 2019 12:11:43 +0530 Subject: staging: most: dim2: Replace function dim_norm_ctrl_async_buffer_size() Remove function dim_norm_ctrl_async_buffer_size as it does nothing except call norm_ctrl_async_buffer_size. Rename norm_ctrl_async_buffer_size to dim_norm_ctrl_async_buffer_size to maintain compatibility with call sites of the latter. Change type of new dim_norm_ctrl_async_buffer_size from static inline to non-static to match the old version. Modify only remaining call site of norm_ctrl_async_buffer_size to call dim_norm_ctrl_async_buffer_size instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190708064145.3250-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/hal.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index 699e02f83bd4..d4d532e76147 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -471,7 +471,7 @@ static inline bool check_bytes_per_frame(u32 bytes_per_frame) return true; } -static inline u16 norm_ctrl_async_buffer_size(u16 buf_size) +u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) { u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u; @@ -652,7 +652,7 @@ static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size) return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size"); if (ch->packet_length == 0 && ch->bytes_per_frame == 0 && - buf_size != norm_ctrl_async_buffer_size(buf_size)) + buf_size != dim_norm_ctrl_async_buffer_size(buf_size)) return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad control/async buffer size"); @@ -780,11 +780,6 @@ void dim_service_mlb_int_irq(void) dimcb_io_write(&g.dim2->MS1, 0); } -u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) -{ - return norm_ctrl_async_buffer_size(buf_size); -} - /** * Retrieves maximal possible correct buffer size for isochronous data type * conform to given packet length and not bigger than given buffer size. -- cgit v1.2.3-59-g8ed1b From 41e359e6daf47cd47c9fde77220653886b8f5969 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 8 Jul 2019 12:11:44 +0530 Subject: staging: most: dim2: Remove function dimcb_io_read() Remove function dimcb_io_read as it does nothing except call inbuilt function readl. Modify call sites accordingly. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190708064145.3250-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/dim2.c | 9 --------- drivers/staging/most/dim2/hal.c | 15 ++++++++------- drivers/staging/most/dim2/hal.h | 2 -- 3 files changed, 8 insertions(+), 18 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 31fbc1a75b06..8d3da8e1d436 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -128,15 +128,6 @@ bool dim2_sysfs_get_state_cb(void) return state; } -/** - * dimcb_io_read - callback from HAL to read an I/O register - * @ptr32: register address - */ -u32 dimcb_io_read(u32 __iomem *ptr32) -{ - return readl(ptr32); -} - /** * dimcb_io_write - callback from HAL to write value to an I/O register * @ptr32: register address diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index d4d532e76147..fcf5d2a0f491 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -13,6 +13,7 @@ #include "reg.h" #include #include +#include /* * Size factor for isochronous DBR buffer. @@ -146,7 +147,7 @@ static void dim2_transfer_madr(u32 val) dimcb_io_write(&g.dim2->MADR, val); /* wait for transfer completion */ - while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) + while ((readl(&g.dim2->MCTL) & 1) != 1) continue; dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ @@ -170,7 +171,7 @@ static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx) { dim2_transfer_madr(ctr_addr); - return dimcb_io_read((&g.dim2->MDAT0) + mdat_idx); + return readl((&g.dim2->MDAT0) + mdat_idx); } static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) @@ -357,14 +358,14 @@ static void dim2_configure_channel( /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) | bit_mask(ch_addr)); + readl(&g.dim2->ACMR0) | bit_mask(ch_addr)); } static void dim2_clear_channel(u8 ch_addr) { /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ dimcb_io_write(&g.dim2->ACMR0, - dimcb_io_read(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); dim2_clear_cat(AHB_CAT, ch_addr); dim2_clear_adt(ch_addr); @@ -562,12 +563,12 @@ static bool dim2_is_mlb_locked(void) u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT); u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) | bit_mask(MLBC1_LOCKERR_BIT); - u32 const c1 = dimcb_io_read(&g.dim2->MLBC1); + u32 const c1 = readl(&g.dim2->MLBC1); u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); - return (dimcb_io_read(&g.dim2->MLBC1) & mask1) == 0 && - (dimcb_io_read(&g.dim2->MLBC0) & mask0) != 0; + return (readl(&g.dim2->MLBC1) & mask1) == 0 && + (readl(&g.dim2->MLBC0) & mask0) != 0; } /* -------------------------------------------------------------------------- */ diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h index fca6c22de8a6..d16268bd9317 100644 --- a/drivers/staging/most/dim2/hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -97,8 +97,6 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -u32 dimcb_io_read(u32 __iomem *ptr32); - void dimcb_io_write(u32 __iomem *ptr32, u32 value); void dimcb_on_error(u8 error_id, const char *error_message); -- cgit v1.2.3-59-g8ed1b From 6fa4e8eb3f1906decdd9d426708bf5134d77f5ad Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 8 Jul 2019 12:11:45 +0530 Subject: staging: most: dim2: Remove function dimcb_io_write() Remove function dimcb_io_write as all it does is call writel. Modify calls to dimcb_io_write to writel, flipping the order of the arguments as required. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190708064145.3250-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/dim2/dim2.c | 10 ----- drivers/staging/most/dim2/hal.c | 79 +++++++++++++++++++--------------------- drivers/staging/most/dim2/hal.h | 2 - 3 files changed, 38 insertions(+), 53 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 8d3da8e1d436..043a3e14fdfc 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -128,16 +128,6 @@ bool dim2_sysfs_get_state_cb(void) return state; } -/** - * dimcb_io_write - callback from HAL to write value to an I/O register - * @ptr32: register address - * @value: value to write - */ -void dimcb_io_write(u32 __iomem *ptr32, u32 value) -{ - writel(value, ptr32); -} - /** * dimcb_on_error - callback from HAL to report miscommunication between * HDM and HAL diff --git a/drivers/staging/most/dim2/hal.c b/drivers/staging/most/dim2/hal.c index fcf5d2a0f491..39e17a7d2f24 100644 --- a/drivers/staging/most/dim2/hal.c +++ b/drivers/staging/most/dim2/hal.c @@ -144,13 +144,13 @@ static void free_dbr(int offs, int size) static void dim2_transfer_madr(u32 val) { - dimcb_io_write(&g.dim2->MADR, val); + writel(val, &g.dim2->MADR); /* wait for transfer completion */ while ((readl(&g.dim2->MCTL) & 1) != 1) continue; - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + writel(0, &g.dim2->MCTL); /* clear transfer complete */ } static void dim2_clear_dbr(u16 addr, u16 size) @@ -160,8 +160,8 @@ static void dim2_clear_dbr(u16 addr, u16 size) u16 const end_addr = addr + size; u32 const cmd = bit_mask(MADR_WNR_BIT) | bit_mask(MADR_TB_BIT); - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ - dimcb_io_write(&g.dim2->MDAT0, 0); + writel(0, &g.dim2->MCTL); /* clear transfer complete */ + writel(0, &g.dim2->MDAT0); for (; addr < end_addr; addr++) dim2_transfer_madr(cmd | addr); @@ -178,21 +178,21 @@ static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value) { enum { MADR_WNR_BIT = 31 }; - dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + writel(0, &g.dim2->MCTL); /* clear transfer complete */ if (mask[0] != 0) - dimcb_io_write(&g.dim2->MDAT0, value[0]); + writel(value[0], &g.dim2->MDAT0); if (mask[1] != 0) - dimcb_io_write(&g.dim2->MDAT1, value[1]); + writel(value[1], &g.dim2->MDAT1); if (mask[2] != 0) - dimcb_io_write(&g.dim2->MDAT2, value[2]); + writel(value[2], &g.dim2->MDAT2); if (mask[3] != 0) - dimcb_io_write(&g.dim2->MDAT3, value[3]); + writel(value[3], &g.dim2->MDAT3); - dimcb_io_write(&g.dim2->MDWE0, mask[0]); - dimcb_io_write(&g.dim2->MDWE1, mask[1]); - dimcb_io_write(&g.dim2->MDWE2, mask[2]); - dimcb_io_write(&g.dim2->MDWE3, mask[3]); + writel(mask[0], &g.dim2->MDWE0); + writel(mask[1], &g.dim2->MDWE1); + writel(mask[2], &g.dim2->MDWE2); + writel(mask[3], &g.dim2->MDWE3); dim2_transfer_madr(bit_mask(MADR_WNR_BIT) | ctr_addr); } @@ -357,15 +357,13 @@ static void dim2_configure_channel( dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1); /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - readl(&g.dim2->ACMR0) | bit_mask(ch_addr)); + writel(readl(&g.dim2->ACMR0) | bit_mask(ch_addr), &g.dim2->ACMR0); } static void dim2_clear_channel(u8 ch_addr) { /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */ - dimcb_io_write(&g.dim2->ACMR0, - readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr)); + writel(readl(&g.dim2->ACMR0) & ~bit_mask(ch_addr), &g.dim2->ACMR0); dim2_clear_cat(AHB_CAT, ch_addr); dim2_clear_adt(ch_addr); @@ -374,7 +372,7 @@ static void dim2_clear_channel(u8 ch_addr) dim2_clear_cdt(ch_addr); /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + writel(bit_mask(ch_addr), &g.dim2->ACSR0); } /* -------------------------------------------------------------------------- */ @@ -518,20 +516,20 @@ static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame) static void dim2_cleanup(void) { /* disable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT); + writel(false << MLBC0_MLBEN_BIT, &g.dim2->MLBC0); dim2_clear_ctram(); /* disable mlb_int interrupt */ - dimcb_io_write(&g.dim2->MIEN, 0); + writel(0, &g.dim2->MIEN); /* clear status for all dma channels */ - dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); + writel(0xFFFFFFFF, &g.dim2->ACSR0); + writel(0xFFFFFFFF, &g.dim2->ACSR1); /* mask interrupts for all channels */ - dimcb_io_write(&g.dim2->ACMR0, 0); - dimcb_io_write(&g.dim2->ACMR1, 0); + writel(0, &g.dim2->ACMR0); + writel(0, &g.dim2->ACMR1); } static void dim2_initialize(bool enable_6pin, u8 mlb_clock) @@ -539,23 +537,22 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) dim2_cleanup(); /* configure and enable MediaLB */ - dimcb_io_write(&g.dim2->MLBC0, - enable_6pin << MLBC0_MLBPEN_BIT | - mlb_clock << MLBC0_MLBCLK_SHIFT | - g.fcnt << MLBC0_FCNT_SHIFT | - true << MLBC0_MLBEN_BIT); + writel(enable_6pin << MLBC0_MLBPEN_BIT | + mlb_clock << MLBC0_MLBCLK_SHIFT | + g.fcnt << MLBC0_FCNT_SHIFT | + true << MLBC0_MLBEN_BIT, + &g.dim2->MLBC0); /* activate all HBI channels */ - dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); - dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); + writel(0xFFFFFFFF, &g.dim2->HCMR0); + writel(0xFFFFFFFF, &g.dim2->HCMR1); /* enable HBI */ - dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); + writel(bit_mask(HCTL_EN_BIT), &g.dim2->HCTL); /* configure DMA */ - dimcb_io_write(&g.dim2->ACTL, - ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | - true << ACTL_SCE_BIT); + writel(ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT | + true << ACTL_SCE_BIT, &g.dim2->ACTL); } static bool dim2_is_mlb_locked(void) @@ -566,7 +563,7 @@ static bool dim2_is_mlb_locked(void) u32 const c1 = readl(&g.dim2->MLBC1); u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT; - dimcb_io_write(&g.dim2->MLBC1, c1 & nda_mask); + writel(c1 & nda_mask, &g.dim2->MLBC1); return (readl(&g.dim2->MLBC1) & mask1) == 0 && (readl(&g.dim2->MLBC0) & mask0) != 0; } @@ -591,7 +588,7 @@ static inline bool service_channel(u8 ch_addr, u8 idx) dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w); /* clear channel status bit */ - dimcb_io_write(&g.dim2->ACSR0, bit_mask(ch_addr)); + writel(bit_mask(ch_addr), &g.dim2->ACSR0); return true; } @@ -777,8 +774,8 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, void dim_service_mlb_int_irq(void) { - dimcb_io_write(&g.dim2->MS0, 0); - dimcb_io_write(&g.dim2->MS1, 0); + writel(0, &g.dim2->MS0); + writel(0, &g.dim2->MS1); } /** @@ -825,7 +822,7 @@ u8 dim_init_async(struct dim_channel *ch, u8 is_tx, u16 ch_address, if (is_tx && !g.atx_dbr.ch_addr) { g.atx_dbr.ch_addr = ch->addr; dbrcnt_init(ch->addr, ch->dbr_size); - dimcb_io_write(&g.dim2->MIEN, bit_mask(20)); + writel(bit_mask(20), &g.dim2->MIEN); } return ret; @@ -892,7 +889,7 @@ u8 dim_destroy_channel(struct dim_channel *ch) return DIM_ERR_DRIVER_NOT_INITIALIZED; if (ch->addr == g.atx_dbr.ch_addr) { - dimcb_io_write(&g.dim2->MIEN, 0); + writel(0, &g.dim2->MIEN); g.atx_dbr.ch_addr = 0; } diff --git a/drivers/staging/most/dim2/hal.h b/drivers/staging/most/dim2/hal.h index d16268bd9317..20531449acab 100644 --- a/drivers/staging/most/dim2/hal.h +++ b/drivers/staging/most/dim2/hal.h @@ -97,8 +97,6 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -void dimcb_io_write(u32 __iomem *ptr32, u32 value); - void dimcb_on_error(u8 error_id, const char *error_message); #endif /* _DIM2_HAL_H */ -- cgit v1.2.3-59-g8ed1b From 72da91bc590a3a789b2130718c9dc810851273fe Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:57:58 +0530 Subject: staging: wlan-ng: Remove function hfa384x_dorrid_wait() Remove function hfa384x_dorrid_wait as it is only called once and it does nothing except call hfa384x_dorrid. Move contents of hfa384x_dorrid_wait to its only call site to maintain functionality. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index ab734534093b..4befc615d8e2 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -834,14 +834,6 @@ hfa384x_docmd_async(struct hfa384x *hw, return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dorrid_wait(struct hfa384x *hw, u16 rid, void *riddata, - unsigned int riddatalen) -{ - return hfa384x_dorrid(hw, DOWAIT, - rid, riddata, riddatalen, NULL, NULL, NULL); -} - static inline int hfa384x_dorrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, @@ -2061,7 +2053,7 @@ exit_proc: */ int hfa384x_drvr_getconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dorrid_wait(hw, rid, buf, len); + return hfa384x_dorrid(hw, DOWAIT, rid, buf, len, NULL, NULL, NULL); } /*---------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 83c23c8e79ee85c0e7f71844a50aab0c1156a788 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:57:59 +0530 Subject: staging: wlan-ng: Remove function hfa384x_dowrid_wait() Remove inline function hfa384x_dowrid_wait as it is only called once (in hfa384x_drvr_setconfig) and its contents are only a single line (a call to hfa384x_dowrid). Replace the call to hfa384x_dowrid_wait with its contents i.e the call to hfa384x_dowrid. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 4befc615d8e2..dc6abc654165 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -845,14 +845,6 @@ hfa384x_dorrid_async(struct hfa384x *hw, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dowrid_wait(struct hfa384x *hw, u16 rid, void *riddata, - unsigned int riddatalen) -{ - return hfa384x_dowrid(hw, DOWAIT, - rid, riddata, riddatalen, NULL, NULL, NULL); -} - static inline int hfa384x_dowrid_async(struct hfa384x *hw, u16 rid, void *riddata, unsigned int riddatalen, @@ -2414,7 +2406,7 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) */ int hfa384x_drvr_setconfig(struct hfa384x *hw, u16 rid, void *buf, u16 len) { - return hfa384x_dowrid_wait(hw, rid, buf, len); + return hfa384x_dowrid(hw, DOWAIT, rid, buf, len, NULL, NULL, NULL); } /*---------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From 57d100b8aa686ce7bccc74e702aa1f3e8051d518 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:00 +0530 Subject: staging: wlan-ng: Remove function hfa384x_dowrid_async() Remove function hfa384x_dowrid_async as it does nothing except call hfa384x_dowrid, and itself is called only once. Move the contents of hfa384x_dowrid_async (i.e the call to hfa384x_dowrid) to its call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index dc6abc654165..732ffb6aab0b 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -845,17 +845,6 @@ hfa384x_dorrid_async(struct hfa384x *hw, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dowrid_async(struct hfa384x *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dowrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) @@ -2078,8 +2067,8 @@ hfa384x_drvr_setconfig_async(struct hfa384x *hw, void *buf, u16 len, ctlx_usercb_t usercb, void *usercb_data) { - return hfa384x_dowrid_async(hw, rid, buf, len, - hfa384x_cb_status, usercb, usercb_data); + return hfa384x_dowrid(hw, DOASYNC, rid, buf, len, hfa384x_cb_status, + usercb, usercb_data); } /*---------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From bb75c586cabd0d192b9e713143f49b44112e64cb Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:01 +0530 Subject: staging: wlan-ng: Remove unused function hfa384x_dorrid_async() Remove unused function hfa384x_dorrid_async. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 732ffb6aab0b..c1a315bf5a81 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -834,17 +834,6 @@ hfa384x_docmd_async(struct hfa384x *hw, return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); } -static inline int -hfa384x_dorrid_async(struct hfa384x *hw, - u16 rid, void *riddata, unsigned int riddatalen, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dorrid(hw, DOASYNC, - rid, riddata, riddatalen, - cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) -- cgit v1.2.3-59-g8ed1b From f2a82b0941ea0075fa402792ea8bc9c6c5db7bfe Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:02 +0530 Subject: staging: wlan-ng: Remove unused function hfa384x_dormem_async() Remove unused function hfa384x_dormem_async. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index c1a315bf5a81..95dae0b271fc 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -842,17 +842,6 @@ hfa384x_dormem_wait(struct hfa384x *hw, page, offset, data, len, NULL, NULL, NULL); } -static inline int -hfa384x_dormem_async(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dormem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dowmem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) -- cgit v1.2.3-59-g8ed1b From 71b289cc5aa6b3bbe7e1a87612037b2c5bae9649 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:03 +0530 Subject: staging: wlan-ng: Remove function hfa384x_dowmem_async() Remove unused function hfa384x_dowmem_async. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 95dae0b271fc..20ac2dbd8a00 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -850,20 +850,6 @@ hfa384x_dowmem_wait(struct hfa384x *hw, page, offset, data, len, NULL, NULL, NULL); } -static inline int -hfa384x_dowmem_async(struct hfa384x *hw, - u16 page, - u16 offset, - void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, - ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_dowmem(hw, DOASYNC, - page, offset, data, len, - cmdcb, usercb, usercb_data); -} - /*---------------------------------------------------------------- * hfa384x_cmd_initialize * -- cgit v1.2.3-59-g8ed1b From aef29ca497f005fe3cd38aefc77639dc551bbd18 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:04 +0530 Subject: staging: wlan-ng: Remove unused function hfa384x_docmd_async() Remove unused function hfa384x_docmd_async. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 20ac2dbd8a00..ce1a9ee995a0 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -826,14 +826,6 @@ static inline int hfa384x_docmd_wait(struct hfa384x *hw, return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); } -static inline int -hfa384x_docmd_async(struct hfa384x *hw, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) -{ - return hfa384x_docmd(hw, DOASYNC, cmd, cmdcb, usercb, usercb_data); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) -- cgit v1.2.3-59-g8ed1b From 53055d6a915cb1753334dc18d6249f8b4ac62d88 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:05 +0530 Subject: staging: wlan-ng: Remove function hfa384x_docmd_wait() As hfa384x_docmd is only called by hfa384x_docmd_wait, and hfa384x_docmd_wait always passes 4 constant arguments (DOWAIT, NULL, NULL, NULL) to hfa384x_docmd, these constant parameters may be removed from hfa384x_docmd and their values used directly instead. Remove check for one of these constant parameters of hfa384x_docmd as it is no longer necessary. Remove hfa384x_docmd_wait as it does nothing except call hfa384x_docmd. Modify call sites of hfa384x_docmd_wait to call hfa384x_docmd instead. Change type of hfa384x_docmd to inline to match type of former hfa384x_docmd_wait. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 43 ++++++++++++----------------------- 1 file changed, 14 insertions(+), 29 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index ce1a9ee995a0..c469b89948e6 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -226,11 +226,9 @@ usbctlx_get_rridresult(const struct hfa384x_usb_rridresp *rridresp, /*---------------------------------------------------*/ /* Low level req/resp CTLX formatters and submitters */ -static int +static inline int hfa384x_docmd(struct hfa384x *hw, - enum cmd_mode mode, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + struct hfa384x_metacmd *cmd); static int hfa384x_dorrid(struct hfa384x *hw, @@ -820,12 +818,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int hfa384x_docmd_wait(struct hfa384x *hw, - struct hfa384x_metacmd *cmd) -{ - return hfa384x_docmd(hw, DOWAIT, cmd, NULL, NULL, NULL); -} - static inline int hfa384x_dormem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) @@ -873,7 +865,7 @@ int hfa384x_cmd_initialize(struct hfa384x *hw) cmd.parm1 = 0; cmd.parm2 = 0; - result = hfa384x_docmd_wait(hw, &cmd); + result = hfa384x_docmd(hw, &cmd); pr_debug("cmdresp.init: status=0x%04x, resp0=0x%04x, resp1=0x%04x, resp2=0x%04x\n", cmd.result.status, @@ -919,7 +911,7 @@ int hfa384x_cmd_disable(struct hfa384x *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -953,7 +945,7 @@ int hfa384x_cmd_enable(struct hfa384x *hw, u16 macport) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -996,7 +988,7 @@ int hfa384x_cmd_monitor(struct hfa384x *hw, u16 enable) cmd.parm1 = 0; cmd.parm2 = 0; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1053,7 +1045,7 @@ int hfa384x_cmd_download(struct hfa384x *hw, u16 mode, u16 lowaddr, cmd.parm1 = highaddr; cmd.parm2 = codelen; - return hfa384x_docmd_wait(hw, &cmd); + return hfa384x_docmd(hw, &cmd); } /*---------------------------------------------------------------- @@ -1213,13 +1205,8 @@ cleanup: * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * cmd cmd structure. Includes all arguments and result * data points. All in host order. in host order - * cmdcb command-specific callback - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls, NULL - * for DOWAIT calls * * Returns: * 0 success @@ -1235,11 +1222,9 @@ cleanup: * process *---------------------------------------------------------------- */ -static int +static inline int hfa384x_docmd(struct hfa384x *hw, - enum cmd_mode mode, - struct hfa384x_metacmd *cmd, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + struct hfa384x_metacmd *cmd) { int result; struct hfa384x_usbctlx *ctlx; @@ -1262,15 +1247,15 @@ hfa384x_docmd(struct hfa384x *hw, pr_debug("cmdreq: cmd=0x%04x parm0=0x%04x parm1=0x%04x parm2=0x%04x\n", cmd->cmd, cmd->parm0, cmd->parm1, cmd->parm2); - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_cmd_completor cmd_completor; struct usbctlx_completor *completor; -- cgit v1.2.3-59-g8ed1b From 28c03f82607730901830170259a4a17b33d5152e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:06 +0530 Subject: staging: wlan-ng: Replace function hfa384x_dormem() Remove parameters mode, cmdcb, usercb, and usercb_data from hfa384x_dormem as these parameters are only assigned the same constant values (DOWAIT, NULL, NULL, NULL respectively). Modify hfa384x_dormem to use these constants directly. Remove check for value of mode (as it will always be DOWAIT). Remove function hfa384x_dormem_wait as it does nothing except call hfa384x_dormem with these extra arguments. Modify call sites of hfa384x_dormem_wait to call hfa384x_dormem instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 37 ++++++++++------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index c469b89948e6..9be06a33268c 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -248,12 +248,10 @@ hfa384x_dowrid(struct hfa384x *hw, static int hfa384x_dormem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + unsigned int len); static int hfa384x_dowmem(struct hfa384x *hw, @@ -818,14 +816,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int -hfa384x_dormem_wait(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len) -{ - return hfa384x_dormem(hw, DOWAIT, - page, offset, data, len, NULL, NULL, NULL); -} - static inline int hfa384x_dowmem_wait(struct hfa384x *hw, u16 page, u16 offset, void *data, unsigned int len) @@ -1454,14 +1444,10 @@ done: * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * page MAC address space page (CMD format) * offset MAC address space offset * data Ptr to data buffer to receive read * len Length of the data to read (max == 2048) - * cmdcb command callback for async calls, NULL for DOWAIT calls - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls * * Returns: * 0 success @@ -1473,18 +1459,15 @@ done: * Side effects: * * Call context: - * interrupt (DOASYNC) - * process (DOWAIT or DOASYNC) + * process (DOWAIT) *---------------------------------------------------------------- */ static int hfa384x_dormem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + unsigned int len) { int result; struct hfa384x_usbctlx *ctlx; @@ -1512,15 +1495,15 @@ hfa384x_dormem(struct hfa384x *hw, pr_debug("pktsize=%zd\n", ROUNDUP64(sizeof(ctlx->outbuf.rmemreq))); - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_rmem_completor completor; result = @@ -2252,8 +2235,8 @@ int hfa384x_drvr_readpda(struct hfa384x *hw, void *buf, unsigned int len) curroffset = HFA384x_ADDR_CMD_MKOFF(pdaloc[i].cardaddr); /* units of bytes */ - result = hfa384x_dormem_wait(hw, currpage, curroffset, buf, - len); + result = hfa384x_dormem(hw, currpage, curroffset, buf, + len); if (result) { netdev_warn(hw->wlandev->netdev, -- cgit v1.2.3-59-g8ed1b From 68336404aa5123401133c9433a8c91e4b96322e6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 11:58:07 +0530 Subject: staging: wlan-ng: Replace function hfa384x_dowmem() Remove parameters mode, cmdcb, usercb, and usercb_data from hfa384x_dowmem as these parameters are only assigned the same constant values (DOWAIT, NULL, NULL, NULL respectively). Modify hfa384x_dowmem to use these constants directly. Remove check for value of mode (as it will always be DOWAIT). Remove function hfa384x_dowmem_wait as it does nothing except call hfa384x_dowmem with these extra arguments. Modify call sites of hfa384x_dowmem_wait to call hfa384x_dowmem instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712062807.9361-10-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 51 ++++++++++++----------------------- 1 file changed, 17 insertions(+), 34 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 9be06a33268c..28d372a0663a 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -255,12 +255,10 @@ hfa384x_dormem(struct hfa384x *hw, static int hfa384x_dowmem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data); + unsigned int len); static int hfa384x_isgood_pdrcode(u16 pdrcode); @@ -816,14 +814,6 @@ static void hfa384x_cb_status(struct hfa384x *hw, } } -static inline int -hfa384x_dowmem_wait(struct hfa384x *hw, - u16 page, u16 offset, void *data, unsigned int len) -{ - return hfa384x_dowmem(hw, DOWAIT, - page, offset, data, len, NULL, NULL, NULL); -} - /*---------------------------------------------------------------- * hfa384x_cmd_initialize * @@ -1529,14 +1519,10 @@ done: * * Arguments: * hw device structure - * mode DOWAIT or DOASYNC * page MAC address space page (CMD format) * offset MAC address space offset * data Ptr to data buffer containing write data * len Length of the data to read (max == 2048) - * cmdcb command callback for async calls, NULL for DOWAIT calls - * usercb user callback for async calls, NULL for DOWAIT calls - * usercb_data user supplied data pointer for async calls. * * Returns: * 0 success @@ -1549,17 +1535,15 @@ done: * * Call context: * interrupt (DOWAIT) - * process (DOWAIT or DOASYNC) + * process (DOWAIT) *---------------------------------------------------------------- */ static int hfa384x_dowmem(struct hfa384x *hw, - enum cmd_mode mode, u16 page, u16 offset, void *data, - unsigned int len, - ctlx_cmdcb_t cmdcb, ctlx_usercb_t usercb, void *usercb_data) + unsigned int len) { int result; struct hfa384x_usbctlx *ctlx; @@ -1586,15 +1570,15 @@ hfa384x_dowmem(struct hfa384x *hw, sizeof(ctlx->outbuf.wmemreq.offset) + sizeof(ctlx->outbuf.wmemreq.page) + len; - ctlx->reapable = mode; - ctlx->cmdcb = cmdcb; - ctlx->usercb = usercb; - ctlx->usercb_data = usercb_data; + ctlx->reapable = DOWAIT; + ctlx->cmdcb = NULL; + ctlx->usercb = NULL; + ctlx->usercb_data = NULL; result = hfa384x_usbctlx_submit(hw, ctlx); if (result != 0) { kfree(ctlx); - } else if (mode == DOWAIT) { + } else { struct usbctlx_cmd_completor completor; struct hfa384x_cmdresult wmemresult; @@ -1901,10 +1885,10 @@ int hfa384x_drvr_flashdl_write(struct hfa384x *hw, u32 daddr, writelen = writelen > HFA384x_USB_RWMEM_MAXLEN ? HFA384x_USB_RWMEM_MAXLEN : writelen; - result = hfa384x_dowmem_wait(hw, - writepage, - writeoffset, - writebuf, writelen); + result = hfa384x_dowmem(hw, + writepage, + writeoffset, + writebuf, writelen); } /* set the download 'write flash' mode */ @@ -2158,12 +2142,11 @@ int hfa384x_drvr_ramdl_write(struct hfa384x *hw, u32 daddr, void *buf, u32 len) currlen = HFA384x_USB_RWMEM_MAXLEN; /* Do blocking ctlx */ - result = hfa384x_dowmem_wait(hw, - currpage, - curroffset, - data + - (i * HFA384x_USB_RWMEM_MAXLEN), - currlen); + result = hfa384x_dowmem(hw, + currpage, + curroffset, + data + (i * HFA384x_USB_RWMEM_MAXLEN), + currlen); if (result) break; -- cgit v1.2.3-59-g8ed1b From 4ad366015d0560abf749d62b525177d38b02a1a9 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:50:09 +0530 Subject: staging: wilc1000: Replace function wilc_wlan_cfg_get_val() Include wilc_wlan_cfg.h in wilc_netdev.c to enable it to call functions in wilc_wlan_cfg.c. Remove function wilc_wlan_cfg_get_val as all it does is call wilc_wlan_cfg_get_wid_value in file wilc_wlan_cfg.c. Rename function wilc_wlan_cfg_get_wid_value to wilc_wlan_cfg_get_val to maintain compatibility with call sites (including in wilc_netdev.c). Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712072009.2550-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 1 + drivers/staging/wilc1000/wilc_wlan.c | 5 ----- drivers/staging/wilc1000/wilc_wlan.h | 2 -- drivers/staging/wilc1000/wilc_wlan_cfg.c | 4 ++-- drivers/staging/wilc1000/wilc_wlan_cfg.h | 4 ++-- 5 files changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 565e2b5d0616..8d8b7e4399f7 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -11,6 +11,7 @@ #include #include "wilc_wfi_cfgoperations.h" +#include "wilc_wlan_cfg.h" #define WILC_MULTICAST_TABLE_SIZE 8 diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d46876edcfeb..2cbdbf0090e4 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1196,11 +1196,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, return ret_size; } -int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size) -{ - return wilc_wlan_cfg_get_wid_value(wl, wid, buffer, buffer_size); -} - int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count) { diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index d2eef7b4c3b7..b70014142686 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -291,8 +291,6 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); -int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*func)(void *, int)); void wilc_chip_sleep_manually(struct wilc *wilc); diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 9dc5de4eb08d..f4144f93e4a9 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -320,8 +320,8 @@ int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) return 2; } -int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size) +int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, + u32 buffer_size) { u32 type = (wid >> 12) & 0xf; int i, ret = 0; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wilc_wlan_cfg.h index e5ca6cea0682..614c5673f232 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.h +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.h @@ -44,8 +44,8 @@ struct wilc_cfg { struct wilc; int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size); int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id); -int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, - u32 buffer_size); +int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, + u32 buffer_size); void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, struct wilc_cfg_rsp *rsp); int wilc_wlan_cfg_init(struct wilc *wl); -- cgit v1.2.3-59-g8ed1b From 26a7ae2949a86e1b74e2485d725efb528e2a81bb Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 10 Jul 2019 19:00:56 -0400 Subject: staging: wlan-ng: use "%*pE" for serial number Almost every user of "%*pE" in the kernel uses just bare "%*pE". This is the only user of "%pEhp". I can't see why it's needed. Signed-off-by: J. Bruce Fields Link: https://lore.kernel.org/r/1562799656-13401-1-git-send-email-bfields@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index fb5441399131..8f25496188aa 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -846,7 +846,7 @@ static int prism2sta_getcardinfo(struct wlandevice *wlandev) result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, snum, HFA384x_RID_NICSERIALNUMBER_LEN); if (!result) { - netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n", + netdev_info(wlandev->netdev, "Prism2 card SN: %*pE\n", HFA384x_RID_NICSERIALNUMBER_LEN, snum); } else { netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n"); -- cgit v1.2.3-59-g8ed1b From 543ba01d99cc6b4007c1f9a475c1d572c46a5543 Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:11 +0300 Subject: staging: fsl-dpaa2/ethsw: Fix setting port learning/flooding flags ethsw_set_learning()/ethsw_set_flood() use flags parameter as an enable/disable (1/0) indicator. Previous usage sent incorrect values. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-2-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index f73edaf6ce87..87470070c3a5 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -673,11 +673,12 @@ static int port_attr_br_flags_set(struct net_device *netdev, return 0; /* Learning is enabled per switch */ - err = ethsw_set_learning(port_priv->ethsw_data, flags & BR_LEARNING); + err = ethsw_set_learning(port_priv->ethsw_data, + !!(flags & BR_LEARNING)); if (err) goto exit; - err = ethsw_port_set_flood(port_priv, flags & BR_FLOOD); + err = ethsw_port_set_flood(port_priv, !!(flags & BR_FLOOD)); exit: return err; -- cgit v1.2.3-59-g8ed1b From b2fdbfa91b8c54c8884323b8914b0a7b81e67fc2 Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:12 +0300 Subject: staging: fsl-dpaa2/ethsw: Add network interface statistics Allocate MC portal with atomic context for I/O and enable network interface statistics for hardware counters. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-3-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 87470070c3a5..b2273f840813 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -521,6 +521,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_stop = port_stop, .ndo_set_mac_address = eth_mac_addr, + .ndo_get_stats64 = port_get_stats, .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, @@ -1483,7 +1484,8 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) ethsw->dev = dev; dev_set_drvdata(dev, ethsw); - err = fsl_mc_portal_allocate(sw_dev, 0, ðsw->mc_io); + err = fsl_mc_portal_allocate(sw_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, + ðsw->mc_io); if (err) { if (err == -ENXIO) err = -EPROBE_DEFER; -- cgit v1.2.3-59-g8ed1b From 7dbac0c9a1c4a86be928e2b13398346ca5b57233 Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:13 +0300 Subject: staging: fsl-dpaa2/ethsw: Remove netdevice on port probing error If the ethsw_port_init() call failed, the netdevice remains registered in the system. Use labels to ensure that netdevice is unregistered and freed in this case. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-4-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index b2273f840813..9f1617164865 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1460,13 +1460,23 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) err = register_netdev(port_netdev); if (err < 0) { dev_err(dev, "register_netdev error %d\n", err); - free_netdev(port_netdev); - return err; + goto err_register_netdev; } ethsw->ports[port_idx] = port_priv; - return ethsw_port_init(port_priv, port_idx); + err = ethsw_port_init(port_priv, port_idx); + if (err) + goto err_ethsw_port_init; + + return 0; + +err_ethsw_port_init: + unregister_netdev(port_netdev); +err_register_netdev: + free_netdev(port_netdev); + + return err; } static int ethsw_probe(struct fsl_mc_device *sw_dev) -- cgit v1.2.3-59-g8ed1b From de7ee3aea2e8255b28d047a0d8588f96bf522f4b Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:14 +0300 Subject: staging: fsl-dpaa2/ethsw: Add ndo_get_phys_port_name Add the ndo_get_phys_port_name callback to the ethsw driver. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-5-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 9f1617164865..341c36b3a76d 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -516,6 +516,19 @@ static int swdev_get_port_parent_id(struct net_device *dev, return 0; } +static int port_get_phys_name(struct net_device *netdev, char *name, + size_t len) +{ + struct ethsw_port_priv *port_priv = netdev_priv(netdev); + int err; + + err = snprintf(name, len, "p%d", port_priv->idx); + if (err >= len) + return -EINVAL; + + return 0; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -528,6 +541,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_start_xmit = port_dropframe, .ndo_get_port_parent_id = swdev_get_port_parent_id, + .ndo_get_phys_port_name = port_get_phys_name, }; static void ethsw_links_state_update(struct ethsw_core *ethsw) -- cgit v1.2.3-59-g8ed1b From c5bd72f8713e13085267a8ebccfa5b8b3f2c674d Mon Sep 17 00:00:00 2001 From: Razvan Stefanescu Date: Fri, 5 Jul 2019 17:27:16 +0300 Subject: staging: fsl-dpaa2/ethsw: Add comments to ETHSW_VLAN flags Document each ETHSW_VLAN flag with the appropriate comment. Signed-off-by: Razvan Stefanescu Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1562336836-17119-7-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h index c48783680a05..3ea8a0ad8c10 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.h @@ -23,9 +23,13 @@ /* Number of IRQs supported */ #define DPSW_IRQ_NUM 2 +/* Port is member of VLAN */ #define ETHSW_VLAN_MEMBER 1 +/* VLAN to be treated as untagged on egress */ #define ETHSW_VLAN_UNTAGGED 2 +/* Untagged frames will be assigned to this VLAN */ #define ETHSW_VLAN_PVID 4 +/* VLAN configured on the switch */ #define ETHSW_VLAN_GLOBAL 8 /* Maximum Frame Length supported by HW (currently 10k) */ -- cgit v1.2.3-59-g8ed1b From 6c90bade52bbabdbdf3604d7f9279c878ebafed2 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sun, 7 Jul 2019 18:56:49 +0200 Subject: staging: rtl8188eu: remove unused definitions from hal8188e_phy_reg.h Remove unused definitions from the file hal8188e_phy_reg.h. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20190707165649.1558-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8188eu/include/hal8188e_phy_reg.h | 881 --------------------- 1 file changed, 881 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h index 53afcea21c96..bd915a1f2511 100644 --- a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h +++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h @@ -16,55 +16,10 @@ /* 5. Other definition for BB/RF R/W */ /* */ - -/* */ -/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */ -/* 1. Page1(0x100) */ -/* */ -#define rPMAC_Reset 0x100 -#define rPMAC_TxStart 0x104 -#define rPMAC_TxLegacySIG 0x108 -#define rPMAC_TxHTSIG1 0x10c -#define rPMAC_TxHTSIG2 0x110 -#define rPMAC_PHYDebug 0x114 -#define rPMAC_TxPacketNum 0x118 -#define rPMAC_TxIdle 0x11c -#define rPMAC_TxMACHeader0 0x120 -#define rPMAC_TxMACHeader1 0x124 -#define rPMAC_TxMACHeader2 0x128 -#define rPMAC_TxMACHeader3 0x12c -#define rPMAC_TxMACHeader4 0x130 -#define rPMAC_TxMACHeader5 0x134 -#define rPMAC_TxDataType 0x138 -#define rPMAC_TxRandomSeed 0x13c -#define rPMAC_CCKPLCPPreamble 0x140 -#define rPMAC_CCKPLCPHeader 0x144 -#define rPMAC_CCKCRC16 0x148 -#define rPMAC_OFDMRxCRC32OK 0x170 -#define rPMAC_OFDMRxCRC32Er 0x174 -#define rPMAC_OFDMRxParityEr 0x178 -#define rPMAC_OFDMRxCRC8Er 0x17c -#define rPMAC_CCKCRxRC16Er 0x180 -#define rPMAC_CCKCRxRC32Er 0x184 -#define rPMAC_CCKCRxRC32OK 0x188 -#define rPMAC_TxStatus 0x18c - -/* 2. Page2(0x200) */ -/* The following two definition are only used for USB interface. */ -#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB r/w cmd address. */ -#define RF_BB_CMD_DATA 0x02c4 /* RF/BB r/w cmd data. */ - /* 3. Page8(0x800) */ #define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */ - -#define rFPGA0_TxInfo 0x804 /* Status report?? */ -#define rFPGA0_PSDFunction 0x808 - #define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */ -#define rFPGA0_RFTiming1 0x810 /* Useless now */ -#define rFPGA0_RFTiming2 0x814 - #define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */ #define rFPGA0_XA_HSSIParameter2 0x824 #define rFPGA0_XB_HSSIParameter1 0x828 @@ -73,9 +28,6 @@ #define rFPGA0_XA_LSSIParameter 0x840 #define rFPGA0_XB_LSSIParameter 0x844 -#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */ -#define rFPGA0_RFSleepUpParameter 0x854 - #define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */ #define rFPGA0_XCD_SwitchControl 0x85c @@ -86,181 +38,63 @@ #define rFPGA0_XCD_RFInterfaceSW 0x874 #define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */ -#define rFPGA0_XCD_RFParameter 0x87c - -/* Crystal cap setting RF-R/W protection for parameter4?? */ -#define rFPGA0_AnalogParameter1 0x880 -#define rFPGA0_AnalogParameter2 0x884 -#define rFPGA0_AnalogParameter3 0x888 -/* enable ad/da clock1 for dual-phy */ -#define rFPGA0_AdDaClockEn 0x888 -#define rFPGA0_AnalogParameter4 0x88c #define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */ #define rFPGA0_XB_LSSIReadBack 0x8a4 -#define rFPGA0_XC_LSSIReadBack 0x8a8 -#define rFPGA0_XD_LSSIReadBack 0x8ac -#define rFPGA0_PSDReport 0x8b4 /* Useless now */ -/* Transceiver A HSPI Readback */ #define TransceiverA_HSPI_Readback 0x8b8 -/* Transceiver B HSPI Readback */ #define TransceiverB_HSPI_Readback 0x8bc -/* Useless now RF Interface Readback Value */ #define rFPGA0_XAB_RFInterfaceRB 0x8e0 -#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */ /* 4. Page9(0x900) */ /* RF mode & OFDM TxSC RF BW Setting?? */ #define rFPGA1_RFMOD 0x900 -#define rFPGA1_TxBlock 0x904 /* Useless now */ -#define rFPGA1_DebugSelect 0x908 /* Useless now */ -#define rFPGA1_TxInfo 0x90c /* Useless now Status report */ - /* 5. PageA(0xA00) */ /* Set Control channel to upper or lower - required only for 40MHz */ #define rCCK0_System 0xa00 -/* Disable init gain now Select RX path by RSSI */ -#define rCCK0_AFESetting 0xa04 -/* Disable init gain now Init gain */ -#define rCCK0_CCA 0xa08 - -/* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, - * RX LNA Threshold useless now. Not the same as 90 series - */ -#define rCCK0_RxAGC1 0xa0c -#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */ - -#define rCCK0_RxHP 0xa14 - -/* Timing recovery & Channel estimation threshold */ -#define rCCK0_DSPParameter1 0xa18 -#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */ - -#define rCCK0_TxFilter1 0xa20 -#define rCCK0_TxFilter2 0xa24 -#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */ -#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now */ -#define rCCK0_TRSSIReport 0xa50 -#define rCCK0_RxReport 0xa54 /* 0xa57 */ -#define rCCK0_FACounterLower 0xa5c /* 0xa5b */ -#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */ - /* */ /* PageB(0xB00) */ /* */ -#define rPdp_AntA 0xb00 -#define rPdp_AntA_4 0xb04 -#define rConfig_Pmpd_AntA 0xb28 #define rConfig_AntA 0xb68 #define rConfig_AntB 0xb6c -#define rPdp_AntB 0xb70 -#define rPdp_AntB_4 0xb74 -#define rConfig_Pmpd_AntB 0xb98 -#define rAPK 0xbd8 /* */ /* 6. PageC(0xC00) */ /* */ -#define rOFDM0_LSTF 0xc00 - #define rOFDM0_TRxPathEnable 0xc04 #define rOFDM0_TRMuxPar 0xc08 -#define rOFDM0_TRSWIsolation 0xc0c /* RxIQ DC offset, Rx digital filter, DC notch filter */ #define rOFDM0_XARxAFE 0xc10 #define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */ #define rOFDM0_XBRxAFE 0xc18 #define rOFDM0_XBRxIQImbalance 0xc1c -#define rOFDM0_XCRxAFE 0xc20 -#define rOFDM0_XCRxIQImbalance 0xc24 -#define rOFDM0_XDRxAFE 0xc28 -#define rOFDM0_XDRxIQImbalance 0xc2c - -#define rOFDM0_RxDetector1 0xc30 /*PD,BW & SBD DM tune init gain*/ -#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */ -#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */ -#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */ #define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */ -#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */ -#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */ #define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */ #define rOFDM0_XAAGCCore1 0xc50 /* DIG */ #define rOFDM0_XAAGCCore2 0xc54 #define rOFDM0_XBAGCCore1 0xc58 #define rOFDM0_XBAGCCore2 0xc5c -#define rOFDM0_XCAGCCore1 0xc60 -#define rOFDM0_XCAGCCore2 0xc64 -#define rOFDM0_XDAGCCore1 0xc68 -#define rOFDM0_XDAGCCore2 0xc6c -#define rOFDM0_AGCParameter1 0xc70 -#define rOFDM0_AGCParameter2 0xc74 #define rOFDM0_AGCRSSITable 0xc78 -#define rOFDM0_HTSTFAGC 0xc7c #define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */ #define rOFDM0_XATxAFE 0xc84 #define rOFDM0_XBTxIQImbalance 0xc88 #define rOFDM0_XBTxAFE 0xc8c -#define rOFDM0_XCTxIQImbalance 0xc90 #define rOFDM0_XCTxAFE 0xc94 -#define rOFDM0_XDTxIQImbalance 0xc98 #define rOFDM0_XDTxAFE 0xc9c #define rOFDM0_RxIQExtAnta 0xca0 -#define rOFDM0_TxCoeff1 0xca4 -#define rOFDM0_TxCoeff2 0xca8 -#define rOFDM0_TxCoeff3 0xcac -#define rOFDM0_TxCoeff4 0xcb0 -#define rOFDM0_TxCoeff5 0xcb4 -#define rOFDM0_TxCoeff6 0xcb8 -#define rOFDM0_RxHPParameter 0xce0 -#define rOFDM0_TxPseudoNoiseWgt 0xce4 -#define rOFDM0_FrameSync 0xcf0 -#define rOFDM0_DFSReport 0xcf4 - /* */ /* 7. PageD(0xD00) */ /* */ #define rOFDM1_LSTF 0xd00 -#define rOFDM1_TRxPathEnable 0xd04 - -#define rOFDM1_CFO 0xd08 /* No setting now */ -#define rOFDM1_CSI1 0xd10 -#define rOFDM1_SBD 0xd14 -#define rOFDM1_CSI2 0xd18 -#define rOFDM1_CFOTracking 0xd2c -#define rOFDM1_TRxMesaure1 0xd34 -#define rOFDM1_IntfDet 0xd3c -#define rOFDM1_PseudoNoiseStateAB 0xd50 -#define rOFDM1_PseudoNoiseStateCD 0xd54 -#define rOFDM1_RxPseudoNoiseWgt 0xd58 - -#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */ -#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */ -#define rOFDM_PHYCounter3 0xda8 /* MCS not support */ - -#define rOFDM_ShortCFOAB 0xdac /* No setting now */ -#define rOFDM_ShortCFOCD 0xdb0 -#define rOFDM_LongCFOAB 0xdb4 -#define rOFDM_LongCFOCD 0xdb8 -#define rOFDM_TailCFOAB 0xdbc -#define rOFDM_TailCFOCD 0xdc0 -#define rOFDM_PWMeasure1 0xdc4 -#define rOFDM_PWMeasure2 0xdc8 -#define rOFDM_BWReport 0xdcc -#define rOFDM_AGCReport 0xdd0 -#define rOFDM_RxSNR 0xdd4 -#define rOFDM_RxEVMCSI 0xdd8 -#define rOFDM_SIGReport 0xddc - /* */ /* 8. PageE(0xE00) */ @@ -292,10 +126,6 @@ #define rRx_IQK 0xe44 #define rIQK_AGC_Pts 0xe48 #define rIQK_AGC_Rsp 0xe4c -#define rTx_IQK_Tone_B 0xe50 -#define rRx_IQK_Tone_B 0xe54 -#define rTx_IQK_PI_B 0xe58 -#define rRx_IQK_PI_B 0xe5c #define rIQK_AGC_Cont 0xe60 #define rBlue_Tooth 0xe6c @@ -311,17 +141,13 @@ #define rTx_Power_Before_IQK_A 0xe94 #define rTx_Power_After_IQK_A 0xe9c -#define rRx_Power_Before_IQK_A 0xea0 #define rRx_Power_Before_IQK_A_2 0xea4 -#define rRx_Power_After_IQK_A 0xea8 #define rRx_Power_After_IQK_A_2 0xeac #define rTx_Power_Before_IQK_B 0xeb4 #define rTx_Power_After_IQK_B 0xebc -#define rRx_Power_Before_IQK_B 0xec0 #define rRx_Power_Before_IQK_B_2 0xec4 -#define rRx_Power_After_IQK_B 0xec8 #define rRx_Power_After_IQK_B_2 0xecc #define rRx_OFDM 0xed0 @@ -331,752 +157,45 @@ #define rSleep 0xee0 #define rPMPD_ANAEN 0xeec -/* */ -/* 7. RF Register 0x00-0x2E (RF 8256) */ -/* RF-0222D 0x00-3F */ -/* */ -/* Zebra1 */ -#define rZebra1_HSSIEnable 0x0 /* Useless now */ -#define rZebra1_TRxEnable1 0x1 -#define rZebra1_TRxEnable2 0x2 -#define rZebra1_AGC 0x4 -#define rZebra1_ChargePump 0x5 -#define rZebra1_Channel 0x7 /* RF channel switch */ - -/* endif */ -#define rZebra1_TxGain 0x8 /* Useless now */ -#define rZebra1_TxLPF 0x9 -#define rZebra1_RxLPF 0xb -#define rZebra1_RxHPFCorner 0xc - -/* Zebra4 */ -#define rGlobalCtrl 0 /* Useless now */ -#define rRTL8256_TxLPF 19 -#define rRTL8256_RxLPF 11 - -/* RTL8258 */ -#define rRTL8258_TxLPF 0x11 /* Useless now */ -#define rRTL8258_RxLPF 0x13 -#define rRTL8258_RSSILPF 0xa - /* */ /* RL6052 Register definition */ /* */ #define RF_AC 0x00 /* */ - -#define RF_IQADJ_G1 0x01 /* */ -#define RF_IQADJ_G2 0x02 /* */ - -#define RF_POW_TRSW 0x05 /* */ - -#define RF_GAIN_RX 0x06 /* */ -#define RF_GAIN_TX 0x07 /* */ - -#define RF_TXM_IDAC 0x08 /* */ -#define RF_IPA_G 0x09 /* */ -#define RF_TXBIAS_G 0x0A -#define RF_TXPA_AG 0x0B -#define RF_IPA_A 0x0C /* */ -#define RF_TXBIAS_A 0x0D -#define RF_BS_PA_APSET_G9_G11 0x0E -#define RF_BS_IQGEN 0x0F /* */ - -#define RF_MODE1 0x10 /* */ -#define RF_MODE2 0x11 /* */ - -#define RF_RX_AGC_HP 0x12 /* */ -#define RF_TX_AGC 0x13 /* */ -#define RF_BIAS 0x14 /* */ -#define RF_IPA 0x15 /* */ -#define RF_TXBIAS 0x16 -#define RF_POW_ABILITY 0x17 /* */ #define RF_CHNLBW 0x18 /* RF channel and BW switch */ -#define RF_TOP 0x19 /* */ - -#define RF_RX_G1 0x1A /* */ -#define RF_RX_G2 0x1B /* */ - -#define RF_RX_BB2 0x1C /* */ -#define RF_RX_BB1 0x1D /* */ - -#define RF_RCK1 0x1E /* */ -#define RF_RCK2 0x1F /* */ - -#define RF_TX_G1 0x20 /* */ -#define RF_TX_G2 0x21 /* */ -#define RF_TX_G3 0x22 /* */ - -#define RF_TX_BB1 0x23 /* */ - -#define RF_T_METER_92D 0x42 /* */ #define RF_T_METER_88E 0x42 /* */ -#define RF_T_METER 0x24 /* */ - -#define RF_SYN_G1 0x25 /* RF TX Power control */ -#define RF_SYN_G2 0x26 /* RF TX Power control */ -#define RF_SYN_G3 0x27 /* RF TX Power control */ -#define RF_SYN_G4 0x28 /* RF TX Power control */ -#define RF_SYN_G5 0x29 /* RF TX Power control */ -#define RF_SYN_G6 0x2A /* RF TX Power control */ -#define RF_SYN_G7 0x2B /* RF TX Power control */ -#define RF_SYN_G8 0x2C /* RF TX Power control */ - #define RF_RCK_OS 0x30 /* RF TX PA control */ #define RF_TXPA_G1 0x31 /* RF TX PA control */ #define RF_TXPA_G2 0x32 /* RF TX PA control */ -#define RF_TXPA_G3 0x33 /* RF TX PA control */ -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C /* */ -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B -#define RF_0x52 0x52 #define RF_WE_LUT 0xEF - /* */ /* Bit Mask */ /* */ -/* 1. Page1(0x100) */ -#define bBBResetB 0x100 /* Useless now? */ -#define bGlobalResetB 0x200 -#define bOFDMTxStart 0x4 -#define bCCKTxStart 0x8 -#define bCRC32Debug 0x100 -#define bPMACLoopback 0x10 -#define bTxLSIG 0xffffff -#define bOFDMTxRate 0xf -#define bOFDMTxReserved 0x10 -#define bOFDMTxLength 0x1ffe0 -#define bOFDMTxParity 0x20000 -#define bTxHTSIG1 0xffffff -#define bTxHTMCSRate 0x7f -#define bTxHTBW 0x80 -#define bTxHTLength 0xffff00 -#define bTxHTSIG2 0xffffff -#define bTxHTSmoothing 0x1 -#define bTxHTSounding 0x2 -#define bTxHTReserved 0x4 -#define bTxHTAggreation 0x8 -#define bTxHTSTBC 0x30 -#define bTxHTAdvanceCoding 0x40 -#define bTxHTShortGI 0x80 -#define bTxHTNumberHT_LTF 0x300 -#define bTxHTCRC8 0x3fc00 -#define bCounterReset 0x10000 -#define bNumOfOFDMTx 0xffff -#define bNumOfCCKTx 0xffff0000 -#define bTxIdleInterval 0xffff -#define bOFDMService 0xffff0000 -#define bTxMACHeader 0xffffffff -#define bTxDataInit 0xff -#define bTxHTMode 0x100 -#define bTxDataType 0x30000 -#define bTxRandomSeed 0xffffffff -#define bCCKTxPreamble 0x1 -#define bCCKTxSFD 0xffff0000 -#define bCCKTxSIG 0xff -#define bCCKTxService 0xff00 -#define bCCKLengthExt 0x8000 -#define bCCKTxLength 0xffff0000 -#define bCCKTxCRC16 0xffff -#define bCCKTxStatus 0x1 -#define bOFDMTxStatus 0x2 - -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) /* 2. Page8(0x800) */ #define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */ -#define bJapanMode 0x2 -#define bCCKTxSC 0x30 #define bCCKEn 0x1000000 #define bOFDMEn 0x2000000 -#define bOFDMRxADCPhase 0x10000 /* Useless now */ -#define bOFDMTxDACPhase 0x40000 -#define bXATxAGC 0x3f - -#define bAntennaSelect 0x0300 - -#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */ -#define bXCTxAGC 0xf000 -#define bXDTxAGC 0xf0000 - -#define bPAStart 0xf0000000 /* Useless now */ -#define bTRStart 0x00f00000 -#define bRFStart 0x0000f000 -#define bBBStart 0x000000f0 -#define bBBCCKStart 0x0000000f -#define bPAEnd 0xf /* Reg0x814 */ -#define bTREnd 0x0f000000 -#define bRFEnd 0x000f0000 -#define bCCAMask 0x000000f0 /* T2R */ -#define bR2RCCAMask 0x00000f00 -#define bHSSI_R2TDelay 0xf8000000 -#define bHSSI_T2RDelay 0xf80000 -#define bContTxHSSI 0x400 /* change gain at continue Tx */ -#define bIGFromCCK 0x200 -#define bAGCAddress 0x3f -#define bRxHPTx 0x7000 -#define bRxHPT2R 0x38000 -#define bRxHPCCKIni 0xc0000 -#define bAGCTxCode 0xc00000 -#define bAGCRxCode 0x300000 - -/* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */ -#define b3WireDataLength 0x800 -#define b3WireAddressLength 0x400 - -#define b3WireRFPowerDown 0x1 /* Useless now */ -#define b5GPAPEPolarity 0x40000000 -#define b2GPAPEPolarity 0x80000000 -#define bRFSW_TxDefaultAnt 0x3 -#define bRFSW_TxOptionAnt 0x30 -#define bRFSW_RxDefaultAnt 0x300 -#define bRFSW_RxOptionAnt 0x3000 -#define bRFSI_3WireData 0x1 -#define bRFSI_3WireClock 0x2 -#define bRFSI_3WireLoad 0x4 -#define bRFSI_3WireRW 0x8 -#define bRFSI_3Wire 0xf - -#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */ - -#define bRFSI_TRSW 0x20 /* Useless now */ -#define bRFSI_TRSWB 0x40 -#define bRFSI_ANTSW 0x100 -#define bRFSI_ANTSWB 0x200 -#define bRFSI_PAPE 0x400 -#define bRFSI_PAPE5G 0x800 -#define bBandSelect 0x1 -#define bHTSIG2_GI 0x80 -#define bHTSIG2_Smoothing 0x01 -#define bHTSIG2_Sounding 0x02 -#define bHTSIG2_Aggreaton 0x08 -#define bHTSIG2_STBC 0x30 -#define bHTSIG2_AdvCoding 0x40 -#define bHTSIG2_NumOfHTLTF 0x300 -#define bHTSIG2_CRC8 0x3fc -#define bHTSIG1_MCS 0x7f -#define bHTSIG1_BandWidth 0x80 -#define bHTSIG1_HTLength 0xffff -#define bLSIG_Rate 0xf -#define bLSIG_Reserved 0x10 -#define bLSIG_Length 0x1fffe -#define bLSIG_Parity 0x20 -#define bCCKRxPhase 0x4 - #define bLSSIReadAddress 0x7f800000 /* T65 RF */ - #define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */ - #define bLSSIReadBackData 0xfffff /* T65 RF */ -#define bLSSIReadOKFlag 0x1000 /* Useless now */ -#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */ -#define bRegulator0Standby 0x1 -#define bRegulatorPLLStandby 0x2 -#define bRegulator1Standby 0x4 -#define bPLLPowerUp 0x8 -#define bDPLLPowerUp 0x10 -#define bDA10PowerUp 0x20 -#define bAD7PowerUp 0x200 -#define bDA6PowerUp 0x2000 -#define bXtalPowerUp 0x4000 -#define b40MDClkPowerUP 0x8000 -#define bDA6DebugMode 0x20000 -#define bDA6Swing 0x380000 - -/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */ -#define bADClkPhase 0x4000000 - -#define b80MClkDelay 0x18000000 /* Useless */ -#define bAFEWatchDogEnable 0x20000000 - -/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */ -#define bXtalCap01 0xc0000000 -#define bXtalCap23 0x3 -#define bXtalCap92x 0x0f000000 -#define bXtalCap 0x0f000000 - -#define bIntDifClkEnable 0x400 /* Useless */ -#define bExtSigClkEnable 0x800 -#define bBandgapMbiasPowerUp 0x10000 -#define bAD11SHGain 0xc0000 -#define bAD11InputRange 0x700000 -#define bAD11OPCurrent 0x3800000 -#define bIPathLoopback 0x4000000 -#define bQPathLoopback 0x8000000 -#define bAFELoopback 0x10000000 -#define bDA10Swing 0x7e0 -#define bDA10Reverse 0x800 -#define bDAClkSource 0x1000 -#define bAD7InputRange 0x6000 -#define bAD7Gain 0x38000 -#define bAD7OutputCMMode 0x40000 -#define bAD7InputCMMode 0x380000 -#define bAD7Current 0xc00000 -#define bRegulatorAdjust 0x7000000 -#define bAD11PowerUpAtTx 0x1 -#define bDA10PSAtTx 0x10 -#define bAD11PowerUpAtRx 0x100 -#define bDA10PSAtRx 0x1000 -#define bCCKRxAGCFormat 0x200 -#define bPSDFFTSamplepPoint 0xc000 -#define bPSDAverageNum 0x3000 -#define bIQPathControl 0xc00 -#define bPSDFreq 0x3ff -#define bPSDAntennaPath 0x30 -#define bPSDIQSwitch 0x40 -#define bPSDRxTrigger 0x400000 -#define bPSDTxTrigger 0x80000000 -#define bPSDSineToneScale 0x7f000000 -#define bPSDReport 0xffff - -/* 3. Page9(0x900) */ -#define bOFDMTxSC 0x30000000 /* Useless */ -#define bCCKTxOn 0x1 -#define bOFDMTxOn 0x2 -#define bDebugPage 0xfff /* reset debug page and HWord, LWord */ -#define bDebugItem 0xff /* reset debug page and LWord */ -#define bAntL 0x10 -#define bAntNonHT 0x100 -#define bAntHT1 0x1000 -#define bAntHT2 0x10000 -#define bAntHT1S1 0x100000 -#define bAntNonHTS1 0x1000000 - -/* 4. PageA(0xA00) */ -#define bCCKBBMode 0x3 /* Useless */ -#define bCCKTxPowerSaving 0x80 -#define bCCKRxPowerSaving 0x40 - #define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */ -#define bCCKScramble 0x8 /* Useless */ -#define bCCKAntDiversity 0x8000 -#define bCCKCarrierRecovery 0x4000 -#define bCCKTxRate 0x3000 -#define bCCKDCCancel 0x0800 -#define bCCKISICancel 0x0400 -#define bCCKMatchFilter 0x0200 -#define bCCKEqualizer 0x0100 -#define bCCKPreambleDetect 0x800000 -#define bCCKFastFalseCCA 0x400000 -#define bCCKChEstStart 0x300000 -#define bCCKCCACount 0x080000 -#define bCCKcs_lim 0x070000 -#define bCCKBistMode 0x80000000 -#define bCCKCCAMask 0x40000000 -#define bCCKTxDACPhase 0x4 -#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */ -#define bCCKr_cp_mode0 0x0100 -#define bCCKTxDCOffset 0xf0 -#define bCCKRxDCOffset 0xf -#define bCCKCCAMode 0xc000 -#define bCCKFalseCS_lim 0x3f00 -#define bCCKCS_ratio 0xc00000 -#define bCCKCorgBit_sel 0x300000 -#define bCCKPD_lim 0x0f0000 -#define bCCKNewCCA 0x80000000 -#define bCCKRxHPofIG 0x8000 -#define bCCKRxIG 0x7f00 -#define bCCKLNAPolarity 0x800000 -#define bCCKRx1stGain 0x7f0000 -#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */ -#define bCCKRxAGCSatLevel 0x1f000000 -#define bCCKRxAGCSatCount 0xe0 -#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */ -#define bCCKFixedRxAGC 0x8000 -#define bCCKAntennaPolarity 0x2000 -#define bCCKTxFilterType 0x0c00 -#define bCCKRxAGCReportType 0x0300 -#define bCCKRxDAGCEn 0x80000000 -#define bCCKRxDAGCPeriod 0x20000000 -#define bCCKRxDAGCSatLevel 0x1f000000 -#define bCCKTimingRecovery 0x800000 -#define bCCKTxC0 0x3f0000 -#define bCCKTxC1 0x3f000000 -#define bCCKTxC2 0x3f -#define bCCKTxC3 0x3f00 -#define bCCKTxC4 0x3f0000 -#define bCCKTxC5 0x3f000000 -#define bCCKTxC6 0x3f -#define bCCKTxC7 0x3f00 -#define bCCKDebugPort 0xff0000 -#define bCCKDACDebug 0x0f000000 -#define bCCKFalseAlarmEnable 0x8000 -#define bCCKFalseAlarmRead 0x4000 -#define bCCKTRSSI 0x7f -#define bCCKRxAGCReport 0xfe -#define bCCKRxReport_AntSel 0x80000000 -#define bCCKRxReport_MFOff 0x40000000 -#define bCCKRxRxReport_SQLoss 0x20000000 -#define bCCKRxReport_Pktloss 0x10000000 -#define bCCKRxReport_Lockedbit 0x08000000 -#define bCCKRxReport_RateError 0x04000000 -#define bCCKRxReport_RxRate 0x03000000 -#define bCCKRxFACounterLower 0xff -#define bCCKRxFACounterUpper 0xff000000 -#define bCCKRxHPAGCStart 0xe000 -#define bCCKRxHPAGCFinal 0x1c00 -#define bCCKRxFalseAlarmEnable 0x8000 -#define bCCKFACounterFreeze 0x4000 -#define bCCKTxPathSel 0x10000000 -#define bCCKDefaultRxPath 0xc000000 -#define bCCKOptionRxPath 0x3000000 - -/* 5. PageC(0xC00) */ -#define bNumOfSTF 0x3 /* Useless */ -#define bShift_L 0xc0 -#define bGI_TH 0xc -#define bRxPathA 0x1 -#define bRxPathB 0x2 -#define bRxPathC 0x4 -#define bRxPathD 0x8 -#define bTxPathA 0x1 -#define bTxPathB 0x2 -#define bTxPathC 0x4 -#define bTxPathD 0x8 -#define bTRSSIFreq 0x200 -#define bADCBackoff 0x3000 -#define bDFIRBackoff 0xc000 -#define bTRSSILatchPhase 0x10000 -#define bRxIDCOffset 0xff -#define bRxQDCOffset 0xff00 -#define bRxDFIRMode 0x1800000 -#define bRxDCNFType 0xe000000 -#define bRXIQImb_A 0x3ff -#define bRXIQImb_B 0xfc00 -#define bRXIQImb_C 0x3f0000 -#define bRXIQImb_D 0xffc00000 -#define bDC_dc_Notch 0x60000 -#define bRxNBINotch 0x1f000000 -#define bPD_TH 0xf -#define bPD_TH_Opt2 0xc000 -#define bPWED_TH 0x700 -#define bIfMF_Win_L 0x800 -#define bPD_Option 0x1000 -#define bMF_Win_L 0xe000 -#define bBW_Search_L 0x30000 -#define bwin_enh_L 0xc0000 -#define bBW_TH 0x700000 -#define bED_TH2 0x3800000 -#define bBW_option 0x4000000 -#define bRatio_TH 0x18000000 -#define bWindow_L 0xe0000000 -#define bSBD_Option 0x1 -#define bFrame_TH 0x1c -#define bFS_Option 0x60 -#define bDC_Slope_check 0x80 -#define bFGuard_Counter_DC_L 0xe00 -#define bFrame_Weight_Short 0x7000 -#define bSub_Tune 0xe00000 -#define bFrame_DC_Length 0xe000000 -#define bSBD_start_offset 0x30000000 -#define bFrame_TH_2 0x7 -#define bFrame_GI2_TH 0x38 -#define bGI2_Sync_en 0x40 -#define bSarch_Short_Early 0x300 -#define bSarch_Short_Late 0xc00 -#define bSarch_GI2_Late 0x70000 -#define bCFOAntSum 0x1 -#define bCFOAcc 0x2 -#define bCFOStartOffset 0xc -#define bCFOLookBack 0x70 -#define bCFOSumWeight 0x80 -#define bDAGCEnable 0x10000 -#define bTXIQImb_A 0x3ff -#define bTXIQImb_B 0xfc00 -#define bTXIQImb_C 0x3f0000 -#define bTXIQImb_D 0xffc00000 -#define bTxIDCOffset 0xff -#define bTxQDCOffset 0xff00 -#define bTxDFIRMode 0x10000 -#define bTxPesudoNoiseOn 0x4000000 -#define bTxPesudoNoise_A 0xff -#define bTxPesudoNoise_B 0xff00 -#define bTxPesudoNoise_C 0xff0000 -#define bTxPesudoNoise_D 0xff000000 -#define bCCADropOption 0x20000 -#define bCCADropThres 0xfff00000 -#define bEDCCA_H 0xf -#define bEDCCA_L 0xf0 -#define bLambda_ED 0x300 -#define bRxInitialGain 0x7f -#define bRxAntDivEn 0x80 -#define bRxAGCAddressForLNA 0x7f00 -#define bRxHighPowerFlow 0x8000 -#define bRxAGCFreezeThres 0xc0000 -#define bRxFreezeStep_AGC1 0x300000 -#define bRxFreezeStep_AGC2 0xc00000 -#define bRxFreezeStep_AGC3 0x3000000 -#define bRxFreezeStep_AGC0 0xc000000 -#define bRxRssi_Cmp_En 0x10000000 -#define bRxQuickAGCEn 0x20000000 -#define bRxAGCFreezeThresMode 0x40000000 -#define bRxOverFlowCheckType 0x80000000 -#define bRxAGCShift 0x7f -#define bTRSW_Tri_Only 0x80 -#define bPowerThres 0x300 -#define bRxAGCEn 0x1 -#define bRxAGCTogetherEn 0x2 -#define bRxAGCMin 0x4 -#define bRxHP_Ini 0x7 -#define bRxHP_TRLNA 0x70 -#define bRxHP_RSSI 0x700 -#define bRxHP_BBP1 0x7000 -#define bRxHP_BBP2 0x70000 -#define bRxHP_BBP3 0x700000 -#define bRSSI_H 0x7f0000 /* threshold for high power */ -#define bRSSI_Gen 0x7f000000 /* threshold for ant diversity */ -#define bRxSettle_TRSW 0x7 -#define bRxSettle_LNA 0x38 -#define bRxSettle_RSSI 0x1c0 -#define bRxSettle_BBP 0xe00 -#define bRxSettle_RxHP 0x7000 -#define bRxSettle_AntSW_RSSI 0x38000 -#define bRxSettle_AntSW 0xc0000 -#define bRxProcessTime_DAGC 0x300000 -#define bRxSettle_HSSI 0x400000 -#define bRxProcessTime_BBPPW 0x800000 -#define bRxAntennaPowerShift 0x3000000 -#define bRSSITableSelect 0xc000000 -#define bRxHP_Final 0x7000000 -#define bRxHTSettle_BBP 0x7 -#define bRxHTSettle_HSSI 0x8 -#define bRxHTSettle_RxHP 0x70 -#define bRxHTSettle_BBPPW 0x80 -#define bRxHTSettle_Idle 0x300 -#define bRxHTSettle_Reserved 0x1c00 -#define bRxHTRxHPEn 0x8000 -#define bRxHTAGCFreezeThres 0x30000 -#define bRxHTAGCTogetherEn 0x40000 -#define bRxHTAGCMin 0x80000 -#define bRxHTAGCEn 0x100000 -#define bRxHTDAGCEn 0x200000 -#define bRxHTRxHP_BBP 0x1c00000 -#define bRxHTRxHP_Final 0xe0000000 -#define bRxPWRatioTH 0x3 -#define bRxPWRatioEn 0x4 -#define bRxMFHold 0x3800 -#define bRxPD_Delay_TH1 0x38 -#define bRxPD_Delay_TH2 0x1c0 -#define bRxPD_DC_COUNT_MAX 0x600 -#define bRxPD_Delay_TH 0x8000 -#define bRxProcess_Delay 0xf0000 -#define bRxSearchrange_GI2_Early 0x700000 -#define bRxFrame_Guard_Counter_L 0x3800000 -#define bRxSGI_Guard_L 0xc000000 -#define bRxSGI_Search_L 0x30000000 -#define bRxSGI_TH 0xc0000000 -#define bDFSCnt0 0xff -#define bDFSCnt1 0xff00 -#define bDFSFlag 0xf0000 -#define bMFWeightSum 0x300000 -#define bMinIdxTH 0x7f000000 -#define bDAFormat 0x40000 -#define bTxChEmuEnable 0x01000000 -#define bTRSWIsolation_A 0x7f -#define bTRSWIsolation_B 0x7f00 -#define bTRSWIsolation_C 0x7f0000 -#define bTRSWIsolation_D 0x7f000000 -#define bExtLNAGain 0x7c00 - -/* 6. PageE(0xE00) */ -#define bSTBCEn 0x4 /* Useless */ -#define bAntennaMapping 0x10 -#define bNss 0x20 -#define bCFOAntSumD 0x200 -#define bPHYCounterReset 0x8000000 -#define bCFOReportGet 0x4000000 -#define bOFDMContinueTx 0x10000000 -#define bOFDMSingleCarrier 0x20000000 -#define bOFDMSingleTone 0x40000000 -#define bHTDetect 0x100 -#define bCFOEn 0x10000 -#define bCFOValue 0xfff00000 -#define bSigTone_Re 0x3f -#define bSigTone_Im 0x7f00 -#define bCounter_CCA 0xffff -#define bCounter_ParityFail 0xffff0000 -#define bCounter_RateIllegal 0xffff -#define bCounter_CRC8Fail 0xffff0000 -#define bCounter_MCSNoSupport 0xffff -#define bCounter_FastSync 0xffff -#define bShortCFO 0xfff -#define bShortCFOTLength 12 /* total */ -#define bShortCFOFLength 11 /* fraction */ -#define bLongCFO 0x7ff -#define bLongCFOTLength 11 -#define bLongCFOFLength 11 -#define bTailCFO 0x1fff -#define bTailCFOTLength 13 -#define bTailCFOFLength 12 -#define bmax_en_pwdB 0xffff -#define bCC_power_dB 0xffff0000 -#define bnoise_pwdB 0xffff -#define bPowerMeasTLength 10 -#define bPowerMeasFLength 3 -#define bRx_HT_BW 0x1 -#define bRxSC 0x6 -#define bRx_HT 0x8 -#define bNB_intf_det_on 0x1 -#define bIntf_win_len_cfg 0x30 -#define bNB_Intf_TH_cfg 0x1c0 -#define bRFGain 0x3f -#define bTableSel 0x40 -#define bTRSW 0x80 -#define bRxSNR_A 0xff -#define bRxSNR_B 0xff00 -#define bRxSNR_C 0xff0000 -#define bRxSNR_D 0xff000000 -#define bSNREVMTLength 8 -#define bSNREVMFLength 1 -#define bCSI1st 0xff -#define bCSI2nd 0xff00 -#define bRxEVM1st 0xff0000 -#define bRxEVM2nd 0xff000000 -#define bSIGEVM 0xff -#define bPWDB 0xff00 -#define bSGIEN 0x10000 - -#define bSFactorQAM1 0xf /* Useless */ -#define bSFactorQAM2 0xf0 -#define bSFactorQAM3 0xf00 -#define bSFactorQAM4 0xf000 -#define bSFactorQAM5 0xf0000 -#define bSFactorQAM6 0xf0000 -#define bSFactorQAM7 0xf00000 -#define bSFactorQAM8 0xf000000 -#define bSFactorQAM9 0xf0000000 -#define bCSIScheme 0x100000 - -#define bNoiseLvlTopSet 0x3 /* Useless */ -#define bChSmooth 0x4 -#define bChSmoothCfg1 0x38 -#define bChSmoothCfg2 0x1c0 -#define bChSmoothCfg3 0xe00 -#define bChSmoothCfg4 0x7000 -#define bMRCMode 0x800000 -#define bTHEVMCfg 0x7000000 - -#define bLoopFitType 0x1 /* Useless */ -#define bUpdCFO 0x40 -#define bUpdCFOOffData 0x80 -#define bAdvUpdCFO 0x100 -#define bAdvTimeCtrl 0x800 -#define bUpdClko 0x1000 -#define bFC 0x6000 -#define bTrackingMode 0x8000 -#define bPhCmpEnable 0x10000 -#define bUpdClkoLTF 0x20000 -#define bComChCFO 0x40000 -#define bCSIEstiMode 0x80000 -#define bAdvUpdEqz 0x100000 -#define bUChCfg 0x7000000 -#define bUpdEqz 0x8000000 - -/* Rx Pseduo noise */ -#define bRxPesudoNoiseOn 0x20000000 /* Useless */ -#define bRxPesudoNoise_A 0xff -#define bRxPesudoNoise_B 0xff00 -#define bRxPesudoNoise_C 0xff0000 -#define bRxPesudoNoise_D 0xff000000 -#define bPesudoNoiseState_A 0xffff -#define bPesudoNoiseState_B 0xffff0000 -#define bPesudoNoiseState_C 0xffff -#define bPesudoNoiseState_D 0xffff0000 - -/* 7. RF Register */ -/* Zebra1 */ -#define bZebra1_HSSIEnable 0x8 /* Useless */ -#define bZebra1_TRxControl 0xc00 -#define bZebra1_TRxGainSetting 0x07f -#define bZebra1_RxCorner 0xc00 -#define bZebra1_TxChargePump 0x38 -#define bZebra1_RxChargePump 0x7 -#define bZebra1_ChannelNum 0xf80 -#define bZebra1_TxLPFBW 0x400 -#define bZebra1_RxLPFBW 0x600 - -/* Zebra4 */ -#define bRTL8256RegModeCtrl1 0x100 /* Useless */ -#define bRTL8256RegModeCtrl0 0x40 -#define bRTL8256_TxLPFBW 0x18 -#define bRTL8256_RxLPFBW 0x600 - -/* RTL8258 */ -#define bRTL8258_TxLPFBW 0xc /* Useless */ -#define bRTL8258_RxLPFBW 0xc00 -#define bRTL8258_RSSILPFBW 0xc0 - - /* */ /* Other Definition */ /* */ -/* byte endable for sb_write */ -#define bByte0 0x1 /* Useless */ -#define bByte1 0x2 -#define bByte2 0x4 -#define bByte3 0x8 -#define bWord0 0x3 -#define bWord1 0xc -#define bDWord 0xf - /* for PutRegsetting & GetRegSetting BitMask */ #define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */ #define bMaskByte1 0xff00 -#define bMaskByte2 0xff0000 #define bMaskByte3 0xff000000 -#define bMaskHWord 0xffff0000 -#define bMaskLWord 0x0000ffff #define bMaskDWord 0xffffffff #define bMask12Bits 0xfff -#define bMaskH4Bits 0xf0000000 #define bMaskOFDM_D 0xffc00000 -#define bMaskCCK 0x3f3f3f3f /* for PutRFRegsetting & GetRFRegSetting BitMask */ #define bRFRegOffsetMask 0xfffff -#define bEnable 0x1 /* Useless */ -#define bDisable 0x0 - -#define LeftAntenna 0x0 /* Useless */ -#define RightAntenna 0x1 - -#define tCheckTxStatus 500 /* 500ms Useless */ -#define tUpdateRxCounter 100 /* 100ms */ - -#define rateCCK 0 /* Useless */ -#define rateOFDM 1 -#define rateHT 2 - -/* define Register-End */ -#define bPMAC_End 0x1ff /* Useless */ -#define bFPGAPHY0_End 0x8ff -#define bFPGAPHY1_End 0x9ff -#define bCCKPHY0_End 0xaff -#define bOFDMPHY0_End 0xcff -#define bOFDMPHY1_End 0xdff - -#define bPMACControl 0x0 /* Useless */ -#define bWMACControl 0x1 -#define bWNICControl 0x2 - -#define PathA 0x0 /* Useless */ -#define PathB 0x1 -#define PathC 0x2 -#define PathD 0x3 - -/*--------------------------Define Parameters-------------------------------*/ - - #endif -- cgit v1.2.3-59-g8ed1b From d59381d639af22da6eb49c5d851faf15feb6b462 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 11 Jul 2019 22:07:26 +0800 Subject: staging: kpc2000: kpc_spi: Remove unnecessary null check before kfree A null check before a kfree is redundant, so remove it. This is detected by coccinelle. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190711140726.46732-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000_spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c index 35ac1d7070b3..3be33c450cab 100644 --- a/drivers/staging/kpc2000/kpc2000_spi.c +++ b/drivers/staging/kpc2000/kpc2000_spi.c @@ -412,8 +412,7 @@ kp_spi_cleanup(struct spi_device *spidev) { struct kp_spi_controller_state *cs = spidev->controller_state; - if (cs) - kfree(cs); + kfree(cs); } /****************** -- cgit v1.2.3-59-g8ed1b From 2e7a3f1158eecb0675199d7b030f3ef9db82eb25 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 14 Jul 2019 22:54:51 +0530 Subject: staging: rtl8723bs: hal: Remove code valid only for 5GHz As per TODO ,remove code valid only for 5 GHz(channel > 14). Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190714172451.GA6779@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_com.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index 638b12ae6ee9..eddd56abbb2d 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c @@ -152,10 +152,7 @@ bool HAL_IsLegalChannel(struct adapter *Adapter, u32 Channel) { bool bLegalChannel = true; - if (Channel > 14) { - bLegalChannel = false; - DBG_871X("Channel > 14 but wireless_mode do not support 5G\n"); - } else if ((Channel <= 14) && (Channel >= 1)) { + if ((Channel <= 14) && (Channel >= 1)) { if (IsSupported24G(Adapter->registrypriv.wireless_mode) == false) { bLegalChannel = false; DBG_871X("(Channel <= 14) && (Channel >= 1) but wireless_mode do not support 2.4G\n"); -- cgit v1.2.3-59-g8ed1b From 2615f966f9f27b30de7d9c10316bf482d1d2964e Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 14 Jul 2019 22:58:26 +0530 Subject: staging: rtl8723bs: core: Remove code valid only for 5GHz As per TODO ,remove code valid only for 5 GHz(channel > 14). Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190714172826.GA6950@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 4285844420cb..967da715ffa4 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -295,11 +295,7 @@ static void init_mlme_ext_priv_value(struct adapter *padapter) init_mlme_default_rate_set(padapter); - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - + pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; pmlmeext->sitesurvey_res.state = SCAN_DISABLE; pmlmeext->sitesurvey_res.channel_idx = 0; pmlmeext->sitesurvey_res.bss_cnt = 0; -- cgit v1.2.3-59-g8ed1b From b21f9b8352aa189e708c4ccfb5216b56880a1851 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 14 Jul 2019 23:01:34 +0530 Subject: staging: rtl8723bs: os_dep: Remove code valid only for 5GHz As per TODO ,remove code valid only for 5 GHz(channel > 14). Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190714173134.GA7111@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 544e799d0a03..18d61e5722f5 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -239,9 +239,6 @@ static void loadparam(struct adapter *padapter, _nic_hdl pnetdev) registry_par->channel = (u8)rtw_channel; registry_par->wireless_mode = (u8)rtw_wireless_mode; - if (registry_par->channel > 14) - registry_par->channel = 1; - registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense ; registry_par->vcs_type = (u8)rtw_vcs_type; registry_par->rts_thresh = (u16)rtw_rts_thresh; -- cgit v1.2.3-59-g8ed1b From 067756acdac8e0dd91edf4800e844fcb6e0cc72a Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Mon, 15 Jul 2019 23:16:18 +0530 Subject: staging: rtl8723bs: core: Change return type of init_mlme_ext_priv As init_mlme_ext_priv function always returns SUCCESS , We can change return type from int to void. Fixes below issue identified by coccicheck drivers/staging/rtl8723bs/core/rtw_mlme_ext.c:464:5-8: Unneeded variable: "res". Return "_SUCCESS" on line 492 Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190715174618.GA8947@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 6 +----- drivers/staging/rtl8723bs/include/rtw_mlme_ext.h | 2 +- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 6 +----- 3 files changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 967da715ffa4..6d0014251f86 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -455,9 +455,8 @@ static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_ return chanset_size; } -int init_mlme_ext_priv(struct adapter *padapter) +void init_mlme_ext_priv(struct adapter *padapter) { - int res = _SUCCESS; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -484,9 +483,6 @@ int init_mlme_ext_priv(struct adapter *padapter) #ifdef DBG_FIXED_CHAN pmlmeext->fixed_chan = 0xFF; #endif - - return res; - } void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 733bb9425448..70cd8c0e3641 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -535,7 +535,7 @@ struct mlme_ext_priv }; void init_mlme_default_rate_set(struct adapter *padapter); -int init_mlme_ext_priv(struct adapter *padapter); +void init_mlme_ext_priv(struct adapter *padapter); int init_hw_mlme_ext(struct adapter *padapter); void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext); extern void init_mlme_ext_timer(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 18d61e5722f5..50928b2000b9 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -765,11 +765,7 @@ u8 rtw_init_drv_sw(struct adapter *padapter) goto exit; } - if (init_mlme_ext_priv(padapter) == _FAIL) { - RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_ext_priv\n")); - ret8 = _FAIL; - goto exit; - } + init_mlme_ext_priv(padapter); if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) { DBG_871X("Can't _rtw_init_xmit_priv\n"); -- cgit v1.2.3-59-g8ed1b From 6290da3e439d5aa4a692196b61f34a3b6e8e9b1c Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:38 +0530 Subject: staging: rtl8188eu: core: Replace function Set_MSR() Change reference to Set_NETYPE0_MSR to Set_MSR. Replace the contents of Set_MSR with the contents of Set_NETYPE0_MSR as Set_MSR does nothing but call Set_NETYPE0_MSR. Delete Set_NETYPE0_MSR. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 2 +- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 6f3c03201f64..18dc9fc1c04a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4854,7 +4854,7 @@ u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) } rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); - /* Set_NETYPE0_MSR(padapter, type); */ + /* Set_MSR(padapter, type); */ return H2C_SUCCESS; } diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 7bfc5b7c2757..b75568efb46f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -270,14 +270,9 @@ void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable) rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode)); } -static void Set_NETYPE0_MSR(struct adapter *padapter, u8 type) -{ - rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type)); -} - void Set_MSR(struct adapter *padapter, u8 type) { - Set_NETYPE0_MSR(padapter, type); + rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type)); } inline u8 rtw_get_oper_ch(struct adapter *adapter) -- cgit v1.2.3-59-g8ed1b From d6a496f937523048aab1fef0df74786b0ae6fe17 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:39 +0530 Subject: staging: rtl8188eu: core: Remove function enable_rate_adaptive() Remove function enable_rate_adaptive as it does nothing except call Update_RA_Entry. Modify call site of enable_rate_adaptive to call Update_RA_Entry instead. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index b75568efb46f..1f2763ff2a70 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1174,15 +1174,10 @@ void Update_RA_Entry(struct adapter *padapter, u32 mac_id) rtw_hal_update_ra_mask(padapter, mac_id, 0); } -static void enable_rate_adaptive(struct adapter *padapter, u32 mac_id) -{ - Update_RA_Entry(padapter, mac_id); -} - void set_sta_rate(struct adapter *padapter, struct sta_info *psta) { /* rate adaptive */ - enable_rate_adaptive(padapter, psta->mac_id); + Update_RA_Entry(padapter, psta->mac_id); } /* Update RRSR and Rate for USERATE */ -- cgit v1.2.3-59-g8ed1b From 01625b0bbb523e6ce2818d4691812f66fe9c42b4 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:40 +0530 Subject: staging: rtl8188eu: Replace function beacon_timing_control() Remove function beacon_timing_control as all it does is call rtw_hal_bcn_related_reg_setting. Rename rtw_hal_bcn_related_reg_setting to beacon_timing_control for compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 5 ----- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/hal_intf.h | 2 +- drivers/staging/rtl8188eu/include/rtw_mlme_ext.h | 1 - 4 files changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 1f2763ff2a70..c985b1468d41 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1466,8 +1466,3 @@ void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext) { rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL); } - -void beacon_timing_control(struct adapter *padapter) -{ - rtw_hal_bcn_related_reg_setting(padapter); -} diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index ac5552050752..89babcb12d02 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1934,7 +1934,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) psta->init_rate = init_rate; } -void rtw_hal_bcn_related_reg_setting(struct adapter *adapt) +void beacon_timing_control(struct adapter *adapt) { u32 value32; struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv; diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h index 8b65fcba1967..516a89647003 100644 --- a/drivers/staging/rtl8188eu/include/hal_intf.h +++ b/drivers/staging/rtl8188eu/include/hal_intf.h @@ -199,7 +199,7 @@ void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level); void rtw_hal_clone_data(struct adapter *dst_adapt, struct adapter *src_adapt); -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter); +void beacon_timing_control(struct adapter *padapter); u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath, u32 RegAddr, u32 BitMask); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 327f7d1bc20c..d70780c8fd62 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -535,7 +535,6 @@ void report_del_sta_event(struct adapter *padapter, void report_add_sta_event(struct adapter *padapter, unsigned char *addr, int cam_idx); -void beacon_timing_control(struct adapter *padapter); u8 set_tx_beacon_cmd(struct adapter *padapter); unsigned int setup_beacon_frame(struct adapter *padapter, unsigned char *beacon_frame); -- cgit v1.2.3-59-g8ed1b From c6255d2d2432623ee50f48970c51050e979befc3 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:41 +0530 Subject: staging: rtl8188eu: Remove function rtw_os_indicate_scan_done() In function rtw_indicate_scan_done, replace call to rtw_os_indicate_scan_done with call to indicate_wx_scan_complete_event as all that rtw_os_indicate_scan_done does is call indicate_wx_scan_complete_event. Remove now-unused function rtw_os_indicate_scan_done. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme.c | 2 +- drivers/staging/rtl8188eu/include/mlme_osdep.h | 1 - drivers/staging/rtl8188eu/os_dep/mlme_linux.c | 5 ----- 3 files changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index d2f7a88e992e..43c7531e777e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -827,7 +827,7 @@ void rtw_indicate_disconnect(struct adapter *padapter) inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted) { - rtw_os_indicate_scan_done(padapter, aborted); + indicate_wx_scan_complete_event(padapter); } static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork) diff --git a/drivers/staging/rtl8188eu/include/mlme_osdep.h b/drivers/staging/rtl8188eu/include/mlme_osdep.h index eda16c06336a..8e919441c2aa 100644 --- a/drivers/staging/rtl8188eu/include/mlme_osdep.h +++ b/drivers/staging/rtl8188eu/include/mlme_osdep.h @@ -13,7 +13,6 @@ void rtw_init_mlme_timer(struct adapter *padapter); void rtw_os_indicate_disconnect(struct adapter *adapter); void rtw_os_indicate_connect(struct adapter *adapter); -void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted); void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie); void rtw_reset_securitypriv(struct adapter *adapter); diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c index e660bd4d91ef..321b2c46479c 100644 --- a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c @@ -27,11 +27,6 @@ void rtw_os_indicate_connect(struct adapter *adapter) netif_carrier_on(adapter->pnetdev); } -void rtw_os_indicate_scan_done(struct adapter *padapter, bool aborted) -{ - indicate_wx_scan_complete_event(padapter); -} - static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE]; void rtw_reset_securitypriv(struct adapter *adapter) -- cgit v1.2.3-59-g8ed1b From 04c8c1985618b45e59433d6c46e3f787e146017e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:42 +0530 Subject: staging: rtl8188eu: Remove function rtw_modular64() Remove function rtw_modular64 as all it does is call do_div. Replace call to rtw_modular64 with call to do_div. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- drivers/staging/rtl8188eu/include/osdep_service.h | 2 -- drivers/staging/rtl8188eu/os_dep/osdep_service.c | 5 ----- 3 files changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 89babcb12d02..994392ac249b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1298,7 +1298,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - tsf = pmlmeext->TSFValue - rtw_modular64(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ + tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index cfe5698fbbb1..c0114ad79788 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -80,8 +80,6 @@ void rtw_free_netdev(struct net_device *netdev); #define FUNC_ADPT_FMT "%s(%s)" #define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name -u64 rtw_modular64(u64 x, u64 y); - /* Macros for handling unaligned memory accesses */ #define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c index 105f3f21bdea..69d4b1d66b6f 100644 --- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c +++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c @@ -59,11 +59,6 @@ RETURN: return; } -u64 rtw_modular64(u64 x, u64 y) -{ - return do_div(x, y); -} - void rtw_buf_free(u8 **buf, u32 *buf_len) { *buf_len = 0; -- cgit v1.2.3-59-g8ed1b From 5cace672b9a4da8586ade62d3a7f204a4adced2e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:43 +0530 Subject: staging: rtl8188eu: Replace function rtw_alloc_network() Change external call site of _rtw_alloc_network to rtw_alloc_network. Remove function rtw_alloc_network as all it does is call _rtw_alloc_network. Rename _rtw_alloc_network to rtw_alloc_network to maintain compatibility with call sites. Keep its type as non-static (even though the old rtw_alloc_network was static) as this functionality is used in other files as well. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_cmd.c | 2 +- drivers/staging/rtl8188eu/core/rtw_mlme.c | 9 ++------- drivers/staging/rtl8188eu/include/rtw_mlme.h | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index a24b40761af2..815dfee11968 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -1200,7 +1200,7 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd) rtw_indicate_connect(padapter); } else { - pwlan = _rtw_alloc_network(pmlmepriv); + pwlan = rtw_alloc_network(pmlmepriv); spin_lock_bh(&pmlmepriv->scanned_queue.lock); if (!pwlan) { pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue); diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index 43c7531e777e..1ec3b237212e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -104,7 +104,7 @@ void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) } } -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) +struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) /* _queue *free_queue) */ { struct wlan_network *pnetwork; @@ -119,7 +119,7 @@ struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) list_del_init(&pnetwork->list); RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, - ("_rtw_alloc_network: ptr=%p\n", &pnetwork->list)); + ("rtw_alloc_network: ptr=%p\n", &pnetwork->list)); pnetwork->network_type = 0; pnetwork->fixed = false; pnetwork->last_scanned = jiffies; @@ -272,11 +272,6 @@ u8 *rtw_get_beacon_interval_from_ie(u8 *ie) return ie + 8; } -static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv) -{ - return _rtw_alloc_network(pmlmepriv); -} - int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork) { int ret = true; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h index 9abb7c320192..010f0c42368a 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h @@ -333,7 +333,7 @@ void rtw_dynamic_check_timer_handlder(struct timer_list *t); void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv); -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv); +struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv); int rtw_if_up(struct adapter *padapter); -- cgit v1.2.3-59-g8ed1b From 792d89ee4bd6ca4ba803a9f522cf9d0a35dd763f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:44 +0530 Subject: staging: rtl8188eu: Replace function rtl88e_phy_rf6052_config() Remove function rtl88e_phy_rf6052_config as all it does is call rf6052_conf_para. Rename rf6052_conf_para to rtl88e_phy_rf6052_config to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf_cfg.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 02aeb12c9870..89ee74e795f8 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -218,7 +218,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) return true; } -static bool rf6052_conf_para(struct adapter *adapt) +static bool rtl88e_phy_rf6052_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; @@ -247,11 +247,6 @@ static bool rf6052_conf_para(struct adapter *adapt) return rtstatus; } -static bool rtl88e_phy_rf6052_config(struct adapter *adapt) -{ - return rf6052_conf_para(adapt); -} - bool rtl88eu_phy_rf_config(struct adapter *adapt) { return rtl88e_phy_rf6052_config(adapt); -- cgit v1.2.3-59-g8ed1b From 384329ddc42ad91a9f1f0eab3c53ce0b0402bc60 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 12 Jul 2019 12:47:45 +0530 Subject: staging: rtl8188eu: Replace function rtl88eu_phy_rf_config() Remove function rtl88eu_phy_rf_config as all it does is call rtl88e_phy_rf6052_config. Rename rtl88e_phy_rf6052_config to rtl88eu_phy_rf_config and change its type from static to non-static to maintain compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190712071746.2474-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf_cfg.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 89ee74e795f8..739e62dc60e3 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -218,7 +218,7 @@ static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt) return true; } -static bool rtl88e_phy_rf6052_config(struct adapter *adapt) +bool rtl88eu_phy_rf_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; @@ -246,8 +246,3 @@ static bool rtl88e_phy_rf6052_config(struct adapter *adapt) return rtstatus; } - -bool rtl88eu_phy_rf_config(struct adapter *adapt) -{ - return rtl88e_phy_rf6052_config(adapt); -} -- cgit v1.2.3-59-g8ed1b From 44a22dc3dd890ff476e708e39895c2536ad99cf2 Mon Sep 17 00:00:00 2001 From: Benjamin Sherman Date: Tue, 16 Jul 2019 00:57:55 -0400 Subject: staging: vt6656: change alignment to match parenthesis Change indentation to match parentheses. This complies with the Linux kernel coding style and improves readability. Signed-off-by: Benjamin Sherman Link: https://lore.kernel.org/r/20190716045754.fivh5n44bybe2uce@valkyrie-mobile.localdomain Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/rxtx.c | 10 +++++----- drivers/staging/vt6656/usbpipe.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9def0748ffee..4e9cfacf75f2 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -287,12 +287,12 @@ static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context, buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type, need_ack); buf->duration_b = vnt_get_duration_le(priv, - PK_TYPE_11B, need_ack); + PK_TYPE_11B, need_ack); } buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); + priv->top_cck_basic_rate); tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); @@ -325,7 +325,7 @@ static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context, buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate); buf->time_stamp_off_b = vnt_time_stamp_off(priv, - priv->top_cck_basic_rate); + priv->top_cck_basic_rate); tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr); @@ -655,7 +655,7 @@ static u16 vnt_rxtx_ab(struct vnt_usb_send_context *tx_context, u8 need_ack = tx_context->need_ack; buf->rrv_time = vnt_rxtx_rsvtime_le16(priv, tx_context->pkt_type, - frame_len, current_rate, need_ack); + frame_len, current_rate, need_ack); if (need_mic) head = &tx_head->tx_ab.tx.mic.head; @@ -1036,7 +1036,7 @@ static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb) /* Get Duration and TimeStampOff */ short_head->duration = vnt_get_duration_le(priv, - PK_TYPE_11B, false); + PK_TYPE_11B, false); short_head->time_stamp_off = vnt_time_stamp_off(priv, current_rate); } diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index ff351a7a0876..d3304df6bd53 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -216,7 +216,7 @@ static void vnt_submit_rx_urb_complete(struct urb *urb) } urb->transfer_buffer = skb_put(rcb->skb, - skb_tailroom(rcb->skb)); + skb_tailroom(rcb->skb)); } if (usb_submit_urb(urb, GFP_ATOMIC)) { -- cgit v1.2.3-59-g8ed1b From 441dfcc8861ed9cbc778c655f85e5ce5db08035e Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 16 Jul 2019 17:44:22 +0800 Subject: staging: erofs: avoid opened loop codes Use __GFP_NOFAIL to avoid opened loop codes in z_erofs_vle_unzip(). Signed-off-by: Chao Yu Reviewed-by: Gao Xiang Link: https://lore.kernel.org/r/20190716094422.110805-1-yuchao0@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/unzip_vle.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index f0dab81ff816..56c009cf611e 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -921,18 +921,18 @@ static int z_erofs_vle_unzip(struct super_block *sb, mutex_trylock(&z_pagemap_global_lock)) pages = z_pagemap_global; else { -repeat: + gfp_t gfp_flags = GFP_KERNEL; + + if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) + gfp_flags |= __GFP_NOFAIL; + pages = kvmalloc_array(nr_pages, sizeof(struct page *), - GFP_KERNEL); + gfp_flags); /* fallback to global pagemap for the lowmem scenario */ if (unlikely(!pages)) { - if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) - goto repeat; - else { - mutex_lock(&z_pagemap_global_lock); - pages = z_pagemap_global; - } + mutex_lock(&z_pagemap_global_lock); + pages = z_pagemap_global; } } -- cgit v1.2.3-59-g8ed1b From 9da681e017a36a411f70ca1ff68c499a30d2039d Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Tue, 16 Jul 2019 17:32:56 +0800 Subject: staging: erofs: support bmap Add erofs_bmap() to support FIBMAP ioctl on flatmode inode. Reviewed-by: Gao Xiang Signed-off-by: Chao Yu Link: https://lore.kernel.org/r/20190716093256.108791-1-yuchao0@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/data.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index cc31c3e5984c..f73e4720cd3e 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -392,9 +392,42 @@ static int erofs_raw_access_readpages(struct file *filp, return 0; } +static int erofs_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + struct erofs_map_blocks map = { + .m_la = iblock << 9, + }; + int err; + + err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); + if (err) + return err; + + if (map.m_flags & EROFS_MAP_MAPPED) + bh->b_blocknr = erofs_blknr(map.m_pa); + + return err; +} + +static sector_t erofs_bmap(struct address_space *mapping, sector_t block) +{ + struct inode *inode = mapping->host; + + if (is_inode_flat_inline(inode)) { + erofs_blk_t blks = i_size_read(inode) >> LOG_BLOCK_SIZE; + + if (block >> LOG_SECTORS_PER_BLOCK >= blks) + return 0; + } + + return generic_block_bmap(mapping, block, erofs_get_block); +} + /* for uncompressed (aligned) files and raw access for other files */ const struct address_space_operations erofs_raw_access_aops = { .readpage = erofs_raw_access_readpage, .readpages = erofs_raw_access_readpages, + .bmap = erofs_bmap, }; -- cgit v1.2.3-59-g8ed1b From 2125a44149cdf6be61fdabce898d26e9ba37dcd0 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 16 Jul 2019 11:29:44 +0530 Subject: staging: mt7621-pci: Add of_node_put() before return Each iteration of for_each_available_child_of_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Hence add an of_node_put before the return in two places. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190716055944.3237-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pci/pci-mt7621.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 89fa813142ab..2e37fd136ab8 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -400,6 +400,7 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) err = of_pci_get_devfn(child); if (err < 0) { + of_node_put(child); dev_err(dev, "failed to parse devfn: %d\n", err); return err; } @@ -407,8 +408,10 @@ static int mt7621_pcie_parse_dt(struct mt7621_pcie *pcie) slot = PCI_SLOT(err); err = mt7621_pcie_parse_port(pcie, child, slot); - if (err) + if (err) { + of_node_put(child); return err; + } } return 0; -- cgit v1.2.3-59-g8ed1b From c4011dde241d371972788a735cd1b5d547991d46 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 16 Jul 2019 11:29:08 +0530 Subject: staging: mt7621-pinctrl: Add of_node_put() before return Each iteration of for_each_compatible_node puts the previous node, but in the case of a return from the middle of the loop, there is no put, thus causing a memory leak. Add an of_node_put before the return. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190716055908.3183-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c index 9b52d44abef1..d0f06790d38f 100644 --- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c +++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c @@ -358,12 +358,15 @@ static int rt2880_pinmux_probe(struct platform_device *pdev) gpiobase = of_get_property(np, "ralink,gpio-base", NULL); if (!ngpio || !gpiobase) { dev_err(&pdev->dev, "failed to load chip info\n"); + of_node_put(np); return -EINVAL; } range = devm_kzalloc(p->dev, sizeof(*range), GFP_KERNEL); - if (!range) + if (!range) { + of_node_put(np); return -ENOMEM; + } range->name = "pio"; range->npins = __be32_to_cpu(*ngpio); range->base = __be32_to_cpu(*gpiobase); -- cgit v1.2.3-59-g8ed1b From 3e6998b17f36ab4f8f5608b3599df7b3c17d97a5 Mon Sep 17 00:00:00 2001 From: Lecopzer Chen Date: Fri, 12 Jul 2019 16:47:17 +0800 Subject: staging: android: ion: Remove unused rbtree for ion_buffer ion_buffer_add() insert ion_buffer into rbtree every time creating an ion_buffer but never use it after ION reworking. Also, buffer_lock protects only rbtree operation, remove it together. Signed-off-by: Lecopzer Chen Cc: YJ Chiang Cc: Lecopzer Chen Acked-by: Laura Abbott Link: https://lore.kernel.org/r/20190712084717.12441-1-lecopzer.chen@mediatek.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 36 ------------------------------------ drivers/staging/android/ion/ion.h | 10 +--------- 2 files changed, 1 insertion(+), 45 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 92c2914239e3..e6b1ca141b93 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -29,32 +29,6 @@ static struct ion_device *internal_dev; static int heap_id; -/* this function should only be called while dev->lock is held */ -static void ion_buffer_add(struct ion_device *dev, - struct ion_buffer *buffer) -{ - struct rb_node **p = &dev->buffers.rb_node; - struct rb_node *parent = NULL; - struct ion_buffer *entry; - - while (*p) { - parent = *p; - entry = rb_entry(parent, struct ion_buffer, node); - - if (buffer < entry) { - p = &(*p)->rb_left; - } else if (buffer > entry) { - p = &(*p)->rb_right; - } else { - pr_err("%s: buffer already found.", __func__); - BUG(); - } - } - - rb_link_node(&buffer->node, parent, p); - rb_insert_color(&buffer->node, &dev->buffers); -} - /* this function should only be called while dev->lock is held */ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, struct ion_device *dev, @@ -100,9 +74,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); - mutex_lock(&dev->buffer_lock); - ion_buffer_add(dev, buffer); - mutex_unlock(&dev->buffer_lock); return buffer; err1: @@ -131,11 +102,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer) static void _ion_buffer_destroy(struct ion_buffer *buffer) { struct ion_heap *heap = buffer->heap; - struct ion_device *dev = buffer->dev; - - mutex_lock(&dev->buffer_lock); - rb_erase(&buffer->node, &dev->buffers); - mutex_unlock(&dev->buffer_lock); if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_freelist_add(heap, buffer); @@ -694,8 +660,6 @@ static int ion_device_create(void) } idev->debug_root = debugfs_create_dir("ion", NULL); - idev->buffers = RB_ROOT; - mutex_init(&idev->buffer_lock); init_rwsem(&idev->lock); plist_head_init(&idev->heaps); internal_dev = idev; diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index e291299fd35f..74914a266e25 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -23,7 +23,6 @@ /** * struct ion_buffer - metadata for a particular buffer - * @node: node in the ion_device buffers tree * @list: element in list of deferred freeable buffers * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from @@ -39,10 +38,7 @@ * @attachments: list of devices attached to this buffer */ struct ion_buffer { - union { - struct rb_node node; - struct list_head list; - }; + struct list_head list; struct ion_device *dev; struct ion_heap *heap; unsigned long flags; @@ -61,14 +57,10 @@ void ion_buffer_destroy(struct ion_buffer *buffer); /** * struct ion_device - the metadata of the ion device node * @dev: the actual misc device - * @buffers: an rb tree of all the existing buffers - * @buffer_lock: lock protecting the tree of buffers * @lock: rwsem protecting the tree of heaps and clients */ struct ion_device { struct miscdevice dev; - struct rb_root buffers; - struct mutex buffer_lock; struct rw_semaphore lock; struct plist_head heaps; struct dentry *debug_root; -- cgit v1.2.3-59-g8ed1b From 28771088953f548a637c01cd59b62f9ee3018824 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:53:59 +0530 Subject: staging: comedi: daqboard2000: Remove function db2k_initialize_dac() Remove function db2k_initialize_dac as all it does is call db2k_dac_disarm. Modify call site accordingly. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052359.2308-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/daqboard2000.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index aabcda3f9fc8..28603dfadce2 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -665,11 +665,6 @@ static void db2k_initialize_adc(struct comedi_device *dev) db2k_initialize_tmrs(dev); } -static void db2k_initialize_dac(struct comedi_device *dev) -{ - db2k_dac_disarm(dev); -} - static int db2k_8255_cb(struct comedi_device *dev, int dir, int port, int data, unsigned long iobase) { @@ -719,7 +714,7 @@ static int db2k_auto_attach(struct comedi_device *dev, unsigned long context) return result; db2k_initialize_adc(dev); - db2k_initialize_dac(dev); + db2k_dac_disarm(dev); s = &dev->subdevices[0]; /* ai subdevice */ -- cgit v1.2.3-59-g8ed1b From 7a047abbb6ef8ac0050f8f0aa6a668985fb75a2c Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Thu, 25 Jul 2019 10:52:03 +0800 Subject: staging: wilc1000: Merge memcpy + le32_to_cpus to get_unaligned_le32 Merge the combo use of memcpy and le32_to_cpus. Use get_unaligned_le32 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190725025203.8772-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_mon.c | 3 +-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 3 +-- drivers/staging/wilc1000/wilc_wlan.c | 9 +++------ 3 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_mon.c b/drivers/staging/wilc1000/wilc_mon.c index 7d7933d40924..d6f14f69ad64 100644 --- a/drivers/staging/wilc1000/wilc_mon.c +++ b/drivers/staging/wilc1000/wilc_mon.c @@ -35,8 +35,7 @@ void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size) return; /* Get WILC header */ - memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - le32_to_cpus(&header); + header = get_unaligned_le32(buff - HOST_HDR_OFFSET); /* * The packet offset field contain info about what type of management * the frame we are dealing with and ack status diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d72fdd333050..12fb4add05ec 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1038,8 +1038,7 @@ void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size) s32 freq; __le16 fc; - memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - le32_to_cpus(&header); + header = get_unaligned_le32(buff - HOST_HDR_OFFSET); pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 2cbdbf0090e4..8ca0a7a4fa3f 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -703,8 +703,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) do { buff_ptr = buffer + offset; - memcpy(&header, buff_ptr, 4); - le32_to_cpus(&header); + header = get_unaligned_le32(buff_ptr); is_cfg_packet = (header >> 31) & 0x1; pkt_offset = (header >> 22) & 0x1ff; @@ -874,10 +873,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, offset = 0; do { - memcpy(&addr, &buffer[offset], 4); - memcpy(&size, &buffer[offset + 4], 4); - le32_to_cpus(&addr); - le32_to_cpus(&size); + addr = get_unaligned_le32(&buffer[offset]); + size = get_unaligned_le32(&buffer[offset + 4]); acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); offset += 8; while (((int)size) && (offset < buffer_size)) { -- cgit v1.2.3-59-g8ed1b From 814b75b4ed9c1a7633bfec7bab33c96db87a39db Mon Sep 17 00:00:00 2001 From: Christian L Moreno Date: Tue, 16 Jul 2019 16:09:15 -0300 Subject: staging: rtl8712: recv_linux.c: Align * on block comment Block comments should align the * on each line. This warning was reported by checkpatch.pl Signed-off-by: Christian L Moreno Link: https://lore.kernel.org/r/20190716190915.30869-1-christianluciano.m@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 84c4c8580f9a..70a4dcd4a1e5 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -115,8 +115,8 @@ void r8712_recv_indicatepkt(struct _adapter *adapter, skb->protocol = eth_type_trans(skb, adapter->pnetdev); netif_rx(skb); recvframe->u.hdr.pkt = NULL; /* pointers to NULL before - * r8712_free_recvframe() - */ + * r8712_free_recvframe() + */ r8712_free_recvframe(recvframe, free_recv_queue); return; _recv_indicatepkt_drop: -- cgit v1.2.3-59-g8ed1b From ec2b26f712610a85aab933c9cb4dfa3250aa4f58 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 19 Jul 2019 15:09:22 +0800 Subject: staging: rtl8712: Merge memcpy + be16_to_cpus to get_unaligned_be16 Merge the combo of memcpy and be16_to_cpus. Use get_unaligned_be16 instead. This simplifies the code. Signed-off-by: Chuhong Yuan Link: https://lore.kernel.org/r/20190719070921.27749-1-hslester96@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_recv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 5298fe603437..9969e5265a40 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -245,8 +245,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, if (auth_alg == 2) { /* get ether_type */ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; - memcpy(ðer_type, ptr, 2); - be16_to_cpus(ðer_type); + ether_type = get_unaligned_be16(ptr); if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked -- cgit v1.2.3-59-g8ed1b From 3e67274a41b29dc93915afe857fe27eb1a851d61 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:34 +0530 Subject: staging: rtl8712: r8712_init_mlme_priv(): Change return values Change return values of r8712_init_mlme_priv from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Modify call site accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 2 +- drivers/staging/rtl8712/rtl871x_mlme.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b554cf8bd679..b4059ea17e5c 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -302,7 +302,7 @@ u8 r8712_init_drv_sw(struct _adapter *padapter) padapter->cmdpriv.padapter = padapter; if (r8712_init_evt_priv(&padapter->evtpriv)) return _FAIL; - if (r8712_init_mlme_priv(padapter) == _FAIL) + if (r8712_init_mlme_priv(padapter)) return _FAIL; _r8712_init_xmit_priv(&padapter->xmitpriv, padapter); _r8712_init_recv_priv(&padapter->recvpriv, padapter); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 0cc879a4d43f..a4922af61acd 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -53,7 +53,7 @@ int r8712_init_mlme_priv(struct _adapter *padapter) pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network), GFP_ATOMIC); if (!pbuf) - return _FAIL; + return -ENOMEM; pmlmepriv->free_bss_buf = pbuf; pnetwork = (struct wlan_network *)pbuf; for (i = 0; i < MAX_BSS_CNT; i++) { @@ -67,7 +67,7 @@ int r8712_init_mlme_priv(struct _adapter *padapter) pmlmepriv->sitesurveyctrl.traffic_busy = false; /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */ r8712_init_mlme_timer(padapter); - return _SUCCESS; + return 0; } struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv) -- cgit v1.2.3-59-g8ed1b From 33972d48c2de0a77a5f482bb0728e62cb8420ca3 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:35 +0530 Subject: staging: rtl8712: r8712_set_auth(): Change return values Change return values of r8712_set_auth from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Modify call site accordingly. Also change return type of the function from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 6 +++--- drivers/staging/rtl8712/rtl871x_mlme.c | 10 +++++----- drivers/staging/rtl8712/rtl871x_mlme.h | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index f3c0a9348f56..c12adb9a6c37 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -320,10 +320,10 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter, psecuritypriv->ndisauthtype = authmode; if (psecuritypriv->ndisauthtype > 3) psecuritypriv->AuthAlgrthm = 2; /* 802.1x */ - if (r8712_set_auth(padapter, psecuritypriv) == _SUCCESS) - ret = true; - else + if (r8712_set_auth(padapter, psecuritypriv)) ret = false; + else + ret = true; return ret; } diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index a4922af61acd..9c373a84ca0d 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1144,8 +1144,8 @@ ask_for_joinbss: return r8712_joinbss_cmd(adapter, pnetwork); } -sint r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv) +int r8712_set_auth(struct _adapter *adapter, + struct security_priv *psecuritypriv) { struct cmd_priv *pcmdpriv = &adapter->cmdpriv; struct cmd_obj *pcmd; @@ -1153,12 +1153,12 @@ sint r8712_set_auth(struct _adapter *adapter, pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) - return _FAIL; + return -ENOMEM; psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC); if (!psetauthparm) { kfree(pcmd); - return _FAIL; + return -ENOMEM; } psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm; pcmd->cmdcode = _SetAuth_CMD_; @@ -1168,7 +1168,7 @@ sint r8712_set_auth(struct _adapter *adapter, pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); r8712_enqueue_cmd(pcmdpriv, pcmd); - return _SUCCESS; + return 0; } sint r8712_set_key(struct _adapter *adapter, diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index a160107e9801..47499e879688 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -175,8 +175,8 @@ void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv); int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv); sint r8712_set_key(struct _adapter *adapter, struct security_priv *psecuritypriv, sint keyid); -sint r8712_set_auth(struct _adapter *adapter, - struct security_priv *psecuritypriv); +int r8712_set_auth(struct _adapter *adapter, + struct security_priv *psecuritypriv); uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); void r8712_generate_random_ibss(u8 *pibss); u8 *r8712_get_capability_from_ie(u8 *ie); -- cgit v1.2.3-59-g8ed1b From 8a73a8c4657013e02bd9e6db975e6c3584c158f8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:36 +0530 Subject: staging: rtl8712: r8712_set_key(): Change return values Change return values of r8712_set_key from _SUCCESS and _FAIL to 0 and -ENOMEM or -EINVAL, as the case may require. Modify return statements and return variable accordingly. Change return type from sint to int. As there is only one site where the return value is used, update that call site according to the change in the return values. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 2 +- drivers/staging/rtl8712/rtl871x_mlme.c | 20 ++++++++++---------- drivers/staging/rtl8712/rtl871x_mlme.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index c12adb9a6c37..54b16bc41465 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -351,7 +351,7 @@ u8 r8712_set_802_11_add_wep(struct _adapter *padapter, wep->KeyLength); psecuritypriv->DefKeylen[keyid] = wep->KeyLength; psecuritypriv->PrivacyKeyIndex = keyid; - if (r8712_set_key(padapter, psecuritypriv, keyid) == _FAIL) + if (r8712_set_key(padapter, psecuritypriv, keyid)) return false; return _SUCCESS; } diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index 9c373a84ca0d..cabdb3549a5a 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -1171,22 +1171,22 @@ int r8712_set_auth(struct _adapter *adapter, return 0; } -sint r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, - sint keyid) +int r8712_set_key(struct _adapter *adapter, + struct security_priv *psecuritypriv, + sint keyid) { struct cmd_priv *pcmdpriv = &adapter->cmdpriv; struct cmd_obj *pcmd; struct setkey_parm *psetkeyparm; u8 keylen; - sint ret = _SUCCESS; + int ret; pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); if (!pcmd) - return _FAIL; + return -ENOMEM; psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC); if (!psetkeyparm) { - ret = _FAIL; + ret = -ENOMEM; goto err_free_cmd; } if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */ @@ -1211,7 +1211,7 @@ sint r8712_set_key(struct _adapter *adapter, break; case _TKIP_: if (keyid < 1 || keyid > 2) { - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } keylen = 16; @@ -1221,7 +1221,7 @@ sint r8712_set_key(struct _adapter *adapter, break; case _AES_: if (keyid < 1 || keyid > 2) { - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } keylen = 16; @@ -1230,7 +1230,7 @@ sint r8712_set_key(struct _adapter *adapter, psetkeyparm->grpkey = 1; break; default: - ret = _FAIL; + ret = -EINVAL; goto err_free_parm; } pcmd->cmdcode = _SetKey_CMD_; @@ -1240,7 +1240,7 @@ sint r8712_set_key(struct _adapter *adapter, pcmd->rspsz = 0; INIT_LIST_HEAD(&pcmd->list); r8712_enqueue_cmd(pcmdpriv, pcmd); - return ret; + return 0; err_free_parm: kfree(psetkeyparm); diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h index 47499e879688..46effb469fd4 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.h +++ b/drivers/staging/rtl8712/rtl871x_mlme.h @@ -173,8 +173,8 @@ void r8712_free_network_queue(struct _adapter *adapter); int r8712_init_mlme_priv(struct _adapter *adapter); void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv); int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv); -sint r8712_set_key(struct _adapter *adapter, - struct security_priv *psecuritypriv, sint keyid); +int r8712_set_key(struct _adapter *adapter, + struct security_priv *psecuritypriv, sint keyid); int r8712_set_auth(struct _adapter *adapter, struct security_priv *psecuritypriv); uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss); -- cgit v1.2.3-59-g8ed1b From 7c93fdf090dfed579bbb40aae0cef0853286848c Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:37 +0530 Subject: staging: rtl8712: r8712_register_cmd_alive(): Change return values Change return values of r8712_register_cmd_alive from _SUCCESS and _FAIL to 0 and -EINVAL. Change the return type of this function from sint to int. Modify its call site to check for 0 instead of _SUCCESS. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_cmd.c | 2 +- drivers/staging/rtl8712/rtl871x_pwrctrl.c | 10 +++++----- drivers/staging/rtl8712/rtl871x_pwrctrl.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index 6a72a4ad176a..f99fd7cfa445 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -311,7 +311,7 @@ int r8712_cmd_thread(void *context) break; if (padapter->driver_stopped || padapter->surprise_removed) break; - if (r8712_register_cmd_alive(padapter) != _SUCCESS) + if (r8712_register_cmd_alive(padapter)) continue; _next: pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue); diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c index 2beafc7742b3..23cff43437e2 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c @@ -184,19 +184,19 @@ void r8712_init_pwrctrl_priv(struct _adapter *padapter) * will raise the cpwm to be greater than or equal to P2. * Calling Context: Passive * Return Value: - * _SUCCESS: r8712_cmd_thread can issue cmds to firmware afterwards. - * _FAIL: r8712_cmd_thread can not do anything. + * 0: r8712_cmd_thread can issue cmds to firmware afterwards. + * -EINVAL: r8712_cmd_thread can not do anything. */ -sint r8712_register_cmd_alive(struct _adapter *padapter) +int r8712_register_cmd_alive(struct _adapter *padapter) { - uint res = _SUCCESS; + int res = 0; struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv; mutex_lock(&pwrctrl->mutex_lock); register_task_alive(pwrctrl, CMD_ALIVE); if (pwrctrl->cpwm < PS_STATE_S2) { r8712_set_rpwm(padapter, PS_STATE_S3); - res = _FAIL; + res = -EINVAL; } mutex_unlock(&pwrctrl->mutex_lock); return res; diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 11b5034f203d..dd5a79f90b1a 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -104,7 +104,7 @@ struct pwrctrl_priv { }; void r8712_init_pwrctrl_priv(struct _adapter *adapter); -sint r8712_register_cmd_alive(struct _adapter *padapter); +int r8712_register_cmd_alive(struct _adapter *padapter); void r8712_unregister_cmd_alive(struct _adapter *padapter); void r8712_cpwm_int_hdl(struct _adapter *padapter, struct reportpwrstate_parm *preportpwrstate); -- cgit v1.2.3-59-g8ed1b From 42ceb6731d781e6a9134ee73bbe85988395e0895 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:38 +0530 Subject: staging: rtl8712: init_mp_priv(): Change return values Change return values of init_mp_priv from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Remove label that returns the required value and return the values directly as they are set. Consequently remove now-unnecessary return variable. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_mp.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c index edd3da05fc06..1a39a96b726f 100644 --- a/drivers/staging/rtl8712/rtl871x_mp.c +++ b/drivers/staging/rtl8712/rtl871x_mp.c @@ -35,7 +35,7 @@ static void _init_mp_priv_(struct mp_priv *pmp_priv) static int init_mp_priv(struct mp_priv *pmp_priv) { - int i, res; + int i; struct mp_xmit_frame *pmp_xmitframe; _init_mp_priv_(pmp_priv); @@ -45,8 +45,7 @@ static int init_mp_priv(struct mp_priv *pmp_priv) sizeof(struct mp_xmit_frame) + 4, GFP_ATOMIC); if (!pmp_priv->pallocated_mp_xmitframe_buf) { - res = _FAIL; - goto _exit_init_mp_priv; + return -ENOMEM; } pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf + 4 - @@ -62,9 +61,7 @@ static int init_mp_priv(struct mp_priv *pmp_priv) pmp_xmitframe++; } pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME; - res = _SUCCESS; -_exit_init_mp_priv: - return res; + return 0; } static int free_mp_priv(struct mp_priv *pmp_priv) -- cgit v1.2.3-59-g8ed1b From 34ef8dbe02f403b03999ccefd489ca3a7a5e08f1 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:39 +0530 Subject: staging: rtl8712: r8712_set_802_11_add_wep(): Change return values Change call sites of r8712_set_802_11_add_wep to check for 0 and non-zero values (e.g -EINVAL, -ENOMEM) instead of for _SUCCESS and _FAIL. Change return values of r8712_set_802_11_add_wep from true and false and _SUCCESS to -EINVAL and the return value of r8712_set_key. Change return type from u8 to int to accommodate these new return values. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 5 ++--- drivers/staging/rtl8712/rtl871x_ioctl_set.c | 10 ++++------ drivers/staging/rtl8712/rtl871x_ioctl_set.h | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index b08b9a191a34..944336e0d2e2 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -419,8 +419,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, pwep->KeyIndex |= 0x80000000; memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength); if (param->u.crypt.set_tx) { - if (r8712_set_802_11_add_wep(padapter, pwep) == - (u8)_FAIL) + if (r8712_set_802_11_add_wep(padapter, pwep)) ret = -EOPNOTSUPP; } else { /* don't update "psecuritypriv->PrivacyAlgrthm" and @@ -1585,7 +1584,7 @@ static int r8711_wx_set_enc(struct net_device *dev, } wep.KeyIndex |= 0x80000000; /* transmit key */ memcpy(wep.KeyMaterial, keybuf, wep.KeyLength); - if (r8712_set_802_11_add_wep(padapter, &wep) == _FAIL) + if (r8712_set_802_11_add_wep(padapter, &wep)) return -EOPNOTSUPP; return 0; } diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c index 54b16bc41465..6cdc6f1a6bc6 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c @@ -327,15 +327,15 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter, return ret; } -u8 r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep) +int r8712_set_802_11_add_wep(struct _adapter *padapter, + struct NDIS_802_11_WEP *wep) { sint keyid; struct security_priv *psecuritypriv = &padapter->securitypriv; keyid = wep->KeyIndex & 0x3fffffff; if (keyid >= WEP_KEYS) - return false; + return -EINVAL; switch (wep->KeyLength) { case 5: psecuritypriv->PrivacyAlgrthm = _WEP40_; @@ -351,7 +351,5 @@ u8 r8712_set_802_11_add_wep(struct _adapter *padapter, wep->KeyLength); psecuritypriv->DefKeylen[keyid] = wep->KeyLength; psecuritypriv->PrivacyKeyIndex = keyid; - if (r8712_set_key(padapter, psecuritypriv, keyid)) - return false; - return _SUCCESS; + return r8712_set_key(padapter, psecuritypriv, keyid); } diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h index 8b1085aea962..e2de820f61d9 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h +++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.h @@ -28,8 +28,8 @@ u8 r8712_set_802_11_authentication_mode(struct _adapter *pdapter, u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid); -u8 r8712_set_802_11_add_wep(struct _adapter *padapter, - struct NDIS_802_11_WEP *wep); +int r8712_set_802_11_add_wep(struct _adapter *padapter, + struct NDIS_802_11_WEP *wep); u8 r8712_set_802_11_disassociate(struct _adapter *padapter); -- cgit v1.2.3-59-g8ed1b From 606c5cf07b7907294e74eb5344fcf489b93983a5 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:40 +0530 Subject: staging: rtl8712: r8712_init_recvbuf(): Change return type Change return type of r8712_init_recvbuf from int to void as it always returned _SUCCESS and this return value was never used at any call site. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 3 +-- drivers/staging/rtl8712/rtl8712_recv.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 82ddc0c3ecd4..892ea71c3718 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -107,7 +107,7 @@ void r8712_free_recv_priv(struct recv_priv *precvpriv) skb_queue_len(&precvpriv->free_recv_skb_queue)); } -int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) +void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) { precvbuf->transfer_len = 0; precvbuf->len = 0; @@ -118,7 +118,6 @@ int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) precvbuf->ptail = precvbuf->pbuf; precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ; } - return _SUCCESS; } int r8712_free_recvframe(union recv_frame *precvframe, diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h index 6954c5bfbcaf..3e385b2242d8 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.h +++ b/drivers/staging/rtl8712/rtl8712_recv.h @@ -136,7 +136,7 @@ union recv_frame { } u; }; -int r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); +void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf); void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf); s32 r8712_signal_scale_mapping(s32 cur_sig); void r8712_reordering_ctrl_timeout_handler(void *pcontext); -- cgit v1.2.3-59-g8ed1b From caecc46bf4e78bada4e3f6df3156c711c5ef6b78 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Mon, 22 Jul 2019 14:53:41 +0530 Subject: staging: rtl8712: r8712_free_recvframe(): Change return type Change return type of r8712_free_recvframe from int to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190722092341.21030-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 3 +-- drivers/staging/rtl8712/rtl871x_recv.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 892ea71c3718..d9574ea3ffb2 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -120,7 +120,7 @@ void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf) } } -int r8712_free_recvframe(union recv_frame *precvframe, +void r8712_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue) { unsigned long irqL; @@ -139,7 +139,6 @@ int r8712_free_recvframe(union recv_frame *precvframe, precvpriv->free_recvframe_cnt++; } spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL); - return _SUCCESS; } static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib, diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h index f87b2ff5de1c..0146a774e19d 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.h +++ b/drivers/staging/rtl8712/rtl871x_recv.h @@ -128,7 +128,7 @@ struct sta_recv_priv { /* get a free recv_frame from pfree_recv_queue */ union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue); -int r8712_free_recvframe(union recv_frame *precvframe, +void r8712_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue); void r8712_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue); -- cgit v1.2.3-59-g8ed1b From 8143be90aaab5848b570aa6b706727f8ffe68960 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 17 Jul 2019 22:20:14 +0800 Subject: staging: rtl8723bs: remove set but not used variable 'cck_highpwr' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/hal/odm_HWConfig.c: In function odm_RxPhyStatus92CSeries_Parsing: drivers/staging/rtl8723bs/hal/odm_HWConfig.c:92:5: warning: variable cck_highpwr set but not used [-Wunused-but-set-variable] It is never used and can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190717142014.43216-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm_HWConfig.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c index 49fa814068b8..71919a3d81ab 100644 --- a/drivers/staging/rtl8723bs/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8723bs/hal/odm_HWConfig.c @@ -89,7 +89,6 @@ static void odm_RxPhyStatus92CSeries_Parsing( u8 RSSI, total_rssi = 0; bool isCCKrate = false; u8 rf_rx_num = 0; - u8 cck_highpwr = 0; u8 LNA_idx, VGA_idx; PPHY_STATUS_RPT_8192CD_T pPhyStaRpt = (PPHY_STATUS_RPT_8192CD_T)pPhyStatus; @@ -107,16 +106,10 @@ static void odm_RxPhyStatus92CSeries_Parsing( /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */ /* */ - /* if (pHalData->eRFPowerState == eRfOn) */ - cck_highpwr = pDM_Odm->bCckHighPower; - /* else */ - /* cck_highpwr = false; */ - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ; /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */ /* The RSSI formula should be modified according to the gain table */ - /* In 88E, cck_highpwr is always set to 1 */ LNA_idx = ((cck_agc_rpt & 0xE0)>>5); VGA_idx = (cck_agc_rpt & 0x1F); rx_pwr_all = odm_CCKRSSI_8723B(LNA_idx, VGA_idx); -- cgit v1.2.3-59-g8ed1b From fee0cc591ae4e887c1b4304b7d69a7c209b2f24a Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 17 Jul 2019 23:26:43 +0530 Subject: staging: rtl8723bs: os_dep: change return type of rtw_suspend_ap_wow Change return type of rtw_suspend_ap_wow as its always return SUCCCESS. Issue found with coccicheck Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190717175642.GA10582@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 50928b2000b9..2ddafb07d5b6 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -1354,13 +1354,12 @@ void rtw_suspend_wow(struct adapter *padapter) #endif /* ifdef CONFIG_WOWLAN */ #ifdef CONFIG_AP_WOWLAN -int rtw_suspend_ap_wow(struct adapter *padapter) +void rtw_suspend_ap_wow(struct adapter *padapter) { u8 ch, bw, offset; struct net_device *pnetdev = padapter->pnetdev; struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct wowlan_ioctl_param poidparam; - int ret = _SUCCESS; DBG_871X("==> " FUNC_ADPT_FMT " entry....\n", FUNC_ADPT_ARG(padapter)); @@ -1402,7 +1401,6 @@ int rtw_suspend_ap_wow(struct adapter *padapter) rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, 0, "AP-WOWLAN"); DBG_871X("<== " FUNC_ADPT_FMT " exit....\n", FUNC_ADPT_ARG(padapter)); - return ret; } #endif /* ifdef CONFIG_AP_WOWLAN */ -- cgit v1.2.3-59-g8ed1b From 1c4bfacf1d70c3daba4733eb1a6450d27422e087 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 17 Jul 2019 23:36:35 +0530 Subject: staging: rtl8723bs: core: Remove Unneeded variable ret Remove Unneeded variable ret . Return _FAIL . We cannot change return type of on_action_spct as its callback function. Issue identified with coccicheck. Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190717180635.GA11412@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index 6d0014251f86..2128886c9924 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -1874,7 +1874,6 @@ unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) { - unsigned int ret = _FAIL; struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 *pframe = precv_frame->u.hdr.rx_data; @@ -1906,7 +1905,7 @@ unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_fr } exit: - return ret; + return _FAIL; } unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) -- cgit v1.2.3-59-g8ed1b From 8638eeed74817358280d8d393503d50f60788527 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Sun, 21 Jul 2019 19:57:35 +0200 Subject: staging: rtl8723bs: remove unused file hal_phy.c Remove the unused file hal_phy.c. No function from this file is used in the driver code and it is not listed in the Makefile. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20190721175735.24173-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_phy.c | 157 -------------------------------- 1 file changed, 157 deletions(-) delete mode 100644 drivers/staging/rtl8723bs/hal/hal_phy.c (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_phy.c b/drivers/staging/rtl8723bs/hal/hal_phy.c deleted file mode 100644 index 24a9d8f783f0..000000000000 --- a/drivers/staging/rtl8723bs/hal/hal_phy.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#define _HAL_PHY_C_ - -#include - -/* */ -/* ==> RF shadow Operation API Code Section!!! */ -/* */ -/*----------------------------------------------------------------------------- - * Function: PHY_RFShadowRead - * PHY_RFShadowWrite - * PHY_RFShadowCompare - * PHY_RFShadowRecorver - * PHY_RFShadowCompareAll - * PHY_RFShadowRecorverAll - * PHY_RFShadowCompareFlagSet - * PHY_RFShadowRecorverFlagSet - * - * Overview: When we set RF register, we must write shadow at first. - * When we are running, we must compare shadow abd locate error addr. - * Decide to recorver or not. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 11/20/2008 MHC Create Version 0. - * - *---------------------------------------------------------------------------*/ -u32 PHY_RFShadowRead(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - return RF_Shadow[eRFPath][Offset].Value; - -} /* PHY_RFShadowRead */ - - -void PHY_RFShadowWrite( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u32 Data -) -{ - RF_Shadow[eRFPath][Offset].Value = (Data & bRFRegOffsetMask); - RF_Shadow[eRFPath][Offset].Driver_Write = true; - -} /* PHY_RFShadowWrite */ - - -bool PHY_RFShadowCompare(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - u32 reg; - /* Check if we need to check the register */ - if (RF_Shadow[eRFPath][Offset].Compare == true) { - reg = rtw_hal_read_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask); - /* Compare shadow and real rf register for 20bits!! */ - if (RF_Shadow[eRFPath][Offset].Value != reg) { - /* Locate error position. */ - RF_Shadow[eRFPath][Offset].ErrorOrNot = true; - /* RT_TRACE(COMP_INIT, DBG_LOUD, */ - /* PHY_RFShadowCompare RF-%d Addr%02lx Err = %05lx\n", */ - /* eRFPath, Offset, reg)); */ - } - return RF_Shadow[eRFPath][Offset].ErrorOrNot; - } - return false; -} /* PHY_RFShadowCompare */ - - -void PHY_RFShadowRecorver(IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset) -{ - /* Check if the address is error */ - if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true) { - /* Check if we need to recorver the register. */ - if (RF_Shadow[eRFPath][Offset].Recorver == true) { - rtw_hal_write_rfreg(Adapter, eRFPath, Offset, bRFRegOffsetMask, - RF_Shadow[eRFPath][Offset].Value); - /* RT_TRACE(COMP_INIT, DBG_LOUD, */ - /* PHY_RFShadowRecorver RF-%d Addr%02lx=%05lx", */ - /* eRFPath, Offset, RF_Shadow[eRFPath][Offset].Value)); */ - } - } - -} /* PHY_RFShadowRecorver */ - - -void PHY_RFShadowCompareAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - PHY_RFShadowCompare(Adapter, eRFPath, Offset); - } - } - -} /* PHY_RFShadowCompareAll */ - - -void PHY_RFShadowRecorverAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - PHY_RFShadowRecorver(Adapter, eRFPath, Offset); - } - } - -} /* PHY_RFShadowRecorverAll */ - - -void -PHY_RFShadowCompareFlagSet( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u8 Type -) -{ - /* Set True or False!!! */ - RF_Shadow[eRFPath][Offset].Compare = Type; - -} /* PHY_RFShadowCompareFlagSet */ - - -void PHY_RFShadowRecorverFlagSet( - IN PADAPTER Adapter, IN u8 eRFPath, IN u32 Offset, IN u8 Type -) -{ - /* Set True or False!!! */ - RF_Shadow[eRFPath][Offset].Recorver = Type; - -} /* PHY_RFShadowRecorverFlagSet */ - - -void PHY_RFShadowCompareFlagSetAll(IN PADAPTER Adapter) -{ - u8 eRFPath = 0; - u32 Offset = 0, maxReg = GET_RF6052_REAL_MAX_REG(Adapter); - - for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) { - for (Offset = 0; Offset < maxReg; Offset++) { - /* 2008/11/20 MH For S3S4 test, we only check reg 26/27 now!!!! */ - if (Offset != 0x26 && Offset != 0x27) - PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, false); - else - PHY_RFShadowCompareFlagSet(Adapter, eRFPath, Offset, true); - } - } - -} /* PHY_RFShadowCompareFlagSetAll */ -- cgit v1.2.3-59-g8ed1b From 3774fb6bd2b99858f37d9559bf0e3f9a9649f3f3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Jul 2019 15:59:05 +0100 Subject: staging: rtl8723bs: hal: remove redundant assignment to variable n The variable n is being assigned a value that is never read, the assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190723145905.13514-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index e23b39ab16c5..032d01834f3f 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -486,7 +486,6 @@ initbuferror: } if (precvpriv->pallocated_recv_buf) { - n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; kfree(precvpriv->pallocated_recv_buf); precvpriv->pallocated_recv_buf = NULL; } -- cgit v1.2.3-59-g8ed1b From 756e4624ddcfdc2792fe389262ba7447f22d8913 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 17 Jul 2019 22:35:51 +0800 Subject: staging: rtl8192e: remove set but not used variable 'payload ' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8192e/rtllib_rx.c: In function rtllib_rx_InfraAdhoc: drivers/staging/rtl8192e/rtllib_rx.c:1303:6: warning: variable payload set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190717143551.29200-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 0c19ac2bc3bf..0bae0a0a4cbe 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1300,7 +1300,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, struct rx_ts_record *pTS = NULL; u16 fc, sc, SeqNum = 0; u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0; - u8 *payload; u8 dst[ETH_ALEN]; u8 src[ETH_ALEN]; u8 bssid[ETH_ALEN] = {0}; @@ -1412,7 +1411,6 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, /* Parse rx data frame (For AMSDU) */ /* skb: hdr + (possible reassembled) full plaintext payload */ - payload = skb->data + hdrlen; rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC); if (!rxb) goto rx_dropped; -- cgit v1.2.3-59-g8ed1b From 7f9b583358a4fe31cdbde61e5f50d568be4cc69e Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Sat, 20 Jul 2019 09:29:08 +0200 Subject: staging: mt7621-pci: avoid use 'err' local variable Function 'mt7621_pcie_request_resources' is using 'err' local variable to get value returned from 'devm_request_pci_bus_resources' and returning after that. This is not needed at all. Instead of that just directly return returned value by the function which is also returning zero on success. Signed-off-by: Sergio Paracuellos Link: https://lore.kernel.org/r/20190720072908.16795-1-sergio.paracuellos@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/mt7621-pci/pci-mt7621.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index 2e37fd136ab8..6b98827da57f 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -617,17 +617,12 @@ static int mt7621_pcie_request_resources(struct mt7621_pcie *pcie, struct list_head *res) { struct device *dev = pcie->dev; - int err; pci_add_resource_offset(res, &pcie->io, pcie->offset.io); pci_add_resource_offset(res, &pcie->mem, pcie->offset.mem); pci_add_resource(res, &pcie->busn); - err = devm_request_pci_bus_resources(dev, res); - if (err < 0) - return err; - - return 0; + return devm_request_pci_bus_resources(dev, res); } static int mt7621_pcie_register_host(struct pci_host_bridge *host, -- cgit v1.2.3-59-g8ed1b From 4b2c85cacde3f92c2214af60ff89dd6bd93289ca Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Jul 2019 15:50:22 +0100 Subject: drivers/staging/rtl8192u: fix indentation issue, remove extra tab A statement is indented one level too deeply; clean this up by removing a tab. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190723145022.11608-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index ade14ef05730..c23e43b095d9 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -1334,7 +1334,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) return; } /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ - queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); TM_Trigger = 0; } -- cgit v1.2.3-59-g8ed1b From 2e20a5ac67f8a589ad2ba56717b8419298064354 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:37 +0530 Subject: staging: rtl8723bs: rtw_pwrctrl: Change true/false checks Change comparisons to true to the variable itself. Change comparisons to false to the negation of the variable. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_pwrctrl.c | 117 +++++++++++++-------------- 1 file changed, 54 insertions(+), 63 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index ae7fb7046c93..62b42e29e4fd 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -103,7 +103,7 @@ static bool rtw_pwr_unassociated_idle(struct adapter *adapter) bool ret = false; - if (adapter_to_pwrctl(adapter)->bpower_saving == true) { + if (adapter_to_pwrctl(adapter)->bpower_saving) { /* DBG_871X("%s: already in LPS or IPS mode\n", __func__); */ goto exit; } @@ -167,7 +167,7 @@ void rtw_ps_processor(struct adapter *padapter) goto exit; } - if (pwrpriv->bInSuspend == true) {/* system suspend or autosuspend */ + if (pwrpriv->bInSuspend) {/* system suspend or autosuspend */ pdbgpriv->dbg_ps_insuspend_cnt++; DBG_871X("%s, pwrpriv->bInSuspend == true ignore this process\n", __func__); return; @@ -219,10 +219,9 @@ void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets if (jiffies_to_msecs(jiffies - start_time) > 2000) { /* 2 sec == watch dog timer */ if (xmit_cnt > 8) { - if ((adapter_to_pwrctl(padapter)->bLeisurePs) - && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) - && (hal_btcoex_IsBtControlLps(padapter) == false) - ) { + if (adapter_to_pwrctl(padapter)->bLeisurePs + && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) + && !(hal_btcoex_IsBtControlLps(padapter))) { DBG_871X("leave lps via Tx = %d\n", xmit_cnt); bLeaveLPS = true; } @@ -234,10 +233,9 @@ void traffic_check_for_leave_lps(struct adapter *padapter, u8 tx, u32 tx_packets } else { /* from rx path */ if (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/) { - if ((adapter_to_pwrctl(padapter)->bLeisurePs) - && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) - && (hal_btcoex_IsBtControlLps(padapter) == false) - ) { + if (adapter_to_pwrctl(padapter)->bLeisurePs + && (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE) + && !(hal_btcoex_IsBtControlLps(padapter))) { DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod); bLeaveLPS = true; } @@ -267,7 +265,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) pslv = PS_STATE(pslv); - if (pwrpriv->brpwmtimeout == true) { + if (pwrpriv->brpwmtimeout) { DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __func__, pslv); } else { if ((pwrpriv->rpwm == pslv) @@ -278,8 +276,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) } } - if ((padapter->bSurpriseRemoved == true) || - (padapter->hw_init_completed == false)) { + if ((padapter->bSurpriseRemoved) || !(padapter->hw_init_completed)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n", __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed)); @@ -289,7 +286,7 @@ void rtw_set_rpwm(struct adapter *padapter, u8 pslv) return; } - if (padapter->bDriverStopped == true) { + if (padapter->bDriverStopped) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv)); @@ -355,14 +352,14 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) - if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_mode) + if (pwrpriv->bInSuspend && pwrpriv->wowlan_mode) return true; - else if (true == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode) + else if (pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode) return true; - else if (true == pwrpriv->bInSuspend) + else if (pwrpriv->bInSuspend) return false; #else - if (true == pwrpriv->bInSuspend) + if (pwrpriv->bInSuspend) return false; #endif @@ -381,7 +378,7 @@ static u8 PS_RDY_CHECK(struct adapter *padapter) ) return false; - if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false)) { + if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && !(padapter->securitypriv.binstallGrpkey)) { DBG_871X("Group handshake still in progress !!!\n"); return false; } @@ -417,13 +414,9 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */ if (ps_mode == PS_MODE_ACTIVE) { - if (1 - && (((hal_btcoex_IsBtControlLps(padapter) == false) - ) - || ((hal_btcoex_IsBtControlLps(padapter) == true) - && (hal_btcoex_IsLpsOn(padapter) == false)) - ) - ) { + if (!(hal_btcoex_IsBtControlLps(padapter)) + || (hal_btcoex_IsBtControlLps(padapter) + && !(hal_btcoex_IsLpsOn(padapter)))) { DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n", FUNC_ADPT_ARG(padapter), msg); @@ -431,8 +424,7 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a rtw_set_rpwm(padapter, PS_STATE_S4); #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) - if (pwrpriv->wowlan_mode == true || - pwrpriv->wowlan_ap_mode == true) { + if (pwrpriv->wowlan_mode || pwrpriv->wowlan_ap_mode) { unsigned long start_time; u32 delay_ms; u8 val8; @@ -461,8 +453,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a } } else { if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) - || ((hal_btcoex_IsBtControlLps(padapter) == true) - && (hal_btcoex_IsLpsOn(padapter) == true)) + || ((hal_btcoex_IsBtControlLps(padapter)) + && (hal_btcoex_IsLpsOn(padapter))) ) { u8 pslv; @@ -481,8 +473,8 @@ void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_a if (pwrpriv->alives == 0) pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && (hal_btcoex_IsBtControlLps(padapter))) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -513,10 +505,10 @@ s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms) start_time = jiffies; while (1) { rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake); - if (true == bAwake) + if (bAwake) break; - if (true == padapter->bSurpriseRemoved) { + if (padapter->bSurpriseRemoved) { err = -2; DBG_871X("%s: device surprise removed!!\n", __func__); break; @@ -544,7 +536,7 @@ void LPS_Enter(struct adapter *padapter, const char *msg) int n_assoc_iface = 0; char buf[32] = {0}; - if (hal_btcoex_IsBtControlLps(padapter) == true) + if (hal_btcoex_IsBtControlLps(padapter)) return; /* Skip lps enter request if number of assocated adapters is not 1 */ @@ -557,8 +549,8 @@ void LPS_Enter(struct adapter *padapter, const char *msg) if (get_iface_type(padapter) != IFACE_PORT0) return; - if (PS_RDY_CHECK(dvobj->padapters) == false) - return; + if (!PS_RDY_CHECK(dvobj->padapters)) + return; if (pwrpriv->bLeisurePs) { /* Idle for a while if we connect to AP a while ago. */ @@ -589,7 +581,7 @@ void LPS_Leave(struct adapter *padapter, const char *msg) /* DBG_871X("+LeisurePSLeave\n"); */ - if (hal_btcoex_IsBtControlLps(padapter) == true) + if (hal_btcoex_IsBtControlLps(padapter)) return; if (pwrpriv->bLeisurePs) { @@ -615,13 +607,13 @@ void LeaveAllPowerSaveModeDirect(struct adapter *Adapter) DBG_871X("%s.....\n", __func__); - if (true == Adapter->bSurpriseRemoved) { + if (Adapter->bSurpriseRemoved) { DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved =%d Skip!\n", FUNC_ADPT_ARG(Adapter), Adapter->bSurpriseRemoved); return; } - if ((check_fwstate(pmlmepriv, _FW_LINKED) == true)) { /* connect */ + if (check_fwstate(pmlmepriv, _FW_LINKED)) { /* connect */ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) { DBG_871X("%s: Driver Already Leave LPS\n", __func__); @@ -637,7 +629,7 @@ void LeaveAllPowerSaveModeDirect(struct adapter *Adapter) rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0); } else { if (pwrpriv->rf_pwrstate == rf_off) - if (false == ips_leave(pri_padapter)) + if (!ips_leave(pri_padapter)) DBG_871X("======> ips_leave fail.............\n"); } } @@ -675,7 +667,7 @@ void LeaveAllPowerSaveMode(struct adapter *Adapter) LPS_Leave_check(Adapter); } else { if (adapter_to_pwrctl(Adapter)->rf_pwrstate == rf_off) { - if (false == ips_leave(Adapter)) + if (!ips_leave(Adapter)) DBG_871X("======> ips_leave fail.............\n"); } } @@ -698,15 +690,14 @@ void LPS_Leave_check( while (1) { mutex_lock(&pwrpriv->lock); - if ((padapter->bSurpriseRemoved == true) - || (padapter->hw_init_completed == false) - || (pwrpriv->pwr_mode == PS_MODE_ACTIVE) - ) + if (padapter->bSurpriseRemoved + || !(padapter->hw_init_completed) + || (pwrpriv->pwr_mode == PS_MODE_ACTIVE)) bReady = true; mutex_unlock(&pwrpriv->lock); - if (true == bReady) + if (bReady) break; if (jiffies_to_msecs(jiffies - start_time) > 100) { @@ -870,7 +861,7 @@ s32 rtw_register_task_alive(struct adapter *padapter, u32 task) register_task_alive(pwrctrl, task); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: task = 0x%x cpwm = 0x%02x alives = 0x%08x\n", __func__, task, pwrctrl->cpwm, pwrctrl->alives)); @@ -910,8 +901,8 @@ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -924,7 +915,7 @@ void rtw_unregister_task_alive(struct adapter *padapter, u32 task) unregister_task_alive(pwrctrl, task); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -965,7 +956,7 @@ s32 rtw_register_tx_alive(struct adapter *padapter) register_task_alive(pwrctrl, XMIT_ALIVE); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("rtw_register_tx_alive: cpwm = 0x%02x alives = 0x%08x\n", pwrctrl->cpwm, pwrctrl->alives)); @@ -1014,7 +1005,7 @@ s32 rtw_register_cmd_alive(struct adapter *padapter) register_task_alive(pwrctrl, CMD_ALIVE); - if (pwrctrl->bFwCurrentInPSMode == true) { + if (pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_, ("rtw_register_cmd_alive: cpwm = 0x%02x alives = 0x%08x\n", pwrctrl->cpwm, pwrctrl->alives)); @@ -1051,8 +1042,8 @@ void rtw_unregister_tx_alive(struct adapter *padapter) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -1065,7 +1056,7 @@ void rtw_unregister_tx_alive(struct adapter *padapter) unregister_task_alive(pwrctrl, XMIT_ALIVE); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -1093,8 +1084,8 @@ void rtw_unregister_cmd_alive(struct adapter *padapter) pwrctrl = adapter_to_pwrctl(padapter); pslv = PS_STATE_S0; - if ((hal_btcoex_IsBtDisabled(padapter) == false) - && (hal_btcoex_IsBtControlLps(padapter) == true)) { + if (!(hal_btcoex_IsBtDisabled(padapter)) + && hal_btcoex_IsBtControlLps(padapter)) { u8 val8; val8 = hal_btcoex_LpsVal(padapter); @@ -1107,7 +1098,7 @@ void rtw_unregister_cmd_alive(struct adapter *padapter) unregister_task_alive(pwrctrl, CMD_ALIVE); if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE) - && (pwrctrl->bFwCurrentInPSMode == true)) { + && pwrctrl->bFwCurrentInPSMode) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_, ("%s: cpwm = 0x%02x alives = 0x%08x\n", __func__, pwrctrl->cpwm, pwrctrl->alives)); @@ -1237,7 +1228,7 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal DBG_871X("%s wait ps_processing done\n", __func__); } - if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) { + if (!(pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) { DBG_871X("%s wait bInSuspend...\n", __func__); while (pwrpriv->bInSuspend && jiffies_to_msecs(jiffies - start) <= 3000 @@ -1251,19 +1242,19 @@ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *cal } /* System suspend is not allowed to wakeup */ - if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) { + if (!(pwrpriv->bInternalAutoSuspend) && pwrpriv->bInSuspend) { ret = _FAIL; goto exit; } /* block??? */ - if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) { + if (pwrpriv->bInternalAutoSuspend && padapter->net_closed) { ret = _FAIL; goto exit; } /* I think this should be check in IPS, LPS, autosuspend functions... */ - if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { + if (check_fwstate(pmlmepriv, _FW_LINKED)) { ret = _SUCCESS; goto exit; } -- cgit v1.2.3-59-g8ed1b From fe2ffeb5fdd297ad90f6252defbd635ca3037367 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:38 +0530 Subject: staging: rtl8723bs: hal: Replace function PHY_SetTxPowerIndex() Remove function PHY_SetTxPowerIndex as it does nothing except call PHY_SetTxPowerIndex_8723B. Rename PHY_SetTxPowerIndex_8723B to PHY_SetTxPowerIndex to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_com_phycfg.c | 7 ------- drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c | 2 +- drivers/staging/rtl8723bs/include/hal_com_phycfg.h | 8 -------- drivers/staging/rtl8723bs/include/hal_phy_cfg.h | 2 +- 4 files changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c index 336764464e7d..7b1e6c4a2e8d 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c @@ -2051,13 +2051,6 @@ u8 PHY_GetTxPowerIndex( return PHY_GetTxPowerIndex_8723B(padapter, RFPath, Rate, BandWidth, Channel); } -void PHY_SetTxPowerIndex( - struct adapter *padapter, u32 PowerIndex, u8 RFPath, u8 Rate -) -{ - PHY_SetTxPowerIndex_8723B(padapter, PowerIndex, RFPath, Rate); -} - void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index 25c75b977666..b02ff10fedbf 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -585,7 +585,7 @@ int PHY_RFConfig8723B(struct adapter *Adapter) * <20120830, Kordan> **************************************************************************************************************/ -void PHY_SetTxPowerIndex_8723B( +void PHY_SetTxPowerIndex( struct adapter *Adapter, u32 PowerIndex, u8 RFPath, diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h index f841546584a7..f3521b7ae295 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h @@ -222,14 +222,6 @@ enum CHANNEL_WIDTH BandWidth, u8 Channel ); -void -PHY_SetTxPowerIndex( -struct adapter * padapter, -u32 PowerIndex, -u8 RFPath, -u8 Rate - ); - void Hal_ChannelPlanToRegulation( struct adapter * Adapter, diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index 640427f407e3..1ebd7094705f 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -65,7 +65,7 @@ int PHY_RFConfig8723B(struct adapter *Adapter ); s32 PHY_MACConfig8723B(struct adapter *padapter); void -PHY_SetTxPowerIndex_8723B( +PHY_SetTxPowerIndex( struct adapter * Adapter, u32 PowerIndex, u8 RFPath, -- cgit v1.2.3-59-g8ed1b From 9dd2f1d9a1580717605a8f2ce882105710966b7a Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:39 +0530 Subject: staging: rtl8723bs: hal: Replace function PHY_GetTxPowerIndex() Remove function PHY_GetTxPowerIndex as it does nothing except call PHY_GetTxPowerIndex_8723B. Rename PHY_GetTxPowerIndex_8723B to PHY_GetTxPowerIndex to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_com_phycfg.c | 11 ----------- drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c | 2 +- drivers/staging/rtl8723bs/include/hal_com_phycfg.h | 9 --------- drivers/staging/rtl8723bs/include/hal_phy_cfg.h | 2 +- 4 files changed, 2 insertions(+), 22 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c index 7b1e6c4a2e8d..6539bee9b5ba 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/hal_com_phycfg.c @@ -2040,17 +2040,6 @@ void PHY_SetTxPowerLimit( } } -u8 PHY_GetTxPowerIndex( - struct adapter *padapter, - u8 RFPath, - u8 Rate, - enum CHANNEL_WIDTH BandWidth, - u8 Channel -) -{ - return PHY_GetTxPowerIndex_8723B(padapter, RFPath, Rate, BandWidth, Channel); -} - void Hal_ChannelPlanToRegulation(struct adapter *Adapter, u16 ChannelPlan) { struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index b02ff10fedbf..cb3ec085faa5 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -668,7 +668,7 @@ void PHY_SetTxPowerIndex( } } -u8 PHY_GetTxPowerIndex_8723B( +u8 PHY_GetTxPowerIndex( struct adapter *padapter, u8 RFPath, u8 Rate, diff --git a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h index f3521b7ae295..9167f1e7827f 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_phycfg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_phycfg.h @@ -213,15 +213,6 @@ PHY_GetTxPowerTrackingOffset( u8 RFPath ); -u8 -PHY_GetTxPowerIndex( -struct adapter * padapter, -u8 RFPath, -u8 Rate, -enum CHANNEL_WIDTH BandWidth, -u8 Channel - ); - void Hal_ChannelPlanToRegulation( struct adapter * Adapter, diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h index 1ebd7094705f..b40868b2e76f 100644 --- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h +++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h @@ -73,7 +73,7 @@ u8 Rate ); u8 -PHY_GetTxPowerIndex_8723B( +PHY_GetTxPowerIndex( struct adapter * padapter, u8 RFPath, u8 Rate, -- cgit v1.2.3-59-g8ed1b From 0528096df3778c51a99ae14ee36e1c13f6fd76e8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:40 +0530 Subject: staging: rtl8723bs: hal: Replace function rtl8723b_set_wowlan_cmd() Remove function rtl8723b_set_wowlan_cmd as all it does is call rtl8723b_set_FwWoWlanRelated_cmd. Rename rtl8723b_set_FwWoWlanRelated_cmd to rtl8723b_set_wowlan_cmd to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 080e974914b6..0f2767c0454c 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -1300,7 +1300,7 @@ static void rtl8723b_set_FwScanOffloadInfo_cmd(struct adapter *padapter, PRSVDPA } #endif /* CONFIG_PNO_SUPPORT */ -static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable) +void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable) { struct security_priv *psecpriv = &padapter->securitypriv; struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter); @@ -1346,11 +1346,6 @@ static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); } - -void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable) -{ - rtl8723b_set_FwWoWlanRelated_cmd(padapter, enable); -} #endif /* CONFIG_WOWLAN */ #ifdef CONFIG_AP_WOWLAN -- cgit v1.2.3-59-g8ed1b From 7a9a7332b62b802ca1a71f3e1351767129f3b53e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:41 +0530 Subject: staging: rtl8723bs: hal: Replace function rtl8723b_set_ap_wowlan_cmd() Remove function rtl8723b_set_ap_wowlan_cmd as all it does is call rtl8723b_set_AP_FwWoWlanRelated_cmd. Rename rtl8723b_set_AP_FwWoWlanRelated_cmd to rtl8723b_set_ap_wowlan_cmd to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 0f2767c0454c..79c1e3edb189 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -1393,7 +1393,7 @@ static void rtl8723b_set_Fw_AP_Offload_Cmd(struct adapter *padapter, u8 bFuncEn) H2C_AP_OFFLOAD_LEN, u1H2CAPOffloadCtrlParm); } -static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable) +void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) { DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable); if (enable) { @@ -1408,11 +1408,6 @@ static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable) DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); return ; } - -void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) -{ - rtl8723b_set_AP_FwWoWlan_cmd(padapter, enable); -} #endif /* CONFIG_AP_WOWLAN */ /* */ -- cgit v1.2.3-59-g8ed1b From d40e29d7e219cd214eef295149fd2678871ac982 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:42 +0530 Subject: staging: rtl8723bs: Replace function beacon_timing_control() Remove function beacon_timing_control as it does nothing except call rtw_hal_bcn_related_reg_setting. Rename rtw_hal_bcn_related_reg_setting to beacon_timing_control to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 5 ----- drivers/staging/rtl8723bs/hal/hal_intf.c | 2 +- drivers/staging/rtl8723bs/include/hal_intf.h | 2 +- drivers/staging/rtl8723bs/include/rtw_mlme_ext.h | 1 - 4 files changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index 76c50377f0fe..d78fbbc98fa2 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -1996,11 +1996,6 @@ void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len) } } -void beacon_timing_control(struct adapter *padapter) -{ - rtw_hal_bcn_related_reg_setting(padapter); -} - void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta) { int i; diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c index acb25978a46c..7d8f21f32fb9 100644 --- a/drivers/staging/rtl8723bs/hal/hal_intf.c +++ b/drivers/staging/rtl8723bs/hal/hal_intf.c @@ -369,7 +369,7 @@ void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter) } } -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter) +void beacon_timing_control(struct adapter *padapter) { if (padapter->HalFunc.SetBeaconRelatedRegistersHandler) padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter); diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h index 3a0c3d079d50..24926ebaf950 100644 --- a/drivers/staging/rtl8723bs/include/hal_intf.h +++ b/drivers/staging/rtl8723bs/include/hal_intf.h @@ -362,7 +362,7 @@ void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_l void rtw_hal_start_thread(struct adapter *padapter); void rtw_hal_stop_thread(struct adapter *padapter); -void rtw_hal_bcn_related_reg_setting(struct adapter *padapter); +void beacon_timing_control(struct adapter *padapter); u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask); void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data); diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 70cd8c0e3641..fd3cf955c9f8 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -650,7 +650,6 @@ void report_del_sta_event(struct adapter *padapter, unsigned char* MacAddr, unsi void report_add_sta_event(struct adapter *padapter, unsigned char* MacAddr, int cam_idx); void report_wmm_edca_update(struct adapter *padapter); -void beacon_timing_control(struct adapter *padapter); u8 chk_bmc_sleepq_cmd(struct adapter *padapter); extern u8 set_tx_beacon_cmd(struct adapter *padapter); unsigned int setup_beacon_frame(struct adapter *padapter, unsigned char *beacon_frame); -- cgit v1.2.3-59-g8ed1b From 4e8cc1c2df86f4245a37708bc007f8d530e235a1 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:43 +0530 Subject: staging: rtl8723bs: Replace function odm_TXPowerTrackingInit() Remove function odm_TXPowerTrackingInit as all it does is call odm_TXPowerTrackingThermalMeterInit. Rename odm_TXPowerTrackingThermalMeterInit to odm_TXPowerTrackingInit to maintain compatibility with call sites. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index e3f4307f3d20..01f732853689 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -339,8 +339,6 @@ void ODM_TXPowerTrackingCheck(PDM_ODM_T pDM_Odm); void odm_RateAdaptiveMaskInit(PDM_ODM_T pDM_Odm); -void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm); - void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm); @@ -1324,11 +1322,6 @@ void odm_RSSIMonitorCheckCE(PDM_ODM_T pDM_Odm) /* 3 Tx Power Tracking */ /* 3 ============================================================ */ -void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) -{ - odm_TXPowerTrackingThermalMeterInit(pDM_Odm); -} - static u8 getSwingIndex(PDM_ODM_T pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; @@ -1353,7 +1346,7 @@ static u8 getSwingIndex(PDM_ODM_T pDM_Odm) return i; } -void odm_TXPowerTrackingThermalMeterInit(PDM_ODM_T pDM_Odm) +void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) { u8 defaultSwingIndex = getSwingIndex(pDM_Odm); u8 p = 0; -- cgit v1.2.3-59-g8ed1b From f79670abd541d6abeda238ce91ac5859aa309515 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:44 +0530 Subject: staging: rtl8723bs: Replace function ODM_TXPowerTrackingCheck() Remove function ODM_TXPowerTrackingCheck as all it does is call odm_TXPowerTrackingCheckCE. Rename odm_TXPowerTrackingCheckCE to ODM_TXPowerTrackingCheck to maintain compatibility with call site. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index 01f732853689..dd9a16fb83a4 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -342,8 +342,6 @@ void odm_RateAdaptiveMaskInit(PDM_ODM_T pDM_Odm); void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm); -void odm_TXPowerTrackingCheckCE(PDM_ODM_T pDM_Odm); - /* Remove Edca by Yu Chen */ @@ -1390,13 +1388,7 @@ void odm_TXPowerTrackingInit(PDM_ODM_T pDM_Odm) } - void ODM_TXPowerTrackingCheck(PDM_ODM_T pDM_Odm) -{ - odm_TXPowerTrackingCheckCE(pDM_Odm); -} - -void odm_TXPowerTrackingCheckCE(PDM_ODM_T pDM_Odm) { struct adapter *Adapter = pDM_Odm->Adapter; -- cgit v1.2.3-59-g8ed1b From 4da947b27cdb71b1e5718d202e0028c0aeb9bdfe Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 25 Jul 2019 10:56:45 +0530 Subject: staging: rtl8723bs: Remove unused function prototype ODM_SetAntenna() Remove unused function prototype ODM_SetAntenna. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190725052645.2372-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h index 6ba77bb70889..fba3b9e1491b 100644 --- a/drivers/staging/rtl8723bs/hal/odm.h +++ b/drivers/staging/rtl8723bs/hal/odm.h @@ -1365,10 +1365,6 @@ extern u32 TxScalingTable_Jaguar[TXSCALE_TABLE_SIZE]; #define SWAW_STEP_PEAK 0 #define SWAW_STEP_DETERMINE 1 -/* Remove DIG by yuchen */ - -void ODM_SetAntenna(PDM_ODM_T pDM_Odm, u8 Antenna); - /* Remove BB power saving by Yuchen */ #define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck -- cgit v1.2.3-59-g8ed1b From 0f073df7e731b7b6c30c473dfdd28e0fd3cd489d Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Thu, 25 Jul 2019 08:53:25 +0530 Subject: staging: rtl8723bs: hal: Remove unneeded variable pU1Tmp Both pu8 and pU1Tmp are of same data type u8. So replace pU1Tmp with u8. Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190725032325.GA16473@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 5257287b4f4d..8987b5f892c0 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -389,7 +389,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) u8 *pu8; s32 *pS4Tmp; u32 *pU4Tmp; - u8 *pU1Tmp; u8 ret; @@ -403,7 +402,6 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) pu8 = pOutBuf; pS4Tmp = pOutBuf; pU4Tmp = pOutBuf; - pU1Tmp = pOutBuf; ret = true; switch (getType) { @@ -516,32 +514,32 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) break; case BTC_GET_U1_WIFI_DOT11_CHNL: - *pU1Tmp = padapter->mlmeextpriv.cur_channel; + *pu8 = padapter->mlmeextpriv.cur_channel; break; case BTC_GET_U1_WIFI_CENTRAL_CHNL: - *pU1Tmp = pHalData->CurrentChannel; + *pu8 = pHalData->CurrentChannel; break; case BTC_GET_U1_WIFI_HS_CHNL: - *pU1Tmp = 0; + *pu8 = 0; ret = false; break; case BTC_GET_U1_MAC_PHY_MODE: - *pU1Tmp = BTC_SMSP; + *pu8 = BTC_SMSP; /* *pU1Tmp = BTC_DMSP; */ /* *pU1Tmp = BTC_DMDP; */ /* *pU1Tmp = BTC_MP_UNKNOWN; */ break; case BTC_GET_U1_AP_NUM: - *pU1Tmp = halbtcoutsrc_GetWifiScanAPNum(padapter); + *pu8 = halbtcoutsrc_GetWifiScanAPNum(padapter); break; /* 1Ant =========== */ case BTC_GET_U1_LPS_MODE: - *pU1Tmp = padapter->dvobj->pwrctl_priv.pwr_mode; + *pu8 = padapter->dvobj->pwrctl_priv.pwr_mode; break; default: -- cgit v1.2.3-59-g8ed1b From e59fc52529118aaad9aa666f25530dde6e2180e9 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 10 Jul 2019 18:59:34 -0400 Subject: staging: rtl8192*: display ESSIDs using %pE Everywhere else in the kernel ESSIDs are printed using %pE, and I can't see why there should be an exception here. Signed-off-by: J. Bruce Fields Link: https://lore.kernel.org/r/1562799574-13315-1-git-send-email-bfields@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 2dd57e88276e..096254e422b3 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -2132,7 +2132,7 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) return escaped; } - snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); + snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); return escaped; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index d36963469015..3963a08b9eb2 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -2426,7 +2426,7 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) return escaped; } - snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid); + snprintf(escaped, sizeof(escaped), "%*pE", essid_len, essid); return escaped; } -- cgit v1.2.3-59-g8ed1b From 0eec1f38c7bb53b9dd2221ac982739cce7aab7fc Mon Sep 17 00:00:00 2001 From: Bárbara Fernandes Date: Fri, 28 Jun 2019 16:49:22 -0300 Subject: staging: iio: ad7192: create of_device_id array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create list of compatible device ids to be matched with those stated in the device tree. Signed-off-by: Bárbara Fernandes Signed-off-by: Wilson Sales Co-developed by: Wilson Sales Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index b6d12fe7c12a..df06e0570f9b 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -809,11 +809,23 @@ static const struct spi_device_id ad7192_id[] = { {"ad7195", ID_AD7195}, {} }; + MODULE_DEVICE_TABLE(spi, ad7192_id); +static const struct of_device_id ad7192_of_match[] = { + { .compatible = "adi,ad7190" }, + { .compatible = "adi,ad7192" }, + { .compatible = "adi,ad7193" }, + { .compatible = "adi,ad7195" }, + {} +}; + +MODULE_DEVICE_TABLE(of, ad7192_of_match); + static struct spi_driver ad7192_driver = { .driver = { .name = "ad7192", + .of_match_table = ad7192_of_match, }, .probe = ad7192_probe, .remove = ad7192_remove, -- cgit v1.2.3-59-g8ed1b From 857ba268f918dec28470c2074e7c69ccad52547e Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Fri, 26 Jul 2019 19:07:42 +0800 Subject: staging: iio: ad2s1210: Use device-managed API Use device-managed API to simplify the code. The remove function is redundant now and can be deleted. Signed-off-by: Chuhong Yuan Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/staging/iio/resolver/ad2s1210.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index 0c1bd108c386..4b25a3a314ed 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -671,7 +671,7 @@ static int ad2s1210_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); indio_dev->name = spi_get_device_id(spi)->name; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) return ret; @@ -683,15 +683,6 @@ static int ad2s1210_probe(struct spi_device *spi) return 0; } -static int ad2s1210_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - - return 0; -} - static const struct of_device_id ad2s1210_of_match[] = { { .compatible = "adi,ad2s1210", }, { } @@ -710,7 +701,6 @@ static struct spi_driver ad2s1210_driver = { .of_match_table = of_match_ptr(ad2s1210_of_match), }, .probe = ad2s1210_probe, - .remove = ad2s1210_remove, .id_table = ad2s1210_id, }; module_spi_driver(ad2s1210_driver); -- cgit v1.2.3-59-g8ed1b From 07ca9aa4a4b7fdd3c29cc9f8b07a2d1b8e0b6ba5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:03:21 +0800 Subject: staging: rtl8723bs: remove set but not used variable 'bWifiBusy' Fixes gcc '-Wunused-but-set-variable' warning: In function halbtc8723b1ant_TdmaDurationAdjustForAcl: drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c:1761:7: warning: variable bWifiBusy set but not used [-Wunused-but-set-variable] It is never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190726140321.19200-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c index 8e4caeeb4070..dd349c506da8 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c +++ b/drivers/staging/rtl8723bs/hal/HalBtc8723b1Ant.c @@ -1758,7 +1758,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( static s32 up, dn, m, n, WaitCount; s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */ u8 retryCount = 0, btInfoExt; - bool bWifiBusy = false; BTC_PRINT( BTC_MSG_ALGORITHM, @@ -1766,11 +1765,6 @@ static void halbtc8723b1ant_TdmaDurationAdjustForAcl( ("[BTCoex], TdmaDurationAdjustForAcl()\n") ); - if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifiStatus) - bWifiBusy = true; - else - bWifiBusy = false; - if ( (BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == wifiStatus) || (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifiStatus) || -- cgit v1.2.3-59-g8ed1b From 30833b4b4bc6c3da04e3478552a25a7da4ebc92c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:07:34 +0800 Subject: staging: rtl8723bs: remove set but not used variable 'pszBBRegMpFile' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c: In function phy_BB8723b_Config_ParaFile: drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c:436:77: warning: variable pszBBRegMpFile set but not used [-Wunused-but-set-variable] It is never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190726140734.39564-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c index cb3ec085faa5..6df2b58bdc67 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c @@ -431,14 +431,12 @@ static int phy_BB8723b_Config_ParaFile(struct adapter *Adapter) u8 sz8723BBRegFile[] = RTL8723B_PHY_REG; u8 sz8723AGCTableFile[] = RTL8723B_AGC_TAB; u8 sz8723BBBRegPgFile[] = RTL8723B_PHY_REG_PG; - u8 sz8723BBRegMpFile[] = RTL8723B_PHY_REG_MP; u8 sz8723BRFTxPwrLmtFile[] = RTL8723B_TXPWR_LMT; - u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszBBRegMpFile = NULL, *pszRFTxPwrLmtFile = NULL; + u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL, *pszBBRegPgFile = NULL, *pszRFTxPwrLmtFile = NULL; pszBBRegFile = sz8723BBRegFile; pszAGCTableFile = sz8723AGCTableFile; pszBBRegPgFile = sz8723BBBRegPgFile; - pszBBRegMpFile = sz8723BBRegMpFile; pszRFTxPwrLmtFile = sz8723BRFTxPwrLmtFile; /* Read Tx Power Limit File */ -- cgit v1.2.3-59-g8ed1b From 149726d3d78a6053445aaff6361374a0b67b7ac1 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 26 Jul 2019 22:09:59 +0800 Subject: staging: rtl8723bs: os_dep: remove two set but not used variables Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs//os_dep/osdep_service.c: In function 'rtw_buf_free': drivers/staging/rtl8723bs//os_dep/osdep_service.c:321:6: warning: variable 'ori_len' set but not used [-Wunused-but-set-variable] drivers/staging/rtl8723bs//os_dep/ioctl_linux.c: In function 'rtw_ioctl_wext_private': drivers/staging/rtl8723bs//os_dep/ioctl_linux.c:4915:6: warning: variable 'num_priv' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190726140959.15008-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 -- drivers/staging/rtl8723bs/os_dep/osdep_service.c | 4 ---- 2 files changed, 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 99e6b1028f71..90c2997256b7 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -4912,7 +4912,6 @@ static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_ s32 k; const iw_handler *priv; /* Private ioctl */ const struct iw_priv_args *priv_args; /* Private ioctl description */ - u32 num_priv; /* Number of ioctl */ u32 num_priv_args; /* Number of descriptions */ iw_handler handler; int temp; @@ -4948,7 +4947,6 @@ static int rtw_ioctl_wext_private(struct net_device *dev, union iwreq_data *wrq_ priv = rtw_private_handler; priv_args = rtw_private_args; - num_priv = ARRAY_SIZE(rtw_private_handler); num_priv_args = ARRAY_SIZE(rtw_private_args); if (num_priv_args == 0) { diff --git a/drivers/staging/rtl8723bs/os_dep/osdep_service.c b/drivers/staging/rtl8723bs/os_dep/osdep_service.c index 62fdd24ba427..25a80041ce87 100644 --- a/drivers/staging/rtl8723bs/os_dep/osdep_service.c +++ b/drivers/staging/rtl8723bs/os_dep/osdep_service.c @@ -318,13 +318,9 @@ error: void rtw_buf_free(u8 **buf, u32 *buf_len) { - u32 ori_len; - if (!buf || !buf_len) return; - ori_len = *buf_len; - if (*buf) { *buf_len = 0; kfree(*buf); -- cgit v1.2.3-59-g8ed1b From db0e6a573e9c54151cdc828e80ab82849802337f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 27 Jul 2019 09:35:24 +0800 Subject: staging: vc04_services: fix unused-but-set-variable warning Fix gcc used-but-set-variable warning: drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c: In function vchiq_release_internal: drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:2827:16: warning: variable local_entity_uc set but not used [-Wunused-but-set-variable] drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:2827:6: warning: variable local_uc set but not used [-Wunused-but-set-variable] Remove the unused variables 'local_entity_uc' and 'local_uc' Reported-by: Hulk Robot Signed-off-by: YueHaibing Acked-by: Stefan Wahren Link: https://lore.kernel.org/r/20190727013524.33168-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index cc4383d1ec3e..b1595b13dea8 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2824,7 +2824,6 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; - int local_uc, local_entity_uc; if (!arm_state) goto out; @@ -2849,8 +2848,8 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) ret = VCHIQ_ERROR; goto unlock; } - local_uc = --arm_state->videocore_use_count; - local_entity_uc = --(*entity_uc); + --arm_state->videocore_use_count; + --(*entity_uc); if (!vchiq_videocore_wanted(state)) { if (vchiq_platform_use_suspend_timer() && -- cgit v1.2.3-59-g8ed1b From 5f251e986de05af8a177bfc632980cc64a4d3e7e Mon Sep 17 00:00:00 2001 From: Jerry Lin Date: Mon, 29 Jul 2019 10:35:44 +0800 Subject: staging: olpc_dcon: Remove TODO item All uses of old GPIO API have been converted to new API. This item can be removed from TODO file. Signed-off-by: Jerry Lin Link: https://lore.kernel.org/r/20190729023544.GA25930@compute1 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/olpc_dcon/TODO | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO index fe09efbc7f77..d8296f2ae872 100644 --- a/drivers/staging/olpc_dcon/TODO +++ b/drivers/staging/olpc_dcon/TODO @@ -8,10 +8,6 @@ TODO: internals, but isn't properly integrated, is not the correct solution. - see if vx855 gpio API can be made similar enough to cs5535 so we can share more code - - convert all uses of the old GPIO API from to the - GPIO descriptor API in and look up GPIO - lines from device tree, ACPI or board files, board files should - use - allow simultaneous XO-1 and XO-1.5 support Please send patches to Greg Kroah-Hartman and -- cgit v1.2.3-59-g8ed1b From a20eefaee64610541d125cd2c10fa25e278f0bee Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2019 13:22:14 +0200 Subject: staging: most: Use DEFINE_SPINLOCK() instead of struct spinlock For spinlocks the type spinlock_t should be used instead of "struct spinlock". Use DEFINE_SPINLOCK() and spare the run time initialization Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20190704153803.12739-5-bigeasy@linutronix.de Link: https://lore.kernel.org/r/alpine.DEB.2.21.1907261319100.1791@nanos.tec.linutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/net/net.c | 3 +-- drivers/staging/most/video/video.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index aababdf2be12..26a31854c636 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -69,7 +69,7 @@ struct net_dev_context { static struct list_head net_devices = LIST_HEAD_INIT(net_devices); static struct mutex probe_disc_mt; /* ch->linked = true, most_nd_open */ -static struct spinlock list_lock; /* list_head, ch->linked = false, dev_hold */ +static DEFINE_SPINLOCK(list_lock); /* list_head, ch->linked = false, dev_hold */ static struct core_component comp; static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo) @@ -509,7 +509,6 @@ static int __init most_net_init(void) { int err; - spin_lock_init(&list_lock); mutex_init(&probe_disc_mt); err = most_register_component(&comp); if (err) diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index 6f6e98ab0550..250af9fb704d 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -54,7 +54,7 @@ struct comp_fh { }; static struct list_head video_devices = LIST_HEAD_INIT(video_devices); -static struct spinlock list_lock; +static DEFINE_SPINLOCK(list_lock); static inline bool data_ready(struct most_video_dev *mdev) { @@ -538,7 +538,6 @@ static int __init comp_init(void) { int err; - spin_lock_init(&list_lock); err = most_register_component(&comp); if (err) return err; -- cgit v1.2.3-59-g8ed1b From 9d6b3ee001cba29ad6d8d5f31953926504c67a1d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 25 Jul 2019 20:38:56 +0200 Subject: Staging: fbtft: Fix some typo. pdc8544 --> pcd8544 The driver is related to 'pcd8544'. However, 2 strings are about pdc8544 (c and d switched) Fix it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190725183856.17616-1-christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_pcd8544.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index ad49973ad594..08f8a4bb8772 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -157,10 +157,10 @@ static struct fbtft_display display = { .backlight = 1, }; -FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pdc8544", &display); +FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pcd8544", &display); MODULE_ALIAS("spi:" DRVNAME); -MODULE_ALIAS("spi:pdc8544"); +MODULE_ALIAS("spi:pcd8544"); MODULE_DESCRIPTION("FB driver for the PCD8544 LCD Controller"); MODULE_AUTHOR("Noralf Tronnes"); -- cgit v1.2.3-59-g8ed1b From c47f77eed0da6f829042a266a2f33ef31c250969 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Thu, 25 Jul 2019 19:09:22 +0200 Subject: staging: rtl8188eu: replace hal_EfusePgCheckAvailableAddr() Function hal_EfusePgCheckAvailableAddr() contains just a single if test. Remove the function and replace the call to it with the if test. Signed-off-by: Michael Straube Link: https://lore.kernel.org/r/20190725170922.16465-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 51c3dd6d7ffb..533ca1ddffb0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -763,17 +763,6 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u return ret; } -static bool -hal_EfusePgCheckAvailableAddr( - struct adapter *pAdapter, - u8 efuseType - ) -{ - if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) - return false; - return true; -} - static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) { memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); @@ -789,7 +778,7 @@ bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pD u16 startAddr = 0; u8 efuseType = EFUSE_WIFI; - if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType)) + if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E) return false; hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt); -- cgit v1.2.3-59-g8ed1b From 91e590851f51064a2f4cd11cf6ea01c21c4490bc Mon Sep 17 00:00:00 2001 From: Abhinav Jain Date: Fri, 26 Jul 2019 19:01:46 +0000 Subject: Staging: rtl8192e: fixed a function prototype definition issue Added the identifier name in the function prototype definition. Signed-off-by: Abhinav Jain Link: https://lore.kernel.org/r/20190726190146.10875-1-ubuntu@ip-172-31-129-142.ec2.internal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 096254e422b3..7a012881578f 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1940,7 +1940,7 @@ int rtllib_encrypt_fragment( int hdr_len); int rtllib_xmit(struct sk_buff *skb, struct net_device *dev); -void rtllib_txb_free(struct rtllib_txb *); +void rtllib_txb_free(struct rtllib_txb *txb); /* rtllib_rx.c */ int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, -- cgit v1.2.3-59-g8ed1b From 36475456f3530491460453baae591b0bfd2e94be Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Jul 2019 13:48:03 +0100 Subject: staging: rtl8188eu: remove redundant assignment to rtstatus Variable rtstatus is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190726124803.11349-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/rf_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c index 739e62dc60e3..47b1bf5a6143 100644 --- a/drivers/staging/rtl8188eu/hal/rf_cfg.c +++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c @@ -222,7 +222,7 @@ bool rtl88eu_phy_rf_config(struct adapter *adapt) { struct hal_data_8188e *hal_data = adapt->HalData; u32 u4val = 0; - bool rtstatus = true; + bool rtstatus; struct bb_reg_def *pphyreg; pphyreg = &hal_data->PHYRegDef[RF90_PATH_A]; -- cgit v1.2.3-59-g8ed1b From 8e7cb7352ec85e9e4fbbd7bfe6c5c5a6806f70e3 Mon Sep 17 00:00:00 2001 From: Bharath Vedartham Date: Thu, 25 Jul 2019 18:14:18 +0530 Subject: staging: kpc2000: Convert put_page() to put_user_page*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For pages that were retained via get_user_pages*(), release those pages via the new put_user_page*() routines, instead of via put_page(). This is part a tree-wide conversion, as described in commit fc1d8e7cca2d ("mm: introduce put_user_page*(), placeholder versions"). Cc: Ira Weiny Cc: John Hubbard Cc: Jérôme Glisse Cc: Greg Kroah-Hartman Cc: Matt Sickler Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org Reviewed-by: John Hubbard Signed-off-by: Bharath Vedartham Link: https://lore.kernel.org/r/1564058658-3551-1-git-send-email-linux.bhar@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc_dma/fileops.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index 48ca88bc6b0b..f15e29209d55 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -190,9 +190,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv, sg_free_table(&acd->sgt); err_dma_map_sg: err_alloc_sg_table: - for (i = 0 ; i < acd->page_count ; i++) { - put_page(acd->user_pages[i]); - } + put_user_pages(acd->user_pages, acd->page_count); err_get_user_pages: kfree(acd->user_pages); err_alloc_userpages: @@ -211,16 +209,13 @@ void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) BUG_ON(acd->ldev == NULL); BUG_ON(acd->ldev->pldev == NULL); - for (i = 0 ; i < acd->page_count ; i++) { - if (!PageReserved(acd->user_pages[i])) { - set_page_dirty(acd->user_pages[i]); - } - } - dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - for (i = 0 ; i < acd->page_count ; i++) { - put_page(acd->user_pages[i]); + for (i = 0; i < acd->page_count; i++) { + if (!PageReserved(acd->user_pages[i])) + put_user_pages_dirty(&acd->user_pages[i], 1); + else + put_user_page(acd->user_pages[i]); } sg_free_table(&acd->sgt); -- cgit v1.2.3-59-g8ed1b From f68dc00ee710ba56ee2112ea1184d7c5d3c40370 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:33 +0000 Subject: staging: wilc1000: remove inetaddr notifier Driver registers an inetaddr notifier to disable powersave while the ip address is being obtained which should be controlled only by cfg80211. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 65 ---------------------------------- 1 file changed, 65 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 8d8b7e4399f7..68129a0ba55f 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -504,12 +504,6 @@ static int wlan_initialize_threads(struct net_device *dev) return 0; } -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr); -static struct notifier_block g_dev_notifier = { - .notifier_call = dev_state_ev_handler -}; - static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) { int ret = 0; @@ -575,7 +569,6 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) ret = -EIO; goto fail_fw_start; } - register_inetaddr_notifier(&g_dev_notifier); wl->initialized = true; return 0; @@ -781,7 +774,6 @@ static int wilc_mac_close(struct net_device *ndev) if (wl->open_ifcs == 0) { netdev_dbg(ndev, "Deinitializing wilc1000\n"); wl->close = 1; - unregister_inetaddr_notifier(&g_dev_notifier); wilc_wlan_deinitialize(ndev); } @@ -864,63 +856,6 @@ static const struct net_device_ops wilc_netdev_ops = { .ndo_set_rx_mode = wilc_set_multicast_list, }; -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct in_ifaddr *dev_iface = ptr; - struct wilc_priv *priv; - struct host_if_drv *hif_drv; - struct net_device *dev; - struct wilc_vif *vif; - - if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) - return NOTIFY_DONE; - - dev = (struct net_device *)dev_iface->ifa_dev->dev; - if (dev->netdev_ops != &wilc_netdev_ops) - return NOTIFY_DONE; - - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) - return NOTIFY_DONE; - - vif = netdev_priv(dev); - priv = &vif->priv; - - hif_drv = (struct host_if_drv *)priv->hif_drv; - - switch (event) { - case NETDEV_UP: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 1; - vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); - } - - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, 1, 0); - - break; - - case NETDEV_DOWN: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 0; - vif->obtaining_ip = false; - wilc_set_power_mgmt(vif, 0, 0); - } - - wilc_resolve_disconnect_aberration(vif); - - break; - - default: - break; - } - - return NOTIFY_DONE; -} - void wilc_netdev_cleanup(struct wilc *wilc) { int i; -- cgit v1.2.3-59-g8ed1b From 98af3e7ed6831f001fee70584c08f39264002b1d Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:34 +0000 Subject: staging: wilc1000: remove ip timeout timer during_ip_timer is not required after removing the code that disables powersave while the ip is being obtained. Its handler clear_during_ip is also removed Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 2 -- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 16 ---------------- 2 files changed, 18 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 9345cabe3c93..9bd2d14ad610 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -684,8 +684,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, hif_drv->hif_state = HOST_IF_CONNECTED; vif->obtaining_ip = true; - mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(10000)); } else { hif_drv->hif_state = HOST_IF_IDLE; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 12fb4add05ec..81fe26a6b6db 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -70,15 +70,6 @@ struct wilc_p2p_mgmt_data { static const u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09}; static const u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; -#define WILC_IP_TIMEOUT_MS 15000 - -static void clear_during_ip(struct timer_list *t) -{ - struct wilc_vif *vif = from_timer(vif, t, during_ip_timer); - - vif->obtaining_ip = false; -} - static void cfg_scan_result(enum scan_event scan_event, struct wilc_rcvd_net_info *info, void *user_void) { @@ -1421,7 +1412,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); switch (type) { case NL80211_IFTYPE_STATION: @@ -1469,8 +1459,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, case NL80211_IFTYPE_P2P_GO: vif->obtaining_ip = true; - mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS)); wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; @@ -1948,8 +1936,6 @@ int wilc_init_host_int(struct net_device *net) struct wilc_vif *vif = netdev_priv(net); struct wilc_priv *priv = &vif->priv; - timer_setup(&vif->during_ip_timer, clear_during_ip, 0); - priv->p2p_listen_state = false; mutex_init(&priv->scan_req_lock); @@ -1971,8 +1957,6 @@ void wilc_deinit_host_int(struct net_device *net) mutex_destroy(&priv->scan_req_lock); ret = wilc_deinit(vif); - del_timer_sync(&vif->during_ip_timer); - if (ret) netdev_err(net, "Error while deinitializing host interface\n"); } -- cgit v1.2.3-59-g8ed1b From 5a28d3fd407bf5225e7ab4eea1c5779a8a71c966 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:34 +0000 Subject: staging: wilc1000: remove unused members remove obtaining_ip from struct wilc_vif Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-4-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 9 ++------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 3 --- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 9bd2d14ad610..611f842d2836 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -248,7 +248,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, goto error; } - if (vif->obtaining_ip || vif->connecting) { + if (vif->connecting) { netdev_err(vif->ndev, "Don't do obss scan\n"); result = -EBUSY; goto error; @@ -682,8 +682,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, wilc_set_power_mgmt(vif, 0, 0); hif_drv->hif_state = HOST_IF_CONNECTED; - - vif->obtaining_ip = true; } else { hif_drv->hif_state = HOST_IF_IDLE; } @@ -707,7 +705,6 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) } if (hif_drv->conn_info.conn_result) { - vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, @@ -770,7 +767,6 @@ int wilc_disconnect(struct wilc_vif *vif) wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); - vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); @@ -922,7 +918,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif, if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) return -EBUSY; - if (vif->obtaining_ip || vif->connecting) + if (vif->connecting) return -EBUSY; remain_on_chan_flag = true; @@ -1608,7 +1604,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) *hif_drv_handler = hif_drv; vif->hif_drv = hif_drv; - vif->obtaining_ip = false; if (wilc->clients_count == 0) mutex_init(&wilc->deinit_lock); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 81fe26a6b6db..deaf040f6623 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -167,7 +167,6 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { u16 reason = 0; - vif->obtaining_ip = false; priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; @@ -1411,7 +1410,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; - vif->obtaining_ip = false; switch (type) { case NL80211_IFTYPE_STATION: @@ -1458,7 +1456,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_P2P_GO: - vif->obtaining_ip = true; wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 1e74a08e7cf1..704e4d572695 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -203,7 +203,6 @@ struct wilc_vif { struct net_device *ndev; u8 mode; struct timer_list during_ip_timer; - bool obtaining_ip; struct timer_list periodic_rssi; struct rf_info periodic_stat; struct tcp_ack_filter ack_filter; -- cgit v1.2.3-59-g8ed1b From ded11ab1818440a9e5b35f2cff78a76148762dbd Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:35 +0000 Subject: staging: wilc1000: avoid overriding powersave state Don't override powersave state with respect to the open interfaces and let the firmware take care of when it's appropriate to do so Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-5-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 11 ++--------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 15 +-------------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 3 files changed, 3 insertions(+), 24 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 611f842d2836..16ff610c6a5b 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -679,8 +679,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, if (mac_status == WILC_MAC_STATUS_CONNECTED && conn_info->status == WLAN_STATUS_SUCCESS) { ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid); - wilc_set_power_mgmt(vif, 0, 0); - hif_drv->hif_state = HOST_IF_CONNECTED; } else { hif_drv->hif_state = HOST_IF_IDLE; @@ -704,14 +702,11 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) handle_scan_done(vif, SCAN_EVENT_ABORTED); } - if (hif_drv->conn_info.conn_result) { - wilc_set_power_mgmt(vif, 0, 0); - + if (hif_drv->conn_info.conn_result) hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, hif_drv->conn_info.arg); - } else { + else netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); - } eth_zero_addr(hif_drv->assoc_bssid); @@ -767,8 +762,6 @@ int wilc_disconnect(struct wilc_vif *vif) wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); - wilc_set_power_mgmt(vif, 0, 0); - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); if (result) { netdev_err(vif->ndev, "Failed to send disconnect\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index deaf040f6623..e2d9efed36b0 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1393,8 +1393,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, if (!priv->hif_drv) return -EIO; - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, enabled, timeout); + wilc_set_power_mgmt(vif, enabled, timeout); return 0; } @@ -1424,9 +1423,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, memset(priv->assoc_stainfo.sta_associated_bss, 0, WILC_MAX_NUM_STA * ETH_ALEN); - - wl->enable_ps = true; - wilc_set_power_mgmt(vif, 1, 0); break; case NL80211_IFTYPE_P2P_CLIENT: @@ -1437,12 +1433,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, vif->iftype = WILC_CLIENT_MODE; wilc_set_operation_mode(vif, WILC_STATION_MODE); - wl->enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); break; case NL80211_IFTYPE_AP: - wl->enable_ps = false; dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_AP_MODE; @@ -1451,7 +1444,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), 0, vif->idx); wilc_set_operation_mode(vif, WILC_AP_MODE); - wilc_set_power_mgmt(vif, 0, 0); } break; @@ -1460,9 +1452,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_GO_MODE; - - wl->enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); break; default: @@ -1484,7 +1473,6 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, netdev_err(dev, "Error in setting channel\n"); wilc_wlan_set_bssid(dev, dev->dev_addr, WILC_AP_MODE); - wilc_set_power_mgmt(vif, 0, 0); return wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, &settings->beacon); @@ -1835,7 +1823,6 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type, *wilc = wl; wl->io_type = io_type; wl->hif_func = ops; - wl->enable_ps = false; wl->chip_ps_state = WILC_CHIP_WAKEDUP; INIT_LIST_HEAD(&wl->txq_head.list); INIT_LIST_HEAD(&wl->rxq_head.list); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 704e4d572695..7e7ce9471f67 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -261,7 +261,6 @@ struct wilc { struct device *dev; bool suspend_event; - bool enable_ps; int clients_count; struct workqueue_struct *hif_workqueue; enum chip_ps_states chip_ps_state; -- cgit v1.2.3-59-g8ed1b From 7e0cf3e3bfe94d030c3d3d79f8af8f0e365fdf1c Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:36 +0000 Subject: staging: wilc1000: apply power management regardless of open interfaces Don't ignore power management if 2 interfaces are open Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-6-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 16ff610c6a5b..75a6931aa147 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -2010,9 +2010,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) int result; s8 power_mode; - if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) - return 0; - if (enabled) power_mode = WILC_FW_MIN_FAST_PS; else -- cgit v1.2.3-59-g8ed1b From 25f12201a4ba67451a8be71db83dd734b2f62b30 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 25 Jul 2019 21:31:37 +0000 Subject: staging: wilc1000: remove manual sleep mode manual sleep mode was used to put the wilc1000 chip in sleep while in disconnected state. This is taken care of in the firmware Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190725213125.2810-7-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 4 ---- drivers/staging/wilc1000/wilc_sdio.c | 4 +--- drivers/staging/wilc1000/wilc_wlan.c | 14 -------------- drivers/staging/wilc1000/wilc_wlan.h | 2 -- 4 files changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 75a6931aa147..f8646ea3b0c4 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -1056,13 +1056,9 @@ static void handle_scan_timer(struct work_struct *work) static void handle_scan_complete(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc *wilc = msg->vif->wilc; del_timer(&msg->vif->hif_drv->scan_timer); - if (!wilc_wlan_get_num_conn_ifcs(wilc)) - wilc_chip_sleep_manually(wilc); - handle_scan_done(msg->vif, SCAN_EVENT_DONE); kfree(msg); diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 4c1c81fed11f..2f9aa36e0114 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -193,9 +193,7 @@ static int wilc_sdio_suspend(struct device *dev) dev_info(dev, "sdio suspend\n"); chip_wakeup(wilc); - if (!wilc->suspend_event) { - wilc_chip_sleep_manually(wilc); - } else { + if (wilc->suspend_event) { host_sleep_notify(wilc); chip_allow_sleep(wilc); } diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 8ca0a7a4fa3f..d4ca6467485c 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -455,20 +455,6 @@ void chip_wakeup(struct wilc *wilc) } EXPORT_SYMBOL_GPL(chip_wakeup); -void wilc_chip_sleep_manually(struct wilc *wilc) -{ - if (wilc->chip_ps_state != WILC_CHIP_WAKEDUP) - return; - acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); - - chip_allow_sleep(wilc); - wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1); - - wilc->chip_ps_state = WILC_CHIP_SLEEPING_MANUAL; - release_bus(wilc, WILC_BUS_RELEASE_ONLY); -} -EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually); - void host_wakeup_notify(struct wilc *wilc) { acquire_bus(wilc, WILC_BUS_ACQUIRE_ONLY); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index b70014142686..802f11807659 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -293,8 +293,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, u32 drv_handler); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*func)(void *, int)); -void wilc_chip_sleep_manually(struct wilc *wilc); - void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc); netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); -- cgit v1.2.3-59-g8ed1b From 3455db0e056516f576c3d4a8baf320d814a6e202 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:43 +0200 Subject: staging: rtl8188eu: add spaces around '+' in usb_halinit.c Add spaces around '+' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-1-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 76 ++++++++++++++--------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 994392ac249b..c2e1b000cf89 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -183,7 +183,7 @@ static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy) usb_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); usb_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); usb_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy); - usb_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy); + usb_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy); } static void _InitPageBoundary(struct adapter *Adapter) @@ -504,7 +504,7 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter) switch (haldata->UsbRxAggMode) { case USB_RX_AGG_DMA: usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount); - usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, haldata->UsbRxAggPageTimeout); + usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, haldata->UsbRxAggPageTimeout); break; case USB_RX_AGG_USB: usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount); @@ -512,7 +512,7 @@ static void usb_AggSettingRxUpdate(struct adapter *Adapter) break; case USB_RX_AGG_MIX: usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount); - usb_write8(Adapter, REG_RXDMA_AGG_PG_TH+1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */ + usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */ usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount); usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout); break; @@ -569,9 +569,9 @@ static void _InitBeaconParameters(struct adapter *Adapter) haldata->RegBcnCtrlVal = usb_read8(Adapter, REG_BCN_CTRL); haldata->RegTxPause = usb_read8(Adapter, REG_TXPAUSE); - haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL+2); - haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT+2); - haldata->RegCR_1 = usb_read8(Adapter, REG_CR+1); + haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL + 2); + haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT + 2); + haldata->RegCR_1 = usb_read8(Adapter, REG_CR + 1); } static void _BeaconFunctionEnable(struct adapter *Adapter, @@ -579,7 +579,7 @@ static void _BeaconFunctionEnable(struct adapter *Adapter, { usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1))); - usb_write8(Adapter, REG_RD_CTRL+1, 0x6F); + usb_write8(Adapter, REG_RD_CTRL + 1, 0x6F); } /* Set CCK and OFDM Block "ON" */ @@ -770,7 +770,7 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) value8 = usb_read8(Adapter, REG_TX_RPT_CTRL); usb_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0))); /* Set MAX RPT MACID */ - usb_write8(Adapter, REG_TX_RPT_CTRL+1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ + usb_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */ /* Tx RPT Timer. Unit: 32us */ usb_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0); @@ -827,10 +827,10 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter) pwrctrlpriv->rf_pwrstate = rf_on; /* enable Tx report. */ - usb_write8(Adapter, REG_FWHW_TXQ_CTRL+1, 0x0F); + usb_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F); /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */ - usb_write8(Adapter, REG_EARLY_MODE_CONTROL+3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ + usb_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */ /* tynli_test_tx_report. */ usb_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0); @@ -894,9 +894,9 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_MCUFWDL); if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */ /* Reset MCU 0x2[10]=0. */ - val8 = usb_read8(Adapter, REG_SYS_FUNC_EN+1); + val8 = usb_read8(Adapter, REG_SYS_FUNC_EN + 1); val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */ - usb_write8(Adapter, REG_SYS_FUNC_EN+1, val8); + usb_write8(Adapter, REG_SYS_FUNC_EN + 1, val8); } /* reset MCU ready status */ @@ -912,10 +912,10 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) Rtl8188E_NIC_DISABLE_FLOW); /* Reset MCU IO Wrapper */ - val8 = usb_read8(Adapter, REG_RSV_CTRL+1); - usb_write8(Adapter, REG_RSV_CTRL+1, (val8&(~BIT(3)))); - val8 = usb_read8(Adapter, REG_RSV_CTRL+1); - usb_write8(Adapter, REG_RSV_CTRL+1, val8 | BIT(3)); + val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); + usb_write8(Adapter, REG_RSV_CTRL + 1, (val8&(~BIT(3)))); + val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); + usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3)); /* YJ,test add, 111207. For Power Consumption. */ val8 = usb_read8(Adapter, GPIO_IN); @@ -924,8 +924,8 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); - val8 = usb_read8(Adapter, REG_GPIO_IO_SEL+1); - usb_write8(Adapter, REG_GPIO_IO_SEL+1, val8|0x0F);/* Reg0x43 */ + val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); + usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8|0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; @@ -1103,11 +1103,11 @@ static void ResumeTxBeacon(struct adapter *adapt) /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ - usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) | BIT(6)); + usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6)); haldata->RegFwHwTxQCtrl |= BIT(6); - usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0xff); + usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff); haldata->RegReg542 |= BIT(0); - usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542); + usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); } static void StopTxBeacon(struct adapter *adapt) @@ -1117,11 +1117,11 @@ static void StopTxBeacon(struct adapter *adapt) /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */ /* which should be read from register to a global variable. */ - usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); + usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6))); haldata->RegFwHwTxQCtrl &= (~BIT(6)); - usb_write8(adapt, REG_TBTT_PROHIBIT+1, 0x64); + usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64); haldata->RegReg542 &= ~(BIT(0)); - usb_write8(adapt, REG_TBTT_PROHIBIT+2, haldata->RegReg542); + usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542); /* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */ } @@ -1191,7 +1191,7 @@ static void hw_var_set_macaddr(struct adapter *Adapter, u8 variable, u8 *val) reg_macid = REG_MACID; for (idx = 0; idx < 6; idx++) - usb_write8(Adapter, (reg_macid+idx), val[idx]); + usb_write8(Adapter, (reg_macid + idx), val[idx]); } static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val) @@ -1202,7 +1202,7 @@ static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val) reg_bssid = REG_BSSID; for (idx = 0; idx < 6; idx++) - usb_write8(Adapter, (reg_bssid+idx), val[idx]); + usb_write8(Adapter, (reg_bssid + idx), val[idx]); } static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) @@ -1274,8 +1274,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) BrateCfg |= 0x01; /* default enable 1M ACK rate */ /* Set RRSR rate table. */ usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff); - usb_write8(Adapter, REG_RRSR+1, (BrateCfg >> 8) & 0xff); - usb_write8(Adapter, REG_RRSR+2, usb_read8(Adapter, REG_RRSR+2)&0xf0); + usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff); + usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2)&0xf0); /* Set RTS initial rate */ while (BrateCfg > 0x1) { @@ -1307,7 +1307,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); - usb_write32(Adapter, REG_TSFTR+4, tsf>>32); + usb_write32(Adapter, REG_TSFTR + 4, tsf>>32); /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); @@ -1432,10 +1432,10 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) case HW_VAR_RESP_SIFS: /* RESP_SIFS for CCK */ usb_write8(Adapter, REG_R2T_SIFS, val[0]); /* SIFS_T2T_CCK (0x08) */ - usb_write8(Adapter, REG_R2T_SIFS+1, val[1]); /* SIFS_R2T_CCK(0x08) */ + usb_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */ /* RESP_SIFS for OFDM */ usb_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */ - usb_write8(Adapter, REG_T2T_SIFS+1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ + usb_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */ break; case HW_VAR_ACK_PREAMBLE: { @@ -1446,7 +1446,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if (bShortPreamble) regTmp |= 0x80; - usb_write8(Adapter, REG_RRSR+2, regTmp); + usb_write8(Adapter, REG_RRSR + 2, regTmp); } break; case HW_VAR_SEC_CFG: @@ -1484,7 +1484,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) else ulContent = 0; /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT*ucIndex+i; + ulCommand = CAM_CONTENT_COUNT*ucIndex + i; ulCommand = ulCommand | CAM_POLLINIG|CAM_WRITE; /* write content 0 is equall to mark invalid */ usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */ @@ -1595,7 +1595,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if ((pRegToSet[index] & 0x0f) > FactorToSet) pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); - usb_write8(Adapter, (REG_AGGLEN_LMT+index), pRegToSet[index]); + usb_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]); } } } @@ -1706,8 +1706,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { u8 maxMacid = *val; - DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid+1); - usb_write8(Adapter, REG_TX_RPT_CTRL+1, maxMacid+1); + DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1); + usb_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1); } break; case HW_VAR_H2C_MEDIA_STATUS_RPT: @@ -1715,7 +1715,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_BCN_VALID: /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */ - usb_write8(Adapter, REG_TDECTRL+2, usb_read8(Adapter, REG_TDECTRL+2) | BIT(0)); + usb_write8(Adapter, REG_TDECTRL + 2, usb_read8(Adapter, REG_TDECTRL + 2) | BIT(0)); break; default: break; @@ -1733,7 +1733,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_BCN_VALID: /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */ - val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL+2)) ? true : false; + val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL + 2)) ? true : false; break; case HW_VAR_FWLPS_RF_ON: { -- cgit v1.2.3-59-g8ed1b From 6d7ff7361137cced8aaf7de568ad2fb8c00ec532 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:44 +0200 Subject: staging: rtl8188eu: add spaces around '&' in usb_halinit.c Add spaces around '&' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-2-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index c2e1b000cf89..fe68af7eaf85 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -633,7 +633,7 @@ enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt) DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8); rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on; } else { /* rf on/off */ - usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG)&~(BIT(3))); + usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3))); val8 = usb_read8(adapt, REG_GPIO_IO_SEL); DBG_88E("GPIO_IN=%02x\n", val8); rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off; @@ -880,7 +880,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ val8 = usb_read8(Adapter, REG_TX_RPT_CTRL); - usb_write8(Adapter, REG_TX_RPT_CTRL, val8&(~BIT(1))); + usb_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1))); /* stop rx */ usb_write8(Adapter, REG_CR, 0x0); @@ -905,7 +905,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* YJ,add,111212 */ /* Disable 32k */ val8 = usb_read8(Adapter, REG_32K_CTRL); - usb_write8(Adapter, REG_32K_CTRL, val8&(~BIT(0))); + usb_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0))); /* Card disable power action flow */ rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK, @@ -913,7 +913,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) /* Reset MCU IO Wrapper */ val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); - usb_write8(Adapter, REG_RSV_CTRL + 1, (val8&(~BIT(3)))); + usb_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3)))); val8 = usb_read8(Adapter, REG_RSV_CTRL + 1); usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3)); @@ -1135,7 +1135,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4)); /* set net_type */ - val8 = usb_read8(Adapter, MSR)&0x0c; + val8 = usb_read8(Adapter, MSR) & 0x0c; val8 |= mode; usb_write8(Adapter, MSR, val8); @@ -1214,7 +1214,7 @@ static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val) if (*((u8 *)val)) usb_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT)); else - usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg)&(~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); + usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT))); } void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) @@ -1228,7 +1228,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) { u8 val8; - val8 = usb_read8(Adapter, MSR)&0x0c; + val8 = usb_read8(Adapter, MSR) & 0x0c; val8 |= *((u8 *)val); usb_write8(Adapter, MSR, val8); } @@ -1275,7 +1275,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* Set RRSR rate table. */ usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff); usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff); - usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2)&0xf0); + usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2) & 0xf0); /* Set RTS initial rate */ while (BrateCfg > 0x1) { @@ -1300,11 +1300,11 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ - if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); /* disable related TSF function */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(3))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); usb_write32(Adapter, REG_TSFTR + 4, tsf>>32); @@ -1312,7 +1312,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); - if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) + if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) ResumeTxBeacon(Adapter); } break; @@ -1357,16 +1357,16 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; if ((is_client_associated_to_ap(Adapter)) || - ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)) { + ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) { /* enable to rx data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); - } else if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); + } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); } usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); @@ -1394,7 +1394,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) } else if (type == 2) { /* sta add event call back */ /* enable update TSF */ - usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL)&(~BIT(4))); + usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) RetryLimit = 0x7; @@ -1683,7 +1683,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* RX DMA stop */ usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN)); do { - if (!(usb_read32(Adapter, REG_RXPKT_NUM)&RXDMA_IDLE)) + if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) break; } while (trycnt--); if (trycnt == 0) @@ -1764,7 +1764,7 @@ void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val) *val = Adapter->HalData->bMacPwrCtrlOn; break; case HW_VAR_CHK_HI_QUEUE_EMPTY: - *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION)&0x0000ff00) == 0) ? true : false; + *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION) & 0x0000ff00) == 0) ? true : false; break; default: break; @@ -1925,7 +1925,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) mask &= rate_bitmap; - init_rate = get_highest_rate_idx(mask)&0x3f; + init_rate = get_highest_rate_idx(mask) & 0x3f; ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate); -- cgit v1.2.3-59-g8ed1b From fe6c0d20bb911b9c31ee5d724428551b3aa2f7a9 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:45 +0200 Subject: staging: rtl8188eu: add spaces around '|' in usb_halinit.c Add spaces around '|' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-3-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index fe68af7eaf85..9fa34c5c11c4 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -925,7 +925,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); - usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8|0x0F);/* Reg0x43 */ + usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ Adapter->HalData->bMacPwrCtrlOn = false; Adapter->bFWReady = false; @@ -1176,7 +1176,7 @@ static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val) /* enable BCN0 Function for if1 */ /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */ - usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP|EN_BCN_FUNCTION | BIT(1))); + usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1))); /* dis BCN1 ATIM WND if if2 is station */ usb_write8(Adapter, REG_BCN_CTRL_1, usb_read8(Adapter, REG_BCN_CTRL_1) | BIT(0)); @@ -1318,7 +1318,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) break; case HW_VAR_CHECK_BSSID: if (*((u8 *)val)) { - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); } else { u32 val32; @@ -1369,7 +1369,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); } - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN); } break; case HW_VAR_MLME_JOIN: @@ -1382,7 +1382,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable to rx data frame.Accept all data frame */ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF); - usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR)|RCR_CBSSID_DATA|RCR_CBSSID_BCN); + usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48; @@ -1396,7 +1396,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) /* enable update TSF */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4))); - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) + if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) RetryLimit = 0x7; } usb_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT); @@ -1485,7 +1485,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) ulContent = 0; /* polling bit, and No Write enable, and address */ ulCommand = CAM_CONTENT_COUNT*ucIndex + i; - ulCommand = ulCommand | CAM_POLLINIG|CAM_WRITE; + ulCommand = ulCommand | CAM_POLLINIG | + CAM_WRITE; /* write content 0 is equall to mark invalid */ usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */ usb_write32(Adapter, RWCAM, ulCommand); /* delay_ms(40); */ @@ -1681,7 +1682,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) if (!pwrpriv->bkeepfwalive) { /* RX DMA stop */ - usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM)|RW_RELEASE_EN)); + usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN)); do { if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) break; -- cgit v1.2.3-59-g8ed1b From 8f4686cb7db0839c9d42e3b8e813bf55a9161d29 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:46 +0200 Subject: staging: rtl8188eu: add spaces around '<<' and '>>' in usb_halinit.c Add spaces around '<<' and '>>' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-4-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 9fa34c5c11c4..40162f111195 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -923,7 +923,7 @@ static void CardDisableRTL8188EU(struct adapter *Adapter) usb_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */ val8 = usb_read8(Adapter, REG_GPIO_IO_SEL); - usb_write8(Adapter, REG_GPIO_IO_SEL, (val8<<4)); + usb_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4)); val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1); usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */ @@ -1307,7 +1307,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3))); usb_write32(Adapter, REG_TSFTR, tsf); - usb_write32(Adapter, REG_TSFTR + 4, tsf>>32); + usb_write32(Adapter, REG_TSFTR + 4, tsf >> 32); /* enable related TSF function */ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3)); @@ -1442,7 +1442,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) u8 regTmp; u8 bShortPreamble = *((bool *)val); /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */ - regTmp = (haldata->nCur40MhzPrimeSC)<<5; + regTmp = (haldata->nCur40MhzPrimeSC) << 5; if (bShortPreamble) regTmp |= 0x80; @@ -1480,7 +1480,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) for (i = 0; i < CAM_CONTENT_COUNT; i++) { /* filled id in CAM config 2 byte */ if (i == 0) - ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2); + ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2); else ulContent = 0; /* polling bit, and No Write enable, and address */ @@ -1590,8 +1590,8 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) FactorToSet = 0xf; for (index = 0; index < 4; index++) { - if ((pRegToSet[index] & 0xf0) > (FactorToSet<<4)) - pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet<<4); + if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4)) + pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4); if ((pRegToSet[index] & 0x0f) > FactorToSet) pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet); -- cgit v1.2.3-59-g8ed1b From 1f5bfba56f90afe8e158b655ecdd6eac78205dae Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:47 +0200 Subject: staging: rtl8188eu: add spaces around '-' and '*' in usb_halinit.c Add spaces around '-' and '*' to improve readability and follow kernel coding style. Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-5-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 40162f111195..0f54fde2f47b 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -190,7 +190,7 @@ static void _InitPageBoundary(struct adapter *Adapter) { /* RX Page Boundary */ /* */ - u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E-1; + u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E - 1; usb_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy); } @@ -1298,7 +1298,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024)) - 1024; /* us */ + tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */ if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) StopTxBeacon(Adapter); @@ -1484,7 +1484,7 @@ void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val) else ulContent = 0; /* polling bit, and No Write enable, and address */ - ulCommand = CAM_CONTENT_COUNT*ucIndex + i; + ulCommand = CAM_CONTENT_COUNT * ucIndex + i; ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE; /* write content 0 is equall to mark invalid */ -- cgit v1.2.3-59-g8ed1b From 2c0e81ec21db971eb9eb6adf987f9f15aec75968 Mon Sep 17 00:00:00 2001 From: Michael Straube Date: Fri, 26 Jul 2019 20:04:48 +0200 Subject: staging: rtl8188eu: cleanup comparsion to NULL in usb_halinit.c Use if(!x) instead of if(x == NULL). Reported by checkpatch. Signed-off-by: Michael Straube Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190726180448.2290-6-straube.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/usb_halinit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c index 0f54fde2f47b..16a57b31a439 100644 --- a/drivers/staging/rtl8188eu/hal/usb_halinit.c +++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c @@ -1889,7 +1889,7 @@ void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level) if (mac_id >= NUM_STA) /* CAM_SIZE */ return; psta = pmlmeinfo->FW_sta_info[mac_id].psta; - if (psta == NULL) + if (!psta) return; switch (mac_id) { case 0:/* for infra mode */ -- cgit v1.2.3-59-g8ed1b From e2724c77ca219ef4e7ba2a5399e2d02f560d0c69 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:48 +0300 Subject: staging: fsl-dpaa2/ethsw: remove unused structure The dpsw_cfg structure is only used when creating a new dpsw DPAA2 object. In the DPAA2 architecture, objects are created at boot time by the firmware or dynamically from userspace while drivers on the fsl-mc bus only configure those objects. Remove the structure since it's of no use. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-2-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 25635259ce44..0d9330e01915 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -75,37 +75,6 @@ enum dpsw_component_type { DPSW_COMPONENT_TYPE_S_VLAN }; -/** - * struct dpsw_cfg - DPSW configuration - * @num_ifs: Number of external and internal interfaces - * @adv: Advanced parameters; default is all zeros; - * use this structure to change default settings - * @adv.options: Enable/Disable DPSW features (bitmap) - * @adv.max_vlans: Maximum Number of VLAN's; 0 - indicates default 16 - * @adv.max_meters_per_if: Number of meters per interface - * @adv.max_fdbs: Maximum Number of FDB's; 0 - indicates default 16 - * @adv.max_fdb_entries: Number of FDB entries for default FDB table; - * 0 - indicates default 1024 entries. - * @adv.fdb_aging_time: Default FDB aging time for default FDB table; - * 0 - indicates default 300 seconds - * @adv.max_fdb_mc_groups: Number of multicast groups in each FDB table; - * 0 - indicates default 32 - * @adv.component_type: Indicates the component type of this bridge - */ -struct dpsw_cfg { - u16 num_ifs; - struct { - u64 options; - u16 max_vlans; - u8 max_meters_per_if; - u8 max_fdbs; - u16 max_fdb_entries; - u16 fdb_aging_time; - u16 max_fdb_mc_groups; - enum dpsw_component_type component_type; - } adv; -}; - int dpsw_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -- cgit v1.2.3-59-g8ed1b From b380a4e6e5e1f25eb40ec2a2f40196d0c00e6832 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:49 +0300 Subject: staging: fsl-dpaa2/ethsw: notify switchdev of offloaded entry Notify switchdev in case the FDB entry was successfully offloaded. This will help users to make the distinction between entries known to the HW switch and those that are held only on the software bridge. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-3-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 341c36b3a76d..d6953ac427b1 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1039,6 +1039,7 @@ static void ethsw_switchdev_event_work(struct work_struct *work) container_of(work, struct ethsw_switchdev_event_work, work); struct net_device *dev = switchdev_work->dev; struct switchdev_notifier_fdb_info *fdb_info; + int err; rtnl_lock(); fdb_info = &switchdev_work->fdb_info; @@ -1046,9 +1047,16 @@ static void ethsw_switchdev_event_work(struct work_struct *work) switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: if (is_unicast_ether_addr(fdb_info->addr)) - ethsw_port_fdb_add_uc(netdev_priv(dev), fdb_info->addr); + err = ethsw_port_fdb_add_uc(netdev_priv(dev), + fdb_info->addr); else - ethsw_port_fdb_add_mc(netdev_priv(dev), fdb_info->addr); + err = ethsw_port_fdb_add_mc(netdev_priv(dev), + fdb_info->addr); + if (err) + break; + fdb_info->offloaded = true; + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, + &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: if (is_unicast_ether_addr(fdb_info->addr)) -- cgit v1.2.3-59-g8ed1b From de01ac2e49d5b403c3edca17e7fb257060e5192c Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:50 +0300 Subject: staging: fsl-dpaa2/ethsw: add .ndo_fdb_dump callback Implement the .ndo_fdb_dump callback for the switch net devices. The list of all offloaded FDB entries is retrieved through the dpsw_fdb_dump() firmware call. Filter the entries by the switch port on which the callback was called and for each of them create a new neighbour message. Also remove the requirement from the TODO list. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-4-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/TODO | 1 - drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 15 +++- drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 51 +++++++++++ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 25 ++++++ drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 135 ++++++++++++++++++++++++++++- 5 files changed, 224 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/TODO b/drivers/staging/fsl-dpaa2/ethsw/TODO index 24b5e95a96f8..4d46857b0b2b 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/TODO +++ b/drivers/staging/fsl-dpaa2/ethsw/TODO @@ -1,7 +1,6 @@ * Add I/O capabilities on switch port netdevices. This will allow control traffic to reach the CPU. * Add ACL to redirect control traffic to CPU. -* Add support for displaying learned FDB entries * Add support for multiple FDBs and switch port partitioning * MC firmware uprev; the DPAA2 objects used by the Ethernet Switch driver need to be kept in sync with binary interface changes in MC diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h index 14b974defa3a..5e1339daa7c7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h @@ -10,7 +10,7 @@ /* DPSW Version */ #define DPSW_VER_MAJOR 8 -#define DPSW_VER_MINOR 0 +#define DPSW_VER_MINOR 1 #define DPSW_CMD_BASE_VERSION 1 #define DPSW_CMD_ID_OFFSET 4 @@ -67,6 +67,7 @@ #define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086) #define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087) #define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088) +#define DPSW_CMDID_FDB_DUMP DPSW_CMD_ID(0x08A) /* Macros for accessing command fields smaller than 1byte */ #define DPSW_MASK(field) \ @@ -351,6 +352,18 @@ struct dpsw_cmd_fdb_set_learning_mode { u8 mode; }; +struct dpsw_cmd_fdb_dump { + __le16 fdb_id; + __le16 pad0; + __le32 pad1; + __le64 iova_addr; + __le32 iova_size; +}; + +struct dpsw_rsp_fdb_dump { + __le16 num_entries; +}; + struct dpsw_rsp_get_api_version { __le16 version_major; __le16 version_minor; diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c index cabed77b445d..56b0fa789a67 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c @@ -980,6 +980,57 @@ int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpsw_fdb_dump() - Dump the content of FDB table into memory. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPSW object + * @fdb_id: Forwarding Database Identifier + * @iova_addr: Data will be stored here as an array of struct fdb_dump_entry + * @iova_size: Memory size allocated at iova_addr + * @num_entries:Number of entries written at iova_addr + * + * Return: Completion status. '0' on Success; Error code otherwise. + * + * The memory allocated at iova_addr must be initialized with zero before + * command execution. If the FDB table does not fit into memory MC will stop + * after the memory is filled up. + * The struct fdb_dump_entry array must be parsed until the end of memory + * area or until an entry with mac_addr set to zero is found. + */ +int dpsw_fdb_dump(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id, + u64 iova_addr, + u32 iova_size, + u16 *num_entries) +{ + struct dpsw_cmd_fdb_dump *cmd_params; + struct dpsw_rsp_fdb_dump *rsp_params; + struct fsl_mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_DUMP, + cmd_flags, + token); + cmd_params = (struct dpsw_cmd_fdb_dump *)cmd.params; + cmd_params->fdb_id = cpu_to_le16(fdb_id); + cmd_params->iova_addr = cpu_to_le64(iova_addr); + cmd_params->iova_size = cpu_to_le32(iova_size); + + /* send command to mc */ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + rsp_params = (struct dpsw_rsp_fdb_dump *)cmd.params; + *num_entries = le16_to_cpu(rsp_params->num_entries); + + return 0; +} + /** * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h index 0d9330e01915..25b45850925c 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h @@ -465,6 +465,31 @@ int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, u16 fdb_id, const struct dpsw_fdb_unicast_cfg *cfg); +#define DPSW_FDB_ENTRY_TYPE_DYNAMIC BIT(0) +#define DPSW_FDB_ENTRY_TYPE_UNICAST BIT(1) + +/** + * struct fdb_dump_entry - fdb snapshot entry + * @mac_addr: MAC address + * @type: bit0 - DINAMIC(1)/STATIC(0), bit1 - UNICAST(1)/MULTICAST(0) + * @if_info: unicast - egress interface, multicast - number of egress interfaces + * @if_mask: multicast - egress interface mask + */ +struct fdb_dump_entry { + u8 mac_addr[6]; + u8 type; + u8 if_info; + u8 if_mask[8]; +}; + +int dpsw_fdb_dump(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u16 fdb_id, + u64 iova_addr, + u32 iova_size, + u16 *num_entries); + /** * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration * @type: Select static or dynamic entry diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index d6953ac427b1..e6423f1e190d 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -22,7 +22,7 @@ static struct workqueue_struct *ethsw_owq; /* Minimal supported DPSW version */ #define DPSW_MIN_VER_MAJOR 8 -#define DPSW_MIN_VER_MINOR 0 +#define DPSW_MIN_VER_MINOR 1 #define DEFAULT_VLAN_ID 1 @@ -529,6 +529,138 @@ static int port_get_phys_name(struct net_device *netdev, char *name, return 0; } +struct ethsw_dump_ctx { + struct net_device *dev; + struct sk_buff *skb; + struct netlink_callback *cb; + int idx; +}; + +static int ethsw_fdb_do_dump(struct fdb_dump_entry *entry, + struct ethsw_dump_ctx *dump) +{ + int is_dynamic = entry->type & DPSW_FDB_ENTRY_DINAMIC; + u32 portid = NETLINK_CB(dump->cb->skb).portid; + u32 seq = dump->cb->nlh->nlmsg_seq; + struct nlmsghdr *nlh; + struct ndmsg *ndm; + + if (dump->idx < dump->cb->args[2]) + goto skip; + + nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH, + sizeof(*ndm), NLM_F_MULTI); + if (!nlh) + return -EMSGSIZE; + + ndm = nlmsg_data(nlh); + ndm->ndm_family = AF_BRIDGE; + ndm->ndm_pad1 = 0; + ndm->ndm_pad2 = 0; + ndm->ndm_flags = NTF_SELF; + ndm->ndm_type = 0; + ndm->ndm_ifindex = dump->dev->ifindex; + ndm->ndm_state = is_dynamic ? NUD_REACHABLE : NUD_NOARP; + + if (nla_put(dump->skb, NDA_LLADDR, ETH_ALEN, entry->mac_addr)) + goto nla_put_failure; + + nlmsg_end(dump->skb, nlh); + +skip: + dump->idx++; + return 0; + +nla_put_failure: + nlmsg_cancel(dump->skb, nlh); + return -EMSGSIZE; +} + +static int port_fdb_valid_entry(struct fdb_dump_entry *entry, + struct ethsw_port_priv *port_priv) +{ + int idx = port_priv->idx; + int valid; + + if (entry->type & DPSW_FDB_ENTRY_TYPE_UNICAST) + valid = entry->if_info == port_priv->idx; + else + valid = entry->if_mask[idx / 8] & BIT(idx % 8); + + return valid; +} + +static int port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, + struct net_device *net_dev, + struct net_device *filter_dev, int *idx) +{ + struct ethsw_port_priv *port_priv = netdev_priv(net_dev); + struct ethsw_core *ethsw = port_priv->ethsw_data; + struct device *dev = net_dev->dev.parent; + struct fdb_dump_entry *fdb_entries; + struct fdb_dump_entry fdb_entry; + struct ethsw_dump_ctx dump = { + .dev = net_dev, + .skb = skb, + .cb = cb, + .idx = *idx, + }; + dma_addr_t fdb_dump_iova; + u16 num_fdb_entries; + u32 fdb_dump_size; + int err = 0, i; + u8 *dma_mem; + + fdb_dump_size = ethsw->sw_attr.max_fdb_entries * sizeof(fdb_entry); + dma_mem = kzalloc(fdb_dump_size, GFP_KERNEL); + if (!dma_mem) + return -ENOMEM; + + memset(dma_mem, 0, fdb_dump_size); + + fdb_dump_iova = dma_map_single(dev, dma_mem, fdb_dump_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, fdb_dump_iova)) { + netdev_err(net_dev, "dma_map_single() failed\n"); + err = -ENOMEM; + goto err_map; + } + + err = dpsw_fdb_dump(ethsw->mc_io, 0, ethsw->dpsw_handle, 0, + fdb_dump_iova, fdb_dump_size, &num_fdb_entries); + if (err) { + netdev_err(net_dev, "dpsw_fdb_dump() = %d\n", err); + goto err_dump; + } + + dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_FROM_DEVICE); + + fdb_entries = (struct fdb_dump_entry *)dma_mem; + for (i = 0; i < num_fdb_entries; i++) { + fdb_entry = fdb_entries[i]; + + if (!port_fdb_valid_entry(&fdb_entry, port_priv)) + continue; + + err = ethsw_fdb_do_dump(&fdb_entry, &dump); + if (err) + goto end; + } + +end: + *idx = dump.idx; + + kfree(dma_mem); + + return 0; + +err_dump: + dma_unmap_single(dev, fdb_dump_iova, fdb_dump_size, DMA_TO_DEVICE); +err_map: + kfree(dma_mem); + return err; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -538,6 +670,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, + .ndo_fdb_dump = port_fdb_dump, .ndo_start_xmit = port_dropframe, .ndo_get_port_parent_id = swdev_get_port_parent_id, -- cgit v1.2.3-59-g8ed1b From e1e6a04d97cf747ccbec3ae23008c9faf8557aee Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:51 +0300 Subject: staging: fsl-dpaa2/ethsw: check added_by_user flag We do not want to offload FDB entries if not added by user as static entries. Check the added_by_user flag and break if not set. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-5-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index e6423f1e190d..2d3179c6bad8 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1179,6 +1179,8 @@ static void ethsw_switchdev_event_work(struct work_struct *work) switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: + if (!fdb_info->added_by_user) + break; if (is_unicast_ether_addr(fdb_info->addr)) err = ethsw_port_fdb_add_uc(netdev_priv(dev), fdb_info->addr); @@ -1192,6 +1194,8 @@ static void ethsw_switchdev_event_work(struct work_struct *work) &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: + if (!fdb_info->added_by_user) + break; if (is_unicast_ether_addr(fdb_info->addr)) ethsw_port_fdb_del_uc(netdev_priv(dev), fdb_info->addr); else -- cgit v1.2.3-59-g8ed1b From 939878fe06461dec3edfb31f7dd130dcea1d21e4 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 29 Jul 2019 19:11:52 +0300 Subject: staging: fsl-dpaa2/ethsw: add .ndo_fdb[add|del] callbacks Add the .ndo_fdb_[add|del] callbacks so that FDB entries not associated with a master device still end up offloaded. Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1564416712-16946-6-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 2d3179c6bad8..4b94a01513a7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -316,6 +316,31 @@ static int ethsw_port_fdb_del_mc(struct ethsw_port_priv *port_priv, return err; } +static int port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, const unsigned char *addr, + u16 vid, u16 flags, + struct netlink_ext_ack *extack) +{ + if (is_unicast_ether_addr(addr)) + return ethsw_port_fdb_add_uc(netdev_priv(dev), + addr); + else + return ethsw_port_fdb_add_mc(netdev_priv(dev), + addr); +} + +static int port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, + const unsigned char *addr, u16 vid) +{ + if (is_unicast_ether_addr(addr)) + return ethsw_port_fdb_del_uc(netdev_priv(dev), + addr); + else + return ethsw_port_fdb_del_mc(netdev_priv(dev), + addr); +} + static void port_get_stats(struct net_device *netdev, struct rtnl_link_stats64 *stats) { @@ -670,6 +695,8 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_change_mtu = port_change_mtu, .ndo_has_offload_stats = port_has_offload_stats, .ndo_get_offload_stats = port_get_offload_stats, + .ndo_fdb_add = port_fdb_add, + .ndo_fdb_del = port_fdb_del, .ndo_fdb_dump = port_fdb_dump, .ndo_start_xmit = port_dropframe, -- cgit v1.2.3-59-g8ed1b From 04d15d5cadb8f764ccf978ddd33cf233dcc68e13 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Tue, 30 Jul 2019 11:15:42 -0700 Subject: staging: Remove dev_err() usage after platform_get_irq() We don't need dev_err() messages when platform_get_irq() fails now that platform_get_irq() prints an error message itself when something goes wrong. Let's remove these prints with a simple semantic patch. // @@ expression ret; struct platform_device *E; @@ ret = ( platform_get_irq(E, ...) | platform_get_irq_byname(E, ...) ); if ( \( ret < 0 \| ret <= 0 \) ) { ( -if (ret != -EPROBE_DEFER) -{ ... -dev_err(...); -... } | ... -dev_err(...); ) ... } // While we're here, remove braces on if statements that only have one statement (manually). Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20190730181557.90391-43-swboyd@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 4 +--- drivers/staging/goldfish/goldfish_audio.c | 4 +--- drivers/staging/media/allegro-dvt/allegro-core.c | 4 +--- drivers/staging/media/hantro/hantro_drv.c | 4 +--- drivers/staging/media/imx/imx7-media-csi.c | 4 +--- drivers/staging/media/imx/imx7-mipi-csis.c | 4 +--- drivers/staging/media/meson/vdec/esparser.c | 4 +--- drivers/staging/media/omap4iss/iss.c | 1 - drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 5 +---- drivers/staging/most/dim2/dim2.c | 2 -- drivers/staging/mt7621-dma/mtk-hsdma.c | 4 +--- drivers/staging/nvec/nvec.c | 4 +--- drivers/staging/ralink-gdma/ralink-gdma.c | 4 +--- drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 +--- 14 files changed, 12 insertions(+), 40 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 4f3c2c13a225..489cde4e915e 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3094,10 +3094,8 @@ static int nbu2ss_drv_probe(struct platform_device *pdev) return PTR_ERR(mmio_base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get IRQ\n"); + if (irq < 0) return irq; - } status = devm_request_irq(&pdev->dev, irq, _nbu2ss_udc_irq, 0, driver_name, udc); diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index 24a738238f9f..0c65a0121dde 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -302,10 +302,8 @@ static int goldfish_audio_probe(struct platform_device *pdev) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) { - dev_err(&pdev->dev, "platform_get_irq failed\n"); + if (data->irq < 0) return -ENODEV; - } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index f050c7347fd5..6f0cd0784786 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -2947,10 +2947,8 @@ static int allegro_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (irq < 0) return irq; - } ret = devm_request_threaded_irq(&pdev->dev, irq, allegro_hardirq, allegro_irq_thread, diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index c3665f0e87a2..4a7afad2af92 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -733,10 +733,8 @@ static int hantro_probe(struct platform_device *pdev) continue; irq = platform_get_irq_byname(vpu->pdev, irq_name); - if (irq <= 0) { - dev_err(vpu->dev, "Could not get %s IRQ.\n", irq_name); + if (irq <= 0) return -ENXIO; - } ret = devm_request_irq(vpu->dev, irq, vpu->variant->irqs[i].handler, 0, diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 500b4c08d967..d7d38dd9f168 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1194,10 +1194,8 @@ static int imx7_csi_probe(struct platform_device *pdev) } csi->irq = platform_get_irq(pdev, 0); - if (csi->irq < 0) { - dev_err(dev, "Missing platform resources data\n"); + if (csi->irq < 0) return csi->irq; - } csi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(csi->regbase)) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index d1cdf011c8f1..73d8354e618c 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -975,10 +975,8 @@ static int mipi_csis_probe(struct platform_device *pdev) return PTR_ERR(state->regs); state->irq = platform_get_irq(pdev, 0); - if (state->irq < 0) { - dev_err(dev, "Failed to get irq\n"); + if (state->irq < 0) return state->irq; - } ret = mipi_csis_clk_get(state); if (ret < 0) diff --git a/drivers/staging/media/meson/vdec/esparser.c b/drivers/staging/media/meson/vdec/esparser.c index 3a21a8cec799..95102a4bdc62 100644 --- a/drivers/staging/media/meson/vdec/esparser.c +++ b/drivers/staging/media/meson/vdec/esparser.c @@ -301,10 +301,8 @@ int esparser_init(struct platform_device *pdev, struct amvdec_core *core) int irq; irq = platform_get_irq_byname(pdev, "esparser"); - if (irq < 0) { - dev_err(dev, "Failed getting ESPARSER IRQ from dtb\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(dev, irq, esparser_isr, IRQF_SHARED, "esparserirq", core); diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index c8be1db532ab..1a966cb2f3a6 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1276,7 +1276,6 @@ static int iss_probe(struct platform_device *pdev) /* Interrupt */ ret = platform_get_irq(pdev, 0); if (ret <= 0) { - dev_err(iss->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iss; } diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index c34aec7c6e40..9ce3a65903c5 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c @@ -160,11 +160,8 @@ int cedrus_hw_probe(struct cedrus_dev *dev) dev->capabilities = variant->capabilities; irq_dec = platform_get_irq(dev->pdev, 0); - if (irq_dec <= 0) { - dev_err(dev->dev, "Failed to get IRQ\n"); - + if (irq_dec <= 0) return irq_dec; - } ret = devm_request_irq(dev->dev, irq_dec, cedrus_irq, 0, dev_name(dev->dev), dev); if (ret) { diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index 043a3e14fdfc..64c979155a49 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -778,7 +778,6 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, AHB0_INT_IDX); if (irq < 0) { - dev_err(&pdev->dev, "failed to get ahb0_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } @@ -792,7 +791,6 @@ static int dim2_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, MLB_INT_IDX); if (irq < 0) { - dev_err(&pdev->dev, "failed to get mlb_int irq: %d\n", irq); ret = irq; goto err_shutdown_dim; } diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/mtk-hsdma.c index 60db06768c8a..d964642d95a3 100644 --- a/drivers/staging/mt7621-dma/mtk-hsdma.c +++ b/drivers/staging/mt7621-dma/mtk-hsdma.c @@ -675,10 +675,8 @@ static int mtk_hsdma_probe(struct platform_device *pdev) tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, 0, dev_name(&pdev->dev), hsdma); if (ret) { diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 08027a36e0bc..1cbd7b71fc38 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -796,10 +796,8 @@ static int tegra_nvec_probe(struct platform_device *pdev) return PTR_ERR(base); nvec->irq = platform_get_irq(pdev, 0); - if (nvec->irq < 0) { - dev_err(dev, "no irq resource?\n"); + if (nvec->irq < 0) return -ENODEV; - } i2c_clk = devm_clk_get(dev, "div-clk"); if (IS_ERR(i2c_clk)) { diff --git a/drivers/staging/ralink-gdma/ralink-gdma.c b/drivers/staging/ralink-gdma/ralink-gdma.c index 5854551d0a52..900424db9b97 100644 --- a/drivers/staging/ralink-gdma/ralink-gdma.c +++ b/drivers/staging/ralink-gdma/ralink-gdma.c @@ -826,10 +826,8 @@ static int gdma_dma_probe(struct platform_device *pdev) tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); + if (irq < 0) return -EINVAL; - } ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, 0, dev_name(&pdev->dev), dma_dev); if (ret) { diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 61c69f353cdb..8dc730cfe7a6 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -141,10 +141,8 @@ int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) return PTR_ERR(g_regs); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(dev, "failed to get IRQ\n"); + if (irq <= 0) return irq; - } err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, "VCHIQ doorbell", state); -- cgit v1.2.3-59-g8ed1b From 9a675a13c3bbb6ff46414b4ffaca5fa6bb54b62a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 07:28:04 +0200 Subject: Revert "staging: kpc2000: Convert put_page() to put_user_page*()" This reverts commit 8e7cb7352ec85e9e4fbbd7bfe6c5c5a6806f70e3. Bharath writes: Could you drop this patch from the staging-next tree? This is because John is making some changes to the put_user_page*() functions. He has submitted a patch recently removing put_user_page_dirty() function which is being used in this patch. This might break the kernel build if John's patch gets merged in. I ll submit a patch once the put_user_page*() apis are fixed. Reported-by: Bharath Vedartham Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc_dma/fileops.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index f15e29209d55..48ca88bc6b0b 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -190,7 +190,9 @@ static int kpc_dma_transfer(struct dev_private_data *priv, sg_free_table(&acd->sgt); err_dma_map_sg: err_alloc_sg_table: - put_user_pages(acd->user_pages, acd->page_count); + for (i = 0 ; i < acd->page_count ; i++) { + put_page(acd->user_pages[i]); + } err_get_user_pages: kfree(acd->user_pages); err_alloc_userpages: @@ -209,13 +211,16 @@ void transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags) BUG_ON(acd->ldev == NULL); BUG_ON(acd->ldev->pldev == NULL); + for (i = 0 ; i < acd->page_count ; i++) { + if (!PageReserved(acd->user_pages[i])) { + set_page_dirty(acd->user_pages[i]); + } + } + dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir); - for (i = 0; i < acd->page_count; i++) { - if (!PageReserved(acd->user_pages[i])) - put_user_pages_dirty(&acd->user_pages[i], 1); - else - put_user_page(acd->user_pages[i]); + for (i = 0 ; i < acd->page_count ; i++) { + put_page(acd->user_pages[i]); } sg_free_table(&acd->sgt); -- cgit v1.2.3-59-g8ed1b From f7d120d9e0b9cbdb20d45ff7998d5fe4820d1cdd Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Wed, 31 Jul 2019 18:35:17 +0800 Subject: staging: rtl8723bs: indicate disconnection when disconnecting The Realtek RTL8723BS only connects successfully at the very first time, then it always fails attempting to switch to another AP. No authentication/association observed from the air capture for each attempt due to the cfg80211 believes the device is still connected. Fix this by forcing to indicate the disconnection events during disconnection so the cfg80211_connect can connect to a different AP without problem. Signed-off-by: Chris Chiu Link: https://lore.kernel.org/r/20190731103517.66903-1-chiu@endlessm.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 9bc685632651..57876463b9b2 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -2024,8 +2024,6 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev)); - padapter->mlmepriv.not_indic_disco = true; - old_type = rtw_wdev->iftype; rtw_set_to_roam(padapter, 0); @@ -2047,8 +2045,6 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) } leave_ibss: - padapter->mlmepriv.not_indic_disco = false; - return 0; } @@ -2246,8 +2242,6 @@ static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev)); - padapter->mlmepriv.not_indic_disco = true; - rtw_set_to_roam(padapter, 0); rtw_scan_abort(padapter); @@ -2261,8 +2255,6 @@ static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev, rtw_free_assoc_resources(padapter, 1); rtw_pwr_wakeup(padapter); - padapter->mlmepriv.not_indic_disco = false; - DBG_871X(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev)); return 0; } -- cgit v1.2.3-59-g8ed1b From 9ba2986ff5799551e023d39fa3e8ebc6d0b148c3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Jul 2019 10:47:36 +0100 Subject: staging: rtl8188eu: remove redundant assignment to variable rtstatus Variable rtstatus is being initialized with a value that is never read and rtstatus is being re-assigned a little later on. The assignment is redundant and hence can be removed. Also, make rtstatus a bool to match the function return type. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190731094736.28637-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/bb_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c index 11e0bb9c67d7..51882858fcf0 100644 --- a/drivers/staging/rtl8188eu/hal/bb_cfg.c +++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c @@ -653,7 +653,7 @@ static bool config_parafile(struct adapter *adapt) bool rtl88eu_phy_bb_config(struct adapter *adapt) { - int rtstatus = true; + bool rtstatus; u32 regval; u8 crystal_cap; -- cgit v1.2.3-59-g8ed1b From 572d8be0d4dd2251396dca38d176354180be7683 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 1 Aug 2019 09:53:07 +0800 Subject: staging: rtl8723bs: remove set but not used variable 'bEEPROMCheck' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs//hal/odm_CfoTracking.c: In function 'odm_SetCrystalCap': drivers/staging/rtl8723bs//hal/odm_CfoTracking.c:14:7: warning: variable 'bEEPROMCheck' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190801015307.44572-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm_CfoTracking.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c index a73304639226..95edd148ac24 100644 --- a/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c +++ b/drivers/staging/rtl8723bs/hal/odm_CfoTracking.c @@ -11,11 +11,6 @@ static void odm_SetCrystalCap(void *pDM_VOID, u8 CrystalCap) { PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID; PCFO_TRACKING pCfoTrack = &pDM_Odm->DM_CfoTrack; - bool bEEPROMCheck; - struct adapter *Adapter = pDM_Odm->Adapter; - struct hal_com_data *pHalData = GET_HAL_DATA(Adapter); - - bEEPROMCheck = pHalData->EEPROMVersion >= 0x01; if (pCfoTrack->CrystalCap == CrystalCap) return; -- cgit v1.2.3-59-g8ed1b From 09acf29c8246a20c6e255969df7e1131317181da Mon Sep 17 00:00:00 2001 From: Navid Emamdoost Date: Wed, 31 Jul 2019 09:19:21 -0500 Subject: staging: rtl8192u: null check the kzalloc In rtl8192_init_priv_variable allocation for priv->pFirmware may fail, so a null check is necessary.priv->pFirmware is accessed later in rtl8192_adapter_start. I added the check and made appropriate changes to propagate the errno to the caller. Signed-off-by: Navid Emamdoost Link: https://lore.kernel.org/r/20190731141925.29268-1-navid.emamdoost@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index fe1f279ca368..569d02240bf5 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2096,7 +2096,7 @@ static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) } /* init priv variables here. only non_zero value should be initialized here. */ -static void rtl8192_init_priv_variable(struct net_device *dev) +static int rtl8192_init_priv_variable(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u8 i; @@ -2223,6 +2223,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev) priv->AcmControl = 0; priv->pFirmware = kzalloc(sizeof(rt_firmware), GFP_KERNEL); + if (!priv->pFirmware) + return -ENOMEM; /* rx related queue */ skb_queue_head_init(&priv->rx_queue); @@ -2236,6 +2238,8 @@ static void rtl8192_init_priv_variable(struct net_device *dev) for (i = 0; i < MAX_QUEUE_SIZE; i++) skb_queue_head_init(&priv->ieee80211->skb_drv_aggQ[i]); priv->rf_set_chan = rtl8192_phy_SwChnl; + + return 0; } /* init lock here */ @@ -2605,7 +2609,10 @@ static short rtl8192_init(struct net_device *dev) memcpy(priv->txqueue_to_outpipemap, queuetopipe, 9); } #endif - rtl8192_init_priv_variable(dev); + err = rtl8192_init_priv_variable(dev); + if (err) + return err; + rtl8192_init_priv_lock(priv); rtl8192_init_priv_task(dev); rtl8192_get_eeprom_size(dev); -- cgit v1.2.3-59-g8ed1b From d698b0a09656818beafd8ea7295d7c20bc74f9bc Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 31 Jul 2019 21:59:53 +0800 Subject: staging: rtl8723bs: remove set but not used variables 'prspbuf' and 'auth' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/core/rtw_cmd.c: In function rtw_cmd_thread: drivers/staging/rtl8723bs/core/rtw_cmd.c:405:16: warning: variable prspbuf set but not used [-Wunused-but-set-variable] drivers/staging/rtl8723bs/core/rtw_cmd.c: In function rtw_joinbss_cmd: drivers/staging/rtl8723bs/core/rtw_cmd.c:771:6: warning: variable auth set but not used [-Wunused-but-set-variable] They are never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190731135953.16784-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_cmd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index addc55706a3c..c6565b0e502c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c @@ -402,7 +402,7 @@ int rtw_cmd_thread(void *context) { u8 ret; struct cmd_obj *pcmd; - u8 *pcmdbuf, *prspbuf; + u8 *pcmdbuf; unsigned long cmd_start_time; unsigned long cmd_process_time; u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf); @@ -414,7 +414,6 @@ int rtw_cmd_thread(void *context) thread_enter("RTW_CMD_THREAD"); pcmdbuf = pcmdpriv->cmd_buf; - prspbuf = pcmdpriv->rsp_buf; pcmdpriv->stop_req = 0; atomic_set(&(pcmdpriv->cmdthd_running), true); @@ -768,7 +767,7 @@ exit: u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) { - u8 *auth, res = _SUCCESS; + u8 res = _SUCCESS; uint t_len = 0; struct wlan_bssid_ex *psecnetwork; struct cmd_obj *pcmd; @@ -825,7 +824,6 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork) memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network)); - auth = &psecuritypriv->authenticator_ie[0]; psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->IELength; if ((psecnetwork->IELength-12) < (256-1)) { -- cgit v1.2.3-59-g8ed1b From b0d08afda84dde941226f67cb12dd9cbde40ede4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 31 Jul 2019 22:09:03 +0800 Subject: staging: rtl8723bs: remove set but not used variable 'FirstConnect' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8723bs/hal/odm.c: In function 'odm_RSSIMonitorCheckCE': drivers/staging/rtl8723bs/hal/odm.c:1258:7: warning: variable 'FirstConnect' set but not used [-Wunused-but-set-variable] Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190731140903.304-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/odm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index dd9a16fb83a4..aa6631ee4ea7 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -1255,13 +1255,11 @@ void odm_RSSIMonitorCheckCE(PDM_ODM_T pDM_Odm) int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff; u8 sta_cnt = 0; u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */ - bool FirstConnect = false; pRA_T pRA_Table = &pDM_Odm->DM_RA_Table; if (pDM_Odm->bLinked != true) return; - FirstConnect = (pDM_Odm->bLinked) && (pRA_Table->firstconnect == false); pRA_Table->firstconnect = pDM_Odm->bLinked; /* if (check_fwstate(&Adapter->mlmepriv, WIFI_AP_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true) */ -- cgit v1.2.3-59-g8ed1b From 29b24f6ca112d168ae17c66343464a2581c573e0 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:31 +0800 Subject: staging: erofs: update source file headers - Use the correct style for all SPDX License Identifiers; - Get rid of the unnecessary license boilerplate; - Use "GPL-2.0-only" instead of "GPL-2.0" suggested-by Stephen. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-2-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Kconfig | 2 +- drivers/staging/erofs/Makefile | 2 +- drivers/staging/erofs/compress.h | 2 +- drivers/staging/erofs/data.c | 6 +----- drivers/staging/erofs/decompressor.c | 2 +- drivers/staging/erofs/dir.c | 6 +----- drivers/staging/erofs/erofs_fs.h | 8 ++------ drivers/staging/erofs/include/linux/tagptr.h | 6 +++--- drivers/staging/erofs/include/trace/events/erofs.h | 2 +- drivers/staging/erofs/inode.c | 6 +----- drivers/staging/erofs/internal.h | 8 ++------ drivers/staging/erofs/namei.c | 6 +----- drivers/staging/erofs/super.c | 6 +----- drivers/staging/erofs/unzip_pagevec.h | 8 ++------ drivers/staging/erofs/unzip_vle.c | 6 +----- drivers/staging/erofs/unzip_vle.h | 8 ++------ drivers/staging/erofs/utils.c | 7 +------ drivers/staging/erofs/xattr.c | 6 +----- drivers/staging/erofs/xattr.h | 8 ++------ drivers/staging/erofs/zmap.c | 2 +- 20 files changed, 27 insertions(+), 80 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index d04b798a8efb..2577cbb46a5b 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only config EROFS_FS tristate "EROFS filesystem support" diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile index e704d9e51514..3ade87e78d06 100644 --- a/drivers/staging/erofs/Makefile +++ b/drivers/staging/erofs/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: GPL-2.0-only EROFS_VERSION = "1.0pre1" diff --git a/drivers/staging/erofs/compress.h b/drivers/staging/erofs/compress.h index c43aa3374d28..043013f9ef1b 100644 --- a/drivers/staging/erofs/compress.h +++ b/drivers/staging/erofs/compress.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * linux/drivers/staging/erofs/compress.h * diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index f73e4720cd3e..75b859e48084 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/data.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" #include diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index 1fb0abb98dff..b75524d0b322 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/decompressor.c * diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index dbf6a151886c..2fbfc4935077 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/dir.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h index 9f61abb7c1ca..9cd749d56920 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/drivers/staging/erofs/erofs_fs.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ +/* * linux/drivers/staging/erofs/erofs_fs.h * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is dual-licensed; you may select either the GNU General Public - * License version 2 or Apache License, Version 2.0. See the file COPYING - * in the main directory of the Linux distribution for more details. */ #ifndef __EROFS_FS_H #define __EROFS_FS_H diff --git a/drivers/staging/erofs/include/linux/tagptr.h b/drivers/staging/erofs/include/linux/tagptr.h index ccd106dbd48e..b3f13773fb99 100644 --- a/drivers/staging/erofs/include/linux/tagptr.h +++ b/drivers/staging/erofs/include/linux/tagptr.h @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Tagged pointer implementation +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * A tagged pointer implementation * * Copyright (C) 2018 Gao Xiang */ diff --git a/drivers/staging/erofs/include/trace/events/erofs.h b/drivers/staging/erofs/include/trace/events/erofs.h index 660c92fc1803..bfb2da9c4eee 100644 --- a/drivers/staging/erofs/include/trace/events/erofs.h +++ b/drivers/staging/erofs/include/trace/events/erofs.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0-only */ #undef TRACE_SYSTEM #define TRACE_SYSTEM erofs diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 4c3d8bf8d249..c13d66ccc74a 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/inode.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "xattr.h" diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 0ebc294120c2..501429ec0f91 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/internal.h * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __INTERNAL_H #define __INTERNAL_H diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index fd3ae78d0ba5..50816b4c05fc 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/namei.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "internal.h" #include "xattr.h" diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 3e2a65ba1945..38cd7a59750a 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/super.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include #include diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/unzip_pagevec.h index e65dbca93ae8..f07302c3c3f5 100644 --- a/drivers/staging/erofs/unzip_pagevec.h +++ b/drivers/staging/erofs/unzip_pagevec.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/unzip_pagevec.h * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_UNZIP_PAGEVEC_H #define __EROFS_UNZIP_PAGEVEC_H diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c index 56c009cf611e..28a98e79c1e9 100644 --- a/drivers/staging/erofs/unzip_vle.c +++ b/drivers/staging/erofs/unzip_vle.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/unzip_vle.c * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include "unzip_vle.h" #include "compress.h" diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h index df91ad149439..d92515cd1c06 100644 --- a/drivers/staging/erofs/unzip_vle.h +++ b/drivers/staging/erofs/unzip_vle.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/unzip_vle.h * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_FS_UNZIP_VLE_H #define __EROFS_FS_UNZIP_VLE_H diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 4bbd3bf34acd..a68dbe375fa0 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -1,16 +1,11 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/utils.c * * Copyright (C) 2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ - #include "internal.h" #include diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index df40654b9fbb..b29177a17347 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -1,14 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/xattr.c * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #include #include "xattr.h" diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 3990805dfc6c..fbcd57bdf886 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -1,14 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0 - * +/* SPDX-License-Identifier: GPL-2.0-only */ +/* * linux/drivers/staging/erofs/xattr.h * * Copyright (C) 2017-2018 HUAWEI, Inc. * http://www.huawei.com/ * Created by Gao Xiang - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of the Linux - * distribution for more details. */ #ifndef __EROFS_XATTR_H #define __EROFS_XATTR_H diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 9c0bd65c46bf..205e884ca4e0 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/staging/erofs/zmap.c * -- cgit v1.2.3-59-g8ed1b From 57b78c9fd9ce4df7281d36b0e642bee9b06a4071 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:32 +0800 Subject: staging: erofs: rename source files for better understanding Keep in line with erofs-outofstaging patchset as well, see https://lore.kernel.org/linux-fsdevel/20190725095658.155779-1-gaoxiang25@huawei.com/ Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-3-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Makefile | 2 +- drivers/staging/erofs/include/linux/tagptr.h | 110 -- drivers/staging/erofs/tagptr.h | 110 ++ drivers/staging/erofs/unzip_pagevec.h | 166 --- drivers/staging/erofs/unzip_vle.c | 1587 -------------------------- drivers/staging/erofs/unzip_vle.h | 192 ---- drivers/staging/erofs/zdata.c | 1587 ++++++++++++++++++++++++++ drivers/staging/erofs/zdata.h | 192 ++++ drivers/staging/erofs/zpvec.h | 166 +++ 9 files changed, 2056 insertions(+), 2056 deletions(-) delete mode 100644 drivers/staging/erofs/include/linux/tagptr.h create mode 100644 drivers/staging/erofs/tagptr.h delete mode 100644 drivers/staging/erofs/unzip_pagevec.h delete mode 100644 drivers/staging/erofs/unzip_vle.c delete mode 100644 drivers/staging/erofs/unzip_vle.h create mode 100644 drivers/staging/erofs/zdata.c create mode 100644 drivers/staging/erofs/zdata.h create mode 100644 drivers/staging/erofs/zpvec.h (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile index 3ade87e78d06..5cdae21cb5af 100644 --- a/drivers/staging/erofs/Makefile +++ b/drivers/staging/erofs/Makefile @@ -9,5 +9,5 @@ obj-$(CONFIG_EROFS_FS) += erofs.o ccflags-y += -I $(srctree)/$(src)/include erofs-objs := super.o inode.o data.o namei.o dir.o utils.o erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o -erofs-$(CONFIG_EROFS_FS_ZIP) += unzip_vle.o zmap.o decompressor.o +erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o diff --git a/drivers/staging/erofs/include/linux/tagptr.h b/drivers/staging/erofs/include/linux/tagptr.h deleted file mode 100644 index b3f13773fb99..000000000000 --- a/drivers/staging/erofs/include/linux/tagptr.h +++ /dev/null @@ -1,110 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * A tagged pointer implementation - * - * Copyright (C) 2018 Gao Xiang - */ -#ifndef _LINUX_TAGPTR_H -#define _LINUX_TAGPTR_H - -#include -#include - -/* - * the name of tagged pointer types are tagptr{1, 2, 3...}_t - * avoid directly using the internal structs __tagptr{1, 2, 3...} - */ -#define __MAKE_TAGPTR(n) \ -typedef struct __tagptr##n { \ - uintptr_t v; \ -} tagptr##n##_t; - -__MAKE_TAGPTR(1) -__MAKE_TAGPTR(2) -__MAKE_TAGPTR(3) -__MAKE_TAGPTR(4) - -#undef __MAKE_TAGPTR - -extern void __compiletime_error("bad tagptr tags") - __bad_tagptr_tags(void); - -extern void __compiletime_error("bad tagptr type") - __bad_tagptr_type(void); - -/* fix the broken usage of "#define tagptr2_t tagptr3_t" by users */ -#define __tagptr_mask_1(ptr, n) \ - __builtin_types_compatible_p(typeof(ptr), struct __tagptr##n) ? \ - (1UL << (n)) - 1 : - -#define __tagptr_mask(ptr) (\ - __tagptr_mask_1(ptr, 1) ( \ - __tagptr_mask_1(ptr, 2) ( \ - __tagptr_mask_1(ptr, 3) ( \ - __tagptr_mask_1(ptr, 4) ( \ - __bad_tagptr_type(), 0))))) - -/* generate a tagged pointer from a raw value */ -#define tagptr_init(type, val) \ - ((typeof(type)){ .v = (uintptr_t)(val) }) - -/* - * directly cast a tagged pointer to the native pointer type, which - * could be used for backward compatibility of existing code. - */ -#define tagptr_cast_ptr(tptr) ((void *)(tptr).v) - -/* encode tagged pointers */ -#define tagptr_fold(type, ptr, _tags) ({ \ - const typeof(_tags) tags = (_tags); \ - if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(type))) \ - __bad_tagptr_tags(); \ -tagptr_init(type, (uintptr_t)(ptr) | tags); }) - -/* decode tagged pointers */ -#define tagptr_unfold_ptr(tptr) \ - ((void *)((tptr).v & ~__tagptr_mask(tptr))) - -#define tagptr_unfold_tags(tptr) \ - ((tptr).v & __tagptr_mask(tptr)) - -/* operations for the tagger pointer */ -#define tagptr_eq(_tptr1, _tptr2) ({ \ - typeof(_tptr1) tptr1 = (_tptr1); \ - typeof(_tptr2) tptr2 = (_tptr2); \ - (void)(&tptr1 == &tptr2); \ -(tptr1).v == (tptr2).v; }) - -/* lock-free CAS operation */ -#define tagptr_cmpxchg(_ptptr, _o, _n) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - typeof(_o) o = (_o); \ - typeof(_n) n = (_n); \ - (void)(&o == &n); \ - (void)(&o == ptptr); \ -tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) - -/* wrap WRITE_ONCE if atomic update is needed */ -#define tagptr_replace_tags(_ptptr, tags) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - *ptptr = tagptr_fold(*ptptr, tagptr_unfold_ptr(*ptptr), tags); \ -*ptptr; }) - -#define tagptr_set_tags(_ptptr, _tags) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - const typeof(_tags) tags = (_tags); \ - if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ - __bad_tagptr_tags(); \ - ptptr->v |= tags; \ -*ptptr; }) - -#define tagptr_clear_tags(_ptptr, _tags) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - const typeof(_tags) tags = (_tags); \ - if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ - __bad_tagptr_tags(); \ - ptptr->v &= ~tags; \ -*ptptr; }) - -#endif - diff --git a/drivers/staging/erofs/tagptr.h b/drivers/staging/erofs/tagptr.h new file mode 100644 index 000000000000..a72897c86744 --- /dev/null +++ b/drivers/staging/erofs/tagptr.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * A tagged pointer implementation + * + * Copyright (C) 2018 Gao Xiang + */ +#ifndef __EROFS_FS_TAGPTR_H +#define __EROFS_FS_TAGPTR_H + +#include +#include + +/* + * the name of tagged pointer types are tagptr{1, 2, 3...}_t + * avoid directly using the internal structs __tagptr{1, 2, 3...} + */ +#define __MAKE_TAGPTR(n) \ +typedef struct __tagptr##n { \ + uintptr_t v; \ +} tagptr##n##_t; + +__MAKE_TAGPTR(1) +__MAKE_TAGPTR(2) +__MAKE_TAGPTR(3) +__MAKE_TAGPTR(4) + +#undef __MAKE_TAGPTR + +extern void __compiletime_error("bad tagptr tags") + __bad_tagptr_tags(void); + +extern void __compiletime_error("bad tagptr type") + __bad_tagptr_type(void); + +/* fix the broken usage of "#define tagptr2_t tagptr3_t" by users */ +#define __tagptr_mask_1(ptr, n) \ + __builtin_types_compatible_p(typeof(ptr), struct __tagptr##n) ? \ + (1UL << (n)) - 1 : + +#define __tagptr_mask(ptr) (\ + __tagptr_mask_1(ptr, 1) ( \ + __tagptr_mask_1(ptr, 2) ( \ + __tagptr_mask_1(ptr, 3) ( \ + __tagptr_mask_1(ptr, 4) ( \ + __bad_tagptr_type(), 0))))) + +/* generate a tagged pointer from a raw value */ +#define tagptr_init(type, val) \ + ((typeof(type)){ .v = (uintptr_t)(val) }) + +/* + * directly cast a tagged pointer to the native pointer type, which + * could be used for backward compatibility of existing code. + */ +#define tagptr_cast_ptr(tptr) ((void *)(tptr).v) + +/* encode tagged pointers */ +#define tagptr_fold(type, ptr, _tags) ({ \ + const typeof(_tags) tags = (_tags); \ + if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(type))) \ + __bad_tagptr_tags(); \ +tagptr_init(type, (uintptr_t)(ptr) | tags); }) + +/* decode tagged pointers */ +#define tagptr_unfold_ptr(tptr) \ + ((void *)((tptr).v & ~__tagptr_mask(tptr))) + +#define tagptr_unfold_tags(tptr) \ + ((tptr).v & __tagptr_mask(tptr)) + +/* operations for the tagger pointer */ +#define tagptr_eq(_tptr1, _tptr2) ({ \ + typeof(_tptr1) tptr1 = (_tptr1); \ + typeof(_tptr2) tptr2 = (_tptr2); \ + (void)(&tptr1 == &tptr2); \ +(tptr1).v == (tptr2).v; }) + +/* lock-free CAS operation */ +#define tagptr_cmpxchg(_ptptr, _o, _n) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + typeof(_o) o = (_o); \ + typeof(_n) n = (_n); \ + (void)(&o == &n); \ + (void)(&o == ptptr); \ +tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) + +/* wrap WRITE_ONCE if atomic update is needed */ +#define tagptr_replace_tags(_ptptr, tags) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + *ptptr = tagptr_fold(*ptptr, tagptr_unfold_ptr(*ptptr), tags); \ +*ptptr; }) + +#define tagptr_set_tags(_ptptr, _tags) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + const typeof(_tags) tags = (_tags); \ + if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ + __bad_tagptr_tags(); \ + ptptr->v |= tags; \ +*ptptr; }) + +#define tagptr_clear_tags(_ptptr, _tags) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + const typeof(_tags) tags = (_tags); \ + if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ + __bad_tagptr_tags(); \ + ptptr->v &= ~tags; \ +*ptptr; }) + +#endif /* __EROFS_FS_TAGPTR_H */ + diff --git a/drivers/staging/erofs/unzip_pagevec.h b/drivers/staging/erofs/unzip_pagevec.h deleted file mode 100644 index f07302c3c3f5..000000000000 --- a/drivers/staging/erofs/unzip_pagevec.h +++ /dev/null @@ -1,166 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/unzip_pagevec.h - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_UNZIP_PAGEVEC_H -#define __EROFS_UNZIP_PAGEVEC_H - -#include - -/* page type in pagevec for unzip subsystem */ -enum z_erofs_page_type { - /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ - Z_EROFS_PAGE_TYPE_EXCLUSIVE, - - Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED, - - Z_EROFS_VLE_PAGE_TYPE_HEAD, - Z_EROFS_VLE_PAGE_TYPE_MAX -}; - -extern void __compiletime_error("Z_EROFS_PAGE_TYPE_EXCLUSIVE != 0") - __bad_page_type_exclusive(void); - -/* pagevec tagged pointer */ -typedef tagptr2_t erofs_vtptr_t; - -/* pagevec collector */ -struct z_erofs_pagevec_ctor { - struct page *curr, *next; - erofs_vtptr_t *pages; - - unsigned int nr, index; -}; - -static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, - bool atomic) -{ - if (!ctor->curr) - return; - - if (atomic) - kunmap_atomic(ctor->pages); - else - kunmap(ctor->curr); -} - -static inline struct page * -z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, - unsigned int nr) -{ - unsigned int index; - - /* keep away from occupied pages */ - if (ctor->next) - return ctor->next; - - for (index = 0; index < nr; ++index) { - const erofs_vtptr_t t = ctor->pages[index]; - const unsigned int tags = tagptr_unfold_tags(t); - - if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) - return tagptr_unfold_ptr(t); - } - DBG_BUGON(nr >= ctor->nr); - return NULL; -} - -static inline void -z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, - bool atomic) -{ - struct page *next = z_erofs_pagevec_ctor_next_page(ctor, ctor->nr); - - z_erofs_pagevec_ctor_exit(ctor, atomic); - - ctor->curr = next; - ctor->next = NULL; - ctor->pages = atomic ? - kmap_atomic(ctor->curr) : kmap(ctor->curr); - - ctor->nr = PAGE_SIZE / sizeof(struct page *); - ctor->index = 0; -} - -static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, - unsigned int nr, - erofs_vtptr_t *pages, - unsigned int i) -{ - ctor->nr = nr; - ctor->curr = ctor->next = NULL; - ctor->pages = pages; - - if (i >= nr) { - i -= nr; - z_erofs_pagevec_ctor_pagedown(ctor, false); - while (i > ctor->nr) { - i -= ctor->nr; - z_erofs_pagevec_ctor_pagedown(ctor, false); - } - } - - ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); - ctor->index = i; -} - -static inline bool -z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, - struct page *page, - enum z_erofs_page_type type, - bool *occupied) -{ - *occupied = false; - if (unlikely(!ctor->next && type)) - if (ctor->index + 1 == ctor->nr) - return false; - - if (unlikely(ctor->index >= ctor->nr)) - z_erofs_pagevec_ctor_pagedown(ctor, false); - - /* exclusive page type must be 0 */ - if (Z_EROFS_PAGE_TYPE_EXCLUSIVE != (uintptr_t)NULL) - __bad_page_type_exclusive(); - - /* should remind that collector->next never equal to 1, 2 */ - if (type == (uintptr_t)ctor->next) { - ctor->next = page; - *occupied = true; - } - - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, page, type); - return true; -} - -static inline struct page * -z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, - enum z_erofs_page_type *type) -{ - erofs_vtptr_t t; - - if (unlikely(ctor->index >= ctor->nr)) { - DBG_BUGON(!ctor->next); - z_erofs_pagevec_ctor_pagedown(ctor, true); - } - - t = ctor->pages[ctor->index]; - - *type = tagptr_unfold_tags(t); - - /* should remind that collector->next never equal to 1, 2 */ - if (*type == (uintptr_t)ctor->next) - ctor->next = tagptr_unfold_ptr(t); - - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, NULL, 0); - - return tagptr_unfold_ptr(t); -} - -#endif - diff --git a/drivers/staging/erofs/unzip_vle.c b/drivers/staging/erofs/unzip_vle.c deleted file mode 100644 index 28a98e79c1e9..000000000000 --- a/drivers/staging/erofs/unzip_vle.c +++ /dev/null @@ -1,1587 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/unzip_vle.c - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "unzip_vle.h" -#include "compress.h" -#include - -#include - -/* - * a compressed_pages[] placeholder in order to avoid - * being filled with file pages for in-place decompression. - */ -#define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) - -/* how to allocate cached pages for a workgroup */ -enum z_erofs_cache_alloctype { - DONTALLOC, /* don't allocate any cached pages */ - DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ -}; - -/* - * tagged pointer with 1-bit tag for all compressed pages - * tag 0 - the page is just found with an extra page reference - */ -typedef tagptr1_t compressed_page_t; - -#define tag_compressed_page_justfound(page) \ - tagptr_fold(compressed_page_t, page, 1) - -static struct workqueue_struct *z_erofs_workqueue __read_mostly; -static struct kmem_cache *z_erofs_workgroup_cachep __read_mostly; - -void z_erofs_exit_zip_subsystem(void) -{ - destroy_workqueue(z_erofs_workqueue); - kmem_cache_destroy(z_erofs_workgroup_cachep); -} - -static inline int init_unzip_workqueue(void) -{ - const unsigned int onlinecpus = num_possible_cpus(); - - /* - * we don't need too many threads, limiting threads - * could improve scheduling performance. - */ - z_erofs_workqueue = - alloc_workqueue("erofs_unzipd", - WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, - onlinecpus + onlinecpus / 4); - - return z_erofs_workqueue ? 0 : -ENOMEM; -} - -static void init_once(void *ptr) -{ - struct z_erofs_vle_workgroup *grp = ptr; - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); - unsigned int i; - - mutex_init(&work->lock); - work->nr_pages = 0; - work->vcnt = 0; - for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) - grp->compressed_pages[i] = NULL; -} - -static void init_always(struct z_erofs_vle_workgroup *grp) -{ - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); - - atomic_set(&grp->obj.refcount, 1); - grp->flags = 0; - - DBG_BUGON(work->nr_pages); - DBG_BUGON(work->vcnt); -} - -int __init z_erofs_init_zip_subsystem(void) -{ - z_erofs_workgroup_cachep = - kmem_cache_create("erofs_compress", - Z_EROFS_WORKGROUP_SIZE, 0, - SLAB_RECLAIM_ACCOUNT, init_once); - - if (z_erofs_workgroup_cachep) { - if (!init_unzip_workqueue()) - return 0; - - kmem_cache_destroy(z_erofs_workgroup_cachep); - } - return -ENOMEM; -} - -enum z_erofs_vle_work_role { - Z_EROFS_VLE_WORK_SECONDARY, - Z_EROFS_VLE_WORK_PRIMARY, - /* - * The current work was the tail of an exist chain, and the previous - * processed chained works are all decided to be hooked up to it. - * A new chain should be created for the remaining unprocessed works, - * therefore different from Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - * the next work cannot reuse the whole page in the following scenario: - * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (belongs to the next work) | (belongs to the current work) | - * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| - */ - Z_EROFS_VLE_WORK_PRIMARY_HOOKED, - /* - * The current work has been linked with the processed chained works, - * and could be also linked with the potential remaining works, which - * means if the processing page is the tail partial page of the work, - * the current work can safely use the whole page (since the next work - * is under control) for in-place decompression, as illustrated below: - * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (of the current work) | (of the previous work) | - * | PRIMARY_FOLLOWED or | | - * |_____PRIMARY_HOOKED____|____________PRIMARY_FOLLOWED____________| - * - * [ (*) the above page can be used for the current work itself. ] - */ - Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - Z_EROFS_VLE_WORK_MAX -}; - -struct z_erofs_vle_work_builder { - enum z_erofs_vle_work_role role; - /* - * 'hosted = false' means that the current workgroup doesn't belong to - * the owned chained workgroups. In the other words, it is none of our - * business to submit this workgroup. - */ - bool hosted; - - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; - struct z_erofs_pagevec_ctor vector; - - /* pages used for reading the compressed data */ - struct page **compressed_pages; - unsigned int compressed_deficit; -}; - -#define VLE_WORK_BUILDER_INIT() \ - { .work = NULL, .role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED } - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, - struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) -{ - struct page **const pages = bl->compressed_pages; - const unsigned int remaining = bl->compressed_deficit; - bool standalone = true; - unsigned int i, j = 0; - - if (bl->role < Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) - return; - - gfp = mapping_gfp_constraint(mc, gfp) & ~__GFP_RECLAIM; - - index += clusterpages - remaining; - - for (i = 0; i < remaining; ++i) { - struct page *page; - compressed_page_t t; - - /* the compressed page was loaded before */ - if (READ_ONCE(pages[i])) - continue; - - page = find_get_page(mc, index + i); - - if (page) { - t = tag_compressed_page_justfound(page); - } else if (type == DELAYEDALLOC) { - t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); - } else { /* DONTALLOC */ - if (standalone) - j = i; - standalone = false; - continue; - } - - if (!cmpxchg_relaxed(&pages[i], NULL, tagptr_cast_ptr(t))) - continue; - - if (page) - put_page(page); - } - bl->compressed_pages += j; - bl->compressed_deficit = remaining - j; - - if (standalone) - bl->role = Z_EROFS_VLE_WORK_PRIMARY; -} - -/* called by erofs_shrinker to get rid of all compressed_pages */ -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp) -{ - struct z_erofs_vle_workgroup *const grp = - container_of(egrp, struct z_erofs_vle_workgroup, obj); - struct address_space *const mapping = MNGD_MAPPING(sbi); - const int clusterpages = erofs_clusterpages(sbi); - int i; - - /* - * refcount of workgroup is now freezed as 1, - * therefore no need to worry about available decompression users. - */ - for (i = 0; i < clusterpages; ++i) { - struct page *page = grp->compressed_pages[i]; - - if (!page || page->mapping != mapping) - continue; - - /* block other users from reclaiming or migrating the page */ - if (!trylock_page(page)) - return -EBUSY; - - /* barrier is implied in the following 'unlock_page' */ - WRITE_ONCE(grp->compressed_pages[i], NULL); - - set_page_private(page, 0); - ClearPagePrivate(page); - - unlock_page(page); - put_page(page); - } - return 0; -} - -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page) -{ - struct erofs_sb_info *const sbi = EROFS_SB(mapping->host->i_sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - struct z_erofs_vle_workgroup *const grp = (void *)page_private(page); - int ret = 0; /* 0 - busy */ - - if (erofs_workgroup_try_to_freeze(&grp->obj, 1)) { - unsigned int i; - - for (i = 0; i < clusterpages; ++i) { - if (grp->compressed_pages[i] == page) { - WRITE_ONCE(grp->compressed_pages[i], NULL); - ret = 1; - break; - } - } - erofs_workgroup_unfreeze(&grp->obj, 1); - - if (ret) { - ClearPagePrivate(page); - put_page(page); - } - } - return ret; -} -#else -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, - struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) -{ - /* nowhere to load compressed pages from */ -} -#endif - -/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static inline bool try_to_reuse_as_compressed_page( - struct z_erofs_vle_work_builder *b, - struct page *page) -{ - while (b->compressed_deficit) { - --b->compressed_deficit; - if (!cmpxchg(b->compressed_pages++, NULL, page)) - return true; - } - - return false; -} - -/* callers must be with work->lock held */ -static int z_erofs_vle_work_add_page( - struct z_erofs_vle_work_builder *builder, - struct page *page, - enum z_erofs_page_type type) -{ - int ret; - bool occupied; - - /* give priority for the compressed data storage */ - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY && - type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && - try_to_reuse_as_compressed_page(builder, page)) - return 0; - - ret = z_erofs_pagevec_ctor_enqueue(&builder->vector, - page, type, &occupied); - builder->work->vcnt += (unsigned int)ret; - - return ret ? 0 : -EAGAIN; -} - -static enum z_erofs_vle_work_role -try_to_claim_workgroup(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t *owned_head, - bool *hosted) -{ - DBG_BUGON(*hosted); - - /* let's claim these following types of workgroup */ -retry: - if (grp->next == Z_EROFS_VLE_WORKGRP_NIL) { - /* type 1, nil workgroup */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_NIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_NIL) - goto retry; - - *owned_head = &grp->next; - *hosted = true; - /* lucky, I am the followee :) */ - return Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - - } else if (grp->next == Z_EROFS_VLE_WORKGRP_TAIL) { - /* - * type 2, link to the end of a existing open chain, - * be careful that its submission itself is governed - * by the original owned chain. - */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_TAIL) - goto retry; - *owned_head = Z_EROFS_VLE_WORKGRP_TAIL; - return Z_EROFS_VLE_WORK_PRIMARY_HOOKED; - } - - return Z_EROFS_VLE_WORK_PRIMARY; /* :( better luck next time */ -} - -struct z_erofs_vle_work_finder { - struct super_block *sb; - pgoff_t idx; - unsigned int pageofs; - - struct z_erofs_vle_workgroup **grp_ret; - enum z_erofs_vle_work_role *role; - z_erofs_vle_owned_workgrp_t *owned_head; - bool *hosted; -}; - -static struct z_erofs_vle_work * -z_erofs_vle_work_lookup(const struct z_erofs_vle_work_finder *f) -{ - bool tag, primary; - struct erofs_workgroup *egrp; - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; - - egrp = erofs_find_workgroup(f->sb, f->idx, &tag); - if (!egrp) { - *f->grp_ret = NULL; - return NULL; - } - - grp = container_of(egrp, struct z_erofs_vle_workgroup, obj); - *f->grp_ret = grp; - - work = z_erofs_vle_grab_work(grp, f->pageofs); - /* if multiref is disabled, `primary' is always true */ - primary = true; - - DBG_BUGON(work->pageofs != f->pageofs); - - /* - * lock must be taken first to avoid grp->next == NIL between - * claiming workgroup and adding pages: - * grp->next != NIL - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(&work->lock) - * add all pages to pagevec - * - * [correct locking case 1]: - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[b]) mutex_lock(grp->work[c]) - * ... *role = SECONDARY - * add all pages to pagevec - * ... - * mutex_unlock(grp->work[c]) - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * - * [correct locking case 2]: - * mutex_lock(grp->work[b]) - * ... - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(grp->work[a]) - * *role = PRIMARY_OWNER - * add all pages to pagevec - * ... - */ - mutex_lock(&work->lock); - - *f->hosted = false; - if (!primary) - *f->role = Z_EROFS_VLE_WORK_SECONDARY; - else /* claim the workgroup if possible */ - *f->role = try_to_claim_workgroup(grp, f->owned_head, - f->hosted); - return work; -} - -static struct z_erofs_vle_work * -z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f, - struct erofs_map_blocks *map) -{ - bool gnew = false; - struct z_erofs_vle_workgroup *grp = *f->grp_ret; - struct z_erofs_vle_work *work; - - /* if multiref is disabled, grp should never be nullptr */ - if (unlikely(grp)) { - DBG_BUGON(1); - return ERR_PTR(-EINVAL); - } - - /* no available workgroup, let's allocate one */ - grp = kmem_cache_alloc(z_erofs_workgroup_cachep, GFP_NOFS); - if (unlikely(!grp)) - return ERR_PTR(-ENOMEM); - - init_always(grp); - grp->obj.index = f->idx; - grp->llen = map->m_llen; - - z_erofs_vle_set_workgrp_fmt(grp, (map->m_flags & EROFS_MAP_ZIPPED) ? - Z_EROFS_VLE_WORKGRP_FMT_LZ4 : - Z_EROFS_VLE_WORKGRP_FMT_PLAIN); - - if (map->m_flags & EROFS_MAP_FULL_MAPPED) - grp->flags |= Z_EROFS_VLE_WORKGRP_FULL_LENGTH; - - /* new workgrps have been claimed as type 1 */ - WRITE_ONCE(grp->next, *f->owned_head); - /* primary and followed work for all new workgrps */ - *f->role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - /* it should be submitted by ourselves */ - *f->hosted = true; - - gnew = true; - work = z_erofs_vle_grab_primary_work(grp); - work->pageofs = f->pageofs; - - /* - * lock all primary followed works before visible to others - * and mutex_trylock *never* fails for a new workgroup. - */ - mutex_trylock(&work->lock); - - if (gnew) { - int err = erofs_register_workgroup(f->sb, &grp->obj, 0); - - if (err) { - mutex_unlock(&work->lock); - kmem_cache_free(z_erofs_workgroup_cachep, grp); - return ERR_PTR(-EAGAIN); - } - } - - *f->owned_head = &grp->next; - *f->grp_ret = grp; - return work; -} - -#define builder_is_hooked(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_HOOKED) - -#define builder_is_followed(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) - -static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, - struct super_block *sb, - struct erofs_map_blocks *map, - z_erofs_vle_owned_workgrp_t *owned_head) -{ - const unsigned int clusterpages = erofs_clusterpages(EROFS_SB(sb)); - struct z_erofs_vle_workgroup *grp; - const struct z_erofs_vle_work_finder finder = { - .sb = sb, - .idx = erofs_blknr(map->m_pa), - .pageofs = map->m_la & ~PAGE_MASK, - .grp_ret = &grp, - .role = &builder->role, - .owned_head = owned_head, - .hosted = &builder->hosted - }; - struct z_erofs_vle_work *work; - - DBG_BUGON(builder->work); - - /* must be Z_EROFS_WORK_TAIL or the next chained work */ - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_NIL); - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - DBG_BUGON(erofs_blkoff(map->m_pa)); - -repeat: - work = z_erofs_vle_work_lookup(&finder); - if (work) { - unsigned int orig_llen; - - /* increase workgroup `llen' if needed */ - while ((orig_llen = READ_ONCE(grp->llen)) < map->m_llen && - orig_llen != cmpxchg_relaxed(&grp->llen, - orig_llen, map->m_llen)) - cpu_relax(); - goto got_it; - } - - work = z_erofs_vle_work_register(&finder, map); - if (unlikely(work == ERR_PTR(-EAGAIN))) - goto repeat; - - if (IS_ERR(work)) - return PTR_ERR(work); -got_it: - z_erofs_pagevec_ctor_init(&builder->vector, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, work->vcnt); - - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { - /* enable possibly in-place decompression */ - builder->compressed_pages = grp->compressed_pages; - builder->compressed_deficit = clusterpages; - } else { - builder->compressed_pages = NULL; - builder->compressed_deficit = 0; - } - - builder->grp = grp; - builder->work = work; - return 0; -} - -/* - * keep in mind that no referenced workgroups will be freed - * only after a RCU grace period, so rcu_read_lock() could - * prevent a workgroup from being freed. - */ -static void z_erofs_rcu_callback(struct rcu_head *head) -{ - struct z_erofs_vle_work *work = container_of(head, - struct z_erofs_vle_work, rcu); - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); - - kmem_cache_free(z_erofs_workgroup_cachep, grp); -} - -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) -{ - struct z_erofs_vle_workgroup *const vgrp = container_of(grp, - struct z_erofs_vle_workgroup, obj); - struct z_erofs_vle_work *const work = &vgrp->work; - - call_rcu(&work->rcu, z_erofs_rcu_callback); -} - -static void -__z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, - struct z_erofs_vle_work *work __maybe_unused) -{ - erofs_workgroup_put(&grp->obj); -} - -static void z_erofs_vle_work_release(struct z_erofs_vle_work *work) -{ - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); - - __z_erofs_vle_work_release(grp, work); -} - -static inline bool -z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) -{ - struct z_erofs_vle_work *work = builder->work; - - if (!work) - return false; - - z_erofs_pagevec_ctor_exit(&builder->vector, false); - mutex_unlock(&work->lock); - - /* - * if all pending pages are added, don't hold work reference - * any longer if the current work isn't hosted by ourselves. - */ - if (!builder->hosted) - __z_erofs_vle_work_release(builder->grp, work); - - builder->work = NULL; - builder->grp = NULL; - return true; -} - -static inline struct page *__stagingpage_alloc(struct list_head *pagepool, - gfp_t gfp) -{ - struct page *page = erofs_allocpage(pagepool, gfp); - - if (unlikely(!page)) - return NULL; - - page->mapping = Z_EROFS_MAPPING_STAGING; - return page; -} - -struct z_erofs_vle_frontend { - struct inode *const inode; - - struct z_erofs_vle_work_builder builder; - struct erofs_map_blocks map; - - z_erofs_vle_owned_workgrp_t owned_head; - - /* used for applying cache strategy on the fly */ - bool backmost; - erofs_off_t headoffset; -}; - -#define VLE_FRONTEND_INIT(__i) { \ - .inode = __i, \ - .map = { \ - .m_llen = 0, \ - .m_plen = 0, \ - .mpage = NULL \ - }, \ - .builder = VLE_WORK_BUILDER_INIT(), \ - .owned_head = Z_EROFS_VLE_WORKGRP_TAIL, \ - .backmost = true, } - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) -{ - if (fe->backmost) - return true; - - if (EROFS_FS_ZIP_CACHE_LVL >= 2) - return la < fe->headoffset; - - return false; -} -#else -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) -{ - return false; -} -#endif - -static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, - struct page *page, - struct list_head *page_pool) -{ - struct super_block *const sb = fe->inode->i_sb; - struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); - struct erofs_map_blocks *const map = &fe->map; - struct z_erofs_vle_work_builder *const builder = &fe->builder; - const loff_t offset = page_offset(page); - - bool tight = builder_is_hooked(builder); - struct z_erofs_vle_work *work = builder->work; - - enum z_erofs_cache_alloctype cache_strategy; - enum z_erofs_page_type page_type; - unsigned int cur, end, spiltted, index; - int err = 0; - - /* register locked file pages as online pages in pack */ - z_erofs_onlinepage_init(page); - - spiltted = 0; - end = PAGE_SIZE; -repeat: - cur = end - 1; - - /* lucky, within the range of the current map_blocks */ - if (offset + cur >= map->m_la && - offset + cur < map->m_la + map->m_llen) { - /* didn't get a valid unzip work previously (very rare) */ - if (!builder->work) - goto restart_now; - goto hitted; - } - - /* go ahead the next map_blocks */ - debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); - - if (z_erofs_vle_work_iter_end(builder)) - fe->backmost = false; - - map->m_la = offset + cur; - map->m_llen = 0; - err = z_erofs_map_blocks_iter(fe->inode, map, 0); - if (unlikely(err)) - goto err_out; - -restart_now: - if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) - goto hitted; - - DBG_BUGON(map->m_plen != 1 << sbi->clusterbits); - DBG_BUGON(erofs_blkoff(map->m_pa)); - - err = z_erofs_vle_work_iter_begin(builder, sb, map, &fe->owned_head); - if (unlikely(err)) - goto err_out; - - /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, map->m_la)) - cache_strategy = DELAYEDALLOC; - else - cache_strategy = DONTALLOC; - - preload_compressed_pages(builder, MNGD_MAPPING(sbi), - map->m_pa / PAGE_SIZE, - map->m_plen / PAGE_SIZE, - cache_strategy, page_pool, GFP_KERNEL); - - tight &= builder_is_hooked(builder); - work = builder->work; -hitted: - cur = end - min_t(unsigned int, offset + end - map->m_la, end); - if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { - zero_user_segment(page, cur, end); - goto next_part; - } - - /* let's derive page type */ - page_type = cur ? Z_EROFS_VLE_PAGE_TYPE_HEAD : - (!spiltted ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : - (tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : - Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); - - if (cur) - tight &= builder_is_followed(builder); - -retry: - err = z_erofs_vle_work_add_page(builder, page, page_type); - /* should allocate an additional staging page for pagevec */ - if (err == -EAGAIN) { - struct page *const newpage = - __stagingpage_alloc(page_pool, GFP_NOFS); - - err = z_erofs_vle_work_add_page(builder, newpage, - Z_EROFS_PAGE_TYPE_EXCLUSIVE); - if (likely(!err)) - goto retry; - } - - if (unlikely(err)) - goto err_out; - - index = page->index - map->m_la / PAGE_SIZE; - - /* FIXME! avoid the last relundant fixup & endio */ - z_erofs_onlinepage_fixup(page, index, true); - - /* bump up the number of spiltted parts of a page */ - ++spiltted; - /* also update nr_pages */ - work->nr_pages = max_t(pgoff_t, work->nr_pages, index + 1); -next_part: - /* can be used for verification */ - map->m_llen = offset + cur - map->m_la; - - end = cur; - if (end > 0) - goto repeat; - -out: - /* FIXME! avoid the last relundant fixup & endio */ - z_erofs_onlinepage_endio(page); - - debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", - __func__, page, spiltted, map->m_llen); - return err; - - /* if some error occurred while processing this page */ -err_out: - SetPageError(page); - goto out; -} - -static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) -{ - tagptr1_t t = tagptr_init(tagptr1_t, ptr); - struct z_erofs_vle_unzip_io *io = tagptr_unfold_ptr(t); - bool background = tagptr_unfold_tags(t); - - if (!background) { - unsigned long flags; - - spin_lock_irqsave(&io->u.wait.lock, flags); - if (!atomic_add_return(bios, &io->pending_bios)) - wake_up_locked(&io->u.wait); - spin_unlock_irqrestore(&io->u.wait.lock, flags); - return; - } - - if (!atomic_add_return(bios, &io->pending_bios)) - queue_work(z_erofs_workqueue, &io->u.work); -} - -static inline void z_erofs_vle_read_endio(struct bio *bio) -{ - struct erofs_sb_info *sbi = NULL; - blk_status_t err = bio->bi_status; - struct bio_vec *bvec; - struct bvec_iter_all iter_all; - - bio_for_each_segment_all(bvec, bio, iter_all) { - struct page *page = bvec->bv_page; - bool cachemngd = false; - - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!page->mapping); - - if (unlikely(!sbi && !z_erofs_page_is_staging(page))) { - sbi = EROFS_SB(page->mapping->host->i_sb); - - if (time_to_inject(sbi, FAULT_READ_IO)) { - erofs_show_injection_info(FAULT_READ_IO); - err = BLK_STS_IOERR; - } - } - - /* sbi should already be gotten if the page is managed */ - if (sbi) - cachemngd = erofs_page_is_managed(sbi, page); - - if (unlikely(err)) - SetPageError(page); - else if (cachemngd) - SetPageUptodate(page); - - if (cachemngd) - unlock_page(page); - } - - z_erofs_vle_unzip_kickoff(bio->bi_private, -1); - bio_put(bio); -} - -static struct page *z_pagemap_global[Z_EROFS_VLE_VMAP_GLOBAL_PAGES]; -static DEFINE_MUTEX(z_pagemap_global_lock); - -static int z_erofs_vle_unzip(struct super_block *sb, - struct z_erofs_vle_workgroup *grp, - struct list_head *page_pool) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - - struct z_erofs_pagevec_ctor ctor; - unsigned int nr_pages; - unsigned int sparsemem_pages = 0; - struct page *pages_onstack[Z_EROFS_VLE_VMAP_ONSTACK_PAGES]; - struct page **pages, **compressed_pages, *page; - unsigned int algorithm; - unsigned int i, outputsize; - - enum z_erofs_page_type page_type; - bool overlapped, partial; - struct z_erofs_vle_work *work; - int err; - - might_sleep(); - work = z_erofs_vle_grab_primary_work(grp); - DBG_BUGON(!READ_ONCE(work->nr_pages)); - - mutex_lock(&work->lock); - nr_pages = work->nr_pages; - - if (likely(nr_pages <= Z_EROFS_VLE_VMAP_ONSTACK_PAGES)) - pages = pages_onstack; - else if (nr_pages <= Z_EROFS_VLE_VMAP_GLOBAL_PAGES && - mutex_trylock(&z_pagemap_global_lock)) - pages = z_pagemap_global; - else { - gfp_t gfp_flags = GFP_KERNEL; - - if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) - gfp_flags |= __GFP_NOFAIL; - - pages = kvmalloc_array(nr_pages, sizeof(struct page *), - gfp_flags); - - /* fallback to global pagemap for the lowmem scenario */ - if (unlikely(!pages)) { - mutex_lock(&z_pagemap_global_lock); - pages = z_pagemap_global; - } - } - - for (i = 0; i < nr_pages; ++i) - pages[i] = NULL; - - z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, 0); - - for (i = 0; i < work->vcnt; ++i) { - unsigned int pagenr; - - page = z_erofs_pagevec_ctor_dequeue(&ctor, &page_type); - - /* all pages in pagevec ought to be valid */ - DBG_BUGON(!page); - DBG_BUGON(!page->mapping); - - if (z_erofs_put_stagingpage(page_pool, page)) - continue; - - if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) - pagenr = 0; - else - pagenr = z_erofs_onlinepage_index(page); - - DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); - - pages[pagenr] = page; - } - sparsemem_pages = i; - - z_erofs_pagevec_ctor_exit(&ctor, true); - - overlapped = false; - compressed_pages = grp->compressed_pages; - - err = 0; - for (i = 0; i < clusterpages; ++i) { - unsigned int pagenr; - - page = compressed_pages[i]; - - /* all compressed pages ought to be valid */ - DBG_BUGON(!page); - DBG_BUGON(!page->mapping); - - if (!z_erofs_page_is_staging(page)) { - if (erofs_page_is_managed(sbi, page)) { - if (unlikely(!PageUptodate(page))) - err = -EIO; - continue; - } - - /* - * only if non-head page can be selected - * for inplace decompression - */ - pagenr = z_erofs_onlinepage_index(page); - - DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); - ++sparsemem_pages; - pages[pagenr] = page; - - overlapped = true; - } - - /* PG_error needs checking for inplaced and staging pages */ - if (unlikely(PageError(page))) { - DBG_BUGON(PageUptodate(page)); - err = -EIO; - } - } - - if (unlikely(err)) - goto out; - - if (nr_pages << PAGE_SHIFT >= work->pageofs + grp->llen) { - outputsize = grp->llen; - partial = !(grp->flags & Z_EROFS_VLE_WORKGRP_FULL_LENGTH); - } else { - outputsize = (nr_pages << PAGE_SHIFT) - work->pageofs; - partial = true; - } - - if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) - algorithm = Z_EROFS_COMPRESSION_SHIFTED; - else - algorithm = Z_EROFS_COMPRESSION_LZ4; - - err = z_erofs_decompress(&(struct z_erofs_decompress_req) { - .sb = sb, - .in = compressed_pages, - .out = pages, - .pageofs_out = work->pageofs, - .inputsize = PAGE_SIZE, - .outputsize = outputsize, - .alg = algorithm, - .inplace_io = overlapped, - .partial_decoding = partial - }, page_pool); - -out: - /* must handle all compressed pages before endding pages */ - for (i = 0; i < clusterpages; ++i) { - page = compressed_pages[i]; - - if (erofs_page_is_managed(sbi, page)) - continue; - - /* recycle all individual staging pages */ - (void)z_erofs_put_stagingpage(page_pool, page); - - WRITE_ONCE(compressed_pages[i], NULL); - } - - for (i = 0; i < nr_pages; ++i) { - page = pages[i]; - if (!page) - continue; - - DBG_BUGON(!page->mapping); - - /* recycle all individual staging pages */ - if (z_erofs_put_stagingpage(page_pool, page)) - continue; - - if (unlikely(err < 0)) - SetPageError(page); - - z_erofs_onlinepage_endio(page); - } - - if (pages == z_pagemap_global) - mutex_unlock(&z_pagemap_global_lock); - else if (unlikely(pages != pages_onstack)) - kvfree(pages); - - work->nr_pages = 0; - work->vcnt = 0; - - /* all work locks MUST be taken before the following line */ - - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_NIL); - - /* all work locks SHOULD be released right now */ - mutex_unlock(&work->lock); - - z_erofs_vle_work_release(work); - return err; -} - -static void z_erofs_vle_unzip_all(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - struct list_head *page_pool) -{ - z_erofs_vle_owned_workgrp_t owned = io->head; - - while (owned != Z_EROFS_VLE_WORKGRP_TAIL_CLOSED) { - struct z_erofs_vle_workgroup *grp; - - /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_TAIL); - - /* no possible that 'owned' equals NULL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_NIL); - - grp = container_of(owned, struct z_erofs_vle_workgroup, next); - owned = READ_ONCE(grp->next); - - z_erofs_vle_unzip(sb, grp, page_pool); - } -} - -static void z_erofs_vle_unzip_wq(struct work_struct *work) -{ - struct z_erofs_vle_unzip_io_sb *iosb = container_of(work, - struct z_erofs_vle_unzip_io_sb, io.u.work); - LIST_HEAD(page_pool); - - DBG_BUGON(iosb->io.head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &page_pool); - - put_pages_list(&page_pool); - kvfree(iosb); -} - -static struct page * -pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, - unsigned int nr, - struct list_head *pagepool, - struct address_space *mc, - gfp_t gfp) -{ - /* determined at compile time to avoid too many #ifdefs */ - const bool nocache = __builtin_constant_p(mc) ? !mc : false; - const pgoff_t index = grp->obj.index; - bool tocache = false; - - struct address_space *mapping; - struct page *oldpage, *page; - - compressed_page_t t; - int justfound; - -repeat: - page = READ_ONCE(grp->compressed_pages[nr]); - oldpage = page; - - if (!page) - goto out_allocpage; - - /* - * the cached page has not been allocated and - * an placeholder is out there, prepare it now. - */ - if (!nocache && page == PAGE_UNALLOCATED) { - tocache = true; - goto out_allocpage; - } - - /* process the target tagged pointer */ - t = tagptr_init(compressed_page_t, page); - justfound = tagptr_unfold_tags(t); - page = tagptr_unfold_ptr(t); - - mapping = READ_ONCE(page->mapping); - - /* - * if managed cache is disabled, it's no way to - * get such a cached-like page. - */ - if (nocache) { - /* if managed cache is disabled, it is impossible `justfound' */ - DBG_BUGON(justfound); - - /* and it should be locked, not uptodate, and not truncated */ - DBG_BUGON(!PageLocked(page)); - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!mapping); - goto out; - } - - /* - * unmanaged (file) pages are all locked solidly, - * therefore it is impossible for `mapping' to be NULL. - */ - if (mapping && mapping != mc) - /* ought to be unmanaged pages */ - goto out; - - lock_page(page); - - /* only true if page reclaim goes wrong, should never happen */ - DBG_BUGON(justfound && PagePrivate(page)); - - /* the page is still in manage cache */ - if (page->mapping == mc) { - WRITE_ONCE(grp->compressed_pages[nr], page); - - ClearPageError(page); - if (!PagePrivate(page)) { - /* - * impossible to be !PagePrivate(page) for - * the current restriction as well if - * the page is already in compressed_pages[]. - */ - DBG_BUGON(!justfound); - - justfound = 0; - set_page_private(page, (unsigned long)grp); - SetPagePrivate(page); - } - - /* no need to submit io if it is already up-to-date */ - if (PageUptodate(page)) { - unlock_page(page); - page = NULL; - } - goto out; - } - - /* - * the managed page has been truncated, it's unsafe to - * reuse this one, let's allocate a new cache-managed page. - */ - DBG_BUGON(page->mapping); - DBG_BUGON(!justfound); - - tocache = true; - unlock_page(page); - put_page(page); -out_allocpage: - page = __stagingpage_alloc(pagepool, gfp); - if (oldpage != cmpxchg(&grp->compressed_pages[nr], oldpage, page)) { - list_add(&page->lru, pagepool); - cpu_relax(); - goto repeat; - } - if (nocache || !tocache) - goto out; - if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { - page->mapping = Z_EROFS_MAPPING_STAGING; - goto out; - } - - set_page_private(page, (unsigned long)grp); - SetPagePrivate(page); -out: /* the only exit (for tracing and debugging) */ - return page; -} - -static struct z_erofs_vle_unzip_io * -jobqueue_init(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - bool foreground) -{ - struct z_erofs_vle_unzip_io_sb *iosb; - - if (foreground) { - /* waitqueue available for foreground io */ - DBG_BUGON(!io); - - init_waitqueue_head(&io->u.wait); - atomic_set(&io->pending_bios, 0); - goto out; - } - - iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); - DBG_BUGON(!iosb); - - /* initialize fields in the allocated descriptor */ - io = &iosb->io; - iosb->sb = sb; - INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); -out: - io->head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; - return io; -} - -/* define workgroup jobqueue types */ -enum { -#ifdef EROFS_FS_HAS_MANAGED_CACHE - JQ_BYPASS, -#endif - JQ_SUBMIT, - NR_JOBQUEUES, -}; - -static void *jobqueueset_init(struct super_block *sb, - z_erofs_vle_owned_workgrp_t qtail[], - struct z_erofs_vle_unzip_io *q[], - struct z_erofs_vle_unzip_io *fgq, - bool forcefg) -{ -#ifdef EROFS_FS_HAS_MANAGED_CACHE - /* - * if managed cache is enabled, bypass jobqueue is needed, - * no need to read from device for all workgroups in this queue. - */ - q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); - qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; -#endif - - q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); - qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; - - return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); -} - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) -{ - z_erofs_vle_owned_workgrp_t *const submit_qtail = qtail[JQ_SUBMIT]; - z_erofs_vle_owned_workgrp_t *const bypass_qtail = qtail[JQ_BYPASS]; - - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - if (owned_head == Z_EROFS_VLE_WORKGRP_TAIL) - owned_head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; - - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - WRITE_ONCE(*submit_qtail, owned_head); - WRITE_ONCE(*bypass_qtail, &grp->next); - - qtail[JQ_BYPASS] = &grp->next; -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* - * although background is preferred, no one is pending for submission. - * don't issue workqueue for decompression but drop it directly instead. - */ - if (force_fg || nr_bios) - return false; - - kvfree(container_of(q[JQ_SUBMIT], - struct z_erofs_vle_unzip_io_sb, - io)); - return true; -} -#else -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) -{ - /* impossible to bypass submission for managed cache disabled */ - DBG_BUGON(1); -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* bios should be >0 if managed cache is disabled */ - DBG_BUGON(!nr_bios); - return false; -} -#endif - -static bool z_erofs_vle_submit_all(struct super_block *sb, - z_erofs_vle_owned_workgrp_t owned_head, - struct list_head *pagepool, - struct z_erofs_vle_unzip_io *fgq, - bool force_fg) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - const gfp_t gfp = GFP_NOFS; - - z_erofs_vle_owned_workgrp_t qtail[NR_JOBQUEUES]; - struct z_erofs_vle_unzip_io *q[NR_JOBQUEUES]; - struct bio *bio; - void *bi_private; - /* since bio will be NULL, no need to initialize last_index */ - pgoff_t uninitialized_var(last_index); - bool force_submit = false; - unsigned int nr_bios; - - if (unlikely(owned_head == Z_EROFS_VLE_WORKGRP_TAIL)) - return false; - - force_submit = false; - bio = NULL; - nr_bios = 0; - bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); - - /* by default, all need io submission */ - q[JQ_SUBMIT]->head = owned_head; - - do { - struct z_erofs_vle_workgroup *grp; - pgoff_t first_index; - struct page *page; - unsigned int i = 0, bypass = 0; - int err; - - /* no possible 'owned_head' equals the following */ - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_NIL); - - grp = container_of(owned_head, - struct z_erofs_vle_workgroup, next); - - /* close the main owned chain at first */ - owned_head = cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - first_index = grp->obj.index; - force_submit |= (first_index != last_index + 1); - -repeat: - page = pickup_page_for_submission(grp, i, pagepool, - MNGD_MAPPING(sbi), gfp); - if (!page) { - force_submit = true; - ++bypass; - goto skippage; - } - - if (bio && force_submit) { -submit_bio_retry: - __submit_bio(bio, REQ_OP_READ, 0); - bio = NULL; - } - - if (!bio) { - bio = erofs_grab_bio(sb, first_index + i, - BIO_MAX_PAGES, bi_private, - z_erofs_vle_read_endio, true); - ++nr_bios; - } - - err = bio_add_page(bio, page, PAGE_SIZE, 0); - if (err < PAGE_SIZE) - goto submit_bio_retry; - - force_submit = false; - last_index = first_index + i; -skippage: - if (++i < clusterpages) - goto repeat; - - if (bypass < clusterpages) - qtail[JQ_SUBMIT] = &grp->next; - else - move_to_bypass_jobqueue(grp, qtail, owned_head); - } while (owned_head != Z_EROFS_VLE_WORKGRP_TAIL); - - if (bio) - __submit_bio(bio, REQ_OP_READ, 0); - - if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) - return true; - - z_erofs_vle_unzip_kickoff(bi_private, nr_bios); - return true; -} - -static void z_erofs_submit_and_unzip(struct z_erofs_vle_frontend *f, - struct list_head *pagepool, - bool force_fg) -{ - struct super_block *sb = f->inode->i_sb; - struct z_erofs_vle_unzip_io io[NR_JOBQUEUES]; - - if (!z_erofs_vle_submit_all(sb, f->owned_head, pagepool, io, force_fg)) - return; - -#ifdef EROFS_FS_HAS_MANAGED_CACHE - z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); -#endif - if (!force_fg) - return; - - /* wait until all bios are completed */ - wait_event(io[JQ_SUBMIT].u.wait, - !atomic_read(&io[JQ_SUBMIT].pending_bios)); - - /* let's synchronous decompression */ - z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); -} - -static int z_erofs_vle_normalaccess_readpage(struct file *file, - struct page *page) -{ - struct inode *const inode = page->mapping->host; - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); - int err; - LIST_HEAD(pagepool); - - trace_erofs_readpage(page, false); - - f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; - - err = z_erofs_do_read_page(&f, page, &pagepool); - (void)z_erofs_vle_work_iter_end(&f.builder); - - if (err) { - errln("%s, failed to read, err [%d]", __func__, err); - goto out; - } - - z_erofs_submit_and_unzip(&f, &pagepool, true); -out: - if (f.map.mpage) - put_page(f.map.mpage); - - /* clean up the remaining free pages */ - put_pages_list(&pagepool); - return 0; -} - -static int z_erofs_vle_normalaccess_readpages(struct file *filp, - struct address_space *mapping, - struct list_head *pages, - unsigned int nr_pages) -{ - struct inode *const inode = mapping->host; - struct erofs_sb_info *const sbi = EROFS_I_SB(inode); - - bool sync = __should_decompress_synchronously(sbi, nr_pages); - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); - gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); - struct page *head = NULL; - LIST_HEAD(pagepool); - - trace_erofs_readpages(mapping->host, lru_to_page(pages), - nr_pages, false); - - f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT; - - for (; nr_pages; --nr_pages) { - struct page *page = lru_to_page(pages); - - prefetchw(&page->flags); - list_del(&page->lru); - - /* - * A pure asynchronous readahead is indicated if - * a PG_readahead marked page is hitted at first. - * Let's also do asynchronous decompression for this case. - */ - sync &= !(PageReadahead(page) && !head); - - if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { - list_add(&page->lru, &pagepool); - continue; - } - - set_page_private(page, (unsigned long)head); - head = page; - } - - while (head) { - struct page *page = head; - int err; - - /* traversal in reverse order */ - head = (void *)page_private(page); - - err = z_erofs_do_read_page(&f, page, &pagepool); - if (err) { - struct erofs_vnode *vi = EROFS_V(inode); - - errln("%s, readahead error at page %lu of nid %llu", - __func__, page->index, vi->nid); - } - - put_page(page); - } - - (void)z_erofs_vle_work_iter_end(&f.builder); - - z_erofs_submit_and_unzip(&f, &pagepool, sync); - - if (f.map.mpage) - put_page(f.map.mpage); - - /* clean up the remaining free pages */ - put_pages_list(&pagepool); - return 0; -} - -const struct address_space_operations z_erofs_vle_normalaccess_aops = { - .readpage = z_erofs_vle_normalaccess_readpage, - .readpages = z_erofs_vle_normalaccess_readpages, -}; - diff --git a/drivers/staging/erofs/unzip_vle.h b/drivers/staging/erofs/unzip_vle.h deleted file mode 100644 index d92515cd1c06..000000000000 --- a/drivers/staging/erofs/unzip_vle.h +++ /dev/null @@ -1,192 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/unzip_vle.h - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_FS_UNZIP_VLE_H -#define __EROFS_FS_UNZIP_VLE_H - -#include "internal.h" -#include "unzip_pagevec.h" - -#define Z_EROFS_NR_INLINE_PAGEVECS 3 - -/* - * Structure fields follow one of the following exclusion rules. - * - * I: Modifiable by initialization/destruction paths and read-only - * for everyone else. - * - */ - -struct z_erofs_vle_work { - struct mutex lock; - - /* I: decompression offset in page */ - unsigned short pageofs; - unsigned short nr_pages; - - /* L: queued pages in pagevec[] */ - unsigned int vcnt; - - union { - /* L: pagevec */ - erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; - struct rcu_head rcu; - }; -}; - -#define Z_EROFS_VLE_WORKGRP_FMT_PLAIN 0 -#define Z_EROFS_VLE_WORKGRP_FMT_LZ4 1 -#define Z_EROFS_VLE_WORKGRP_FMT_MASK 1 -#define Z_EROFS_VLE_WORKGRP_FULL_LENGTH 2 - -typedef void *z_erofs_vle_owned_workgrp_t; - -struct z_erofs_vle_workgroup { - struct erofs_workgroup obj; - struct z_erofs_vle_work work; - - /* point to next owned_workgrp_t */ - z_erofs_vle_owned_workgrp_t next; - - /* compressed pages (including multi-usage pages) */ - struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; - unsigned int llen, flags; -}; - -/* let's avoid the valid 32-bit kernel addresses */ - -/* the chained workgroup has't submitted io (still open) */ -#define Z_EROFS_VLE_WORKGRP_TAIL ((void *)0x5F0ECAFE) -/* the chained workgroup has already submitted io */ -#define Z_EROFS_VLE_WORKGRP_TAIL_CLOSED ((void *)0x5F0EDEAD) - -#define Z_EROFS_VLE_WORKGRP_NIL (NULL) - -#define z_erofs_vle_workgrp_fmt(grp) \ - ((grp)->flags & Z_EROFS_VLE_WORKGRP_FMT_MASK) - -static inline void z_erofs_vle_set_workgrp_fmt( - struct z_erofs_vle_workgroup *grp, - unsigned int fmt) -{ - grp->flags = fmt | (grp->flags & ~Z_EROFS_VLE_WORKGRP_FMT_MASK); -} - - -/* definitions if multiref is disabled */ -#define z_erofs_vle_grab_primary_work(grp) (&(grp)->work) -#define z_erofs_vle_grab_work(grp, pageofs) (&(grp)->work) -#define z_erofs_vle_work_workgroup(wrk, primary) \ - ((primary) ? container_of(wrk, \ - struct z_erofs_vle_workgroup, work) : \ - ({ BUG(); (void *)NULL; })) - - -#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_vle_workgroup) - -struct z_erofs_vle_unzip_io { - atomic_t pending_bios; - z_erofs_vle_owned_workgrp_t head; - - union { - wait_queue_head_t wait; - struct work_struct work; - } u; -}; - -struct z_erofs_vle_unzip_io_sb { - struct z_erofs_vle_unzip_io io; - struct super_block *sb; -}; - -#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 -#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) -#define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) - -/* - * waiters (aka. ongoing_packs): # to unlock the page - * sub-index: 0 - for partial page, >= 1 full page sub-index - */ -typedef atomic_t z_erofs_onlinepage_t; - -/* type punning */ -union z_erofs_onlinepage_converter { - z_erofs_onlinepage_t *o; - unsigned long *v; -}; - -static inline unsigned int z_erofs_onlinepage_index(struct page *page) -{ - union z_erofs_onlinepage_converter u; - - DBG_BUGON(!PagePrivate(page)); - u.v = &page_private(page); - - return atomic_read(u.o) >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; -} - -static inline void z_erofs_onlinepage_init(struct page *page) -{ - union { - z_erofs_onlinepage_t o; - unsigned long v; - /* keep from being unlocked in advance */ - } u = { .o = ATOMIC_INIT(1) }; - - set_page_private(page, u.v); - smp_wmb(); - SetPagePrivate(page); -} - -static inline void z_erofs_onlinepage_fixup(struct page *page, - uintptr_t index, bool down) -{ - unsigned long *p, o, v, id; -repeat: - p = &page_private(page); - o = READ_ONCE(*p); - - id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; - if (id) { - if (!index) - return; - - DBG_BUGON(id != index); - } - - v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | - ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); - if (cmpxchg(p, o, v) != o) - goto repeat; -} - -static inline void z_erofs_onlinepage_endio(struct page *page) -{ - union z_erofs_onlinepage_converter u; - unsigned int v; - - DBG_BUGON(!PagePrivate(page)); - u.v = &page_private(page); - - v = atomic_dec_return(u.o); - if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) { - ClearPagePrivate(page); - if (!PageError(page)) - SetPageUptodate(page); - unlock_page(page); - } - - debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); -} - -#define Z_EROFS_VLE_VMAP_ONSTACK_PAGES \ - min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) -#define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048 - -#endif - diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c new file mode 100644 index 000000000000..f7667628bbf1 --- /dev/null +++ b/drivers/staging/erofs/zdata.c @@ -0,0 +1,1587 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * linux/drivers/staging/erofs/zdata.c + * + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "zdata.h" +#include "compress.h" +#include + +#include + +/* + * a compressed_pages[] placeholder in order to avoid + * being filled with file pages for in-place decompression. + */ +#define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) + +/* how to allocate cached pages for a workgroup */ +enum z_erofs_cache_alloctype { + DONTALLOC, /* don't allocate any cached pages */ + DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ +}; + +/* + * tagged pointer with 1-bit tag for all compressed pages + * tag 0 - the page is just found with an extra page reference + */ +typedef tagptr1_t compressed_page_t; + +#define tag_compressed_page_justfound(page) \ + tagptr_fold(compressed_page_t, page, 1) + +static struct workqueue_struct *z_erofs_workqueue __read_mostly; +static struct kmem_cache *z_erofs_workgroup_cachep __read_mostly; + +void z_erofs_exit_zip_subsystem(void) +{ + destroy_workqueue(z_erofs_workqueue); + kmem_cache_destroy(z_erofs_workgroup_cachep); +} + +static inline int init_unzip_workqueue(void) +{ + const unsigned int onlinecpus = num_possible_cpus(); + + /* + * we don't need too many threads, limiting threads + * could improve scheduling performance. + */ + z_erofs_workqueue = + alloc_workqueue("erofs_unzipd", + WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, + onlinecpus + onlinecpus / 4); + + return z_erofs_workqueue ? 0 : -ENOMEM; +} + +static void init_once(void *ptr) +{ + struct z_erofs_vle_workgroup *grp = ptr; + struct z_erofs_vle_work *const work = + z_erofs_vle_grab_primary_work(grp); + unsigned int i; + + mutex_init(&work->lock); + work->nr_pages = 0; + work->vcnt = 0; + for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) + grp->compressed_pages[i] = NULL; +} + +static void init_always(struct z_erofs_vle_workgroup *grp) +{ + struct z_erofs_vle_work *const work = + z_erofs_vle_grab_primary_work(grp); + + atomic_set(&grp->obj.refcount, 1); + grp->flags = 0; + + DBG_BUGON(work->nr_pages); + DBG_BUGON(work->vcnt); +} + +int __init z_erofs_init_zip_subsystem(void) +{ + z_erofs_workgroup_cachep = + kmem_cache_create("erofs_compress", + Z_EROFS_WORKGROUP_SIZE, 0, + SLAB_RECLAIM_ACCOUNT, init_once); + + if (z_erofs_workgroup_cachep) { + if (!init_unzip_workqueue()) + return 0; + + kmem_cache_destroy(z_erofs_workgroup_cachep); + } + return -ENOMEM; +} + +enum z_erofs_vle_work_role { + Z_EROFS_VLE_WORK_SECONDARY, + Z_EROFS_VLE_WORK_PRIMARY, + /* + * The current work was the tail of an exist chain, and the previous + * processed chained works are all decided to be hooked up to it. + * A new chain should be created for the remaining unprocessed works, + * therefore different from Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, + * the next work cannot reuse the whole page in the following scenario: + * ________________________________________________________________ + * | tail (partial) page | head (partial) page | + * | (belongs to the next work) | (belongs to the current work) | + * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| + */ + Z_EROFS_VLE_WORK_PRIMARY_HOOKED, + /* + * The current work has been linked with the processed chained works, + * and could be also linked with the potential remaining works, which + * means if the processing page is the tail partial page of the work, + * the current work can safely use the whole page (since the next work + * is under control) for in-place decompression, as illustrated below: + * ________________________________________________________________ + * | tail (partial) page | head (partial) page | + * | (of the current work) | (of the previous work) | + * | PRIMARY_FOLLOWED or | | + * |_____PRIMARY_HOOKED____|____________PRIMARY_FOLLOWED____________| + * + * [ (*) the above page can be used for the current work itself. ] + */ + Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, + Z_EROFS_VLE_WORK_MAX +}; + +struct z_erofs_vle_work_builder { + enum z_erofs_vle_work_role role; + /* + * 'hosted = false' means that the current workgroup doesn't belong to + * the owned chained workgroups. In the other words, it is none of our + * business to submit this workgroup. + */ + bool hosted; + + struct z_erofs_vle_workgroup *grp; + struct z_erofs_vle_work *work; + struct z_erofs_pagevec_ctor vector; + + /* pages used for reading the compressed data */ + struct page **compressed_pages; + unsigned int compressed_deficit; +}; + +#define VLE_WORK_BUILDER_INIT() \ + { .work = NULL, .role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED } + +#ifdef EROFS_FS_HAS_MANAGED_CACHE +static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, + struct address_space *mc, + pgoff_t index, + unsigned int clusterpages, + enum z_erofs_cache_alloctype type, + struct list_head *pagepool, + gfp_t gfp) +{ + struct page **const pages = bl->compressed_pages; + const unsigned int remaining = bl->compressed_deficit; + bool standalone = true; + unsigned int i, j = 0; + + if (bl->role < Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) + return; + + gfp = mapping_gfp_constraint(mc, gfp) & ~__GFP_RECLAIM; + + index += clusterpages - remaining; + + for (i = 0; i < remaining; ++i) { + struct page *page; + compressed_page_t t; + + /* the compressed page was loaded before */ + if (READ_ONCE(pages[i])) + continue; + + page = find_get_page(mc, index + i); + + if (page) { + t = tag_compressed_page_justfound(page); + } else if (type == DELAYEDALLOC) { + t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); + } else { /* DONTALLOC */ + if (standalone) + j = i; + standalone = false; + continue; + } + + if (!cmpxchg_relaxed(&pages[i], NULL, tagptr_cast_ptr(t))) + continue; + + if (page) + put_page(page); + } + bl->compressed_pages += j; + bl->compressed_deficit = remaining - j; + + if (standalone) + bl->role = Z_EROFS_VLE_WORK_PRIMARY; +} + +/* called by erofs_shrinker to get rid of all compressed_pages */ +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *egrp) +{ + struct z_erofs_vle_workgroup *const grp = + container_of(egrp, struct z_erofs_vle_workgroup, obj); + struct address_space *const mapping = MNGD_MAPPING(sbi); + const int clusterpages = erofs_clusterpages(sbi); + int i; + + /* + * refcount of workgroup is now freezed as 1, + * therefore no need to worry about available decompression users. + */ + for (i = 0; i < clusterpages; ++i) { + struct page *page = grp->compressed_pages[i]; + + if (!page || page->mapping != mapping) + continue; + + /* block other users from reclaiming or migrating the page */ + if (!trylock_page(page)) + return -EBUSY; + + /* barrier is implied in the following 'unlock_page' */ + WRITE_ONCE(grp->compressed_pages[i], NULL); + + set_page_private(page, 0); + ClearPagePrivate(page); + + unlock_page(page); + put_page(page); + } + return 0; +} + +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page) +{ + struct erofs_sb_info *const sbi = EROFS_SB(mapping->host->i_sb); + const unsigned int clusterpages = erofs_clusterpages(sbi); + struct z_erofs_vle_workgroup *const grp = (void *)page_private(page); + int ret = 0; /* 0 - busy */ + + if (erofs_workgroup_try_to_freeze(&grp->obj, 1)) { + unsigned int i; + + for (i = 0; i < clusterpages; ++i) { + if (grp->compressed_pages[i] == page) { + WRITE_ONCE(grp->compressed_pages[i], NULL); + ret = 1; + break; + } + } + erofs_workgroup_unfreeze(&grp->obj, 1); + + if (ret) { + ClearPagePrivate(page); + put_page(page); + } + } + return ret; +} +#else +static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, + struct address_space *mc, + pgoff_t index, + unsigned int clusterpages, + enum z_erofs_cache_alloctype type, + struct list_head *pagepool, + gfp_t gfp) +{ + /* nowhere to load compressed pages from */ +} +#endif + +/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ +static inline bool try_to_reuse_as_compressed_page( + struct z_erofs_vle_work_builder *b, + struct page *page) +{ + while (b->compressed_deficit) { + --b->compressed_deficit; + if (!cmpxchg(b->compressed_pages++, NULL, page)) + return true; + } + + return false; +} + +/* callers must be with work->lock held */ +static int z_erofs_vle_work_add_page( + struct z_erofs_vle_work_builder *builder, + struct page *page, + enum z_erofs_page_type type) +{ + int ret; + bool occupied; + + /* give priority for the compressed data storage */ + if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY && + type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && + try_to_reuse_as_compressed_page(builder, page)) + return 0; + + ret = z_erofs_pagevec_ctor_enqueue(&builder->vector, + page, type, &occupied); + builder->work->vcnt += (unsigned int)ret; + + return ret ? 0 : -EAGAIN; +} + +static enum z_erofs_vle_work_role +try_to_claim_workgroup(struct z_erofs_vle_workgroup *grp, + z_erofs_vle_owned_workgrp_t *owned_head, + bool *hosted) +{ + DBG_BUGON(*hosted); + + /* let's claim these following types of workgroup */ +retry: + if (grp->next == Z_EROFS_VLE_WORKGRP_NIL) { + /* type 1, nil workgroup */ + if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_NIL, + *owned_head) != Z_EROFS_VLE_WORKGRP_NIL) + goto retry; + + *owned_head = &grp->next; + *hosted = true; + /* lucky, I am the followee :) */ + return Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; + + } else if (grp->next == Z_EROFS_VLE_WORKGRP_TAIL) { + /* + * type 2, link to the end of a existing open chain, + * be careful that its submission itself is governed + * by the original owned chain. + */ + if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, + *owned_head) != Z_EROFS_VLE_WORKGRP_TAIL) + goto retry; + *owned_head = Z_EROFS_VLE_WORKGRP_TAIL; + return Z_EROFS_VLE_WORK_PRIMARY_HOOKED; + } + + return Z_EROFS_VLE_WORK_PRIMARY; /* :( better luck next time */ +} + +struct z_erofs_vle_work_finder { + struct super_block *sb; + pgoff_t idx; + unsigned int pageofs; + + struct z_erofs_vle_workgroup **grp_ret; + enum z_erofs_vle_work_role *role; + z_erofs_vle_owned_workgrp_t *owned_head; + bool *hosted; +}; + +static struct z_erofs_vle_work * +z_erofs_vle_work_lookup(const struct z_erofs_vle_work_finder *f) +{ + bool tag, primary; + struct erofs_workgroup *egrp; + struct z_erofs_vle_workgroup *grp; + struct z_erofs_vle_work *work; + + egrp = erofs_find_workgroup(f->sb, f->idx, &tag); + if (!egrp) { + *f->grp_ret = NULL; + return NULL; + } + + grp = container_of(egrp, struct z_erofs_vle_workgroup, obj); + *f->grp_ret = grp; + + work = z_erofs_vle_grab_work(grp, f->pageofs); + /* if multiref is disabled, `primary' is always true */ + primary = true; + + DBG_BUGON(work->pageofs != f->pageofs); + + /* + * lock must be taken first to avoid grp->next == NIL between + * claiming workgroup and adding pages: + * grp->next != NIL + * grp->next = NIL + * mutex_unlock_all + * mutex_lock(&work->lock) + * add all pages to pagevec + * + * [correct locking case 1]: + * mutex_lock(grp->work[a]) + * ... + * mutex_lock(grp->work[b]) mutex_lock(grp->work[c]) + * ... *role = SECONDARY + * add all pages to pagevec + * ... + * mutex_unlock(grp->work[c]) + * mutex_lock(grp->work[c]) + * ... + * grp->next = NIL + * mutex_unlock_all + * + * [correct locking case 2]: + * mutex_lock(grp->work[b]) + * ... + * mutex_lock(grp->work[a]) + * ... + * mutex_lock(grp->work[c]) + * ... + * grp->next = NIL + * mutex_unlock_all + * mutex_lock(grp->work[a]) + * *role = PRIMARY_OWNER + * add all pages to pagevec + * ... + */ + mutex_lock(&work->lock); + + *f->hosted = false; + if (!primary) + *f->role = Z_EROFS_VLE_WORK_SECONDARY; + else /* claim the workgroup if possible */ + *f->role = try_to_claim_workgroup(grp, f->owned_head, + f->hosted); + return work; +} + +static struct z_erofs_vle_work * +z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f, + struct erofs_map_blocks *map) +{ + bool gnew = false; + struct z_erofs_vle_workgroup *grp = *f->grp_ret; + struct z_erofs_vle_work *work; + + /* if multiref is disabled, grp should never be nullptr */ + if (unlikely(grp)) { + DBG_BUGON(1); + return ERR_PTR(-EINVAL); + } + + /* no available workgroup, let's allocate one */ + grp = kmem_cache_alloc(z_erofs_workgroup_cachep, GFP_NOFS); + if (unlikely(!grp)) + return ERR_PTR(-ENOMEM); + + init_always(grp); + grp->obj.index = f->idx; + grp->llen = map->m_llen; + + z_erofs_vle_set_workgrp_fmt(grp, (map->m_flags & EROFS_MAP_ZIPPED) ? + Z_EROFS_VLE_WORKGRP_FMT_LZ4 : + Z_EROFS_VLE_WORKGRP_FMT_PLAIN); + + if (map->m_flags & EROFS_MAP_FULL_MAPPED) + grp->flags |= Z_EROFS_VLE_WORKGRP_FULL_LENGTH; + + /* new workgrps have been claimed as type 1 */ + WRITE_ONCE(grp->next, *f->owned_head); + /* primary and followed work for all new workgrps */ + *f->role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; + /* it should be submitted by ourselves */ + *f->hosted = true; + + gnew = true; + work = z_erofs_vle_grab_primary_work(grp); + work->pageofs = f->pageofs; + + /* + * lock all primary followed works before visible to others + * and mutex_trylock *never* fails for a new workgroup. + */ + mutex_trylock(&work->lock); + + if (gnew) { + int err = erofs_register_workgroup(f->sb, &grp->obj, 0); + + if (err) { + mutex_unlock(&work->lock); + kmem_cache_free(z_erofs_workgroup_cachep, grp); + return ERR_PTR(-EAGAIN); + } + } + + *f->owned_head = &grp->next; + *f->grp_ret = grp; + return work; +} + +#define builder_is_hooked(builder) \ + ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_HOOKED) + +#define builder_is_followed(builder) \ + ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) + +static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, + struct super_block *sb, + struct erofs_map_blocks *map, + z_erofs_vle_owned_workgrp_t *owned_head) +{ + const unsigned int clusterpages = erofs_clusterpages(EROFS_SB(sb)); + struct z_erofs_vle_workgroup *grp; + const struct z_erofs_vle_work_finder finder = { + .sb = sb, + .idx = erofs_blknr(map->m_pa), + .pageofs = map->m_la & ~PAGE_MASK, + .grp_ret = &grp, + .role = &builder->role, + .owned_head = owned_head, + .hosted = &builder->hosted + }; + struct z_erofs_vle_work *work; + + DBG_BUGON(builder->work); + + /* must be Z_EROFS_WORK_TAIL or the next chained work */ + DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_NIL); + DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + + DBG_BUGON(erofs_blkoff(map->m_pa)); + +repeat: + work = z_erofs_vle_work_lookup(&finder); + if (work) { + unsigned int orig_llen; + + /* increase workgroup `llen' if needed */ + while ((orig_llen = READ_ONCE(grp->llen)) < map->m_llen && + orig_llen != cmpxchg_relaxed(&grp->llen, + orig_llen, map->m_llen)) + cpu_relax(); + goto got_it; + } + + work = z_erofs_vle_work_register(&finder, map); + if (unlikely(work == ERR_PTR(-EAGAIN))) + goto repeat; + + if (IS_ERR(work)) + return PTR_ERR(work); +got_it: + z_erofs_pagevec_ctor_init(&builder->vector, Z_EROFS_NR_INLINE_PAGEVECS, + work->pagevec, work->vcnt); + + if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { + /* enable possibly in-place decompression */ + builder->compressed_pages = grp->compressed_pages; + builder->compressed_deficit = clusterpages; + } else { + builder->compressed_pages = NULL; + builder->compressed_deficit = 0; + } + + builder->grp = grp; + builder->work = work; + return 0; +} + +/* + * keep in mind that no referenced workgroups will be freed + * only after a RCU grace period, so rcu_read_lock() could + * prevent a workgroup from being freed. + */ +static void z_erofs_rcu_callback(struct rcu_head *head) +{ + struct z_erofs_vle_work *work = container_of(head, + struct z_erofs_vle_work, rcu); + struct z_erofs_vle_workgroup *grp = + z_erofs_vle_work_workgroup(work, true); + + kmem_cache_free(z_erofs_workgroup_cachep, grp); +} + +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) +{ + struct z_erofs_vle_workgroup *const vgrp = container_of(grp, + struct z_erofs_vle_workgroup, obj); + struct z_erofs_vle_work *const work = &vgrp->work; + + call_rcu(&work->rcu, z_erofs_rcu_callback); +} + +static void +__z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, + struct z_erofs_vle_work *work __maybe_unused) +{ + erofs_workgroup_put(&grp->obj); +} + +static void z_erofs_vle_work_release(struct z_erofs_vle_work *work) +{ + struct z_erofs_vle_workgroup *grp = + z_erofs_vle_work_workgroup(work, true); + + __z_erofs_vle_work_release(grp, work); +} + +static inline bool +z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) +{ + struct z_erofs_vle_work *work = builder->work; + + if (!work) + return false; + + z_erofs_pagevec_ctor_exit(&builder->vector, false); + mutex_unlock(&work->lock); + + /* + * if all pending pages are added, don't hold work reference + * any longer if the current work isn't hosted by ourselves. + */ + if (!builder->hosted) + __z_erofs_vle_work_release(builder->grp, work); + + builder->work = NULL; + builder->grp = NULL; + return true; +} + +static inline struct page *__stagingpage_alloc(struct list_head *pagepool, + gfp_t gfp) +{ + struct page *page = erofs_allocpage(pagepool, gfp); + + if (unlikely(!page)) + return NULL; + + page->mapping = Z_EROFS_MAPPING_STAGING; + return page; +} + +struct z_erofs_vle_frontend { + struct inode *const inode; + + struct z_erofs_vle_work_builder builder; + struct erofs_map_blocks map; + + z_erofs_vle_owned_workgrp_t owned_head; + + /* used for applying cache strategy on the fly */ + bool backmost; + erofs_off_t headoffset; +}; + +#define VLE_FRONTEND_INIT(__i) { \ + .inode = __i, \ + .map = { \ + .m_llen = 0, \ + .m_plen = 0, \ + .mpage = NULL \ + }, \ + .builder = VLE_WORK_BUILDER_INIT(), \ + .owned_head = Z_EROFS_VLE_WORKGRP_TAIL, \ + .backmost = true, } + +#ifdef EROFS_FS_HAS_MANAGED_CACHE +static inline bool +should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) +{ + if (fe->backmost) + return true; + + if (EROFS_FS_ZIP_CACHE_LVL >= 2) + return la < fe->headoffset; + + return false; +} +#else +static inline bool +should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) +{ + return false; +} +#endif + +static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, + struct page *page, + struct list_head *page_pool) +{ + struct super_block *const sb = fe->inode->i_sb; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + struct erofs_map_blocks *const map = &fe->map; + struct z_erofs_vle_work_builder *const builder = &fe->builder; + const loff_t offset = page_offset(page); + + bool tight = builder_is_hooked(builder); + struct z_erofs_vle_work *work = builder->work; + + enum z_erofs_cache_alloctype cache_strategy; + enum z_erofs_page_type page_type; + unsigned int cur, end, spiltted, index; + int err = 0; + + /* register locked file pages as online pages in pack */ + z_erofs_onlinepage_init(page); + + spiltted = 0; + end = PAGE_SIZE; +repeat: + cur = end - 1; + + /* lucky, within the range of the current map_blocks */ + if (offset + cur >= map->m_la && + offset + cur < map->m_la + map->m_llen) { + /* didn't get a valid unzip work previously (very rare) */ + if (!builder->work) + goto restart_now; + goto hitted; + } + + /* go ahead the next map_blocks */ + debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); + + if (z_erofs_vle_work_iter_end(builder)) + fe->backmost = false; + + map->m_la = offset + cur; + map->m_llen = 0; + err = z_erofs_map_blocks_iter(fe->inode, map, 0); + if (unlikely(err)) + goto err_out; + +restart_now: + if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) + goto hitted; + + DBG_BUGON(map->m_plen != 1 << sbi->clusterbits); + DBG_BUGON(erofs_blkoff(map->m_pa)); + + err = z_erofs_vle_work_iter_begin(builder, sb, map, &fe->owned_head); + if (unlikely(err)) + goto err_out; + + /* preload all compressed pages (maybe downgrade role if necessary) */ + if (should_alloc_managed_pages(fe, map->m_la)) + cache_strategy = DELAYEDALLOC; + else + cache_strategy = DONTALLOC; + + preload_compressed_pages(builder, MNGD_MAPPING(sbi), + map->m_pa / PAGE_SIZE, + map->m_plen / PAGE_SIZE, + cache_strategy, page_pool, GFP_KERNEL); + + tight &= builder_is_hooked(builder); + work = builder->work; +hitted: + cur = end - min_t(unsigned int, offset + end - map->m_la, end); + if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { + zero_user_segment(page, cur, end); + goto next_part; + } + + /* let's derive page type */ + page_type = cur ? Z_EROFS_VLE_PAGE_TYPE_HEAD : + (!spiltted ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : + (tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : + Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); + + if (cur) + tight &= builder_is_followed(builder); + +retry: + err = z_erofs_vle_work_add_page(builder, page, page_type); + /* should allocate an additional staging page for pagevec */ + if (err == -EAGAIN) { + struct page *const newpage = + __stagingpage_alloc(page_pool, GFP_NOFS); + + err = z_erofs_vle_work_add_page(builder, newpage, + Z_EROFS_PAGE_TYPE_EXCLUSIVE); + if (likely(!err)) + goto retry; + } + + if (unlikely(err)) + goto err_out; + + index = page->index - map->m_la / PAGE_SIZE; + + /* FIXME! avoid the last relundant fixup & endio */ + z_erofs_onlinepage_fixup(page, index, true); + + /* bump up the number of spiltted parts of a page */ + ++spiltted; + /* also update nr_pages */ + work->nr_pages = max_t(pgoff_t, work->nr_pages, index + 1); +next_part: + /* can be used for verification */ + map->m_llen = offset + cur - map->m_la; + + end = cur; + if (end > 0) + goto repeat; + +out: + /* FIXME! avoid the last relundant fixup & endio */ + z_erofs_onlinepage_endio(page); + + debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", + __func__, page, spiltted, map->m_llen); + return err; + + /* if some error occurred while processing this page */ +err_out: + SetPageError(page); + goto out; +} + +static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) +{ + tagptr1_t t = tagptr_init(tagptr1_t, ptr); + struct z_erofs_vle_unzip_io *io = tagptr_unfold_ptr(t); + bool background = tagptr_unfold_tags(t); + + if (!background) { + unsigned long flags; + + spin_lock_irqsave(&io->u.wait.lock, flags); + if (!atomic_add_return(bios, &io->pending_bios)) + wake_up_locked(&io->u.wait); + spin_unlock_irqrestore(&io->u.wait.lock, flags); + return; + } + + if (!atomic_add_return(bios, &io->pending_bios)) + queue_work(z_erofs_workqueue, &io->u.work); +} + +static inline void z_erofs_vle_read_endio(struct bio *bio) +{ + struct erofs_sb_info *sbi = NULL; + blk_status_t err = bio->bi_status; + struct bio_vec *bvec; + struct bvec_iter_all iter_all; + + bio_for_each_segment_all(bvec, bio, iter_all) { + struct page *page = bvec->bv_page; + bool cachemngd = false; + + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!page->mapping); + + if (unlikely(!sbi && !z_erofs_page_is_staging(page))) { + sbi = EROFS_SB(page->mapping->host->i_sb); + + if (time_to_inject(sbi, FAULT_READ_IO)) { + erofs_show_injection_info(FAULT_READ_IO); + err = BLK_STS_IOERR; + } + } + + /* sbi should already be gotten if the page is managed */ + if (sbi) + cachemngd = erofs_page_is_managed(sbi, page); + + if (unlikely(err)) + SetPageError(page); + else if (cachemngd) + SetPageUptodate(page); + + if (cachemngd) + unlock_page(page); + } + + z_erofs_vle_unzip_kickoff(bio->bi_private, -1); + bio_put(bio); +} + +static struct page *z_pagemap_global[Z_EROFS_VLE_VMAP_GLOBAL_PAGES]; +static DEFINE_MUTEX(z_pagemap_global_lock); + +static int z_erofs_vle_unzip(struct super_block *sb, + struct z_erofs_vle_workgroup *grp, + struct list_head *page_pool) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + const unsigned int clusterpages = erofs_clusterpages(sbi); + + struct z_erofs_pagevec_ctor ctor; + unsigned int nr_pages; + unsigned int sparsemem_pages = 0; + struct page *pages_onstack[Z_EROFS_VLE_VMAP_ONSTACK_PAGES]; + struct page **pages, **compressed_pages, *page; + unsigned int algorithm; + unsigned int i, outputsize; + + enum z_erofs_page_type page_type; + bool overlapped, partial; + struct z_erofs_vle_work *work; + int err; + + might_sleep(); + work = z_erofs_vle_grab_primary_work(grp); + DBG_BUGON(!READ_ONCE(work->nr_pages)); + + mutex_lock(&work->lock); + nr_pages = work->nr_pages; + + if (likely(nr_pages <= Z_EROFS_VLE_VMAP_ONSTACK_PAGES)) + pages = pages_onstack; + else if (nr_pages <= Z_EROFS_VLE_VMAP_GLOBAL_PAGES && + mutex_trylock(&z_pagemap_global_lock)) + pages = z_pagemap_global; + else { + gfp_t gfp_flags = GFP_KERNEL; + + if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) + gfp_flags |= __GFP_NOFAIL; + + pages = kvmalloc_array(nr_pages, sizeof(struct page *), + gfp_flags); + + /* fallback to global pagemap for the lowmem scenario */ + if (unlikely(!pages)) { + mutex_lock(&z_pagemap_global_lock); + pages = z_pagemap_global; + } + } + + for (i = 0; i < nr_pages; ++i) + pages[i] = NULL; + + z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, + work->pagevec, 0); + + for (i = 0; i < work->vcnt; ++i) { + unsigned int pagenr; + + page = z_erofs_pagevec_ctor_dequeue(&ctor, &page_type); + + /* all pages in pagevec ought to be valid */ + DBG_BUGON(!page); + DBG_BUGON(!page->mapping); + + if (z_erofs_put_stagingpage(page_pool, page)) + continue; + + if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) + pagenr = 0; + else + pagenr = z_erofs_onlinepage_index(page); + + DBG_BUGON(pagenr >= nr_pages); + DBG_BUGON(pages[pagenr]); + + pages[pagenr] = page; + } + sparsemem_pages = i; + + z_erofs_pagevec_ctor_exit(&ctor, true); + + overlapped = false; + compressed_pages = grp->compressed_pages; + + err = 0; + for (i = 0; i < clusterpages; ++i) { + unsigned int pagenr; + + page = compressed_pages[i]; + + /* all compressed pages ought to be valid */ + DBG_BUGON(!page); + DBG_BUGON(!page->mapping); + + if (!z_erofs_page_is_staging(page)) { + if (erofs_page_is_managed(sbi, page)) { + if (unlikely(!PageUptodate(page))) + err = -EIO; + continue; + } + + /* + * only if non-head page can be selected + * for inplace decompression + */ + pagenr = z_erofs_onlinepage_index(page); + + DBG_BUGON(pagenr >= nr_pages); + DBG_BUGON(pages[pagenr]); + ++sparsemem_pages; + pages[pagenr] = page; + + overlapped = true; + } + + /* PG_error needs checking for inplaced and staging pages */ + if (unlikely(PageError(page))) { + DBG_BUGON(PageUptodate(page)); + err = -EIO; + } + } + + if (unlikely(err)) + goto out; + + if (nr_pages << PAGE_SHIFT >= work->pageofs + grp->llen) { + outputsize = grp->llen; + partial = !(grp->flags & Z_EROFS_VLE_WORKGRP_FULL_LENGTH); + } else { + outputsize = (nr_pages << PAGE_SHIFT) - work->pageofs; + partial = true; + } + + if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) + algorithm = Z_EROFS_COMPRESSION_SHIFTED; + else + algorithm = Z_EROFS_COMPRESSION_LZ4; + + err = z_erofs_decompress(&(struct z_erofs_decompress_req) { + .sb = sb, + .in = compressed_pages, + .out = pages, + .pageofs_out = work->pageofs, + .inputsize = PAGE_SIZE, + .outputsize = outputsize, + .alg = algorithm, + .inplace_io = overlapped, + .partial_decoding = partial + }, page_pool); + +out: + /* must handle all compressed pages before endding pages */ + for (i = 0; i < clusterpages; ++i) { + page = compressed_pages[i]; + + if (erofs_page_is_managed(sbi, page)) + continue; + + /* recycle all individual staging pages */ + (void)z_erofs_put_stagingpage(page_pool, page); + + WRITE_ONCE(compressed_pages[i], NULL); + } + + for (i = 0; i < nr_pages; ++i) { + page = pages[i]; + if (!page) + continue; + + DBG_BUGON(!page->mapping); + + /* recycle all individual staging pages */ + if (z_erofs_put_stagingpage(page_pool, page)) + continue; + + if (unlikely(err < 0)) + SetPageError(page); + + z_erofs_onlinepage_endio(page); + } + + if (pages == z_pagemap_global) + mutex_unlock(&z_pagemap_global_lock); + else if (unlikely(pages != pages_onstack)) + kvfree(pages); + + work->nr_pages = 0; + work->vcnt = 0; + + /* all work locks MUST be taken before the following line */ + + WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_NIL); + + /* all work locks SHOULD be released right now */ + mutex_unlock(&work->lock); + + z_erofs_vle_work_release(work); + return err; +} + +static void z_erofs_vle_unzip_all(struct super_block *sb, + struct z_erofs_vle_unzip_io *io, + struct list_head *page_pool) +{ + z_erofs_vle_owned_workgrp_t owned = io->head; + + while (owned != Z_EROFS_VLE_WORKGRP_TAIL_CLOSED) { + struct z_erofs_vle_workgroup *grp; + + /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ + DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_TAIL); + + /* no possible that 'owned' equals NULL */ + DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_NIL); + + grp = container_of(owned, struct z_erofs_vle_workgroup, next); + owned = READ_ONCE(grp->next); + + z_erofs_vle_unzip(sb, grp, page_pool); + } +} + +static void z_erofs_vle_unzip_wq(struct work_struct *work) +{ + struct z_erofs_vle_unzip_io_sb *iosb = container_of(work, + struct z_erofs_vle_unzip_io_sb, io.u.work); + LIST_HEAD(page_pool); + + DBG_BUGON(iosb->io.head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &page_pool); + + put_pages_list(&page_pool); + kvfree(iosb); +} + +static struct page * +pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, + unsigned int nr, + struct list_head *pagepool, + struct address_space *mc, + gfp_t gfp) +{ + /* determined at compile time to avoid too many #ifdefs */ + const bool nocache = __builtin_constant_p(mc) ? !mc : false; + const pgoff_t index = grp->obj.index; + bool tocache = false; + + struct address_space *mapping; + struct page *oldpage, *page; + + compressed_page_t t; + int justfound; + +repeat: + page = READ_ONCE(grp->compressed_pages[nr]); + oldpage = page; + + if (!page) + goto out_allocpage; + + /* + * the cached page has not been allocated and + * an placeholder is out there, prepare it now. + */ + if (!nocache && page == PAGE_UNALLOCATED) { + tocache = true; + goto out_allocpage; + } + + /* process the target tagged pointer */ + t = tagptr_init(compressed_page_t, page); + justfound = tagptr_unfold_tags(t); + page = tagptr_unfold_ptr(t); + + mapping = READ_ONCE(page->mapping); + + /* + * if managed cache is disabled, it's no way to + * get such a cached-like page. + */ + if (nocache) { + /* if managed cache is disabled, it is impossible `justfound' */ + DBG_BUGON(justfound); + + /* and it should be locked, not uptodate, and not truncated */ + DBG_BUGON(!PageLocked(page)); + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!mapping); + goto out; + } + + /* + * unmanaged (file) pages are all locked solidly, + * therefore it is impossible for `mapping' to be NULL. + */ + if (mapping && mapping != mc) + /* ought to be unmanaged pages */ + goto out; + + lock_page(page); + + /* only true if page reclaim goes wrong, should never happen */ + DBG_BUGON(justfound && PagePrivate(page)); + + /* the page is still in manage cache */ + if (page->mapping == mc) { + WRITE_ONCE(grp->compressed_pages[nr], page); + + ClearPageError(page); + if (!PagePrivate(page)) { + /* + * impossible to be !PagePrivate(page) for + * the current restriction as well if + * the page is already in compressed_pages[]. + */ + DBG_BUGON(!justfound); + + justfound = 0; + set_page_private(page, (unsigned long)grp); + SetPagePrivate(page); + } + + /* no need to submit io if it is already up-to-date */ + if (PageUptodate(page)) { + unlock_page(page); + page = NULL; + } + goto out; + } + + /* + * the managed page has been truncated, it's unsafe to + * reuse this one, let's allocate a new cache-managed page. + */ + DBG_BUGON(page->mapping); + DBG_BUGON(!justfound); + + tocache = true; + unlock_page(page); + put_page(page); +out_allocpage: + page = __stagingpage_alloc(pagepool, gfp); + if (oldpage != cmpxchg(&grp->compressed_pages[nr], oldpage, page)) { + list_add(&page->lru, pagepool); + cpu_relax(); + goto repeat; + } + if (nocache || !tocache) + goto out; + if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { + page->mapping = Z_EROFS_MAPPING_STAGING; + goto out; + } + + set_page_private(page, (unsigned long)grp); + SetPagePrivate(page); +out: /* the only exit (for tracing and debugging) */ + return page; +} + +static struct z_erofs_vle_unzip_io * +jobqueue_init(struct super_block *sb, + struct z_erofs_vle_unzip_io *io, + bool foreground) +{ + struct z_erofs_vle_unzip_io_sb *iosb; + + if (foreground) { + /* waitqueue available for foreground io */ + DBG_BUGON(!io); + + init_waitqueue_head(&io->u.wait); + atomic_set(&io->pending_bios, 0); + goto out; + } + + iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); + DBG_BUGON(!iosb); + + /* initialize fields in the allocated descriptor */ + io = &iosb->io; + iosb->sb = sb; + INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); +out: + io->head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; + return io; +} + +/* define workgroup jobqueue types */ +enum { +#ifdef EROFS_FS_HAS_MANAGED_CACHE + JQ_BYPASS, +#endif + JQ_SUBMIT, + NR_JOBQUEUES, +}; + +static void *jobqueueset_init(struct super_block *sb, + z_erofs_vle_owned_workgrp_t qtail[], + struct z_erofs_vle_unzip_io *q[], + struct z_erofs_vle_unzip_io *fgq, + bool forcefg) +{ +#ifdef EROFS_FS_HAS_MANAGED_CACHE + /* + * if managed cache is enabled, bypass jobqueue is needed, + * no need to read from device for all workgroups in this queue. + */ + q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); + qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; +#endif + + q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); + qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; + + return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); +} + +#ifdef EROFS_FS_HAS_MANAGED_CACHE +static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, + z_erofs_vle_owned_workgrp_t qtail[], + z_erofs_vle_owned_workgrp_t owned_head) +{ + z_erofs_vle_owned_workgrp_t *const submit_qtail = qtail[JQ_SUBMIT]; + z_erofs_vle_owned_workgrp_t *const bypass_qtail = qtail[JQ_BYPASS]; + + DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + if (owned_head == Z_EROFS_VLE_WORKGRP_TAIL) + owned_head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; + + WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + + WRITE_ONCE(*submit_qtail, owned_head); + WRITE_ONCE(*bypass_qtail, &grp->next); + + qtail[JQ_BYPASS] = &grp->next; +} + +static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], + unsigned int nr_bios, + bool force_fg) +{ + /* + * although background is preferred, no one is pending for submission. + * don't issue workqueue for decompression but drop it directly instead. + */ + if (force_fg || nr_bios) + return false; + + kvfree(container_of(q[JQ_SUBMIT], + struct z_erofs_vle_unzip_io_sb, + io)); + return true; +} +#else +static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, + z_erofs_vle_owned_workgrp_t qtail[], + z_erofs_vle_owned_workgrp_t owned_head) +{ + /* impossible to bypass submission for managed cache disabled */ + DBG_BUGON(1); +} + +static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], + unsigned int nr_bios, + bool force_fg) +{ + /* bios should be >0 if managed cache is disabled */ + DBG_BUGON(!nr_bios); + return false; +} +#endif + +static bool z_erofs_vle_submit_all(struct super_block *sb, + z_erofs_vle_owned_workgrp_t owned_head, + struct list_head *pagepool, + struct z_erofs_vle_unzip_io *fgq, + bool force_fg) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + const unsigned int clusterpages = erofs_clusterpages(sbi); + const gfp_t gfp = GFP_NOFS; + + z_erofs_vle_owned_workgrp_t qtail[NR_JOBQUEUES]; + struct z_erofs_vle_unzip_io *q[NR_JOBQUEUES]; + struct bio *bio; + void *bi_private; + /* since bio will be NULL, no need to initialize last_index */ + pgoff_t uninitialized_var(last_index); + bool force_submit = false; + unsigned int nr_bios; + + if (unlikely(owned_head == Z_EROFS_VLE_WORKGRP_TAIL)) + return false; + + force_submit = false; + bio = NULL; + nr_bios = 0; + bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); + + /* by default, all need io submission */ + q[JQ_SUBMIT]->head = owned_head; + + do { + struct z_erofs_vle_workgroup *grp; + pgoff_t first_index; + struct page *page; + unsigned int i = 0, bypass = 0; + int err; + + /* no possible 'owned_head' equals the following */ + DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_NIL); + + grp = container_of(owned_head, + struct z_erofs_vle_workgroup, next); + + /* close the main owned chain at first */ + owned_head = cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, + Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + + first_index = grp->obj.index; + force_submit |= (first_index != last_index + 1); + +repeat: + page = pickup_page_for_submission(grp, i, pagepool, + MNGD_MAPPING(sbi), gfp); + if (!page) { + force_submit = true; + ++bypass; + goto skippage; + } + + if (bio && force_submit) { +submit_bio_retry: + __submit_bio(bio, REQ_OP_READ, 0); + bio = NULL; + } + + if (!bio) { + bio = erofs_grab_bio(sb, first_index + i, + BIO_MAX_PAGES, bi_private, + z_erofs_vle_read_endio, true); + ++nr_bios; + } + + err = bio_add_page(bio, page, PAGE_SIZE, 0); + if (err < PAGE_SIZE) + goto submit_bio_retry; + + force_submit = false; + last_index = first_index + i; +skippage: + if (++i < clusterpages) + goto repeat; + + if (bypass < clusterpages) + qtail[JQ_SUBMIT] = &grp->next; + else + move_to_bypass_jobqueue(grp, qtail, owned_head); + } while (owned_head != Z_EROFS_VLE_WORKGRP_TAIL); + + if (bio) + __submit_bio(bio, REQ_OP_READ, 0); + + if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) + return true; + + z_erofs_vle_unzip_kickoff(bi_private, nr_bios); + return true; +} + +static void z_erofs_submit_and_unzip(struct z_erofs_vle_frontend *f, + struct list_head *pagepool, + bool force_fg) +{ + struct super_block *sb = f->inode->i_sb; + struct z_erofs_vle_unzip_io io[NR_JOBQUEUES]; + + if (!z_erofs_vle_submit_all(sb, f->owned_head, pagepool, io, force_fg)) + return; + +#ifdef EROFS_FS_HAS_MANAGED_CACHE + z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); +#endif + if (!force_fg) + return; + + /* wait until all bios are completed */ + wait_event(io[JQ_SUBMIT].u.wait, + !atomic_read(&io[JQ_SUBMIT].pending_bios)); + + /* let's synchronous decompression */ + z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); +} + +static int z_erofs_vle_normalaccess_readpage(struct file *file, + struct page *page) +{ + struct inode *const inode = page->mapping->host; + struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); + int err; + LIST_HEAD(pagepool); + + trace_erofs_readpage(page, false); + + f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; + + err = z_erofs_do_read_page(&f, page, &pagepool); + (void)z_erofs_vle_work_iter_end(&f.builder); + + if (err) { + errln("%s, failed to read, err [%d]", __func__, err); + goto out; + } + + z_erofs_submit_and_unzip(&f, &pagepool, true); +out: + if (f.map.mpage) + put_page(f.map.mpage); + + /* clean up the remaining free pages */ + put_pages_list(&pagepool); + return 0; +} + +static int z_erofs_vle_normalaccess_readpages(struct file *filp, + struct address_space *mapping, + struct list_head *pages, + unsigned int nr_pages) +{ + struct inode *const inode = mapping->host; + struct erofs_sb_info *const sbi = EROFS_I_SB(inode); + + bool sync = __should_decompress_synchronously(sbi, nr_pages); + struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); + gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); + struct page *head = NULL; + LIST_HEAD(pagepool); + + trace_erofs_readpages(mapping->host, lru_to_page(pages), + nr_pages, false); + + f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT; + + for (; nr_pages; --nr_pages) { + struct page *page = lru_to_page(pages); + + prefetchw(&page->flags); + list_del(&page->lru); + + /* + * A pure asynchronous readahead is indicated if + * a PG_readahead marked page is hitted at first. + * Let's also do asynchronous decompression for this case. + */ + sync &= !(PageReadahead(page) && !head); + + if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { + list_add(&page->lru, &pagepool); + continue; + } + + set_page_private(page, (unsigned long)head); + head = page; + } + + while (head) { + struct page *page = head; + int err; + + /* traversal in reverse order */ + head = (void *)page_private(page); + + err = z_erofs_do_read_page(&f, page, &pagepool); + if (err) { + struct erofs_vnode *vi = EROFS_V(inode); + + errln("%s, readahead error at page %lu of nid %llu", + __func__, page->index, vi->nid); + } + + put_page(page); + } + + (void)z_erofs_vle_work_iter_end(&f.builder); + + z_erofs_submit_and_unzip(&f, &pagepool, sync); + + if (f.map.mpage) + put_page(f.map.mpage); + + /* clean up the remaining free pages */ + put_pages_list(&pagepool); + return 0; +} + +const struct address_space_operations z_erofs_vle_normalaccess_aops = { + .readpage = z_erofs_vle_normalaccess_readpage, + .readpages = z_erofs_vle_normalaccess_readpages, +}; + diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h new file mode 100644 index 000000000000..8d0119d697da --- /dev/null +++ b/drivers/staging/erofs/zdata.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/drivers/staging/erofs/zdata.h + * + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_FS_ZDATA_H +#define __EROFS_FS_ZDATA_H + +#include "internal.h" +#include "zpvec.h" + +#define Z_EROFS_NR_INLINE_PAGEVECS 3 + +/* + * Structure fields follow one of the following exclusion rules. + * + * I: Modifiable by initialization/destruction paths and read-only + * for everyone else. + * + */ + +struct z_erofs_vle_work { + struct mutex lock; + + /* I: decompression offset in page */ + unsigned short pageofs; + unsigned short nr_pages; + + /* L: queued pages in pagevec[] */ + unsigned int vcnt; + + union { + /* L: pagevec */ + erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; + struct rcu_head rcu; + }; +}; + +#define Z_EROFS_VLE_WORKGRP_FMT_PLAIN 0 +#define Z_EROFS_VLE_WORKGRP_FMT_LZ4 1 +#define Z_EROFS_VLE_WORKGRP_FMT_MASK 1 +#define Z_EROFS_VLE_WORKGRP_FULL_LENGTH 2 + +typedef void *z_erofs_vle_owned_workgrp_t; + +struct z_erofs_vle_workgroup { + struct erofs_workgroup obj; + struct z_erofs_vle_work work; + + /* point to next owned_workgrp_t */ + z_erofs_vle_owned_workgrp_t next; + + /* compressed pages (including multi-usage pages) */ + struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; + unsigned int llen, flags; +}; + +/* let's avoid the valid 32-bit kernel addresses */ + +/* the chained workgroup has't submitted io (still open) */ +#define Z_EROFS_VLE_WORKGRP_TAIL ((void *)0x5F0ECAFE) +/* the chained workgroup has already submitted io */ +#define Z_EROFS_VLE_WORKGRP_TAIL_CLOSED ((void *)0x5F0EDEAD) + +#define Z_EROFS_VLE_WORKGRP_NIL (NULL) + +#define z_erofs_vle_workgrp_fmt(grp) \ + ((grp)->flags & Z_EROFS_VLE_WORKGRP_FMT_MASK) + +static inline void z_erofs_vle_set_workgrp_fmt( + struct z_erofs_vle_workgroup *grp, + unsigned int fmt) +{ + grp->flags = fmt | (grp->flags & ~Z_EROFS_VLE_WORKGRP_FMT_MASK); +} + + +/* definitions if multiref is disabled */ +#define z_erofs_vle_grab_primary_work(grp) (&(grp)->work) +#define z_erofs_vle_grab_work(grp, pageofs) (&(grp)->work) +#define z_erofs_vle_work_workgroup(wrk, primary) \ + ((primary) ? container_of(wrk, \ + struct z_erofs_vle_workgroup, work) : \ + ({ BUG(); (void *)NULL; })) + + +#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_vle_workgroup) + +struct z_erofs_vle_unzip_io { + atomic_t pending_bios; + z_erofs_vle_owned_workgrp_t head; + + union { + wait_queue_head_t wait; + struct work_struct work; + } u; +}; + +struct z_erofs_vle_unzip_io_sb { + struct z_erofs_vle_unzip_io io; + struct super_block *sb; +}; + +#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 +#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) +#define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) + +/* + * waiters (aka. ongoing_packs): # to unlock the page + * sub-index: 0 - for partial page, >= 1 full page sub-index + */ +typedef atomic_t z_erofs_onlinepage_t; + +/* type punning */ +union z_erofs_onlinepage_converter { + z_erofs_onlinepage_t *o; + unsigned long *v; +}; + +static inline unsigned int z_erofs_onlinepage_index(struct page *page) +{ + union z_erofs_onlinepage_converter u; + + DBG_BUGON(!PagePrivate(page)); + u.v = &page_private(page); + + return atomic_read(u.o) >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; +} + +static inline void z_erofs_onlinepage_init(struct page *page) +{ + union { + z_erofs_onlinepage_t o; + unsigned long v; + /* keep from being unlocked in advance */ + } u = { .o = ATOMIC_INIT(1) }; + + set_page_private(page, u.v); + smp_wmb(); + SetPagePrivate(page); +} + +static inline void z_erofs_onlinepage_fixup(struct page *page, + uintptr_t index, bool down) +{ + unsigned long *p, o, v, id; +repeat: + p = &page_private(page); + o = READ_ONCE(*p); + + id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; + if (id) { + if (!index) + return; + + DBG_BUGON(id != index); + } + + v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | + ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); + if (cmpxchg(p, o, v) != o) + goto repeat; +} + +static inline void z_erofs_onlinepage_endio(struct page *page) +{ + union z_erofs_onlinepage_converter u; + unsigned int v; + + DBG_BUGON(!PagePrivate(page)); + u.v = &page_private(page); + + v = atomic_dec_return(u.o); + if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) { + ClearPagePrivate(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + } + + debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); +} + +#define Z_EROFS_VLE_VMAP_ONSTACK_PAGES \ + min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) +#define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048 + +#endif + diff --git a/drivers/staging/erofs/zpvec.h b/drivers/staging/erofs/zpvec.h new file mode 100644 index 000000000000..77bf6877bad8 --- /dev/null +++ b/drivers/staging/erofs/zpvec.h @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/drivers/staging/erofs/zpvec.h + * + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_FS_ZPVEC_H +#define __EROFS_FS_ZPVEC_H + +#include "tagptr.h" + +/* page type in pagevec for unzip subsystem */ +enum z_erofs_page_type { + /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ + Z_EROFS_PAGE_TYPE_EXCLUSIVE, + + Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED, + + Z_EROFS_VLE_PAGE_TYPE_HEAD, + Z_EROFS_VLE_PAGE_TYPE_MAX +}; + +extern void __compiletime_error("Z_EROFS_PAGE_TYPE_EXCLUSIVE != 0") + __bad_page_type_exclusive(void); + +/* pagevec tagged pointer */ +typedef tagptr2_t erofs_vtptr_t; + +/* pagevec collector */ +struct z_erofs_pagevec_ctor { + struct page *curr, *next; + erofs_vtptr_t *pages; + + unsigned int nr, index; +}; + +static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, + bool atomic) +{ + if (!ctor->curr) + return; + + if (atomic) + kunmap_atomic(ctor->pages); + else + kunmap(ctor->curr); +} + +static inline struct page * +z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, + unsigned int nr) +{ + unsigned int index; + + /* keep away from occupied pages */ + if (ctor->next) + return ctor->next; + + for (index = 0; index < nr; ++index) { + const erofs_vtptr_t t = ctor->pages[index]; + const unsigned int tags = tagptr_unfold_tags(t); + + if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) + return tagptr_unfold_ptr(t); + } + DBG_BUGON(nr >= ctor->nr); + return NULL; +} + +static inline void +z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, + bool atomic) +{ + struct page *next = z_erofs_pagevec_ctor_next_page(ctor, ctor->nr); + + z_erofs_pagevec_ctor_exit(ctor, atomic); + + ctor->curr = next; + ctor->next = NULL; + ctor->pages = atomic ? + kmap_atomic(ctor->curr) : kmap(ctor->curr); + + ctor->nr = PAGE_SIZE / sizeof(struct page *); + ctor->index = 0; +} + +static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, + unsigned int nr, + erofs_vtptr_t *pages, + unsigned int i) +{ + ctor->nr = nr; + ctor->curr = ctor->next = NULL; + ctor->pages = pages; + + if (i >= nr) { + i -= nr; + z_erofs_pagevec_ctor_pagedown(ctor, false); + while (i > ctor->nr) { + i -= ctor->nr; + z_erofs_pagevec_ctor_pagedown(ctor, false); + } + } + + ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); + ctor->index = i; +} + +static inline bool +z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, + enum z_erofs_page_type type, + bool *occupied) +{ + *occupied = false; + if (unlikely(!ctor->next && type)) + if (ctor->index + 1 == ctor->nr) + return false; + + if (unlikely(ctor->index >= ctor->nr)) + z_erofs_pagevec_ctor_pagedown(ctor, false); + + /* exclusive page type must be 0 */ + if (Z_EROFS_PAGE_TYPE_EXCLUSIVE != (uintptr_t)NULL) + __bad_page_type_exclusive(); + + /* should remind that collector->next never equal to 1, 2 */ + if (type == (uintptr_t)ctor->next) { + ctor->next = page; + *occupied = true; + } + + ctor->pages[ctor->index++] = + tagptr_fold(erofs_vtptr_t, page, type); + return true; +} + +static inline struct page * +z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, + enum z_erofs_page_type *type) +{ + erofs_vtptr_t t; + + if (unlikely(ctor->index >= ctor->nr)) { + DBG_BUGON(!ctor->next); + z_erofs_pagevec_ctor_pagedown(ctor, true); + } + + t = ctor->pages[ctor->index]; + + *type = tagptr_unfold_tags(t); + + /* should remind that collector->next never equal to 1, 2 */ + if (*type == (uintptr_t)ctor->next) + ctor->next = tagptr_unfold_ptr(t); + + ctor->pages[ctor->index++] = + tagptr_fold(erofs_vtptr_t, NULL, 0); + + return tagptr_unfold_ptr(t); +} + +#endif + -- cgit v1.2.3-59-g8ed1b From 5734fa217f27bc08667930e862dbe536ed6a77ea Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:33 +0800 Subject: staging: erofs: fix dummy functions erofs_{get, list}xattr dummy functions erofs_{get,list}xattr should be inlined without xattr enabled. Signed-off-by: Yue Hu [ Gao Xiang : this patch was "staging: erofs: remove needless dummy functions of erofs_{get,list}xattr. "] Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-4-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/xattr.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index fbcd57bdf886..63cc87e3d3f4 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -39,6 +39,7 @@ static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; } +#ifdef CONFIG_EROFS_FS_XATTR extern const struct xattr_handler erofs_xattr_user_handler; extern const struct xattr_handler erofs_xattr_trusted_handler; #ifdef CONFIG_EROFS_FS_SECURITY @@ -64,25 +65,24 @@ static const struct xattr_handler *xattr_handler_map[] = { xattr_handler_map[idx] : NULL; } -#ifdef CONFIG_EROFS_FS_XATTR extern const struct xattr_handler *erofs_xattr_handlers[]; int erofs_getxattr(struct inode *, int, const char *, void *, size_t); ssize_t erofs_listxattr(struct dentry *, char *, size_t); #else -static int __maybe_unused erofs_getxattr(struct inode *inode, int index, - const char *name, - void *buffer, size_t buffer_size) +static inline int erofs_getxattr(struct inode *inode, int index, + const char *name, void *buffer, + size_t buffer_size) { return -ENOTSUPP; } -static ssize_t __maybe_unused erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) +static inline ssize_t erofs_listxattr(struct dentry *dentry, + char *buffer, size_t buffer_size) { return -ENOTSUPP; } -#endif +#endif /* !CONFIG_EROFS_FS_XATTR */ #ifdef CONFIG_EROFS_FS_POSIX_ACL struct posix_acl *erofs_get_acl(struct inode *inode, int type); -- cgit v1.2.3-59-g8ed1b From cead56f85baa783a1ed56bea235a4c1c2556c3fa Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:34 +0800 Subject: staging: erofs: keep up erofs_fs.h with erofs-outofstaging patchset The main change is to reserve all checksums except for superblock, since it's more useful to do block-based verity for read-only fs. Some comments change as well, which is minor. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-5-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/erofs_fs.h | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h index 9cd749d56920..e82e833985e4 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/drivers/staging/erofs/erofs_fs.h @@ -96,7 +96,7 @@ struct erofs_inode_v1 { /* 20 */__le32 i_ino; /* only used for 32-bit stat compatibility */ /* 24 */__le16 i_uid; /* 26 */__le16 i_gid; -/* 28 */__le32 i_checksum; +/* 28 */__le32 i_reserved2; } __packed; /* 32 bytes on-disk inode */ @@ -105,14 +105,14 @@ struct erofs_inode_v1 { #define EROFS_INODE_LAYOUT_V2 1 struct erofs_inode_v2 { - __le16 i_advise; +/* 0 */__le16 i_advise; - /* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ - __le16 i_xattr_icount; - __le16 i_mode; - __le16 i_reserved; /* 8 bytes */ - __le64 i_size; /* 16 bytes */ - union { +/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ +/* 2 */__le16 i_xattr_icount; +/* 4 */__le16 i_mode; +/* 6 */__le16 i_reserved; +/* 8 */__le64 i_size; +/* 16 */union { /* file total compressed blocks for data mapping 1 */ __le32 compressed_blocks; __le32 raw_blkaddr; @@ -122,16 +122,15 @@ struct erofs_inode_v2 { } i_u __packed; /* only used for 32-bit stat compatibility */ - __le32 i_ino; /* 24 bytes */ - - __le32 i_uid; - __le32 i_gid; - __le64 i_ctime; /* 32 bytes */ - __le32 i_ctime_nsec; - __le32 i_nlink; - __u8 i_reserved2[12]; - __le32 i_checksum; /* 64 bytes */ -} __packed; +/* 20 */__le32 i_ino; + +/* 24 */__le32 i_uid; +/* 28 */__le32 i_gid; +/* 32 */__le64 i_ctime; +/* 40 */__le32 i_ctime_nsec; +/* 44 */__le32 i_nlink; +/* 48 */__u8 i_reserved2[16]; +} __packed; /* 64 bytes */ #define EROFS_MAX_SHARED_XATTRS (128) /* h_shared_count between 129 ... 255 are special # */ @@ -149,9 +148,9 @@ struct erofs_inode_v2 { * for read-only fs, no need to introduce h_refcount */ struct erofs_xattr_ibody_header { - __le32 h_checksum; + __le32 h_reserved; __u8 h_shared_count; - __u8 h_reserved[7]; + __u8 h_reserved2[7]; __le32 h_shared_xattrs[0]; /* shared xattr id array */ } __packed; -- cgit v1.2.3-59-g8ed1b From b1897c60b14dc565e9a308c09bbb696faf9d1944 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:35 +0800 Subject: staging: erofs: sunset erofs_workstn_{lock,unlock} It was used for Linux backward compatibility, and no use for upstream kernel. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-6-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 3 --- drivers/staging/erofs/utils.c | 10 +++++----- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 501429ec0f91..ed487ee56f74 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -179,9 +179,6 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP -#define erofs_workstn_lock(sbi) xa_lock(&(sbi)->workstn_tree) -#define erofs_workstn_unlock(sbi) xa_unlock(&(sbi)->workstn_tree) - /* basic unit of the workstation of a super_block */ struct erofs_workgroup { /* the workgroup index in the workstation */ diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index a68dbe375fa0..024806003297 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -102,14 +102,14 @@ int erofs_register_workgroup(struct super_block *sb, return err; sbi = EROFS_SB(sb); - erofs_workstn_lock(sbi); + xa_lock(&sbi->workstn_tree); grp = xa_tag_pointer(grp, tag); /* * Bump up reference count before making this workgroup * visible to other users in order to avoid potential UAF - * without serialized by erofs_workstn_lock. + * without serialized by workstn_lock. */ __erofs_workgroup_get(grp); @@ -122,7 +122,7 @@ int erofs_register_workgroup(struct super_block *sb, */ __erofs_workgroup_put(grp); - erofs_workstn_unlock(sbi); + xa_unlock(&sbi->workstn_tree); radix_tree_preload_end(); return err; } @@ -225,7 +225,7 @@ unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, int i, found; repeat: - erofs_workstn_lock(sbi); + xa_lock(&sbi->workstn_tree); found = radix_tree_gang_lookup(&sbi->workstn_tree, batch, first_index, PAGEVEC_SIZE); @@ -243,7 +243,7 @@ repeat: if (unlikely(!--nr_shrink)) break; } - erofs_workstn_unlock(sbi); + xa_unlock(&sbi->workstn_tree); if (i && nr_shrink) goto repeat; -- cgit v1.2.3-59-g8ed1b From 14f362b4f405804e219ac016b9e771d8f5dff5db Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:36 +0800 Subject: staging: erofs: clean up internal.h Tidy up relative order of variables / declarations in internal.h, move some local static functions out into other files and add tags at the end of #endif acrossing several lines. No logic change. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-7-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/decompressor.c | 27 ++++++ drivers/staging/erofs/internal.h | 157 ++++++++++------------------------- drivers/staging/erofs/super.c | 2 +- drivers/staging/erofs/zdata.c | 8 +- drivers/staging/erofs/zdata.h | 13 +++ 5 files changed, 92 insertions(+), 115 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index b75524d0b322..ee5762351f80 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -223,6 +223,33 @@ static void copy_from_pcpubuf(struct page **out, const char *dst, } } +static void *erofs_vmap(struct page **pages, unsigned int count) +{ +#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM + int i = 0; + + while (1) { + void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); + /* retry two more times (totally 3 times) */ + if (addr || ++i >= 3) + return addr; + vm_unmap_aliases(); + } + return NULL; +#else + return vmap(pages, count, VM_MAP, PAGE_KERNEL); +#endif +} + +static void erofs_vunmap(const void *mem, unsigned int count) +{ +#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM + vm_unmap_ram(mem, count); +#else + vunmap(mem); +#endif +} + static int decompress_generic(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index ed487ee56f74..959bd0ae9d74 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -6,8 +6,8 @@ * http://www.huawei.com/ * Created by Gao Xiang */ -#ifndef __INTERNAL_H -#define __INTERNAL_H +#ifndef __EROFS_INTERNAL_H +#define __EROFS_INTERNAL_H #include #include @@ -28,15 +28,11 @@ #define infoln(x, ...) pr_info(x "\n", ##__VA_ARGS__) #ifdef CONFIG_EROFS_FS_DEBUG #define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__) - -#define dbg_might_sleep might_sleep #define DBG_BUGON BUG_ON #else #define debugln(x, ...) ((void)0) - -#define dbg_might_sleep() ((void)0) #define DBG_BUGON(x) ((void)(x)) -#endif +#endif /* !CONFIG_EROFS_FS_DEBUG */ enum { FAULT_KMALLOC, @@ -53,7 +49,7 @@ struct erofs_fault_info { unsigned int inject_rate; unsigned int inject_type; }; -#endif +#endif /* CONFIG_EROFS_FAULT_INJECTION */ #ifdef CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR #define EROFS_FS_ZIP_CACHE_LVL (2) @@ -71,6 +67,9 @@ struct erofs_fault_info { #define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 typedef u64 erofs_nid_t; +typedef u64 erofs_off_t; +/* data type for filesystem-wide blocks number */ +typedef u32 erofs_blk_t; struct erofs_sb_info { /* list for all registered superblocks, mainly for shrinker */ @@ -154,7 +153,7 @@ static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) static inline void erofs_show_injection_info(int type) { } -#endif +#endif /* !CONFIG_EROFS_FAULT_INJECTION */ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, size_t size, gfp_t flags) @@ -179,6 +178,8 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP +#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) + /* basic unit of the workstation of a super_block */ struct erofs_workgroup { /* the workgroup index in the workstation */ @@ -188,8 +189,6 @@ struct erofs_workgroup { atomic_t refcount; }; -#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) - #if defined(CONFIG_SMP) static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, int val) @@ -246,50 +245,24 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) DBG_BUGON(v == EROFS_LOCKED_MAGIC); return v; } -#endif - -int erofs_workgroup_put(struct erofs_workgroup *grp); -struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag); -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, bool tag); -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, bool cleanup); -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); - -#ifdef EROFS_FS_HAS_MANAGED_CACHE -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp); -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page); - -#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) -{ - return page->mapping == MNGD_MAPPING(sbi); -} -#else -#define MNGD_MAPPING(sbi) (NULL) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) { return false; } -#endif +#endif /* !CONFIG_SMP */ -#define DEFAULT_MAX_SYNC_DECOMPRESS_PAGES 3 +/* hard limit of pages per compressed cluster */ +#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) +#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -static inline bool __should_decompress_synchronously(struct erofs_sb_info *sbi, - unsigned int nr) -{ - return nr <= sbi->max_sync_decompress_pages; -} +/* page count of a compressed cluster */ +#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) int __init z_erofs_init_zip_subsystem(void); void z_erofs_exit_zip_subsystem(void); #else +#define EROFS_PCPUBUF_NR_PAGES 0 + /* dummy initializer/finalizer for the decompression subsystem */ static inline int z_erofs_init_zip_subsystem(void) { return 0; } static inline void z_erofs_exit_zip_subsystem(void) {} -#endif +#endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ #define LOG_BLOCK_SIZE PAGE_SHIFT @@ -308,23 +281,6 @@ static inline void z_erofs_exit_zip_subsystem(void) {} #define ROOT_NID(sb) ((sb)->root_nid) -#ifdef CONFIG_EROFS_FS_ZIP -/* hard limit of pages per compressed cluster */ -#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) - -/* page count of a compressed cluster */ -#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) - -#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -#else -#define EROFS_PCPUBUF_NR_PAGES 0 -#endif - -typedef u64 erofs_off_t; - -/* data type for filesystem-wide blocks number */ -typedef u32 erofs_blk_t; - #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) #define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) #define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) @@ -364,7 +320,7 @@ struct erofs_vnode { unsigned char z_logical_clusterbits; unsigned char z_physical_clusterbits[2]; }; -#endif +#endif /* CONFIG_EROFS_FS_ZIP */ }; /* the corresponding vfs inode */ struct inode vfs_inode; @@ -472,13 +428,14 @@ static inline int z_erofs_map_blocks_iter(struct inode *inode, { return -ENOTSUPP; } -#endif +#endif /* !CONFIG_EROFS_FS_ZIP */ /* data.c */ -static inline struct bio * -erofs_grab_bio(struct super_block *sb, - erofs_blk_t blkaddr, unsigned int nr_pages, void *bi_private, - bio_end_io_t endio, bool nofail) +static inline struct bio *erofs_grab_bio(struct super_block *sb, + erofs_blk_t blkaddr, + unsigned int nr_pages, + void *bi_private, bio_end_io_t endio, + bool nofail) { const gfp_t gfp = GFP_NOIO; struct bio *bio; @@ -525,20 +482,13 @@ static inline struct page *erofs_get_meta_page(struct super_block *sb, return __erofs_get_meta_page(sb, blkaddr, prio, false); } -static inline struct page *erofs_get_meta_page_nofail(struct super_block *sb, - erofs_blk_t blkaddr, bool prio) -{ - return __erofs_get_meta_page(sb, blkaddr, prio, true); -} - int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); -static inline struct page * -erofs_get_inline_page(struct inode *inode, - erofs_blk_t blkaddr) +static inline struct page *erofs_get_inline_page(struct inode *inode, + erofs_blk_t blkaddr) { - return erofs_get_meta_page(inode->i_sb, - blkaddr, S_ISDIR(inode->i_mode)); + return erofs_get_meta_page(inode->i_sb, blkaddr, + S_ISDIR(inode->i_mode)); } /* inode.c */ @@ -578,34 +528,7 @@ int erofs_namei(struct inode *dir, struct qstr *name, /* dir.c */ extern const struct file_operations erofs_dir_fops; -static inline void *erofs_vmap(struct page **pages, unsigned int count) -{ -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - int i = 0; - - while (1) { - void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); - /* retry two more times (totally 3 times) */ - if (addr || ++i >= 3) - return addr; - vm_unmap_aliases(); - } - return NULL; -#else - return vmap(pages, count, VM_MAP, PAGE_KERNEL); -#endif -} - -static inline void erofs_vunmap(const void *mem, unsigned int count) -{ -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - vm_unmap_ram(mem, count); -#else - vunmap(mem); -#endif -} - -/* utils.c */ +/* utils.c / zdata.c */ extern struct shrinker erofs_shrinker_info; struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); @@ -625,12 +548,20 @@ static inline void *erofs_get_pcpubuf(unsigned int pagenr) #define erofs_put_pcpubuf(buf) do {} while (0) #endif +int erofs_workgroup_put(struct erofs_workgroup *grp); +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag); +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, bool tag); +unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, bool cleanup); +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *egrp); +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page); void erofs_register_super(struct super_block *sb); void erofs_unregister_super(struct super_block *sb); -#ifndef lru_to_page -#define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) -#endif - -#endif +#endif /* __EROFS_INTERNAL_H */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 38cd7a59750a..55f51d2b3930 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -211,7 +211,7 @@ static void default_options(struct erofs_sb_info *sbi) { /* set up some FS parameters */ #ifdef CONFIG_EROFS_FS_ZIP - sbi->max_sync_decompress_pages = DEFAULT_MAX_SYNC_DECOMPRESS_PAGES; + sbi->max_sync_decompress_pages = 3; #endif #ifdef CONFIG_EROFS_FS_XATTR diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index f7667628bbf1..bc478eebf509 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -1509,6 +1509,12 @@ out: return 0; } +static bool should_decompress_synchronously(struct erofs_sb_info *sbi, + unsigned int nr) +{ + return nr <= sbi->max_sync_decompress_pages; +} + static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct address_space *mapping, struct list_head *pages, @@ -1517,7 +1523,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct inode *const inode = mapping->host; struct erofs_sb_info *const sbi = EROFS_I_SB(inode); - bool sync = __should_decompress_synchronously(sbi, nr_pages); + bool sync = should_decompress_synchronously(sbi, nr_pages); struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); struct page *head = NULL; diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h index 8d0119d697da..6574d43ba877 100644 --- a/drivers/staging/erofs/zdata.h +++ b/drivers/staging/erofs/zdata.h @@ -104,6 +104,19 @@ struct z_erofs_vle_unzip_io_sb { struct super_block *sb; }; +#ifdef EROFS_FS_HAS_MANAGED_CACHE +#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) +{ + return page->mapping == MNGD_MAPPING(sbi); +} +#else +#define MNGD_MAPPING(sbi) (NULL) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) { return false; } +#endif /* !EROFS_FS_HAS_MANAGED_CACHE */ + #define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 #define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) #define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) -- cgit v1.2.3-59-g8ed1b From 22ee1347a8fb6d3eba91aacad7c691dee274cc1f Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:37 +0800 Subject: staging: erofs: remove redundant #include "internal.h" Because #include "internal.h" is included in xattr.h Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190731155752.210602-8-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/namei.c | 1 - drivers/staging/erofs/super.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index 50816b4c05fc..8e06526da023 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -6,7 +6,6 @@ * http://www.huawei.com/ * Created by Gao Xiang */ -#include "internal.h" #include "xattr.h" #include diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 55f51d2b3930..c20a94b035a7 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -11,7 +11,6 @@ #include #include #include -#include "internal.h" #include "xattr.h" #define CREATE_TRACE_POINTS -- cgit v1.2.3-59-g8ed1b From beb5f3c4a1f8daa9175f0044d2fa4185c7813a30 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:38 +0800 Subject: staging: erofs: kill CONFIG_EROFS_FS_IO_MAX_RETRIES CONFIG_EROFS_FS_IO_MAX_RETRIES seems a runtime setting and users have no idea about the change in behaviour. Let's remove the setting currently and could turn it into a module parameter if it's really needed. Suggested-by: David Sterba Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190731155752.210602-9-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Kconfig | 9 --------- drivers/staging/erofs/internal.h | 8 ++------ 2 files changed, 2 insertions(+), 15 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 2577cbb46a5b..747e9eebfaa5 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -78,15 +78,6 @@ config EROFS_FAULT_INJECTION Test EROFS to inject faults such as ENOMEM, EIO, and so on. If unsure, say N. -config EROFS_FS_IO_MAX_RETRIES - int "EROFS IO Maximum Retries" - depends on EROFS_FS - default "5" - help - Maximum retry count of IO Errors. - - If unsure, leave the default value (5 retries, 6 IOs at most). - config EROFS_FS_ZIP bool "EROFS Data Compresssion Support" depends on EROFS_FS diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 959bd0ae9d74..a3b9fcdd0c27 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -279,6 +279,8 @@ static inline void z_erofs_exit_zip_subsystem(void) {} #error erofs cannot be used in this platform #endif +#define EROFS_IO_MAX_RETRIES_NOFAIL 5 + #define ROOT_NID(sb) ((sb)->root_nid) #define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) @@ -467,12 +469,6 @@ static inline void __submit_bio(struct bio *bio, unsigned int op, submit_bio(bio); } -#ifndef CONFIG_EROFS_FS_IO_MAX_RETRIES -#define EROFS_IO_MAX_RETRIES_NOFAIL 0 -#else -#define EROFS_IO_MAX_RETRIES_NOFAIL CONFIG_EROFS_FS_IO_MAX_RETRIES -#endif - struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, bool prio, bool nofail); -- cgit v1.2.3-59-g8ed1b From 22fe04a77d104996d838a487a1d031eda8d439b7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:39 +0800 Subject: staging: erofs: clean up shrinker stuffs - rename erofs_register_super / erofs_unregister_super to erofs_shrinker_register / erofs_shrinker_unregister; - fold the only erofs_shrink_workstation external call to erofs_shrinker_unregister; - localize erofs_shrink_workstation; - localize erofs_shrinker_info by introducing erofs_init_shrinker and erofs_exit_shrinker. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-10-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 50 +++++++++++++++++++++------------------- drivers/staging/erofs/super.c | 20 ++++------------ drivers/staging/erofs/utils.c | 37 +++++++++++++++++++---------- 3 files changed, 56 insertions(+), 51 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index a3b9fcdd0c27..e149cf9fc23f 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -72,34 +72,35 @@ typedef u64 erofs_off_t; typedef u32 erofs_blk_t; struct erofs_sb_info { +#ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; struct mutex umount_mutex; - u32 blocks; - u32 meta_blkaddr; -#ifdef CONFIG_EROFS_FS_XATTR - u32 xattr_blkaddr; -#endif - - /* inode slot unit size in bit shift */ - unsigned char islotbits; -#ifdef CONFIG_EROFS_FS_ZIP /* cluster size in bit shift */ unsigned char clusterbits; - /* the dedicated workstation for compression */ struct radix_tree_root workstn_tree; /* threshold for decompression synchronously */ unsigned int max_sync_decompress_pages; + unsigned int shrinker_run_no; + #ifdef EROFS_FS_HAS_MANAGED_CACHE struct inode *managed_cache; #endif +#endif /* CONFIG_EROFS_FS_ZIP */ + u32 blocks; + u32 meta_blkaddr; +#ifdef CONFIG_EROFS_FS_XATTR + u32 xattr_blkaddr; #endif + /* inode slot unit size in bit shift */ + unsigned char islotbits; + u32 build_time_nsec; u64 build_time; @@ -115,7 +116,6 @@ struct erofs_sb_info { char *dev_name; unsigned int mount_opt; - unsigned int shrinker_run_no; #ifdef CONFIG_EROFS_FAULT_INJECTION struct erofs_fault_info fault_info; /* For fault injection */ @@ -253,15 +253,8 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) /* page count of a compressed cluster */ #define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) - -int __init z_erofs_init_zip_subsystem(void); -void z_erofs_exit_zip_subsystem(void); #else #define EROFS_PCPUBUF_NR_PAGES 0 - -/* dummy initializer/finalizer for the decompression subsystem */ -static inline int z_erofs_init_zip_subsystem(void) { return 0; } -static inline void z_erofs_exit_zip_subsystem(void) {} #endif /* !CONFIG_EROFS_FS_ZIP */ /* we strictly follow PAGE_SIZE and no buffer head yet */ @@ -525,8 +518,6 @@ int erofs_namei(struct inode *dir, struct qstr *name, extern const struct file_operations erofs_dir_fops; /* utils.c / zdata.c */ -extern struct shrinker erofs_shrinker_info; - struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); #if (EROFS_PCPUBUF_NR_PAGES > 0) @@ -544,20 +535,31 @@ static inline void *erofs_get_pcpubuf(unsigned int pagenr) #define erofs_put_pcpubuf(buf) do {} while (0) #endif +#ifdef CONFIG_EROFS_FS_ZIP int erofs_workgroup_put(struct erofs_workgroup *grp); struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, pgoff_t index, bool *tag); int erofs_register_workgroup(struct super_block *sb, struct erofs_workgroup *grp, bool tag); -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, bool cleanup); void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +void erofs_shrinker_register(struct super_block *sb); +void erofs_shrinker_unregister(struct super_block *sb); +int __init erofs_init_shrinker(void); +void erofs_exit_shrinker(void); +int __init z_erofs_init_zip_subsystem(void); +void z_erofs_exit_zip_subsystem(void); int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, struct erofs_workgroup *egrp); int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page); -void erofs_register_super(struct super_block *sb); -void erofs_unregister_super(struct super_block *sb); +#else +static inline void erofs_shrinker_register(struct super_block *sb) {} +static inline void erofs_shrinker_unregister(struct super_block *sb) {} +static inline int erofs_init_shrinker(void) { return 0; } +static inline void erofs_exit_shrinker(void) {} +static inline int z_erofs_init_zip_subsystem(void) { return 0; } +static inline void z_erofs_exit_zip_subsystem(void) {} +#endif /* !CONFIG_EROFS_FS_ZIP */ #endif /* __EROFS_INTERNAL_H */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index c20a94b035a7..7e6fe9cd45e7 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -458,7 +458,7 @@ static int erofs_read_super(struct super_block *sb, snprintf(sbi->dev_name, PATH_MAX, "%s", dev_name); sbi->dev_name[PATH_MAX - 1] = '\0'; - erofs_register_super(sb); + erofs_shrinker_register(sb); if (!silent) infoln("mounted on %s with opts: %s.", dev_name, @@ -502,20 +502,10 @@ static void erofs_put_super(struct super_block *sb) infoln("unmounted for %s", sbi->dev_name); __putname(sbi->dev_name); + erofs_shrinker_unregister(sb); #ifdef EROFS_FS_HAS_MANAGED_CACHE iput(sbi->managed_cache); #endif - - mutex_lock(&sbi->umount_mutex); - -#ifdef CONFIG_EROFS_FS_ZIP - /* clean up the compression space of this sb */ - erofs_shrink_workstation(EROFS_SB(sb), ~0UL, true); -#endif - - erofs_unregister_super(sb); - mutex_unlock(&sbi->umount_mutex); - kfree(sbi); sb->s_fs_info = NULL; } @@ -569,7 +559,7 @@ static int __init erofs_module_init(void) if (err) goto icache_err; - err = register_shrinker(&erofs_shrinker_info); + err = erofs_init_shrinker(); if (err) goto shrinker_err; @@ -587,7 +577,7 @@ static int __init erofs_module_init(void) fs_err: z_erofs_exit_zip_subsystem(); zip_err: - unregister_shrinker(&erofs_shrinker_info); + erofs_exit_shrinker(); shrinker_err: erofs_exit_inode_cache(); icache_err: @@ -598,7 +588,7 @@ static void __exit erofs_module_exit(void) { unregister_filesystem(&erofs_fs_type); z_erofs_exit_zip_subsystem(); - unregister_shrinker(&erofs_shrinker_info); + erofs_exit_shrinker(); erofs_exit_inode_cache(); infoln("successfully finalize erofs"); } diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 024806003297..0e86e44d60d0 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -34,10 +34,10 @@ void *erofs_get_pcpubuf(unsigned int pagenr) } #endif +#ifdef CONFIG_EROFS_FS_ZIP /* global shrink count (for all mounted EROFS instances) */ static atomic_long_t erofs_global_shrink_cnt; -#ifdef CONFIG_EROFS_FS_ZIP #define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) #define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) @@ -215,9 +215,9 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, #endif -unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, - bool cleanup) +static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, + bool cleanup) { pgoff_t first_index = 0; void *batch[PAGEVEC_SIZE]; @@ -250,8 +250,6 @@ repeat: return freed; } -#endif - /* protected by 'erofs_sb_list_lock' */ static unsigned int shrinker_run_no; @@ -259,7 +257,7 @@ static unsigned int shrinker_run_no; static DEFINE_SPINLOCK(erofs_sb_list_lock); static LIST_HEAD(erofs_sb_list); -void erofs_register_super(struct super_block *sb) +void erofs_shrinker_register(struct super_block *sb) { struct erofs_sb_info *sbi = EROFS_SB(sb); @@ -270,11 +268,17 @@ void erofs_register_super(struct super_block *sb) spin_unlock(&erofs_sb_list_lock); } -void erofs_unregister_super(struct super_block *sb) +void erofs_shrinker_unregister(struct super_block *sb) { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + mutex_lock(&sbi->umount_mutex); + erofs_shrink_workstation(sbi, ~0UL, true); + spin_lock(&erofs_sb_list_lock); - list_del(&EROFS_SB(sb)->list); + list_del(&sbi->list); spin_unlock(&erofs_sb_list_lock); + mutex_unlock(&sbi->umount_mutex); } static unsigned long erofs_shrink_count(struct shrinker *shrink, @@ -318,9 +322,7 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, spin_unlock(&erofs_sb_list_lock); sbi->shrinker_run_no = run_no; -#ifdef CONFIG_EROFS_FS_ZIP freed += erofs_shrink_workstation(sbi, nr, false); -#endif spin_lock(&erofs_sb_list_lock); /* Get the next list element before we move this one */ @@ -340,9 +342,20 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, return freed; } -struct shrinker erofs_shrinker_info = { +static struct shrinker erofs_shrinker_info = { .scan_objects = erofs_shrink_scan, .count_objects = erofs_shrink_count, .seeks = DEFAULT_SEEKS, }; +int __init erofs_init_shrinker(void) +{ + return register_shrinker(&erofs_shrinker_info); +} + +void erofs_exit_shrinker(void) +{ + unregister_shrinker(&erofs_shrinker_info); +} +#endif /* !CONFIG_EROFS_FS_ZIP */ + -- cgit v1.2.3-59-g8ed1b From 9e794de573d7d54e3742628227e585bd90acc38a Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:40 +0800 Subject: staging: erofs: kill sbi->dev_name As Al said, "the only use of sbi->dev_name is debugging printks and all of those have sb->s_id available, with device name stored in there. Which makes the whole thing bloody weird". sbi->dev_name was used for our debugging use and it's better to just use s_id in community and delete the whole erofs_mount_private stuff. Suggested-by: Al Viro Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-11-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 2 -- drivers/staging/erofs/super.c | 54 ++++++---------------------------------- 2 files changed, 7 insertions(+), 49 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index e149cf9fc23f..5e1ef2b5a458 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -113,8 +113,6 @@ struct erofs_sb_info { u8 volume_name[16]; /* volume name */ u32 requirements; - char *dev_name; - unsigned int mount_opt; #ifdef CONFIG_EROFS_FAULT_INJECTION diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 7e6fe9cd45e7..bfb6e1e09781 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -362,15 +362,13 @@ static struct inode *erofs_init_managed_cache(struct super_block *sb) #endif -static int erofs_read_super(struct super_block *sb, - const char *dev_name, - void *data, int silent) +static int erofs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct erofs_sb_info *sbi; int err = -EINVAL; - infoln("read_super, device -> %s", dev_name); + infoln("fill_super, device -> %s", sb->s_id); infoln("options -> %s", (char *)data); if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { @@ -448,30 +446,16 @@ static int erofs_read_super(struct super_block *sb, goto err_iget; } - /* save the device name to sbi */ - sbi->dev_name = __getname(); - if (!sbi->dev_name) { - err = -ENOMEM; - goto err_devname; - } - - snprintf(sbi->dev_name, PATH_MAX, "%s", dev_name); - sbi->dev_name[PATH_MAX - 1] = '\0'; - erofs_shrinker_register(sb); if (!silent) - infoln("mounted on %s with opts: %s.", dev_name, - (char *)data); + infoln("mounted on %s with opts: %s.", sb->s_id, (char *)data); return 0; /* * please add a label for each exit point and use * the following name convention, thus new features * can be integrated easily without renaming labels. */ -err_devname: - dput(sb->s_root); - sb->s_root = NULL; err_iget: #ifdef EROFS_FS_HAS_MANAGED_CACHE iput(sbi->managed_cache); @@ -499,8 +483,7 @@ static void erofs_put_super(struct super_block *sb) WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); - infoln("unmounted for %s", sbi->dev_name); - __putname(sbi->dev_name); + infoln("unmounted for %s", sb->s_id); erofs_shrinker_unregister(sb); #ifdef EROFS_FS_HAS_MANAGED_CACHE @@ -510,33 +493,10 @@ static void erofs_put_super(struct super_block *sb) sb->s_fs_info = NULL; } - -struct erofs_mount_private { - const char *dev_name; - char *options; -}; - -/* support mount_bdev() with options */ -static int erofs_fill_super(struct super_block *sb, - void *_priv, int silent) -{ - struct erofs_mount_private *priv = _priv; - - return erofs_read_super(sb, priv->dev_name, - priv->options, silent); -} - -static struct dentry *erofs_mount( - struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) { - struct erofs_mount_private priv = { - .dev_name = dev_name, - .options = data - }; - - return mount_bdev(fs_type, flags, dev_name, - &priv, erofs_fill_super); + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } static struct file_system_type erofs_fs_type = { -- cgit v1.2.3-59-g8ed1b From 8f7acdae2cd4b843d1fcb49e449cc7860556e3ef Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:41 +0800 Subject: staging: erofs: kill all failure handling in fill_super() .kill_sb() will do that instead in order to remove duplicated code. Note that the initialzation of managed_cache is now moved after s_root is assigned since it's more preferred to iput() in .put_super() and all inodes should be evicted before the end of generic_shutdown_super(sb). Suggested-by: Al Viro Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-12-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 118 +++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 66 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index bfb6e1e09781..7c31030daf4e 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -343,12 +343,13 @@ static const struct address_space_operations managed_cache_aops = { .invalidatepage = managed_cache_invalidatepage, }; -static struct inode *erofs_init_managed_cache(struct super_block *sb) +static int erofs_init_managed_cache(struct super_block *sb) { - struct inode *inode = new_inode(sb); + struct erofs_sb_info *const sbi = EROFS_SB(sb); + struct inode *const inode = new_inode(sb); if (unlikely(!inode)) - return ERR_PTR(-ENOMEM); + return -ENOMEM; set_nlink(inode, 1); inode->i_size = OFFSET_MAX; @@ -357,37 +358,38 @@ static struct inode *erofs_init_managed_cache(struct super_block *sb) mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE | __GFP_NOFAIL); - return inode; + sbi->managed_cache = inode; + return 0; } - +#else +static int erofs_init_managed_cache(struct super_block *sb) { return 0; } #endif static int erofs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct erofs_sb_info *sbi; - int err = -EINVAL; + int err; infoln("fill_super, device -> %s", sb->s_id); infoln("options -> %s", (char *)data); + sb->s_magic = EROFS_SUPER_MAGIC; + if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { errln("failed to set erofs blksize"); - goto err; + return -EINVAL; } sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (unlikely(!sbi)) { - err = -ENOMEM; - goto err; - } - sb->s_fs_info = sbi; + if (unlikely(!sbi)) + return -ENOMEM; + sb->s_fs_info = sbi; err = superblock_read(sb); if (err) - goto err_sbread; + return err; - sb->s_magic = EROFS_SUPER_MAGIC; sb->s_flags |= SB_RDONLY | SB_NOATIME; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_time_gran = 1; @@ -397,13 +399,12 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_EROFS_FS_XATTR sb->s_xattr = erofs_xattr_handlers; #endif - /* set erofs default mount options */ default_options(sbi); err = parse_options(sb, data); - if (err) - goto err_parseopt; + if (unlikely(err)) + return err; if (!silent) infoln("root inode @ nid %llu", ROOT_NID(sbi)); @@ -417,93 +418,78 @@ static int erofs_fill_super(struct super_block *sb, void *data, int silent) INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); #endif -#ifdef EROFS_FS_HAS_MANAGED_CACHE - sbi->managed_cache = erofs_init_managed_cache(sb); - if (IS_ERR(sbi->managed_cache)) { - err = PTR_ERR(sbi->managed_cache); - goto err_init_managed_cache; - } -#endif - /* get the root inode */ inode = erofs_iget(sb, ROOT_NID(sbi), true); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto err_iget; - } + if (IS_ERR(inode)) + return PTR_ERR(inode); - if (!S_ISDIR(inode->i_mode)) { + if (unlikely(!S_ISDIR(inode->i_mode))) { errln("rootino(nid %llu) is not a directory(i_mode %o)", ROOT_NID(sbi), inode->i_mode); - err = -EINVAL; iput(inode); - goto err_iget; + return -EINVAL; } sb->s_root = d_make_root(inode); - if (!sb->s_root) { - err = -ENOMEM; - goto err_iget; - } + if (unlikely(!sb->s_root)) + return -ENOMEM; erofs_shrinker_register(sb); + /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ + err = erofs_init_managed_cache(sb); + if (unlikely(err)) + return err; if (!silent) infoln("mounted on %s with opts: %s.", sb->s_id, (char *)data); return 0; - /* - * please add a label for each exit point and use - * the following name convention, thus new features - * can be integrated easily without renaming labels. - */ -err_iget: -#ifdef EROFS_FS_HAS_MANAGED_CACHE - iput(sbi->managed_cache); -err_init_managed_cache: -#endif -err_parseopt: -err_sbread: - sb->s_fs_info = NULL; - kfree(sbi); -err: - return err; +} + +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } /* * could be triggered after deactivate_locked_super() * is called, thus including umount and failed to initialize. */ -static void erofs_put_super(struct super_block *sb) +static void erofs_kill_sb(struct super_block *sb) { - struct erofs_sb_info *sbi = EROFS_SB(sb); + struct erofs_sb_info *sbi; + + WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); + infoln("unmounting for %s", sb->s_id); - /* for cases which are failed in "read_super" */ + kill_block_super(sb); + + sbi = EROFS_SB(sb); if (!sbi) return; + kfree(sbi); + sb->s_fs_info = NULL; +} - WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); +/* called when ->s_root is non-NULL */ +static void erofs_put_super(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); - infoln("unmounted for %s", sb->s_id); + DBG_BUGON(!sbi); erofs_shrinker_unregister(sb); #ifdef EROFS_FS_HAS_MANAGED_CACHE iput(sbi->managed_cache); + sbi->managed_cache = NULL; #endif - kfree(sbi); - sb->s_fs_info = NULL; -} - -static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); } static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", .mount = erofs_mount, - .kill_sb = kill_block_super, + .kill_sb = erofs_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("erofs"); -- cgit v1.2.3-59-g8ed1b From 8494c29ffe22dcd166a86b490dce10ecf1c20065 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:42 +0800 Subject: staging: erofs: drop __GFP_NOFAIL for managed inode For historical reasons, __GFP_NOFAIL was set for managed inode. It's no need using that since EROFS can handle it properly. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190731155752.210602-13-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index 7c31030daf4e..af5d87793e4d 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -356,8 +356,7 @@ static int erofs_init_managed_cache(struct super_block *sb) inode->i_mapping->a_ops = &managed_cache_aops; mapping_set_gfp_mask(inode->i_mapping, - GFP_NOFS | __GFP_HIGHMEM | - __GFP_MOVABLE | __GFP_NOFAIL); + GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE); sbi->managed_cache = inode; return 0; } -- cgit v1.2.3-59-g8ed1b From b25a15191c5cf090f79fd220238b93f30b022b0d Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:43 +0800 Subject: staging: erofs: refine erofs_allocpage() remove duplicated code in decompressor by introducing failable erofs_allocpage(). Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-14-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/decompressor.c | 12 +++--------- drivers/staging/erofs/internal.h | 2 +- drivers/staging/erofs/utils.c | 5 +++-- drivers/staging/erofs/zdata.c | 5 +---- 4 files changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index ee5762351f80..744c43a456e9 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -74,15 +74,9 @@ static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, victim = availables[--top]; get_page(victim); } else { - if (!list_empty(pagepool)) { - victim = lru_to_page(pagepool); - list_del(&victim->lru); - DBG_BUGON(page_ref_count(victim) != 1); - } else { - victim = alloc_pages(GFP_KERNEL, 0); - if (!victim) - return -ENOMEM; - } + victim = erofs_allocpage(pagepool, GFP_KERNEL, false); + if (unlikely(!victim)) + return -ENOMEM; victim->mapping = Z_EROFS_MAPPING_STAGING; } rq->out[i] = victim; diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 5e1ef2b5a458..a631acd0dc62 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -516,7 +516,7 @@ int erofs_namei(struct inode *dir, struct qstr *name, extern const struct file_operations erofs_dir_fops; /* utils.c / zdata.c */ -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp); +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); #if (EROFS_PCPUBUF_NR_PAGES > 0) void *erofs_get_pcpubuf(unsigned int pagenr); diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 0e86e44d60d0..260ea2970b4b 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -9,15 +9,16 @@ #include "internal.h" #include -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) { struct page *page; if (!list_empty(pool)) { page = lru_to_page(pool); + DBG_BUGON(page_ref_count(page) != 1); list_del(&page->lru); } else { - page = alloc_pages(gfp | __GFP_NOFAIL, 0); + page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); } return page; } diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index bc478eebf509..3078510e350d 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -634,10 +634,7 @@ z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) static inline struct page *__stagingpage_alloc(struct list_head *pagepool, gfp_t gfp) { - struct page *page = erofs_allocpage(pagepool, gfp); - - if (unlikely(!page)) - return NULL; + struct page *page = erofs_allocpage(pagepool, gfp, true); page->mapping = Z_EROFS_MAPPING_STAGING; return page; -- cgit v1.2.3-59-g8ed1b From 46c2d1494332ece4f136d167b62afe91a63796fb Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:44 +0800 Subject: staging: erofs: kill CONFIG_EROFS_FS_USE_VM_MAP_RAM Turn into a module parameter ("use_vmap") as it can be set at runtime. Suggested-by: David Sterba Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-15-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- .../erofs/Documentation/filesystems/erofs.txt | 4 ++++ drivers/staging/erofs/Kconfig | 8 -------- drivers/staging/erofs/decompressor.c | 22 +++++++++++++--------- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt index 74cf84ac48a3..04cf47865c50 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt @@ -66,6 +66,10 @@ fault_injection=%d Enable fault injection in all supported types with (no)acl Setup POSIX Access Control List. Note: acl is enabled by default if CONFIG_EROFS_FS_POSIX_ACL is selected. +Module parameters +================= +use_vmap=[0|1] Use vmap() instead of vm_map_ram() (default 0). + On-disk details =============== diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 747e9eebfaa5..788beebf3f7d 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -63,14 +63,6 @@ config EROFS_FS_SECURITY If you are not using a security module, say N. -config EROFS_FS_USE_VM_MAP_RAM - bool "EROFS VM_MAP_RAM Support" - depends on EROFS_FS - help - use vm_map_ram/vm_unmap_ram instead of vmap/vunmap. - - If you don't know what these are, say N. - config EROFS_FAULT_INJECTION bool "EROFS fault injection facility" depends on EROFS_FS diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index 744c43a456e9..5361a2bbedb6 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -7,6 +7,7 @@ * Created by Gao Xiang */ #include "compress.h" +#include #include #ifndef LZ4_DISTANCE_MAX /* history window size */ @@ -29,6 +30,10 @@ struct z_erofs_decompressor { char *name; }; +static bool use_vmap; +module_param(use_vmap, bool, 0444); +MODULE_PARM_DESC(use_vmap, "Use vmap() instead of vm_map_ram() (default 0)"); + static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, struct list_head *pagepool) { @@ -219,29 +224,28 @@ static void copy_from_pcpubuf(struct page **out, const char *dst, static void *erofs_vmap(struct page **pages, unsigned int count) { -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM int i = 0; + if (use_vmap) + return vmap(pages, count, VM_MAP, PAGE_KERNEL); + while (1) { void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); + /* retry two more times (totally 3 times) */ if (addr || ++i >= 3) return addr; vm_unmap_aliases(); } return NULL; -#else - return vmap(pages, count, VM_MAP, PAGE_KERNEL); -#endif } static void erofs_vunmap(const void *mem, unsigned int count) { -#ifdef CONFIG_EROFS_FS_USE_VM_MAP_RAM - vm_unmap_ram(mem, count); -#else - vunmap(mem); -#endif + if (!use_vmap) + vm_unmap_ram(mem, count); + else + vunmap(mem); } static int decompress_generic(struct z_erofs_decompress_req *rq, -- cgit v1.2.3-59-g8ed1b From 046d64e1189fea79eb8705015ccc621a2f25e1da Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:45 +0800 Subject: staging: erofs: tidy up zpvec.h - use shorter function names: z_erofs_pagevec_enqueue and z_erofs_pagevec_dequeue; - minor code cleanup. In order to keep in line with erofs-outofstaging patchset. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-16-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 6 +++--- drivers/staging/erofs/zpvec.h | 25 +++++++++---------------- 2 files changed, 12 insertions(+), 19 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 3078510e350d..88c8c4082498 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -314,8 +314,8 @@ static int z_erofs_vle_work_add_page( try_to_reuse_as_compressed_page(builder, page)) return 0; - ret = z_erofs_pagevec_ctor_enqueue(&builder->vector, - page, type, &occupied); + ret = z_erofs_pagevec_enqueue(&builder->vector, + page, type, &occupied); builder->work->vcnt += (unsigned int)ret; return ret ? 0 : -EAGAIN; @@ -938,7 +938,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, for (i = 0; i < work->vcnt; ++i) { unsigned int pagenr; - page = z_erofs_pagevec_ctor_dequeue(&ctor, &page_type); + page = z_erofs_pagevec_dequeue(&ctor, &page_type); /* all pages in pagevec ought to be valid */ DBG_BUGON(!page); diff --git a/drivers/staging/erofs/zpvec.h b/drivers/staging/erofs/zpvec.h index 77bf6877bad8..9798f5627786 100644 --- a/drivers/staging/erofs/zpvec.h +++ b/drivers/staging/erofs/zpvec.h @@ -11,7 +11,7 @@ #include "tagptr.h" -/* page type in pagevec for unzip subsystem */ +/* page type in pagevec for decompress subsystem */ enum z_erofs_page_type { /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ Z_EROFS_PAGE_TYPE_EXCLUSIVE, @@ -103,16 +103,14 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, z_erofs_pagevec_ctor_pagedown(ctor, false); } } - ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); ctor->index = i; } -static inline bool -z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, - struct page *page, - enum z_erofs_page_type type, - bool *occupied) +static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, + enum z_erofs_page_type type, + bool *occupied) { *occupied = false; if (unlikely(!ctor->next && type)) @@ -131,15 +129,13 @@ z_erofs_pagevec_ctor_enqueue(struct z_erofs_pagevec_ctor *ctor, ctor->next = page; *occupied = true; } - - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, page, type); + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); return true; } static inline struct page * -z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, - enum z_erofs_page_type *type) +z_erofs_pagevec_dequeue(struct z_erofs_pagevec_ctor *ctor, + enum z_erofs_page_type *type) { erofs_vtptr_t t; @@ -156,11 +152,8 @@ z_erofs_pagevec_ctor_dequeue(struct z_erofs_pagevec_ctor *ctor, if (*type == (uintptr_t)ctor->next) ctor->next = tagptr_unfold_ptr(t); - ctor->pages[ctor->index++] = - tagptr_fold(erofs_vtptr_t, NULL, 0); - + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, NULL, 0); return tagptr_unfold_ptr(t); } - #endif -- cgit v1.2.3-59-g8ed1b From febde7b3ac4de7d12f03a555e400d08ae3237a01 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:46 +0800 Subject: staging: erofs: remove redundant braces in inode.c Remove redundant braces in inode.c since these are all single statements. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-17-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/inode.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index c13d66ccc74a..286729143365 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -35,16 +35,15 @@ static int read_inode(struct inode *inode, void *data) inode->i_mode = le16_to_cpu(v2->i_mode); if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { + S_ISLNK(inode->i_mode)) vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = new_decode_dev(le32_to_cpu(v2->i_u.rdev)); - } else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) inode->i_rdev = 0; - } else { + else return -EIO; - } i_uid_write(inode, le32_to_cpu(v2->i_uid)); i_gid_write(inode, le32_to_cpu(v2->i_gid)); @@ -69,16 +68,15 @@ static int read_inode(struct inode *inode, void *data) inode->i_mode = le16_to_cpu(v1->i_mode); if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) { + S_ISLNK(inode->i_mode)) vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) inode->i_rdev = new_decode_dev(le32_to_cpu(v1->i_u.rdev)); - } else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) inode->i_rdev = 0; - } else { + else return -EIO; - } i_uid_write(inode, le16_to_cpu(v1->i_uid)); i_gid_write(inode, le16_to_cpu(v1->i_gid)); -- cgit v1.2.3-59-g8ed1b From 97e86a858bc360c9cded74ce9a06595d40f7ad81 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:47 +0800 Subject: staging: erofs: tidy up decompression frontend Although this patch has an amount of changes, it is hard to separate into smaller patches. Most changes are due to structure renaming for better understand and straightforward, z_erofs_vle_workgroup to z_erofs_pcluster since it represents a physical cluster; z_erofs_vle_work to z_erofs_collection since it represents a collection of logical pages; z_erofs_vle_work_builder to z_erofs_collector since it's used to fill z_erofs_{pcluster,collection}. struct z_erofs_vle_work_finder has no extra use compared with struct z_erofs_collector, delete it. FULL_LENGTH bit is integrated into .length of pcluster so that it can be updated with the corresponding length change in atomic. Minor, add comments for better description. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-18-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 983 ++++++++++++++++++------------------------ drivers/staging/erofs/zdata.h | 96 ++--- 2 files changed, 465 insertions(+), 614 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 88c8c4082498..6ebee2ca8dc5 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -18,7 +18,7 @@ */ #define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) -/* how to allocate cached pages for a workgroup */ +/* how to allocate cached pages for a pcluster */ enum z_erofs_cache_alloctype { DONTALLOC, /* don't allocate any cached pages */ DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ @@ -34,156 +34,158 @@ typedef tagptr1_t compressed_page_t; tagptr_fold(compressed_page_t, page, 1) static struct workqueue_struct *z_erofs_workqueue __read_mostly; -static struct kmem_cache *z_erofs_workgroup_cachep __read_mostly; +static struct kmem_cache *pcluster_cachep __read_mostly; void z_erofs_exit_zip_subsystem(void) { destroy_workqueue(z_erofs_workqueue); - kmem_cache_destroy(z_erofs_workgroup_cachep); + kmem_cache_destroy(pcluster_cachep); } static inline int init_unzip_workqueue(void) { const unsigned int onlinecpus = num_possible_cpus(); + const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; /* - * we don't need too many threads, limiting threads - * could improve scheduling performance. + * no need to spawn too many threads, limiting threads could minimum + * scheduling overhead, perhaps per-CPU threads should be better? */ - z_erofs_workqueue = - alloc_workqueue("erofs_unzipd", - WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE, - onlinecpus + onlinecpus / 4); - + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, + onlinecpus + onlinecpus / 4); return z_erofs_workqueue ? 0 : -ENOMEM; } static void init_once(void *ptr) { - struct z_erofs_vle_workgroup *grp = ptr; - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); + struct z_erofs_pcluster *pcl = ptr; + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); unsigned int i; - mutex_init(&work->lock); - work->nr_pages = 0; - work->vcnt = 0; + mutex_init(&cl->lock); + cl->nr_pages = 0; + cl->vcnt = 0; for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) - grp->compressed_pages[i] = NULL; + pcl->compressed_pages[i] = NULL; } -static void init_always(struct z_erofs_vle_workgroup *grp) +static void init_always(struct z_erofs_pcluster *pcl) { - struct z_erofs_vle_work *const work = - z_erofs_vle_grab_primary_work(grp); + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); - atomic_set(&grp->obj.refcount, 1); - grp->flags = 0; + atomic_set(&pcl->obj.refcount, 1); - DBG_BUGON(work->nr_pages); - DBG_BUGON(work->vcnt); + DBG_BUGON(cl->nr_pages); + DBG_BUGON(cl->vcnt); } int __init z_erofs_init_zip_subsystem(void) { - z_erofs_workgroup_cachep = - kmem_cache_create("erofs_compress", - Z_EROFS_WORKGROUP_SIZE, 0, - SLAB_RECLAIM_ACCOUNT, init_once); - - if (z_erofs_workgroup_cachep) { + pcluster_cachep = kmem_cache_create("erofs_compress", + Z_EROFS_WORKGROUP_SIZE, 0, + SLAB_RECLAIM_ACCOUNT, init_once); + if (pcluster_cachep) { if (!init_unzip_workqueue()) return 0; - kmem_cache_destroy(z_erofs_workgroup_cachep); + kmem_cache_destroy(pcluster_cachep); } return -ENOMEM; } -enum z_erofs_vle_work_role { - Z_EROFS_VLE_WORK_SECONDARY, - Z_EROFS_VLE_WORK_PRIMARY, +enum z_erofs_collectmode { + COLLECT_SECONDARY, + COLLECT_PRIMARY, /* - * The current work was the tail of an exist chain, and the previous - * processed chained works are all decided to be hooked up to it. - * A new chain should be created for the remaining unprocessed works, - * therefore different from Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - * the next work cannot reuse the whole page in the following scenario: + * The current collection was the tail of an exist chain, in addition + * that the previous processed chained collections are all decided to + * be hooked up to it. + * A new chain will be created for the remaining collections which are + * not processed yet, therefore different from COLLECT_PRIMARY_FOLLOWED, + * the next collection cannot reuse the whole page safely in + * the following scenario: * ________________________________________________________________ * | tail (partial) page | head (partial) page | - * | (belongs to the next work) | (belongs to the current work) | + * | (belongs to the next cl) | (belongs to the current cl) | * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| */ - Z_EROFS_VLE_WORK_PRIMARY_HOOKED, + COLLECT_PRIMARY_HOOKED, + COLLECT_PRIMARY_FOLLOWED_NOINPLACE, /* - * The current work has been linked with the processed chained works, - * and could be also linked with the potential remaining works, which - * means if the processing page is the tail partial page of the work, - * the current work can safely use the whole page (since the next work - * is under control) for in-place decompression, as illustrated below: + * The current collection has been linked with the owned chain, and + * could also be linked with the remaining collections, which means + * if the processing page is the tail page of the collection, thus + * the current collection can safely use the whole page (since + * the previous collection is under control) for in-place I/O, as + * illustrated below: * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (of the current work) | (of the previous work) | - * | PRIMARY_FOLLOWED or | | - * |_____PRIMARY_HOOKED____|____________PRIMARY_FOLLOWED____________| + * | tail (partial) page | head (partial) page | + * | (of the current cl) | (of the previous collection) | + * | PRIMARY_FOLLOWED or | | + * |_____PRIMARY_HOOKED___|____________PRIMARY_FOLLOWED____________| * - * [ (*) the above page can be used for the current work itself. ] + * [ (*) the above page can be used as inplace I/O. ] */ - Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED, - Z_EROFS_VLE_WORK_MAX + COLLECT_PRIMARY_FOLLOWED, }; -struct z_erofs_vle_work_builder { - enum z_erofs_vle_work_role role; - /* - * 'hosted = false' means that the current workgroup doesn't belong to - * the owned chained workgroups. In the other words, it is none of our - * business to submit this workgroup. - */ - bool hosted; - - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; +struct z_erofs_collector { struct z_erofs_pagevec_ctor vector; - /* pages used for reading the compressed data */ - struct page **compressed_pages; - unsigned int compressed_deficit; + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + struct page **compressedpages; + z_erofs_next_pcluster_t owned_head; + + enum z_erofs_collectmode mode; }; -#define VLE_WORK_BUILDER_INIT() \ - { .work = NULL, .role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED } +struct z_erofs_decompress_frontend { + struct inode *const inode; + + struct z_erofs_collector clt; + struct erofs_map_blocks map; + + /* used for applying cache strategy on the fly */ + bool backmost; + erofs_off_t headoffset; +}; + +#define COLLECTOR_INIT() { \ + .owned_head = Z_EROFS_PCLUSTER_TAIL, \ + .mode = COLLECT_PRIMARY_FOLLOWED } + +#define DECOMPRESS_FRONTEND_INIT(__i) { \ + .inode = __i, .clt = COLLECTOR_INIT(), \ + .backmost = true, } + +static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; +static DEFINE_MUTEX(z_pagemap_global_lock); #ifdef EROFS_FS_HAS_MANAGED_CACHE -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, +static void preload_compressed_pages(struct z_erofs_collector *clt, struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) + struct list_head *pagepool) { - struct page **const pages = bl->compressed_pages; - const unsigned int remaining = bl->compressed_deficit; + const struct z_erofs_pcluster *pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct page **pages = clt->compressedpages; + pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); bool standalone = true; - unsigned int i, j = 0; - if (bl->role < Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) + if (clt->mode < COLLECT_PRIMARY_FOLLOWED) return; - gfp = mapping_gfp_constraint(mc, gfp) & ~__GFP_RECLAIM; - - index += clusterpages - remaining; - - for (i = 0; i < remaining; ++i) { + for (; pages < pcl->compressed_pages + clusterpages; ++pages) { struct page *page; compressed_page_t t; /* the compressed page was loaded before */ - if (READ_ONCE(pages[i])) + if (READ_ONCE(*pages)) continue; - page = find_get_page(mc, index + i); + page = find_get_page(mc, index); if (page) { t = tag_compressed_page_justfound(page); @@ -191,32 +193,30 @@ static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); } else { /* DONTALLOC */ if (standalone) - j = i; + clt->compressedpages = pages; standalone = false; continue; } - if (!cmpxchg_relaxed(&pages[i], NULL, tagptr_cast_ptr(t))) + if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) continue; if (page) put_page(page); } - bl->compressed_pages += j; - bl->compressed_deficit = remaining - j; - if (standalone) - bl->role = Z_EROFS_VLE_WORK_PRIMARY; + if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ + clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; } /* called by erofs_shrinker to get rid of all compressed_pages */ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp) + struct erofs_workgroup *grp) { - struct z_erofs_vle_workgroup *const grp = - container_of(egrp, struct z_erofs_vle_workgroup, obj); + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); struct address_space *const mapping = MNGD_MAPPING(sbi); - const int clusterpages = erofs_clusterpages(sbi); + const unsigned int clusterpages = BIT(pcl->clusterbits); int i; /* @@ -224,18 +224,20 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, * therefore no need to worry about available decompression users. */ for (i = 0; i < clusterpages; ++i) { - struct page *page = grp->compressed_pages[i]; + struct page *page = pcl->compressed_pages[i]; - if (!page || page->mapping != mapping) + if (!page) continue; /* block other users from reclaiming or migrating the page */ if (!trylock_page(page)) return -EBUSY; - /* barrier is implied in the following 'unlock_page' */ - WRITE_ONCE(grp->compressed_pages[i], NULL); + if (unlikely(page->mapping != mapping)) + continue; + /* barrier is implied in the following 'unlock_page' */ + WRITE_ONCE(pcl->compressed_pages[i], NULL); set_page_private(page, 0); ClearPagePrivate(page); @@ -248,22 +250,21 @@ int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, int erofs_try_to_free_cached_page(struct address_space *mapping, struct page *page) { - struct erofs_sb_info *const sbi = EROFS_SB(mapping->host->i_sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - struct z_erofs_vle_workgroup *const grp = (void *)page_private(page); + struct z_erofs_pcluster *const pcl = (void *)page_private(page); + const unsigned int clusterpages = BIT(pcl->clusterbits); int ret = 0; /* 0 - busy */ - if (erofs_workgroup_try_to_freeze(&grp->obj, 1)) { + if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { unsigned int i; for (i = 0; i < clusterpages; ++i) { - if (grp->compressed_pages[i] == page) { - WRITE_ONCE(grp->compressed_pages[i], NULL); + if (pcl->compressed_pages[i] == page) { + WRITE_ONCE(pcl->compressed_pages[i], NULL); ret = 1; break; } } - erofs_workgroup_unfreeze(&grp->obj, 1); + erofs_workgroup_unfreeze(&pcl->obj, 1); if (ret) { ClearPagePrivate(page); @@ -273,361 +274,267 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, return ret; } #else -static void preload_compressed_pages(struct z_erofs_vle_work_builder *bl, +static void preload_compressed_pages(struct z_erofs_collector *clt, struct address_space *mc, - pgoff_t index, - unsigned int clusterpages, enum z_erofs_cache_alloctype type, - struct list_head *pagepool, - gfp_t gfp) + struct list_head *pagepool) { /* nowhere to load compressed pages from */ } #endif /* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static inline bool try_to_reuse_as_compressed_page( - struct z_erofs_vle_work_builder *b, - struct page *page) +static inline bool try_inplace_io(struct z_erofs_collector *clt, + struct page *page) { - while (b->compressed_deficit) { - --b->compressed_deficit; - if (!cmpxchg(b->compressed_pages++, NULL, page)) + struct z_erofs_pcluster *const pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + + while (clt->compressedpages < pcl->compressed_pages + clusterpages) { + if (!cmpxchg(clt->compressedpages++, NULL, page)) return true; } - return false; } -/* callers must be with work->lock held */ -static int z_erofs_vle_work_add_page( - struct z_erofs_vle_work_builder *builder, - struct page *page, - enum z_erofs_page_type type) +/* callers must be with collection lock held */ +static int z_erofs_attach_page(struct z_erofs_collector *clt, + struct page *page, + enum z_erofs_page_type type) { int ret; bool occupied; - /* give priority for the compressed data storage */ - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY && + /* give priority for inplaceio */ + if (clt->mode >= COLLECT_PRIMARY && type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && - try_to_reuse_as_compressed_page(builder, page)) + try_inplace_io(clt, page)) return 0; - ret = z_erofs_pagevec_enqueue(&builder->vector, + ret = z_erofs_pagevec_enqueue(&clt->vector, page, type, &occupied); - builder->work->vcnt += (unsigned int)ret; + clt->cl->vcnt += (unsigned int)ret; return ret ? 0 : -EAGAIN; } -static enum z_erofs_vle_work_role -try_to_claim_workgroup(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t *owned_head, - bool *hosted) +static enum z_erofs_collectmode +try_to_claim_pcluster(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t *owned_head) { - DBG_BUGON(*hosted); - - /* let's claim these following types of workgroup */ + /* let's claim these following types of pclusters */ retry: - if (grp->next == Z_EROFS_VLE_WORKGRP_NIL) { - /* type 1, nil workgroup */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_NIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_NIL) + if (pcl->next == Z_EROFS_PCLUSTER_NIL) { + /* type 1, nil pcluster */ + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_NIL, + *owned_head) != Z_EROFS_PCLUSTER_NIL) goto retry; - *owned_head = &grp->next; - *hosted = true; + *owned_head = &pcl->next; /* lucky, I am the followee :) */ - return Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - - } else if (grp->next == Z_EROFS_VLE_WORKGRP_TAIL) { + return COLLECT_PRIMARY_FOLLOWED; + } else if (pcl->next == Z_EROFS_PCLUSTER_TAIL) { /* * type 2, link to the end of a existing open chain, * be careful that its submission itself is governed * by the original owned chain. */ - if (cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - *owned_head) != Z_EROFS_VLE_WORKGRP_TAIL) + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + *owned_head) != Z_EROFS_PCLUSTER_TAIL) goto retry; - *owned_head = Z_EROFS_VLE_WORKGRP_TAIL; - return Z_EROFS_VLE_WORK_PRIMARY_HOOKED; + *owned_head = Z_EROFS_PCLUSTER_TAIL; + return COLLECT_PRIMARY_HOOKED; } - - return Z_EROFS_VLE_WORK_PRIMARY; /* :( better luck next time */ + return COLLECT_PRIMARY; /* :( better luck next time */ } -struct z_erofs_vle_work_finder { - struct super_block *sb; - pgoff_t idx; - unsigned int pageofs; - - struct z_erofs_vle_workgroup **grp_ret; - enum z_erofs_vle_work_role *role; - z_erofs_vle_owned_workgrp_t *owned_head; - bool *hosted; -}; - -static struct z_erofs_vle_work * -z_erofs_vle_work_lookup(const struct z_erofs_vle_work_finder *f) +static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { - bool tag, primary; - struct erofs_workgroup *egrp; - struct z_erofs_vle_workgroup *grp; - struct z_erofs_vle_work *work; - - egrp = erofs_find_workgroup(f->sb, f->idx, &tag); - if (!egrp) { - *f->grp_ret = NULL; + struct erofs_workgroup *grp; + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + unsigned int length; + bool tag; + + grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); + if (!grp) return NULL; - } - grp = container_of(egrp, struct z_erofs_vle_workgroup, obj); - *f->grp_ret = grp; + pcl = container_of(grp, struct z_erofs_pcluster, obj); + + cl = z_erofs_primarycollection(pcl); + if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { + DBG_BUGON(1); + return ERR_PTR(-EIO); + } - work = z_erofs_vle_grab_work(grp, f->pageofs); - /* if multiref is disabled, `primary' is always true */ - primary = true; + length = READ_ONCE(pcl->length); + if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { + if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { + DBG_BUGON(1); + return ERR_PTR(-EIO); + } + } else { + unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; - DBG_BUGON(work->pageofs != f->pageofs); + if (map->m_flags & EROFS_MAP_FULL_MAPPED) + llen |= Z_EROFS_PCLUSTER_FULL_LENGTH; - /* - * lock must be taken first to avoid grp->next == NIL between - * claiming workgroup and adding pages: - * grp->next != NIL - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(&work->lock) - * add all pages to pagevec - * - * [correct locking case 1]: - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[b]) mutex_lock(grp->work[c]) - * ... *role = SECONDARY - * add all pages to pagevec - * ... - * mutex_unlock(grp->work[c]) - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * - * [correct locking case 2]: - * mutex_lock(grp->work[b]) - * ... - * mutex_lock(grp->work[a]) - * ... - * mutex_lock(grp->work[c]) - * ... - * grp->next = NIL - * mutex_unlock_all - * mutex_lock(grp->work[a]) - * *role = PRIMARY_OWNER - * add all pages to pagevec - * ... - */ - mutex_lock(&work->lock); - - *f->hosted = false; - if (!primary) - *f->role = Z_EROFS_VLE_WORK_SECONDARY; - else /* claim the workgroup if possible */ - *f->role = try_to_claim_workgroup(grp, f->owned_head, - f->hosted); - return work; + while (llen > length && + length != cmpxchg_relaxed(&pcl->length, length, llen)) { + cpu_relax(); + length = READ_ONCE(pcl->length); + } + } + mutex_lock(&cl->lock); + clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); + clt->pcl = pcl; + clt->cl = cl; + return cl; } -static struct z_erofs_vle_work * -z_erofs_vle_work_register(const struct z_erofs_vle_work_finder *f, - struct erofs_map_blocks *map) +static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) { - bool gnew = false; - struct z_erofs_vle_workgroup *grp = *f->grp_ret; - struct z_erofs_vle_work *work; - - /* if multiref is disabled, grp should never be nullptr */ - if (unlikely(grp)) { - DBG_BUGON(1); - return ERR_PTR(-EINVAL); - } + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + int err; /* no available workgroup, let's allocate one */ - grp = kmem_cache_alloc(z_erofs_workgroup_cachep, GFP_NOFS); - if (unlikely(!grp)) + pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); + if (unlikely(!pcl)) return ERR_PTR(-ENOMEM); - init_always(grp); - grp->obj.index = f->idx; - grp->llen = map->m_llen; + init_always(pcl); + pcl->obj.index = map->m_pa >> PAGE_SHIFT; - z_erofs_vle_set_workgrp_fmt(grp, (map->m_flags & EROFS_MAP_ZIPPED) ? - Z_EROFS_VLE_WORKGRP_FMT_LZ4 : - Z_EROFS_VLE_WORKGRP_FMT_PLAIN); + pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | + (map->m_flags & EROFS_MAP_FULL_MAPPED ? + Z_EROFS_PCLUSTER_FULL_LENGTH : 0); - if (map->m_flags & EROFS_MAP_FULL_MAPPED) - grp->flags |= Z_EROFS_VLE_WORKGRP_FULL_LENGTH; + if (map->m_flags & EROFS_MAP_ZIPPED) + pcl->algorithmformat = Z_EROFS_COMPRESSION_LZ4; + else + pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; + + pcl->clusterbits = EROFS_V(inode)->z_physical_clusterbits[0]; + pcl->clusterbits -= PAGE_SHIFT; - /* new workgrps have been claimed as type 1 */ - WRITE_ONCE(grp->next, *f->owned_head); - /* primary and followed work for all new workgrps */ - *f->role = Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED; - /* it should be submitted by ourselves */ - *f->hosted = true; + /* new pclusters should be claimed as type 1, primary and followed */ + pcl->next = clt->owned_head; + clt->mode = COLLECT_PRIMARY_FOLLOWED; - gnew = true; - work = z_erofs_vle_grab_primary_work(grp); - work->pageofs = f->pageofs; + cl = z_erofs_primarycollection(pcl); + cl->pageofs = map->m_la & ~PAGE_MASK; /* * lock all primary followed works before visible to others - * and mutex_trylock *never* fails for a new workgroup. + * and mutex_trylock *never* fails for a new pcluster. */ - mutex_trylock(&work->lock); + mutex_trylock(&cl->lock); - if (gnew) { - int err = erofs_register_workgroup(f->sb, &grp->obj, 0); - - if (err) { - mutex_unlock(&work->lock); - kmem_cache_free(z_erofs_workgroup_cachep, grp); - return ERR_PTR(-EAGAIN); - } + err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); + if (err) { + mutex_unlock(&cl->lock); + kmem_cache_free(pcluster_cachep, pcl); + return ERR_PTR(-EAGAIN); } - - *f->owned_head = &grp->next; - *f->grp_ret = grp; - return work; + clt->owned_head = &pcl->next; + clt->pcl = pcl; + clt->cl = cl; + return cl; } -#define builder_is_hooked(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_HOOKED) +static int z_erofs_collector_begin(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct z_erofs_collection *cl; -#define builder_is_followed(builder) \ - ((builder)->role >= Z_EROFS_VLE_WORK_PRIMARY_FOLLOWED) + DBG_BUGON(clt->cl); -static int z_erofs_vle_work_iter_begin(struct z_erofs_vle_work_builder *builder, - struct super_block *sb, - struct erofs_map_blocks *map, - z_erofs_vle_owned_workgrp_t *owned_head) -{ - const unsigned int clusterpages = erofs_clusterpages(EROFS_SB(sb)); - struct z_erofs_vle_workgroup *grp; - const struct z_erofs_vle_work_finder finder = { - .sb = sb, - .idx = erofs_blknr(map->m_pa), - .pageofs = map->m_la & ~PAGE_MASK, - .grp_ret = &grp, - .role = &builder->role, - .owned_head = owned_head, - .hosted = &builder->hosted - }; - struct z_erofs_vle_work *work; - - DBG_BUGON(builder->work); - - /* must be Z_EROFS_WORK_TAIL or the next chained work */ - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_NIL); - DBG_BUGON(*owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - - DBG_BUGON(erofs_blkoff(map->m_pa)); + /* must be Z_EROFS_PCLUSTER_TAIL or pointed to previous collection */ + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_NIL); + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); -repeat: - work = z_erofs_vle_work_lookup(&finder); - if (work) { - unsigned int orig_llen; - - /* increase workgroup `llen' if needed */ - while ((orig_llen = READ_ONCE(grp->llen)) < map->m_llen && - orig_llen != cmpxchg_relaxed(&grp->llen, - orig_llen, map->m_llen)) - cpu_relax(); - goto got_it; + if (!PAGE_ALIGNED(map->m_pa)) { + DBG_BUGON(1); + return -EINVAL; } - work = z_erofs_vle_work_register(&finder, map); - if (unlikely(work == ERR_PTR(-EAGAIN))) - goto repeat; - - if (IS_ERR(work)) - return PTR_ERR(work); -got_it: - z_erofs_pagevec_ctor_init(&builder->vector, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, work->vcnt); +repeat: + cl = cllookup(clt, inode, map); + if (!cl) { + cl = clregister(clt, inode, map); - if (builder->role >= Z_EROFS_VLE_WORK_PRIMARY) { - /* enable possibly in-place decompression */ - builder->compressed_pages = grp->compressed_pages; - builder->compressed_deficit = clusterpages; - } else { - builder->compressed_pages = NULL; - builder->compressed_deficit = 0; + if (unlikely(cl == ERR_PTR(-EAGAIN))) + goto repeat; } - builder->grp = grp; - builder->work = work; + if (IS_ERR(cl)) + return PTR_ERR(cl); + + z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, + cl->pagevec, cl->vcnt); + + clt->compressedpages = clt->pcl->compressed_pages; + if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ + clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; return 0; } /* - * keep in mind that no referenced workgroups will be freed - * only after a RCU grace period, so rcu_read_lock() could - * prevent a workgroup from being freed. + * keep in mind that no referenced pclusters will be freed + * only after a RCU grace period. */ static void z_erofs_rcu_callback(struct rcu_head *head) { - struct z_erofs_vle_work *work = container_of(head, - struct z_erofs_vle_work, rcu); - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); + struct z_erofs_collection *const cl = + container_of(head, struct z_erofs_collection, rcu); - kmem_cache_free(z_erofs_workgroup_cachep, grp); + kmem_cache_free(pcluster_cachep, + container_of(cl, struct z_erofs_pcluster, + primary_collection)); } void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) { - struct z_erofs_vle_workgroup *const vgrp = container_of(grp, - struct z_erofs_vle_workgroup, obj); - struct z_erofs_vle_work *const work = &vgrp->work; + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + struct z_erofs_collection *const cl = z_erofs_primarycollection(pcl); - call_rcu(&work->rcu, z_erofs_rcu_callback); + call_rcu(&cl->rcu, z_erofs_rcu_callback); } -static void -__z_erofs_vle_work_release(struct z_erofs_vle_workgroup *grp, - struct z_erofs_vle_work *work __maybe_unused) +static void z_erofs_collection_put(struct z_erofs_collection *cl) { - erofs_workgroup_put(&grp->obj); -} + struct z_erofs_pcluster *const pcl = + container_of(cl, struct z_erofs_pcluster, primary_collection); -static void z_erofs_vle_work_release(struct z_erofs_vle_work *work) -{ - struct z_erofs_vle_workgroup *grp = - z_erofs_vle_work_workgroup(work, true); - - __z_erofs_vle_work_release(grp, work); + erofs_workgroup_put(&pcl->obj); } -static inline bool -z_erofs_vle_work_iter_end(struct z_erofs_vle_work_builder *builder) +static bool z_erofs_collector_end(struct z_erofs_collector *clt) { - struct z_erofs_vle_work *work = builder->work; + struct z_erofs_collection *cl = clt->cl; - if (!work) + if (!cl) return false; - z_erofs_pagevec_ctor_exit(&builder->vector, false); - mutex_unlock(&work->lock); + z_erofs_pagevec_ctor_exit(&clt->vector, false); + mutex_unlock(&cl->lock); /* - * if all pending pages are added, don't hold work reference - * any longer if the current work isn't hosted by ourselves. + * if all pending pages are added, don't hold its reference + * any longer if the pcluster isn't hosted by ourselves. */ - if (!builder->hosted) - __z_erofs_vle_work_release(builder->grp, work); + if (clt->mode < COLLECT_PRIMARY_FOLLOWED_NOINPLACE) + z_erofs_collection_put(cl); - builder->work = NULL; - builder->grp = NULL; + clt->cl = NULL; return true; } @@ -640,33 +547,9 @@ static inline struct page *__stagingpage_alloc(struct list_head *pagepool, return page; } -struct z_erofs_vle_frontend { - struct inode *const inode; - - struct z_erofs_vle_work_builder builder; - struct erofs_map_blocks map; - - z_erofs_vle_owned_workgrp_t owned_head; - - /* used for applying cache strategy on the fly */ - bool backmost; - erofs_off_t headoffset; -}; - -#define VLE_FRONTEND_INIT(__i) { \ - .inode = __i, \ - .map = { \ - .m_llen = 0, \ - .m_plen = 0, \ - .mpage = NULL \ - }, \ - .builder = VLE_WORK_BUILDER_INIT(), \ - .owned_head = Z_EROFS_VLE_WORKGRP_TAIL, \ - .backmost = true, } - #ifdef EROFS_FS_HAS_MANAGED_CACHE -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) +static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + erofs_off_t la) { if (fe->backmost) return true; @@ -677,25 +560,23 @@ should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) return false; } #else -static inline bool -should_alloc_managed_pages(struct z_erofs_vle_frontend *fe, erofs_off_t la) +static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + erofs_off_t la) { return false; } #endif -static int z_erofs_do_read_page(struct z_erofs_vle_frontend *fe, +static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, struct page *page, - struct list_head *page_pool) + struct list_head *pagepool) { - struct super_block *const sb = fe->inode->i_sb; - struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + struct inode *const inode = fe->inode; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); struct erofs_map_blocks *const map = &fe->map; - struct z_erofs_vle_work_builder *const builder = &fe->builder; + struct z_erofs_collector *const clt = &fe->clt; const loff_t offset = page_offset(page); - - bool tight = builder_is_hooked(builder); - struct z_erofs_vle_work *work = builder->work; + bool tight = (clt->mode >= COLLECT_PRIMARY_HOOKED); enum z_erofs_cache_alloctype cache_strategy; enum z_erofs_page_type page_type; @@ -713,8 +594,8 @@ repeat: /* lucky, within the range of the current map_blocks */ if (offset + cur >= map->m_la && offset + cur < map->m_la + map->m_llen) { - /* didn't get a valid unzip work previously (very rare) */ - if (!builder->work) + /* didn't get a valid collection previously (very rare) */ + if (!clt->cl) goto restart_now; goto hitted; } @@ -722,12 +603,12 @@ repeat: /* go ahead the next map_blocks */ debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); - if (z_erofs_vle_work_iter_end(builder)) + if (z_erofs_collector_end(clt)) fe->backmost = false; map->m_la = offset + cur; map->m_llen = 0; - err = z_erofs_map_blocks_iter(fe->inode, map, 0); + err = z_erofs_map_blocks_iter(inode, map, 0); if (unlikely(err)) goto err_out; @@ -735,10 +616,7 @@ restart_now: if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) goto hitted; - DBG_BUGON(map->m_plen != 1 << sbi->clusterbits); - DBG_BUGON(erofs_blkoff(map->m_pa)); - - err = z_erofs_vle_work_iter_begin(builder, sb, map, &fe->owned_head); + err = z_erofs_collector_begin(clt, inode, map); if (unlikely(err)) goto err_out; @@ -748,13 +626,10 @@ restart_now: else cache_strategy = DONTALLOC; - preload_compressed_pages(builder, MNGD_MAPPING(sbi), - map->m_pa / PAGE_SIZE, - map->m_plen / PAGE_SIZE, - cache_strategy, page_pool, GFP_KERNEL); + preload_compressed_pages(clt, MNGD_MAPPING(sbi), + cache_strategy, pagepool); - tight &= builder_is_hooked(builder); - work = builder->work; + tight &= (clt->mode >= COLLECT_PRIMARY_HOOKED); hitted: cur = end - min_t(unsigned int, offset + end - map->m_la, end); if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { @@ -769,17 +644,17 @@ hitted: Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); if (cur) - tight &= builder_is_followed(builder); + tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); retry: - err = z_erofs_vle_work_add_page(builder, page, page_type); + err = z_erofs_attach_page(clt, page, page_type); /* should allocate an additional staging page for pagevec */ if (err == -EAGAIN) { struct page *const newpage = - __stagingpage_alloc(page_pool, GFP_NOFS); + __stagingpage_alloc(pagepool, GFP_NOFS); - err = z_erofs_vle_work_add_page(builder, newpage, - Z_EROFS_PAGE_TYPE_EXCLUSIVE); + err = z_erofs_attach_page(clt, newpage, + Z_EROFS_PAGE_TYPE_EXCLUSIVE); if (likely(!err)) goto retry; } @@ -787,15 +662,14 @@ retry: if (unlikely(err)) goto err_out; - index = page->index - map->m_la / PAGE_SIZE; + index = page->index - (map->m_la >> PAGE_SHIFT); - /* FIXME! avoid the last relundant fixup & endio */ z_erofs_onlinepage_fixup(page, index, true); /* bump up the number of spiltted parts of a page */ ++spiltted; /* also update nr_pages */ - work->nr_pages = max_t(pgoff_t, work->nr_pages, index + 1); + clt->cl->nr_pages = max_t(pgoff_t, clt->cl->nr_pages, index + 1); next_part: /* can be used for verification */ map->m_llen = offset + cur - map->m_la; @@ -805,7 +679,6 @@ next_part: goto repeat; out: - /* FIXME! avoid the last relundant fixup & endio */ z_erofs_onlinepage_endio(page); debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", @@ -821,7 +694,7 @@ err_out: static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) { tagptr1_t t = tagptr_init(tagptr1_t, ptr); - struct z_erofs_vle_unzip_io *io = tagptr_unfold_ptr(t); + struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); bool background = tagptr_unfold_tags(t); if (!background) { @@ -878,45 +751,38 @@ static inline void z_erofs_vle_read_endio(struct bio *bio) bio_put(bio); } -static struct page *z_pagemap_global[Z_EROFS_VLE_VMAP_GLOBAL_PAGES]; -static DEFINE_MUTEX(z_pagemap_global_lock); - -static int z_erofs_vle_unzip(struct super_block *sb, - struct z_erofs_vle_workgroup *grp, - struct list_head *page_pool) +static int z_erofs_decompress_pcluster(struct super_block *sb, + struct z_erofs_pcluster *pcl, + struct list_head *pagepool) { struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - + const unsigned int clusterpages = BIT(pcl->clusterbits); struct z_erofs_pagevec_ctor ctor; - unsigned int nr_pages; - unsigned int sparsemem_pages = 0; - struct page *pages_onstack[Z_EROFS_VLE_VMAP_ONSTACK_PAGES]; + unsigned int i, outputsize, llen, nr_pages; + struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; struct page **pages, **compressed_pages, *page; - unsigned int algorithm; - unsigned int i, outputsize; enum z_erofs_page_type page_type; bool overlapped, partial; - struct z_erofs_vle_work *work; + struct z_erofs_collection *cl; int err; might_sleep(); - work = z_erofs_vle_grab_primary_work(grp); - DBG_BUGON(!READ_ONCE(work->nr_pages)); + cl = z_erofs_primarycollection(pcl); + DBG_BUGON(!READ_ONCE(cl->nr_pages)); - mutex_lock(&work->lock); - nr_pages = work->nr_pages; + mutex_lock(&cl->lock); + nr_pages = cl->nr_pages; - if (likely(nr_pages <= Z_EROFS_VLE_VMAP_ONSTACK_PAGES)) + if (likely(nr_pages <= Z_EROFS_VMAP_ONSTACK_PAGES)) { pages = pages_onstack; - else if (nr_pages <= Z_EROFS_VLE_VMAP_GLOBAL_PAGES && - mutex_trylock(&z_pagemap_global_lock)) + } else if (nr_pages <= Z_EROFS_VMAP_GLOBAL_PAGES && + mutex_trylock(&z_pagemap_global_lock)) { pages = z_pagemap_global; - else { + } else { gfp_t gfp_flags = GFP_KERNEL; - if (nr_pages > Z_EROFS_VLE_VMAP_GLOBAL_PAGES) + if (nr_pages > Z_EROFS_VMAP_GLOBAL_PAGES) gfp_flags |= __GFP_NOFAIL; pages = kvmalloc_array(nr_pages, sizeof(struct page *), @@ -933,9 +799,9 @@ static int z_erofs_vle_unzip(struct super_block *sb, pages[i] = NULL; z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, - work->pagevec, 0); + cl->pagevec, 0); - for (i = 0; i < work->vcnt; ++i) { + for (i = 0; i < cl->vcnt; ++i) { unsigned int pagenr; page = z_erofs_pagevec_dequeue(&ctor, &page_type); @@ -944,7 +810,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, DBG_BUGON(!page); DBG_BUGON(!page->mapping); - if (z_erofs_put_stagingpage(page_pool, page)) + if (z_erofs_put_stagingpage(pagepool, page)) continue; if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) @@ -957,12 +823,10 @@ static int z_erofs_vle_unzip(struct super_block *sb, pages[pagenr] = page; } - sparsemem_pages = i; - z_erofs_pagevec_ctor_exit(&ctor, true); overlapped = false; - compressed_pages = grp->compressed_pages; + compressed_pages = pcl->compressed_pages; err = 0; for (i = 0; i < clusterpages; ++i) { @@ -989,7 +853,6 @@ static int z_erofs_vle_unzip(struct super_block *sb, DBG_BUGON(pagenr >= nr_pages); DBG_BUGON(pages[pagenr]); - ++sparsemem_pages; pages[pagenr] = page; overlapped = true; @@ -1005,30 +868,26 @@ static int z_erofs_vle_unzip(struct super_block *sb, if (unlikely(err)) goto out; - if (nr_pages << PAGE_SHIFT >= work->pageofs + grp->llen) { - outputsize = grp->llen; - partial = !(grp->flags & Z_EROFS_VLE_WORKGRP_FULL_LENGTH); + llen = pcl->length >> Z_EROFS_PCLUSTER_LENGTH_BIT; + if (nr_pages << PAGE_SHIFT >= cl->pageofs + llen) { + outputsize = llen; + partial = !(pcl->length & Z_EROFS_PCLUSTER_FULL_LENGTH); } else { - outputsize = (nr_pages << PAGE_SHIFT) - work->pageofs; + outputsize = (nr_pages << PAGE_SHIFT) - cl->pageofs; partial = true; } - if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) - algorithm = Z_EROFS_COMPRESSION_SHIFTED; - else - algorithm = Z_EROFS_COMPRESSION_LZ4; - err = z_erofs_decompress(&(struct z_erofs_decompress_req) { .sb = sb, .in = compressed_pages, .out = pages, - .pageofs_out = work->pageofs, + .pageofs_out = cl->pageofs, .inputsize = PAGE_SIZE, .outputsize = outputsize, - .alg = algorithm, + .alg = pcl->algorithmformat, .inplace_io = overlapped, .partial_decoding = partial - }, page_pool); + }, pagepool); out: /* must handle all compressed pages before endding pages */ @@ -1039,7 +898,7 @@ out: continue; /* recycle all individual staging pages */ - (void)z_erofs_put_stagingpage(page_pool, page); + (void)z_erofs_put_stagingpage(pagepool, page); WRITE_ONCE(compressed_pages[i], NULL); } @@ -1052,7 +911,7 @@ out: DBG_BUGON(!page->mapping); /* recycle all individual staging pages */ - if (z_erofs_put_stagingpage(page_pool, page)) + if (z_erofs_put_stagingpage(pagepool, page)) continue; if (unlikely(err < 0)) @@ -1066,65 +925,63 @@ out: else if (unlikely(pages != pages_onstack)) kvfree(pages); - work->nr_pages = 0; - work->vcnt = 0; + cl->nr_pages = 0; + cl->vcnt = 0; - /* all work locks MUST be taken before the following line */ + /* all cl locks MUST be taken before the following line */ + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_NIL); - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_NIL); + /* all cl locks SHOULD be released right now */ + mutex_unlock(&cl->lock); - /* all work locks SHOULD be released right now */ - mutex_unlock(&work->lock); - - z_erofs_vle_work_release(work); + z_erofs_collection_put(cl); return err; } static void z_erofs_vle_unzip_all(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - struct list_head *page_pool) + struct z_erofs_unzip_io *io, + struct list_head *pagepool) { - z_erofs_vle_owned_workgrp_t owned = io->head; + z_erofs_next_pcluster_t owned = io->head; - while (owned != Z_EROFS_VLE_WORKGRP_TAIL_CLOSED) { - struct z_erofs_vle_workgroup *grp; + while (owned != Z_EROFS_PCLUSTER_TAIL_CLOSED) { + struct z_erofs_pcluster *pcl; /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_TAIL); + DBG_BUGON(owned == Z_EROFS_PCLUSTER_TAIL); /* no possible that 'owned' equals NULL */ - DBG_BUGON(owned == Z_EROFS_VLE_WORKGRP_NIL); + DBG_BUGON(owned == Z_EROFS_PCLUSTER_NIL); - grp = container_of(owned, struct z_erofs_vle_workgroup, next); - owned = READ_ONCE(grp->next); + pcl = container_of(owned, struct z_erofs_pcluster, next); + owned = READ_ONCE(pcl->next); - z_erofs_vle_unzip(sb, grp, page_pool); + z_erofs_decompress_pcluster(sb, pcl, pagepool); } } static void z_erofs_vle_unzip_wq(struct work_struct *work) { - struct z_erofs_vle_unzip_io_sb *iosb = container_of(work, - struct z_erofs_vle_unzip_io_sb, io.u.work); - LIST_HEAD(page_pool); + struct z_erofs_unzip_io_sb *iosb = + container_of(work, struct z_erofs_unzip_io_sb, io.u.work); + LIST_HEAD(pagepool); - DBG_BUGON(iosb->io.head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &page_pool); + DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); - put_pages_list(&page_pool); + put_pages_list(&pagepool); kvfree(iosb); } -static struct page * -pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, - unsigned int nr, - struct list_head *pagepool, - struct address_space *mc, - gfp_t gfp) +static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, + unsigned int nr, + struct list_head *pagepool, + struct address_space *mc, + gfp_t gfp) { /* determined at compile time to avoid too many #ifdefs */ const bool nocache = __builtin_constant_p(mc) ? !mc : false; - const pgoff_t index = grp->obj.index; + const pgoff_t index = pcl->obj.index; bool tocache = false; struct address_space *mapping; @@ -1134,7 +991,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, int justfound; repeat: - page = READ_ONCE(grp->compressed_pages[nr]); + page = READ_ONCE(pcl->compressed_pages[nr]); oldpage = page; if (!page) @@ -1186,7 +1043,7 @@ repeat: /* the page is still in manage cache */ if (page->mapping == mc) { - WRITE_ONCE(grp->compressed_pages[nr], page); + WRITE_ONCE(pcl->compressed_pages[nr], page); ClearPageError(page); if (!PagePrivate(page)) { @@ -1198,7 +1055,7 @@ repeat: DBG_BUGON(!justfound); justfound = 0; - set_page_private(page, (unsigned long)grp); + set_page_private(page, (unsigned long)pcl); SetPagePrivate(page); } @@ -1222,7 +1079,7 @@ repeat: put_page(page); out_allocpage: page = __stagingpage_alloc(pagepool, gfp); - if (oldpage != cmpxchg(&grp->compressed_pages[nr], oldpage, page)) { + if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { list_add(&page->lru, pagepool); cpu_relax(); goto repeat; @@ -1234,18 +1091,17 @@ out_allocpage: goto out; } - set_page_private(page, (unsigned long)grp); + set_page_private(page, (unsigned long)pcl); SetPagePrivate(page); out: /* the only exit (for tracing and debugging) */ return page; } -static struct z_erofs_vle_unzip_io * -jobqueue_init(struct super_block *sb, - struct z_erofs_vle_unzip_io *io, - bool foreground) +static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, + struct z_erofs_unzip_io *io, + bool foreground) { - struct z_erofs_vle_unzip_io_sb *iosb; + struct z_erofs_unzip_io_sb *iosb; if (foreground) { /* waitqueue available for foreground io */ @@ -1264,11 +1120,11 @@ jobqueue_init(struct super_block *sb, iosb->sb = sb; INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); out: - io->head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; + io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; return io; } -/* define workgroup jobqueue types */ +/* define decompression jobqueue types */ enum { #ifdef EROFS_FS_HAS_MANAGED_CACHE JQ_BYPASS, @@ -1278,15 +1134,15 @@ enum { }; static void *jobqueueset_init(struct super_block *sb, - z_erofs_vle_owned_workgrp_t qtail[], - struct z_erofs_vle_unzip_io *q[], - struct z_erofs_vle_unzip_io *fgq, + z_erofs_next_pcluster_t qtail[], + struct z_erofs_unzip_io *q[], + struct z_erofs_unzip_io *fgq, bool forcefg) { #ifdef EROFS_FS_HAS_MANAGED_CACHE /* * if managed cache is enabled, bypass jobqueue is needed, - * no need to read from device for all workgroups in this queue. + * no need to read from device for all pclusters in this queue. */ q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; @@ -1299,26 +1155,26 @@ static void *jobqueueset_init(struct super_block *sb, } #ifdef EROFS_FS_HAS_MANAGED_CACHE -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) +static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t qtail[], + z_erofs_next_pcluster_t owned_head) { - z_erofs_vle_owned_workgrp_t *const submit_qtail = qtail[JQ_SUBMIT]; - z_erofs_vle_owned_workgrp_t *const bypass_qtail = qtail[JQ_BYPASS]; + z_erofs_next_pcluster_t *const submit_qtail = qtail[JQ_SUBMIT]; + z_erofs_next_pcluster_t *const bypass_qtail = qtail[JQ_BYPASS]; - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - if (owned_head == Z_EROFS_VLE_WORKGRP_TAIL) - owned_head = Z_EROFS_VLE_WORKGRP_TAIL_CLOSED; + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + if (owned_head == Z_EROFS_PCLUSTER_TAIL) + owned_head = Z_EROFS_PCLUSTER_TAIL_CLOSED; - WRITE_ONCE(grp->next, Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_TAIL_CLOSED); WRITE_ONCE(*submit_qtail, owned_head); - WRITE_ONCE(*bypass_qtail, &grp->next); + WRITE_ONCE(*bypass_qtail, &pcl->next); - qtail[JQ_BYPASS] = &grp->next; + qtail[JQ_BYPASS] = &pcl->next; } -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], unsigned int nr_bios, bool force_fg) { @@ -1329,21 +1185,19 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], if (force_fg || nr_bios) return false; - kvfree(container_of(q[JQ_SUBMIT], - struct z_erofs_vle_unzip_io_sb, - io)); + kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); return true; } #else -static void move_to_bypass_jobqueue(struct z_erofs_vle_workgroup *grp, - z_erofs_vle_owned_workgrp_t qtail[], - z_erofs_vle_owned_workgrp_t owned_head) +static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t qtail[], + z_erofs_next_pcluster_t owned_head) { /* impossible to bypass submission for managed cache disabled */ DBG_BUGON(1); } -static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], unsigned int nr_bios, bool force_fg) { @@ -1354,17 +1208,14 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_vle_unzip_io *q[], #endif static bool z_erofs_vle_submit_all(struct super_block *sb, - z_erofs_vle_owned_workgrp_t owned_head, + z_erofs_next_pcluster_t owned_head, struct list_head *pagepool, - struct z_erofs_vle_unzip_io *fgq, + struct z_erofs_unzip_io *fgq, bool force_fg) { - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = erofs_clusterpages(sbi); - const gfp_t gfp = GFP_NOFS; - - z_erofs_vle_owned_workgrp_t qtail[NR_JOBQUEUES]; - struct z_erofs_vle_unzip_io *q[NR_JOBQUEUES]; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; + struct z_erofs_unzip_io *q[NR_JOBQUEUES]; struct bio *bio; void *bi_private; /* since bio will be NULL, no need to initialize last_index */ @@ -1372,7 +1223,7 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, bool force_submit = false; unsigned int nr_bios; - if (unlikely(owned_head == Z_EROFS_VLE_WORKGRP_TAIL)) + if (unlikely(owned_head == Z_EROFS_PCLUSTER_TAIL)) return false; force_submit = false; @@ -1384,29 +1235,32 @@ static bool z_erofs_vle_submit_all(struct super_block *sb, q[JQ_SUBMIT]->head = owned_head; do { - struct z_erofs_vle_workgroup *grp; + struct z_erofs_pcluster *pcl; + unsigned int clusterpages; pgoff_t first_index; struct page *page; unsigned int i = 0, bypass = 0; int err; /* no possible 'owned_head' equals the following */ - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); - DBG_BUGON(owned_head == Z_EROFS_VLE_WORKGRP_NIL); + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_NIL); + + pcl = container_of(owned_head, struct z_erofs_pcluster, next); - grp = container_of(owned_head, - struct z_erofs_vle_workgroup, next); + clusterpages = BIT(pcl->clusterbits); /* close the main owned chain at first */ - owned_head = cmpxchg(&grp->next, Z_EROFS_VLE_WORKGRP_TAIL, - Z_EROFS_VLE_WORKGRP_TAIL_CLOSED); + owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + Z_EROFS_PCLUSTER_TAIL_CLOSED); - first_index = grp->obj.index; + first_index = pcl->obj.index; force_submit |= (first_index != last_index + 1); repeat: - page = pickup_page_for_submission(grp, i, pagepool, - MNGD_MAPPING(sbi), gfp); + page = pickup_page_for_submission(pcl, i, pagepool, + MNGD_MAPPING(sbi), + GFP_NOFS); if (!page) { force_submit = true; ++bypass; @@ -1437,10 +1291,10 @@ skippage: goto repeat; if (bypass < clusterpages) - qtail[JQ_SUBMIT] = &grp->next; + qtail[JQ_SUBMIT] = &pcl->next; else - move_to_bypass_jobqueue(grp, qtail, owned_head); - } while (owned_head != Z_EROFS_VLE_WORKGRP_TAIL); + move_to_bypass_jobqueue(pcl, qtail, owned_head); + } while (owned_head != Z_EROFS_PCLUSTER_TAIL); if (bio) __submit_bio(bio, REQ_OP_READ, 0); @@ -1452,17 +1306,19 @@ skippage: return true; } -static void z_erofs_submit_and_unzip(struct z_erofs_vle_frontend *f, +static void z_erofs_submit_and_unzip(struct super_block *sb, + struct z_erofs_collector *clt, struct list_head *pagepool, bool force_fg) { - struct super_block *sb = f->inode->i_sb; - struct z_erofs_vle_unzip_io io[NR_JOBQUEUES]; + struct z_erofs_unzip_io io[NR_JOBQUEUES]; - if (!z_erofs_vle_submit_all(sb, f->owned_head, pagepool, io, force_fg)) + if (!z_erofs_vle_submit_all(sb, clt->owned_head, + pagepool, io, force_fg)) return; #ifdef EROFS_FS_HAS_MANAGED_CACHE + /* decompress no I/O pclusters immediately */ z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); #endif if (!force_fg) @@ -1480,7 +1336,7 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, struct page *page) { struct inode *const inode = page->mapping->host; - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); int err; LIST_HEAD(pagepool); @@ -1489,14 +1345,14 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; err = z_erofs_do_read_page(&f, page, &pagepool); - (void)z_erofs_vle_work_iter_end(&f.builder); + (void)z_erofs_collector_end(&f.clt); if (err) { errln("%s, failed to read, err [%d]", __func__, err); goto out; } - z_erofs_submit_and_unzip(&f, &pagepool, true); + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); out: if (f.map.mpage) put_page(f.map.mpage); @@ -1521,7 +1377,7 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, struct erofs_sb_info *const sbi = EROFS_I_SB(inode); bool sync = should_decompress_synchronously(sbi, nr_pages); - struct z_erofs_vle_frontend f = VLE_FRONTEND_INIT(inode); + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); struct page *head = NULL; LIST_HEAD(pagepool); @@ -1567,13 +1423,12 @@ static int z_erofs_vle_normalaccess_readpages(struct file *filp, errln("%s, readahead error at page %lu of nid %llu", __func__, page->index, vi->nid); } - put_page(page); } - (void)z_erofs_vle_work_iter_end(&f.builder); + (void)z_erofs_collector_end(&f.clt); - z_erofs_submit_and_unzip(&f, &pagepool, sync); + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); if (f.map.mpage) put_page(f.map.mpage); diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h index 6574d43ba877..1f51d80fa89f 100644 --- a/drivers/staging/erofs/zdata.h +++ b/drivers/staging/erofs/zdata.h @@ -18,80 +18,77 @@ * Structure fields follow one of the following exclusion rules. * * I: Modifiable by initialization/destruction paths and read-only - * for everyone else. + * for everyone else; * + * L: Field should be protected by pageset lock; + * + * A: Field should be accessed / updated in atomic for parallelized code. */ - -struct z_erofs_vle_work { +struct z_erofs_collection { struct mutex lock; - /* I: decompression offset in page */ + /* I: page offset of start position of decompression */ unsigned short pageofs; + + /* L: maximum relative page index in pagevec[] */ unsigned short nr_pages; - /* L: queued pages in pagevec[] */ + /* L: total number of pages in pagevec[] */ unsigned int vcnt; union { - /* L: pagevec */ + /* L: inline a certain number of pagevecs for bootstrap */ erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; + + /* I: can be used to free the pcluster by RCU. */ struct rcu_head rcu; }; }; -#define Z_EROFS_VLE_WORKGRP_FMT_PLAIN 0 -#define Z_EROFS_VLE_WORKGRP_FMT_LZ4 1 -#define Z_EROFS_VLE_WORKGRP_FMT_MASK 1 -#define Z_EROFS_VLE_WORKGRP_FULL_LENGTH 2 +#define Z_EROFS_PCLUSTER_FULL_LENGTH 0x00000001 +#define Z_EROFS_PCLUSTER_LENGTH_BIT 1 -typedef void *z_erofs_vle_owned_workgrp_t; +/* + * let's leave a type here in case of introducing + * another tagged pointer later. + */ +typedef void *z_erofs_next_pcluster_t; -struct z_erofs_vle_workgroup { +struct z_erofs_pcluster { struct erofs_workgroup obj; - struct z_erofs_vle_work work; + struct z_erofs_collection primary_collection; - /* point to next owned_workgrp_t */ - z_erofs_vle_owned_workgrp_t next; + /* A: point to next chained pcluster or TAILs */ + z_erofs_next_pcluster_t next; - /* compressed pages (including multi-usage pages) */ + /* A: compressed pages (including multi-usage pages) */ struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; - unsigned int llen, flags; + + /* A: lower limit of decompressed length and if full length or not */ + unsigned int length; + + /* I: compression algorithm format */ + unsigned char algorithmformat; + /* I: bit shift of physical cluster size */ + unsigned char clusterbits; }; +#define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) + /* let's avoid the valid 32-bit kernel addresses */ /* the chained workgroup has't submitted io (still open) */ -#define Z_EROFS_VLE_WORKGRP_TAIL ((void *)0x5F0ECAFE) +#define Z_EROFS_PCLUSTER_TAIL ((void *)0x5F0ECAFE) /* the chained workgroup has already submitted io */ -#define Z_EROFS_VLE_WORKGRP_TAIL_CLOSED ((void *)0x5F0EDEAD) +#define Z_EROFS_PCLUSTER_TAIL_CLOSED ((void *)0x5F0EDEAD) -#define Z_EROFS_VLE_WORKGRP_NIL (NULL) +#define Z_EROFS_PCLUSTER_NIL (NULL) -#define z_erofs_vle_workgrp_fmt(grp) \ - ((grp)->flags & Z_EROFS_VLE_WORKGRP_FMT_MASK) +#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) -static inline void z_erofs_vle_set_workgrp_fmt( - struct z_erofs_vle_workgroup *grp, - unsigned int fmt) -{ - grp->flags = fmt | (grp->flags & ~Z_EROFS_VLE_WORKGRP_FMT_MASK); -} - - -/* definitions if multiref is disabled */ -#define z_erofs_vle_grab_primary_work(grp) (&(grp)->work) -#define z_erofs_vle_grab_work(grp, pageofs) (&(grp)->work) -#define z_erofs_vle_work_workgroup(wrk, primary) \ - ((primary) ? container_of(wrk, \ - struct z_erofs_vle_workgroup, work) : \ - ({ BUG(); (void *)NULL; })) - - -#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_vle_workgroup) - -struct z_erofs_vle_unzip_io { +struct z_erofs_unzip_io { atomic_t pending_bios; - z_erofs_vle_owned_workgrp_t head; + z_erofs_next_pcluster_t head; union { wait_queue_head_t wait; @@ -99,8 +96,8 @@ struct z_erofs_vle_unzip_io { } u; }; -struct z_erofs_vle_unzip_io_sb { - struct z_erofs_vle_unzip_io io; +struct z_erofs_unzip_io_sb { + struct z_erofs_unzip_io io; struct super_block *sb; }; @@ -117,8 +114,8 @@ static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, struct page *page) { return false; } #endif /* !EROFS_FS_HAS_MANAGED_CACHE */ -#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 -#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) +#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 +#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) #define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) /* @@ -193,13 +190,12 @@ static inline void z_erofs_onlinepage_endio(struct page *page) SetPageUptodate(page); unlock_page(page); } - debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); } -#define Z_EROFS_VLE_VMAP_ONSTACK_PAGES \ +#define Z_EROFS_VMAP_ONSTACK_PAGES \ min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) -#define Z_EROFS_VLE_VMAP_GLOBAL_PAGES 2048 +#define Z_EROFS_VMAP_GLOBAL_PAGES 2048 #endif -- cgit v1.2.3-59-g8ed1b From eace994a116c9704738be3388f5777c740d9558d Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:48 +0800 Subject: staging: erofs: remove clusterbits in sbi clustersize can now be set on per-file basis rather than per-filesystem basis. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-19-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/internal.h | 5 ----- drivers/staging/erofs/super.c | 9 --------- drivers/staging/erofs/zmap.c | 3 +-- 3 files changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index a631acd0dc62..3176c350779e 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -77,8 +77,6 @@ struct erofs_sb_info { struct list_head list; struct mutex umount_mutex; - /* cluster size in bit shift */ - unsigned char clusterbits; /* the dedicated workstation for compression */ struct radix_tree_root workstn_tree; @@ -248,9 +246,6 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) /* hard limit of pages per compressed cluster */ #define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) #define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES - -/* page count of a compressed cluster */ -#define erofs_clusterpages(sbi) ((1 << (sbi)->clusterbits) / PAGE_SIZE) #else #define EROFS_PCPUBUF_NR_PAGES 0 #endif /* !CONFIG_EROFS_FS_ZIP */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index af5d87793e4d..dad5a3137988 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -124,15 +124,6 @@ static int superblock_read(struct super_block *sb) sbi->xattr_blkaddr = le32_to_cpu(layout->xattr_blkaddr); #endif sbi->islotbits = ffs(sizeof(struct erofs_inode_v1)) - 1; -#ifdef CONFIG_EROFS_FS_ZIP - /* TODO: clusterbits should be related to inode */ - sbi->clusterbits = blkszbits; - - if (1 << (sbi->clusterbits - PAGE_SHIFT) > Z_EROFS_CLUSTER_MAX_PAGES) - errln("clusterbits %u is not supported on this kernel", - sbi->clusterbits); -#endif - sbi->root_nid = le16_to_cpu(layout->root_nid); sbi->inos = le64_to_cpu(layout->inos); diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 205e884ca4e0..aeed5c674d9e 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -13,13 +13,12 @@ int z_erofs_fill_inode(struct inode *inode) { struct erofs_vnode *const vi = EROFS_V(inode); - struct super_block *const sb = inode->i_sb; if (vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { vi->z_advise = 0; vi->z_algorithmtype[0] = 0; vi->z_algorithmtype[1] = 0; - vi->z_logical_clusterbits = EROFS_SB(sb)->clusterbits; + vi->z_logical_clusterbits = LOG_BLOCK_SIZE; vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); -- cgit v1.2.3-59-g8ed1b From 4279f3f9889f26bcdc4d35c0bf868a08e09470c7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:49 +0800 Subject: staging: erofs: turn cache strategies into mount options Kill all kconfig cache strategies and turn them into mount options "cache_strategy={disable|readahead|readaround}". As the first step, cached pages can still be usable after cache is disabled by remounting, and these pages will be fallen out over time, which can be refined in the later version if some requirement is needed. Update related document as well. Suggested-by: Theodore Ts'o Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-20-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- .../erofs/Documentation/filesystems/erofs.txt | 10 ++++ drivers/staging/erofs/Kconfig | 38 ------------- drivers/staging/erofs/internal.h | 25 ++++----- drivers/staging/erofs/super.c | 64 +++++++++++++++++++--- drivers/staging/erofs/utils.c | 26 --------- drivers/staging/erofs/zdata.c | 56 +++---------------- drivers/staging/erofs/zdata.h | 6 -- 7 files changed, 85 insertions(+), 140 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt index 04cf47865c50..0eab600ca7ca 100644 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ b/drivers/staging/erofs/Documentation/filesystems/erofs.txt @@ -65,6 +65,16 @@ fault_injection=%d Enable fault injection in all supported types with by default if CONFIG_EROFS_FS_XATTR is selected. (no)acl Setup POSIX Access Control List. Note: acl is enabled by default if CONFIG_EROFS_FS_POSIX_ACL is selected. +cache_strategy=%s Select a strategy for cached decompression from now on: + disabled: In-place I/O decompression only; + readahead: Cache the last incomplete compressed physical + cluster for further reading. It still does + in-place I/O decompression for the rest + compressed physical clusters; + readaround: Cache the both ends of incomplete compressed + physical clusters for further reading. + It still does in-place I/O decompression + for the rest compressed physical clusters. Module parameters ================= diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 788beebf3f7d..1a8e48943e50 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -94,41 +94,3 @@ config EROFS_FS_CLUSTER_PAGE_LIMIT than 2. Otherwise, the image cannot be mounted correctly on this kernel. -choice - prompt "EROFS VLE Data Decompression mode" - depends on EROFS_FS_ZIP - default EROFS_FS_ZIP_CACHE_BIPOLAR - help - EROFS supports three options for VLE decompression. - "In-place Decompression Only" consumes the minimum memory - with lowest random read. - - "Bipolar Cached Decompression" consumes the maximum memory - with highest random read. - - If unsure, select "Bipolar Cached Decompression" - -config EROFS_FS_ZIP_NO_CACHE - bool "In-place Decompression Only" - help - Read compressed data into page cache and do in-place - decompression directly. - -config EROFS_FS_ZIP_CACHE_UNIPOLAR - bool "Unipolar Cached Decompression" - help - For each request, it caches the last compressed page - for further reading. - It still decompresses in place for the rest compressed pages. - -config EROFS_FS_ZIP_CACHE_BIPOLAR - bool "Bipolar Cached Decompression" - help - For each request, it caches the both end compressed pages - for further reading. - It still decompresses in place for the rest compressed pages. - - Recommended for performance priority. - -endchoice - diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 3176c350779e..118e7c7e4d4d 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -51,18 +51,6 @@ struct erofs_fault_info { }; #endif /* CONFIG_EROFS_FAULT_INJECTION */ -#ifdef CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR -#define EROFS_FS_ZIP_CACHE_LVL (2) -#elif defined(EROFS_FS_ZIP_CACHE_UNIPOLAR) -#define EROFS_FS_ZIP_CACHE_LVL (1) -#else -#define EROFS_FS_ZIP_CACHE_LVL (0) -#endif - -#if (!defined(EROFS_FS_HAS_MANAGED_CACHE) && (EROFS_FS_ZIP_CACHE_LVL > 0)) -#define EROFS_FS_HAS_MANAGED_CACHE -#endif - /* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ #define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 @@ -85,10 +73,11 @@ struct erofs_sb_info { unsigned int shrinker_run_no; -#ifdef EROFS_FS_HAS_MANAGED_CACHE - struct inode *managed_cache; -#endif + /* current strategy of how to use managed cache */ + unsigned char cache_strategy; + /* pseudo inode to manage cached pages */ + struct inode *managed_cache; #endif /* CONFIG_EROFS_FS_ZIP */ u32 blocks; u32 meta_blkaddr; @@ -174,6 +163,12 @@ static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, #define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) #ifdef CONFIG_EROFS_FS_ZIP +enum { + EROFS_ZIP_CACHE_DISABLED, + EROFS_ZIP_CACHE_READAHEAD, + EROFS_ZIP_CACHE_READAROUND +}; + #define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) /* basic unit of the workstation of a super_block */ diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index dad5a3137988..a14fa5228bca 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -197,17 +197,50 @@ static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) } #endif +#ifdef CONFIG_EROFS_FS_ZIP +static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, + substring_t *args) +{ + const char *cs = match_strdup(args); + int err = 0; + + if (!cs) { + errln("Not enough memory to store cache strategy"); + return -ENOMEM; + } + + if (!strcmp(cs, "disabled")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; + } else if (!strcmp(cs, "readahead")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; + } else if (!strcmp(cs, "readaround")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + } else { + errln("Unrecognized cache strategy \"%s\"", cs); + err = -EINVAL; + } + kfree(cs); + return err; +} +#else +static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, + substring_t *args) +{ + infoln("EROFS compression is disabled, so cache strategy is ignored"); + return 0; +} +#endif + +/* set up default EROFS parameters */ static void default_options(struct erofs_sb_info *sbi) { - /* set up some FS parameters */ #ifdef CONFIG_EROFS_FS_ZIP + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; sbi->max_sync_decompress_pages = 3; #endif - #ifdef CONFIG_EROFS_FS_XATTR set_opt(sbi, XATTR_USER); #endif - #ifdef CONFIG_EROFS_FS_POSIX_ACL set_opt(sbi, POSIX_ACL); #endif @@ -219,6 +252,7 @@ enum { Opt_acl, Opt_noacl, Opt_fault_injection, + Opt_cache_strategy, Opt_err }; @@ -228,6 +262,7 @@ static match_table_t erofs_tokens = { {Opt_acl, "acl"}, {Opt_noacl, "noacl"}, {Opt_fault_injection, "fault_injection=%u"}, + {Opt_cache_strategy, "cache_strategy=%s"}, {Opt_err, NULL} }; @@ -285,7 +320,11 @@ static int parse_options(struct super_block *sb, char *options) if (err) return err; break; - + case Opt_cache_strategy: + err = erofs_build_cache_strategy(EROFS_SB(sb), args); + if (err) + return err; + break; default: errln("Unrecognized mount option \"%s\" " "or missing value", p); @@ -295,8 +334,7 @@ static int parse_options(struct super_block *sb, char *options) return 0; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE - +#ifdef CONFIG_EROFS_FS_ZIP static const struct address_space_operations managed_cache_aops; static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask) @@ -469,7 +507,7 @@ static void erofs_put_super(struct super_block *sb) DBG_BUGON(!sbi); erofs_shrinker_unregister(sb); -#ifdef EROFS_FS_HAS_MANAGED_CACHE +#ifdef CONFIG_EROFS_FS_ZIP iput(sbi->managed_cache); sbi->managed_cache = NULL; #endif @@ -570,6 +608,18 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root) if (test_opt(sbi, FAULT_INJECTION)) seq_printf(seq, ",fault_injection=%u", erofs_get_fault_rate(sbi)); +#ifdef CONFIG_EROFS_FS_ZIP + if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { + seq_puts(seq, ",cache_strategy=disabled"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { + seq_puts(seq, ",cache_strategy=readahead"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { + seq_puts(seq, ",cache_strategy=readaround"); + } else { + seq_puts(seq, ",cache_strategy=(unknown)"); + DBG_BUGON(1); + } +#endif return 0; } diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 260ea2970b4b..0e6308b15717 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -145,8 +145,6 @@ int erofs_workgroup_put(struct erofs_workgroup *grp) return count; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE -/* for cache-managed case, customized reclaim paths exist */ static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) { erofs_workgroup_unfreeze(grp, 0); @@ -192,30 +190,6 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, return true; } -#else -/* for nocache case, no customized reclaim path at all */ -static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) -{ - int cnt = atomic_read(&grp->refcount); - - DBG_BUGON(cnt <= 0); - DBG_BUGON(cleanup && cnt != 1); - - if (cnt > 1) - return false; - - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, - grp->index)) != grp); - - /* (rarely) could be grabbed again when freeing */ - erofs_workgroup_put(grp); - return true; -} - -#endif - static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, unsigned long nr_shrink, bool cleanup) diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 6ebee2ca8dc5..2d7aaf98f7de 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -162,7 +162,6 @@ struct z_erofs_decompress_frontend { static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; static DEFINE_MUTEX(z_pagemap_global_lock); -#ifdef EROFS_FS_HAS_MANAGED_CACHE static void preload_compressed_pages(struct z_erofs_collector *clt, struct address_space *mc, enum z_erofs_cache_alloctype type, @@ -273,15 +272,6 @@ int erofs_try_to_free_cached_page(struct address_space *mapping, } return ret; } -#else -static void preload_compressed_pages(struct z_erofs_collector *clt, - struct address_space *mc, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool) -{ - /* nowhere to load compressed pages from */ -} -#endif /* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ static inline bool try_inplace_io(struct z_erofs_collector *clt, @@ -547,25 +537,19 @@ static inline struct page *__stagingpage_alloc(struct list_head *pagepool, return page; } -#ifdef EROFS_FS_HAS_MANAGED_CACHE static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + unsigned int cachestrategy, erofs_off_t la) { + if (cachestrategy <= EROFS_ZIP_CACHE_DISABLED) + return false; + if (fe->backmost) return true; - if (EROFS_FS_ZIP_CACHE_LVL >= 2) - return la < fe->headoffset; - - return false; -} -#else -static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, - erofs_off_t la) -{ - return false; + return cachestrategy >= EROFS_ZIP_CACHE_READAROUND && + la < fe->headoffset; } -#endif static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, struct page *page, @@ -621,7 +605,7 @@ restart_now: goto err_out; /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, map->m_la)) + if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) cache_strategy = DELAYEDALLOC; else cache_strategy = DONTALLOC; @@ -1126,9 +1110,7 @@ out: /* define decompression jobqueue types */ enum { -#ifdef EROFS_FS_HAS_MANAGED_CACHE JQ_BYPASS, -#endif JQ_SUBMIT, NR_JOBQUEUES, }; @@ -1139,14 +1121,12 @@ static void *jobqueueset_init(struct super_block *sb, struct z_erofs_unzip_io *fgq, bool forcefg) { -#ifdef EROFS_FS_HAS_MANAGED_CACHE /* * if managed cache is enabled, bypass jobqueue is needed, * no need to read from device for all pclusters in this queue. */ q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; -#endif q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; @@ -1154,7 +1134,6 @@ static void *jobqueueset_init(struct super_block *sb, return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); } -#ifdef EROFS_FS_HAS_MANAGED_CACHE static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, z_erofs_next_pcluster_t qtail[], z_erofs_next_pcluster_t owned_head) @@ -1188,24 +1167,6 @@ static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); return true; } -#else -static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, - z_erofs_next_pcluster_t qtail[], - z_erofs_next_pcluster_t owned_head) -{ - /* impossible to bypass submission for managed cache disabled */ - DBG_BUGON(1); -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* bios should be >0 if managed cache is disabled */ - DBG_BUGON(!nr_bios); - return false; -} -#endif static bool z_erofs_vle_submit_all(struct super_block *sb, z_erofs_next_pcluster_t owned_head, @@ -1317,10 +1278,9 @@ static void z_erofs_submit_and_unzip(struct super_block *sb, pagepool, io, force_fg)) return; -#ifdef EROFS_FS_HAS_MANAGED_CACHE /* decompress no I/O pclusters immediately */ z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); -#endif + if (!force_fg) return; diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h index 1f51d80fa89f..e11fe1959ca2 100644 --- a/drivers/staging/erofs/zdata.h +++ b/drivers/staging/erofs/zdata.h @@ -101,18 +101,12 @@ struct z_erofs_unzip_io_sb { struct super_block *sb; }; -#ifdef EROFS_FS_HAS_MANAGED_CACHE #define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, struct page *page) { return page->mapping == MNGD_MAPPING(sbi); } -#else -#define MNGD_MAPPING(sbi) (NULL) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) { return false; } -#endif /* !EROFS_FS_HAS_MANAGED_CACHE */ #define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 #define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) -- cgit v1.2.3-59-g8ed1b From 2bb90cc275e242eb3965a9091c359c2c8327a1e7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:50 +0800 Subject: staging: erofs: tidy up utils.c Keep in line with erofs-outofstaging patchset: - Update comments in erofs_try_to_release_workgroup; - code style cleanup. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-21-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/utils.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 0e6308b15717..814c2ee037ae 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -114,8 +114,7 @@ int erofs_register_workgroup(struct super_block *sb, */ __erofs_workgroup_get(grp); - err = radix_tree_insert(&sbi->workstn_tree, - grp->index, grp); + err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); if (unlikely(err)) /* * it's safe to decrease since the workgroup isn't visible @@ -156,18 +155,18 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, bool cleanup) { /* - * for managed cache enabled, the refcount of workgroups - * themselves could be < 0 (freezed). So there is no guarantee - * that all refcount > 0 if managed cache is enabled. + * If managed cache is on, refcount of workgroups + * themselves could be < 0 (freezed). In other words, + * there is no guarantee that all refcounts > 0. */ if (!erofs_workgroup_try_to_freeze(grp, 1)) return false; /* - * note that all cached pages should be unlinked - * before delete it from the radix tree. - * Otherwise some cached pages of an orphan old workgroup - * could be still linked after the new one is available. + * Note that all cached pages should be unattached + * before deleted from the radix tree. Otherwise some + * cached pages could be still attached to the orphan + * old workgroup when the new one is available in the tree. */ if (erofs_try_to_free_all_cached_pages(sbi, grp)) { erofs_workgroup_unfreeze(grp, 1); @@ -175,7 +174,7 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, } /* - * it is impossible to fail after the workgroup is freezed, + * It's impossible to fail after the workgroup is freezed, * however in order to avoid some race conditions, add a * DBG_BUGON to observe this in advance. */ @@ -183,8 +182,8 @@ static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, grp->index)) != grp); /* - * if managed cache is enable, the last refcount - * should indicate the related workstation. + * If managed cache is on, last refcount should indicate + * the related workstation. */ erofs_workgroup_unfreeze_final(grp); return true; @@ -273,9 +272,9 @@ static unsigned long erofs_shrink_scan(struct shrinker *shrink, unsigned long freed = 0; spin_lock(&erofs_sb_list_lock); - do + do { run_no = ++shrinker_run_no; - while (run_no == 0); + } while (run_no == 0); /* Iterate over all mounted superblocks and try to shrink them */ p = erofs_sb_list.next; -- cgit v1.2.3-59-g8ed1b From bc33d9f35da87cccd73fe5d3e007acb084411309 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:51 +0800 Subject: staging: erofs: update super.c Keep in line with erofs-outofstaging patchset: - "Chao Yu" is most commonly used in Linux community; - quoted string split across lines. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-22-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index a14fa5228bca..f65a1ff9f42f 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -326,8 +326,7 @@ static int parse_options(struct super_block *sb, char *options) return err; break; default: - errln("Unrecognized mount option \"%s\" " - "or missing value", p); + errln("Unrecognized mount option \"%s\" or missing value", p); return -EINVAL; } } @@ -662,6 +661,6 @@ module_init(erofs_module_init); module_exit(erofs_module_exit); MODULE_DESCRIPTION("Enhanced ROM File System"); -MODULE_AUTHOR("Gao Xiang, Yu Chao, Miao Xie, CONSUMER BG, HUAWEI Inc."); +MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 0b800f3dbae710ed72ad544d17fd186ea5b5e504 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 31 Jul 2019 23:57:52 +0800 Subject: staging: erofs: update Kconfig Keep in line with erofs-outofstaging patchset: - turn on CONFIG_EROFS_FS_ZIP by default; - turn on CONFIG_EROFS_FS_SECURITY by default suggested by David; - update Kconfig description. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190731155752.210602-23-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/Kconfig | 54 ++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig index 1a8e48943e50..16316d1adca3 100644 --- a/drivers/staging/erofs/Kconfig +++ b/drivers/staging/erofs/Kconfig @@ -4,16 +4,16 @@ config EROFS_FS tristate "EROFS filesystem support" depends on BLOCK help - EROFS(Enhanced Read-Only File System) is a lightweight + EROFS (Enhanced Read-Only File System) is a lightweight read-only file system with modern designs (eg. page-sized blocks, inline xattrs/data, etc.) for scenarios which need - high-performance read-only requirements, eg. firmwares in - mobile phone or LIVECDs. + high-performance read-only requirements, e.g. Android OS + for mobile phones and LIVECDs. - It also provides VLE compression support, focusing on - random read improvements, keeping relatively lower - compression ratios, which is useful for high-performance - devices with limited memory and ROM space. + It also provides fixed-sized output compression support, + which improves storage density, keeps relatively higher + compression ratios, which is more useful to achieve high + performance for embedded devices with limited memory. If unsure, say N. @@ -21,11 +21,19 @@ config EROFS_FS_DEBUG bool "EROFS debugging feature" depends on EROFS_FS help - Print EROFS debugging messages and enable more BUG_ONs - which check the filesystem consistency aggressively. + Print debugging messages and enable more BUG_ONs which check + filesystem consistency and find potential issues aggressively, + which can be used for Android eng build, for example. For daily use, say N. +config EROFS_FAULT_INJECTION + bool "EROFS fault injection facility" + depends on EROFS_FS + help + Test EROFS to inject faults such as ENOMEM, EIO, and so on. + If unsure, say N. + config EROFS_FS_XATTR bool "EROFS extended attributes" depends on EROFS_FS @@ -54,6 +62,7 @@ config EROFS_FS_POSIX_ACL config EROFS_FS_SECURITY bool "EROFS Security Labels" depends on EROFS_FS_XATTR + default y help Security labels provide an access control facility to support Linux Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO @@ -63,22 +72,15 @@ config EROFS_FS_SECURITY If you are not using a security module, say N. -config EROFS_FAULT_INJECTION - bool "EROFS fault injection facility" - depends on EROFS_FS - help - Test EROFS to inject faults such as ENOMEM, EIO, and so on. - If unsure, say N. - config EROFS_FS_ZIP - bool "EROFS Data Compresssion Support" + bool "EROFS Data Compression Support" depends on EROFS_FS select LZ4_DECOMPRESS + default y help - Currently we support LZ4 VLE Compression only. - Play at your own risk. + Enable fixed-sized output compression for EROFS. - If you don't want to use compression feature, say N. + If you don't want to enable compression feature, say N. config EROFS_FS_CLUSTER_PAGE_LIMIT int "EROFS Cluster Pages Hard Limit" @@ -86,11 +88,11 @@ config EROFS_FS_CLUSTER_PAGE_LIMIT range 1 256 default "1" help - Indicates VLE compressed pages hard limit of a - compressed cluster. + Indicates maximum # of pages of a compressed + physical cluster. - For example, if files of a image are compressed - into 8k-unit, the hard limit should not be less - than 2. Otherwise, the image cannot be mounted - correctly on this kernel. + For example, if files in a image were compressed + into 8k-unit, hard limit should not be configured + less than 2. Otherwise, the image will be refused + to mount on this kernel. -- cgit v1.2.3-59-g8ed1b From a5589269e660a14ab8580235909100f245d73cb9 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 2 Aug 2019 01:31:49 +0000 Subject: staging: fsl-dpaa2/ethsw: Remove useless set memory to zero use memset() The memory return by kzalloc() has already be set to zero, so remove useless memset(0). Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20190802013149.80952-1-weiyongjun1@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 4b94a01513a7..aac98ece2335 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -641,8 +641,6 @@ static int port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, if (!dma_mem) return -ENOMEM; - memset(dma_mem, 0, fdb_dump_size); - fdb_dump_iova = dma_map_single(dev, dma_mem, fdb_dump_size, DMA_FROM_DEVICE); if (dma_mapping_error(dev, fdb_dump_iova)) { -- cgit v1.2.3-59-g8ed1b From 129d0561a3e81836aeeba2bbdb89249c0012af24 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 31 Jul 2019 15:42:07 +0200 Subject: staging: bcm2835-camera: Spelling s/conencted/connected/ Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20190731134207.18549-1-geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h index f738e7f99e96..47897e81ec58 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.h @@ -56,7 +56,7 @@ struct vchiq_mmal_port { /* component port belongs to, allows simple deref */ struct vchiq_mmal_component *component; - struct vchiq_mmal_port *connected; /* port conencted to */ + struct vchiq_mmal_port *connected; /* port connected to */ /* buffer info */ struct vchiq_mmal_port_buffer minimum_buffer; -- cgit v1.2.3-59-g8ed1b From b7a40c32f18a88b2a1e894a4406cf9d97423c078 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:39:13 +0530 Subject: staging: wlan-ng: Remove function prism2mib_excludeunencrypted() Remove function prism2mib_excludeunencrypted as all it does is call prism2mib_flag. Modify call sites accordingly. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802060913.30241-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mib.c | 44 +------------------------------------ 1 file changed, 1 insertion(+), 43 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index 1eba5fa28d8f..7d7d77b04255 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -126,13 +126,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, struct p80211msg_dot11req_mibset *msg, void *data); -static int prism2mib_excludeunencrypted(struct mibrec *mib, - int isget, - struct wlandevice *wlandev, - struct hfa384x *hw, - struct p80211msg_dot11req_mibset *msg, - void *data); - static int prism2mib_fragmentationthreshold(struct mibrec *mib, int isget, @@ -176,7 +169,7 @@ static struct mibrec mibtab[] = { {DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED, F_STA | F_READ | F_WRITE, HFA384x_RID_CNFWEPFLAGS, HFA384x_WEPFLAGS_EXCLUDE, 0, - prism2mib_excludeunencrypted}, + prism2mib_flag}, /* dot11mac MIB's */ @@ -593,41 +586,6 @@ static int prism2mib_privacyinvoked(struct mibrec *mib, return prism2mib_flag(mib, isget, wlandev, hw, msg, data); } -/* - * prism2mib_excludeunencrypted - * - * Get/set the dot11ExcludeUnencrypted value. - * - * MIB record parameters: - * parm1 Prism2 RID value. - * parm2 Bit value for ExcludeUnencrypted flag. - * parm3 Not used. - * - * Arguments: - * mib MIB record. - * isget MIBGET/MIBSET flag. - * wlandev wlan device structure. - * priv "priv" structure. - * hw "hw" structure. - * msg Message structure. - * data Data buffer. - * - * Returns: - * 0 - Success. - * ~0 - Error. - * - */ - -static int prism2mib_excludeunencrypted(struct mibrec *mib, - int isget, - struct wlandevice *wlandev, - struct hfa384x *hw, - struct p80211msg_dot11req_mibset *msg, - void *data) -{ - return prism2mib_flag(mib, isget, wlandev, hw, msg, data); -} - /* * prism2mib_fragmentationthreshold * -- cgit v1.2.3-59-g8ed1b From 4b1b8b08ab9f4db41e30e3a1bbdba1d58aa624a3 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 1 Aug 2019 20:15:11 +0000 Subject: staging: wilc1000: merge drv_handle and operation_mode wids wilc_set_wfi_drv_handler and wilc_set_operation_mode sends the same parameters to the FW, so it's better to combine them together. Kept wilc_set_wfi_drv_handler implementation since it sends all the required parameters, and renamed it to wilc_set_operation_mode to be more descriptive. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190801200909.12605-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 32 +++-------------------- drivers/staging/wilc1000/wilc_hif.h | 5 ++-- drivers/staging/wilc1000/wilc_netdev.c | 6 ++--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 26 +++++++++--------- drivers/staging/wilc1000/wilc_wlan_if.h | 3 +-- 5 files changed, 21 insertions(+), 51 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index f8646ea3b0c4..2b4c83b225a4 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -1409,18 +1409,14 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) return result; } -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id) +int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, + u8 ifc_id) { struct wid wid; - struct host_if_drv *hif_drv = vif->hif_drv; int result; struct wilc_drv_handler drv; - if (!hif_drv) - return -EFAULT; - - wid.id = WID_SET_DRV_HANDLER; + wid.id = WID_SET_OPERATION_MODE; wid.type = WID_STR; wid.size = sizeof(drv); wid.val = (u8 *)&drv; @@ -1435,26 +1431,6 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, return result; } -int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode) -{ - struct wid wid; - struct wilc_op_mode op_mode; - int result; - - wid.id = WID_SET_OPERATION_MODE; - wid.type = WID_INT; - wid.size = sizeof(op_mode); - wid.val = (u8 *)&op_mode; - - op_mode.mode = cpu_to_le32(mode); - - result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1); - if (result) - netdev_err(vif->ndev, "Failed to set operation mode\n"); - - return result; -} - s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val) { struct wid wid; @@ -1630,8 +1606,6 @@ int wilc_deinit(struct wilc_vif *vif) del_timer_sync(&vif->periodic_rssi); del_timer_sync(&hif_drv->remain_on_ch_timer); - wilc_set_wfi_drv_handler(vif, 0, 0, 0); - if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, hif_drv->usr_scan_req.arg); diff --git a/drivers/staging/wilc1000/wilc_hif.h b/drivers/staging/wilc1000/wilc_hif.h index be1d2497cde9..3bc305151651 100644 --- a/drivers/staging/wilc1000/wilc_hif.h +++ b/drivers/staging/wilc1000/wilc_hif.h @@ -219,9 +219,8 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie); void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id); -int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); +int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, + u8 ifc_id); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 68129a0ba55f..57510400f243 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -626,10 +626,8 @@ static int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), vif->iftype, - vif->idx); - wilc_set_operation_mode(vif, vif->iftype); - + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, + vif->idx); wilc_get_mac_address(vif, mac_add); netdev_dbg(ndev, "Mac address: %pM\n", mac_add); ether_addr_copy(ndev->dev_addr, mac_add); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index e2d9efed36b0..f3b12f3b6d61 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1419,7 +1419,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) wilc_wfi_deinit_mon_interface(wl, true); vif->iftype = WILC_STATION_MODE; - wilc_set_operation_mode(vif, WILC_STATION_MODE); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_STATION_MODE, vif->idx); memset(priv->assoc_stainfo.sta_associated_bss, 0, WILC_MAX_NUM_STA * ETH_ALEN); @@ -1431,8 +1432,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev.iftype = type; vif->monitor_flag = 0; vif->iftype = WILC_CLIENT_MODE; - wilc_set_operation_mode(vif, WILC_STATION_MODE); - + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_STATION_MODE, vif->idx); break; case NL80211_IFTYPE_AP: @@ -1440,18 +1441,17 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev.iftype = type; vif->iftype = WILC_AP_MODE; - if (wl->initialized) { - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - 0, vif->idx); - wilc_set_operation_mode(vif, WILC_AP_MODE); - } + if (wl->initialized) + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_AP_MODE, vif->idx); break; case NL80211_IFTYPE_P2P_GO: - wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev.iftype = type; vif->iftype = WILC_GO_MODE; + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + WILC_AP_MODE, vif->idx); break; default: @@ -1659,16 +1659,16 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) vif->monitor_flag = 0; mutex_lock(&wl->vif_mutex); - wilc_set_wfi_drv_handler(vif, 0, 0, 0); - for (i = vif->idx; i < wl->vif_num ; i++) { + wilc_set_operation_mode(vif, 0, 0, 0); + for (i = vif->idx; i < wl->vif_num; i++) { if ((i + 1) >= wl->vif_num) { wl->vif[i] = NULL; } else { vif = wl->vif[i + 1]; vif->idx = i; wl->vif[i] = vif; - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), - vif->iftype, vif->idx); + wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), + vif->iftype, vif->idx); } } wl->vif_num--; diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index b89d0e0f04cc..70eac586f80c 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -724,7 +724,6 @@ enum { /* NMAC Integer WID list */ /* Custom Integer WID list */ WID_GET_INACTIVE_TIME = 0x2084, - WID_SET_OPERATION_MODE = 0X2086, /* EMAC String WID list */ WID_SSID = 0x3000, WID_FIRMWARE_VERSION = 0x3001, @@ -755,9 +754,9 @@ enum { WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ - WID_SET_DRV_HANDLER = 0x3079, /* NMAC String WID list */ + WID_SET_OPERATION_MODE = 0x3079, WID_11N_P_ACTION_REQ = 0x3080, WID_HUT_TEST_ID = 0x3081, WID_PMKID_INFO = 0x3082, -- cgit v1.2.3-59-g8ed1b From 9104688c321a7e82ec95fddff6c98729f4e4fefd Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Thu, 1 Aug 2019 20:15:12 +0000 Subject: staging: wilc1000: remove unused function function wilc_resolve_disconnect_aberration isn't referenced, so removing it Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190801200909.12605-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_hif.c | 9 --------- drivers/staging/wilc1000/wilc_hif.h | 1 - 2 files changed, 10 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_hif.c b/drivers/staging/wilc1000/wilc_hif.c index 2b4c83b225a4..f2b7d5a1be17 100644 --- a/drivers/staging/wilc1000/wilc_hif.c +++ b/drivers/staging/wilc1000/wilc_hif.c @@ -798,15 +798,6 @@ int wilc_disconnect(struct wilc_vif *vif) return 0; } -void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) -{ - if (!vif->hif_drv) - return; - if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || - vif->hif_drv->hif_state == HOST_IF_CONNECTING) - wilc_disconnect(vif); -} - int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) { struct wid wid_list[5]; diff --git a/drivers/staging/wilc1000/wilc_hif.h b/drivers/staging/wilc1000/wilc_hif.h index 3bc305151651..ac5fe57f872b 100644 --- a/drivers/staging/wilc1000/wilc_hif.h +++ b/drivers/staging/wilc1000/wilc_hif.h @@ -222,7 +222,6 @@ void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode, u8 ifc_id); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); -- cgit v1.2.3-59-g8ed1b From 42755adcce8897a60a766bc102fcb23f1dd28f43 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:41 +0530 Subject: staging: rtl8723bs: Change return type of hal_btcoex_IsBtExist() Change return type of hal_btcoex_IsBtExist from u8 to bool as its only possible return values are true and false. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 2 +- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 8987b5f892c0..73f3d93d2d1a 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -1335,7 +1335,7 @@ void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist) *true Enable BT co-exist mechanism *false Disable BT co-exist mechanism */ -u8 hal_btcoex_IsBtExist(struct adapter *padapter) +bool hal_btcoex_IsBtExist(struct adapter *padapter) { struct hal_com_data *pHalData; diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index 6f7514be998f..a91116e5c549 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -22,7 +22,7 @@ typedef struct _BT_COEXIST void DBG_BT_INFO(u8 *dbgmsg); void hal_btcoex_SetBTCoexist(struct adapter *padapter, u8 bBtExist); -u8 hal_btcoex_IsBtExist(struct adapter *padapter); +bool hal_btcoex_IsBtExist(struct adapter *padapter); bool hal_btcoex_IsBtDisabled(struct adapter *); void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType); void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum); -- cgit v1.2.3-59-g8ed1b From 84881dd37beb0626d2622ccbfbdcfdc4bda2546d Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:42 +0530 Subject: staging: rtl8723bs: Change return type of hal_btcoex_IsBtControlLps() Change return type of hal_btcoex_IsBtControlLps from u8 to bool as it only returns boolean values. Change comparison to false within this function; check the boolean variable directly instead. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 4 ++-- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 73f3d93d2d1a..85f5371d349b 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -1475,9 +1475,9 @@ void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual) GLBtCoexist.bManualControl = bmanual; } -u8 hal_btcoex_IsBtControlLps(struct adapter *padapter) +bool hal_btcoex_IsBtControlLps(struct adapter *padapter) { - if (hal_btcoex_IsBtExist(padapter) == false) + if (!hal_btcoex_IsBtExist(padapter)) return false; if (GLBtCoexist.btInfo.bBtDisabled) diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index a91116e5c549..da25f8e98ec7 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -47,7 +47,7 @@ void hal_btcoex_Handler(struct adapter *padapter); s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter); void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual); -u8 hal_btcoex_IsBtControlLps(struct adapter *); +bool hal_btcoex_IsBtControlLps(struct adapter *padapter); u8 hal_btcoex_IsLpsOn(struct adapter *); u8 hal_btcoex_RpwmVal(struct adapter *); u8 hal_btcoex_LpsVal(struct adapter *); -- cgit v1.2.3-59-g8ed1b From 365231fcd67c97ea464c17d8d413f0860400547b Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:43 +0530 Subject: staging: rtl8723bs: Change return type of hal_btcoex_IsLpsOn() Change return type of hal_btcoex_IsLpsOn from u8 to bool as the function only returns boolean values. Modify a comparison of a boolean value to false to instead check that boolean value directly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 4 ++-- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 85f5371d349b..d2147a65c1cd 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -1489,9 +1489,9 @@ bool hal_btcoex_IsBtControlLps(struct adapter *padapter) return false; } -u8 hal_btcoex_IsLpsOn(struct adapter *padapter) +bool hal_btcoex_IsLpsOn(struct adapter *padapter) { - if (hal_btcoex_IsBtExist(padapter) == false) + if (!hal_btcoex_IsBtExist(padapter)) return false; if (GLBtCoexist.btInfo.bBtDisabled) diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index da25f8e98ec7..a0b502c34a25 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -48,7 +48,7 @@ void hal_btcoex_Handler(struct adapter *padapter); s32 hal_btcoex_IsBTCoexCtrlAMPDUSize(struct adapter *padapter); void hal_btcoex_SetManualControl(struct adapter *padapter, u8 bmanual); bool hal_btcoex_IsBtControlLps(struct adapter *padapter); -u8 hal_btcoex_IsLpsOn(struct adapter *); +bool hal_btcoex_IsLpsOn(struct adapter *padapter); u8 hal_btcoex_RpwmVal(struct adapter *); u8 hal_btcoex_LpsVal(struct adapter *); u32 hal_btcoex_GetRaMask(struct adapter *); -- cgit v1.2.3-59-g8ed1b From 6250a57e6cf45440e2230bda226162532b0130e4 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 11:54:44 +0530 Subject: staging: rtl8723bs: Replace hal_btcoex_Initialize() Remove hal_btcoex_Initialize as all it does is perform a memset and call EXhalbtcoutsrc_InitlizeVariables. Rename EXhalbtcoutsrc_InitlizeVariables to hal_btcoex_Initialize and add the memset of hal_btcoex_Initialize in order to maintain compatibility with call sites of the latter (EXhalbtcoutsrc is not called anywhere else except in now-removed old hal_btcoex_Initialize). Change return type of new hal_btcoex_Initialize from u8 to void and remove its return statement as the return value of hal_btcoex_Initialize is never used. Change the type of function argument at call site to match the function parameter of new hal_btcoex_Initialize. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802062444.30384-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h | 1 - drivers/staging/rtl8723bs/hal/hal_btcoex.c | 16 ++++++---------- drivers/staging/rtl8723bs/include/hal_btcoex.h | 2 +- drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h index aad86570b59c..7150d54d49ab 100644 --- a/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h +++ b/drivers/staging/rtl8723bs/hal/HalBtcOutSrc.h @@ -532,7 +532,6 @@ typedef struct _BTC_COEXIST { extern BTC_COEXIST GLBtCoexist; -u8 EXhalbtcoutsrc_InitlizeVariables(void *Adapter); void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist); void EXhalbtcoutsrc_InitHwConfig(PBTC_COEXIST pBtCoexist, u8 bWifiOnly); void EXhalbtcoutsrc_InitCoexDm(PBTC_COEXIST pBtCoexist); diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index d2147a65c1cd..19486f0e0ead 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -957,9 +957,13 @@ static u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter) return true; } -u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) +void hal_btcoex_Initialize(void *padapter) { - PBTC_COEXIST pBtCoexist = &GLBtCoexist; + PBTC_COEXIST pBtCoexist; + + memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); + + pBtCoexist = &GLBtCoexist; /* pBtCoexist->statistics.cntBind++; */ @@ -999,8 +1003,6 @@ u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter) GLBtcWiFiInScanState = false; GLBtcWiFiInIQKState = false; - - return true; } void EXhalbtcoutsrc_PowerOnSetting(PBTC_COEXIST pBtCoexist) @@ -1382,12 +1384,6 @@ void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath) EXhalbtcoutsrc_SetSingleAntPath(singleAntPath); } -u8 hal_btcoex_Initialize(struct adapter *padapter) -{ - memset(&GLBtCoexist, 0, sizeof(GLBtCoexist)); - return EXhalbtcoutsrc_InitlizeVariables((void *)padapter); -} - void hal_btcoex_PowerOnSetting(struct adapter *padapter) { EXhalbtcoutsrc_PowerOnSetting(&GLBtCoexist); diff --git a/drivers/staging/rtl8723bs/include/hal_btcoex.h b/drivers/staging/rtl8723bs/include/hal_btcoex.h index a0b502c34a25..eb03813fdcb9 100644 --- a/drivers/staging/rtl8723bs/include/hal_btcoex.h +++ b/drivers/staging/rtl8723bs/include/hal_btcoex.h @@ -28,7 +28,7 @@ void hal_btcoex_SetChipType(struct adapter *padapter, u8 chipType); void hal_btcoex_SetPgAntNum(struct adapter *padapter, u8 antNum); void hal_btcoex_SetSingleAntPath(struct adapter *padapter, u8 singleAntPath); -u8 hal_btcoex_Initialize(struct adapter *padapter); +void hal_btcoex_Initialize(void *padapter); void hal_btcoex_PowerOnSetting(struct adapter *padapter); void hal_btcoex_InitHwConfig(struct adapter *padapter, u8 bWifiOnly); diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index 540a7eed621d..65ffb807eda2 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -371,7 +371,7 @@ static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct rtw_hal_chip_configure(padapter); - hal_btcoex_Initialize(padapter); + hal_btcoex_Initialize((void *) padapter); /* 3 6. read efuse/eeprom data */ rtw_hal_read_chip_info(padapter); -- cgit v1.2.3-59-g8ed1b From a0afad481b83690449a119a9384a3b0f54cacf11 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:04 +0530 Subject: staging: rtl8712: r8712_os_recv_resource_alloc(): Change return type Change return type of function r8712_os_recv_resource_alloc from int to void as its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 5 ++--- drivers/staging/rtl8712/recv_osdep.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 70a4dcd4a1e5..aaa77823115a 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -29,12 +29,11 @@ /*init os related resource in struct recv_priv*/ /*alloc os related resource in union recv_frame*/ -int r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe) +void r8712_os_recv_resource_alloc(struct _adapter *padapter, + union recv_frame *precvframe) { precvframe->u.hdr.pkt_newalloc = NULL; precvframe->u.hdr.pkt = NULL; - return _SUCCESS; } /*alloc os related resource in struct recv_buf*/ diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index dcd3b484c793..c93ba4c3eb9b 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -28,8 +28,8 @@ void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void r8712_free_recv_priv(struct recv_priv *precvpriv); -int r8712_os_recv_resource_alloc(struct _adapter *padapter, - union recv_frame *precvframe); +void r8712_os_recv_resource_alloc(struct _adapter *padapter, + union recv_frame *precvframe); int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); int r8712_os_recvbuf_resource_free(struct _adapter *padapter, -- cgit v1.2.3-59-g8ed1b From 1ce0212ab8c103f36aa8d7b43ff8d738bc98699b Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:05 +0530 Subject: staging: rtl8712: _r8712_init_recv_priv(): Change return type Change return type of _r8712_init_recv_priv as its return value is never checked or used. Modify return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_osdep.h | 2 +- drivers/staging/rtl8712/rtl871x_recv.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index c93ba4c3eb9b..7a0fa227de73 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -18,7 +18,7 @@ #include "drv_types.h" #include -sint _r8712_init_recv_priv(struct recv_priv *precvpriv, +void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void _r8712_free_recv_priv(struct recv_priv *precvpriv); s32 r8712_recv_entry(union recv_frame *precv_frame); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 9969e5265a40..79c7a329e9f6 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -48,7 +48,7 @@ void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) _init_queue(&psta_recvpriv->defrag_q); } -sint _r8712_init_recv_priv(struct recv_priv *precvpriv, +void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) { sint i; @@ -64,7 +64,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, sizeof(union recv_frame) + RXFRAME_ALIGN_SZ, GFP_ATOMIC); if (precvpriv->pallocated_frame_buf == NULL) - return _FAIL; + return; kmemleak_not_leak(precvpriv->pallocated_frame_buf); precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - @@ -80,7 +80,7 @@ sint _r8712_init_recv_priv(struct recv_priv *precvpriv, precvframe++; } precvpriv->rx_pending_cnt = 1; - return r8712_init_recv_priv(precvpriv, padapter); + r8712_init_recv_priv(precvpriv, padapter); } void _r8712_free_recv_priv(struct recv_priv *precvpriv) -- cgit v1.2.3-59-g8ed1b From 0bf36e605286eaa53ec90c09a2f8eaac5d4d1cc4 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:06 +0530 Subject: staging: rtl8712: r8712_init_recv_priv(): Change return type Change return type of r8712_init_recv_priv from int to void as its return value is never used. Remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_osdep.h | 4 ++-- drivers/staging/rtl8712/rtl8712_recv.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index 7a0fa227de73..3cfafef1af91 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -25,8 +25,8 @@ s32 r8712_recv_entry(union recv_frame *precv_frame); void r8712_recv_indicatepkt(struct _adapter *adapter, union recv_frame *precv_frame); void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); -int r8712_init_recv_priv(struct recv_priv *precvpriv, - struct _adapter *padapter); +void r8712_init_recv_priv(struct recv_priv *precvpriv, + struct _adapter *padapter); void r8712_free_recv_priv(struct recv_priv *precvpriv); void r8712_os_recv_resource_alloc(struct _adapter *padapter, union recv_frame *precvframe); diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index d9574ea3ffb2..bb0407cac1ae 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -35,7 +35,7 @@ static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; static void recv_tasklet(void *priv); -int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) +void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) { int i; struct recv_buf *precvbuf; @@ -83,7 +83,6 @@ int r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) } pskb = NULL; } - return res; } void r8712_free_recv_priv(struct recv_priv *precvpriv) -- cgit v1.2.3-59-g8ed1b From 14b4302ff028afc5fc09f243a21ee6cad6118c40 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:07 +0530 Subject: staging: rtl8712: r8712_os_recvbuf_resource_alloc(): Change return values Change return values of r8712_os_recvbuf_resource_alloc from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Modify check at call site to check for non-zero return value instead of _FAIL. Thereafter remove variable at call site that stored the return value and perform the check directly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 4 ++-- drivers/staging/rtl8712/rtl8712_recv.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index aaa77823115a..682f5b2802ee 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -40,12 +40,12 @@ void r8712_os_recv_resource_alloc(struct _adapter *padapter, int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf) { - int res = _SUCCESS; + int res = 0; precvbuf->irp_pending = false; precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); if (!precvbuf->purb) - res = _FAIL; + res = -ENOMEM; precvbuf->pskb = NULL; precvbuf->pallocated_buf = NULL; precvbuf->pbuf = NULL; diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index bb0407cac1ae..eb9a4a5ed740 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -39,7 +39,6 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter { int i; struct recv_buf *precvbuf; - int res = _SUCCESS; addr_t tmpaddr = 0; int alignment = 0; struct sk_buff *pskb = NULL; @@ -49,15 +48,14 @@ void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC); if (!precvpriv->pallocated_recv_buf) - return _FAIL; + return; precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 - ((addr_t)(precvpriv->pallocated_recv_buf) & 3); precvbuf = (struct recv_buf *)precvpriv->precv_buf; for (i = 0; i < NR_RECVBUFF; i++) { INIT_LIST_HEAD(&precvbuf->list); spin_lock_init(&precvbuf->recvbuf_lock); - res = r8712_os_recvbuf_resource_alloc(padapter, precvbuf); - if (res == _FAIL) + if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf)) break; precvbuf->ref_cnt = 0; precvbuf->adapter = padapter; -- cgit v1.2.3-59-g8ed1b From dcca75a495f9a8b7a6a0fd66bdbe0ed08ffe4884 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:08 +0530 Subject: staging: rtl8712: r8712_os_recvbuf_resource_free(): Change return type Change return type of r8712_os_recvbuf_resource_free from int to void as it always returns _SUCCESS and this return value is never stored, checked or otherwise used. Remove return statement accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_linux.c | 5 ++--- drivers/staging/rtl8712/recv_osdep.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 682f5b2802ee..215fca4abb3a 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -59,8 +59,8 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, } /*free os related resource in struct recv_buf*/ -int r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf) +void r8712_os_recvbuf_resource_free(struct _adapter *padapter, + struct recv_buf *precvbuf) { if (precvbuf->pskb) dev_kfree_skb_any(precvbuf->pskb); @@ -68,7 +68,6 @@ int r8712_os_recvbuf_resource_free(struct _adapter *padapter, usb_kill_urb(precvbuf->purb); usb_free_urb(precvbuf->purb); } - return _SUCCESS; } void r8712_handle_tkip_mic_err(struct _adapter *adapter, u8 bgroup) diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index 3cfafef1af91..792f9cfbacd9 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -32,8 +32,8 @@ void r8712_os_recv_resource_alloc(struct _adapter *padapter, union recv_frame *precvframe); int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); -int r8712_os_recvbuf_resource_free(struct _adapter *padapter, - struct recv_buf *precvbuf); +void r8712_os_recvbuf_resource_free(struct _adapter *padapter, + struct recv_buf *precvbuf); void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); #endif -- cgit v1.2.3-59-g8ed1b From f8dbe3f0acaff86c8c12540bb1b76c34d32a563f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:09 +0530 Subject: staging: rtl8712: r8712_tkip_decrypt(): Change return type Change return type of r8712_tkip_decrypt from u8 to void as the return value is never used. Modify or remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 12 ++---------- drivers/staging/rtl8712/rtl871x_security.h | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 693008bba83e..66586a9d9f73 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -636,7 +636,7 @@ u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe) } /* The hlen doesn't include the IV */ -u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) +void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) { /* exclude ICV */ u16 pnl; u32 pnh; @@ -670,7 +670,7 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) prwskey = &psecuritypriv->XGrpKey[ ((idx >> 6) & 0x3) - 1].skey[0]; if (!psecuritypriv->binstallGrpkey) - return _FAIL; + return; } else { prwskey = &stainfo->x_UncstKey.skey[0]; } @@ -686,16 +686,8 @@ u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe) arcfour_encrypt(&mycontext, payload, payload, length); *((__le32 *)crc) = cpu_to_le32(getcrc32(payload, length - 4)); - if (crc[3] != payload[length - 1] || - crc[2] != payload[length - 2] || - crc[1] != payload[length - 3] || - crc[0] != payload[length - 4]) - return _FAIL; - } else { - return _FAIL; } } - return _SUCCESS; } /* 3 =====AES related===== */ diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 25b4d379766d..25220afa61e9 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -210,7 +210,7 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe); void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); -u32 r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); +void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_use_tkipkey_handler(struct timer_list *t); -- cgit v1.2.3-59-g8ed1b From e48a3add05d1b3e0c2ead1e809edd4d02f2f5f10 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:10 +0530 Subject: staging: rtl8712: aes_cipher(): Change return type Change return type of aes_cipher from sint to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 66586a9d9f73..8f3781c5dd25 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1011,8 +1011,8 @@ static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) out[i] = ina[i] ^ inb[i]; } -static sint aes_cipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) +static void aes_cipher(u8 *key, uint hdrlen, + u8 *pframe, uint plen) { uint qc_exists, a4_exists, i, j, payload_remainder; uint num_blocks, payload_index; @@ -1132,7 +1132,6 @@ static sint aes_cipher(u8 *key, uint hdrlen, bitwise_xor(aes_out, padded_buffer, chain_buffer); for (j = 0; j < 8; j++) pframe[payload_index++] = chain_buffer[j]; - return _SUCCESS; } u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) -- cgit v1.2.3-59-g8ed1b From eb43590f50a393ec4156be59eec9287fb711ffd8 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:11 +0530 Subject: staging: rtl8712: aes_decipher(): Change return type Change return type of aes_decipher from sint to void as it always returns _SUCCESS and this value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index 8f3781c5dd25..bf55a697dd5f 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1184,8 +1184,8 @@ u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe) return res; } -static sint aes_decipher(u8 *key, uint hdrlen, - u8 *pframe, uint plen) +static void aes_decipher(u8 *key, uint hdrlen, + u8 *pframe, uint plen) { static u8 message[MAX_MSG_SIZE]; uint qc_exists, a4_exists, i, j, payload_remainder; @@ -1339,7 +1339,6 @@ static sint aes_decipher(u8 *key, uint hdrlen, for (j = 0; j < 8; j++) message[payload_index++] = chain_buffer[j]; /* compare the mic */ - return _SUCCESS; } u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) -- cgit v1.2.3-59-g8ed1b From b35105a3a32343ecdd777497a300a7680f15bf08 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 2 Aug 2019 12:12:12 +0530 Subject: staging: rtl8712: r8712_aes_decrypt(): Change return type Change return type of r8712_aes_decrypt from u8 to void as its return value is never checked. Modify return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190802064212.30476-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_security.c | 7 ++----- drivers/staging/rtl8712/rtl871x_security.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c index bf55a697dd5f..73e3d5ef3af2 100644 --- a/drivers/staging/rtl8712/rtl871x_security.c +++ b/drivers/staging/rtl8712/rtl871x_security.c @@ -1341,7 +1341,7 @@ static void aes_decipher(u8 *key, uint hdrlen, /* compare the mic */ } -u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) +void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) { /* exclude ICV */ /* Intermediate Buffers */ sint length; @@ -1364,7 +1364,7 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) prwskey = &psecuritypriv->XGrpKey[ ((idx >> 6) & 0x3) - 1].skey[0]; if (!psecuritypriv->binstallGrpkey) - return _FAIL; + return; } else { prwskey = &stainfo->x_UncstKey.skey[0]; @@ -1374,11 +1374,8 @@ u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe) prxattrib->iv_len; aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); - } else { - return _FAIL; } } - return _SUCCESS; } void r8712_use_tkipkey_handler(struct timer_list *t) diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h index 25220afa61e9..b2dda16cbd0a 100644 --- a/drivers/staging/rtl8712/rtl871x_security.h +++ b/drivers/staging/rtl8712/rtl871x_security.h @@ -209,7 +209,7 @@ void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst); u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe); u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe); void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe); -u32 r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); +void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe); void r8712_use_tkipkey_handler(struct timer_list *t); -- cgit v1.2.3-59-g8ed1b From 8ca9d8ad30f39651d6ff9428aaeb1940489a7754 Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sat, 3 Aug 2019 12:14:12 +0530 Subject: staging: rtl8188eu: core: rtw_recv.c: Remove Unnecessary parentheses Remove Unnecessary parentheses around precvframe->list, pmlmeext->mlmext_info and precvpriv->free_recv_queue Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803064408.GA30111@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 9caf7041ad60..620da6c003d8 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -145,8 +145,8 @@ int rtw_free_recvframe(struct recv_frame *precvframe, int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue) { - list_del_init(&(precvframe->list)); - list_add_tail(&(precvframe->list), get_list_head(queue)); + list_del_init(&precvframe->list); + list_add_tail(&precvframe->list, get_list_head(queue)); return _SUCCESS; } @@ -219,7 +219,7 @@ static int recvframe_chkmic(struct adapter *adapter, struct security_priv *psecuritypriv = &adapter->securitypriv; struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]); @@ -1500,7 +1500,7 @@ static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe) struct rx_pkt_attrib *pattrib; struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT]; struct recv_priv *precvpriv = &padapter->recvpriv; - struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue); + struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue; nr_subframes = 0; pattrib = &prframe->attrib; -- cgit v1.2.3-59-g8ed1b From 7cbf0108247da2001a591583d2fc6433918b8a47 Mon Sep 17 00:00:00 2001 From: Thiago Bonotto Date: Fri, 2 Aug 2019 20:23:23 +0000 Subject: staging: isdn: remove unnecessary parentheses Fix the following checkpatch error: ERROR: return is not a function, parentheses are not required FILE: drivers/staging/isdn/hysdn/hysdn_net.c:289: + return (0); /* and return success */ Signed-off-by: Thiago Bonotto Link: https://lore.kernel.org/r/20190802202323.27117-1-thbonotto@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/isdn/hysdn/hysdn_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/isdn/hysdn/hysdn_net.c b/drivers/staging/isdn/hysdn/hysdn_net.c index bea37ae30ebb..dcb9ef7a2651 100644 --- a/drivers/staging/isdn/hysdn/hysdn_net.c +++ b/drivers/staging/isdn/hysdn/hysdn_net.c @@ -286,7 +286,7 @@ hysdn_net_create(hysdn_card *card) if (card->debug_flags & LOG_NET_INIT) hysdn_addlog(card, "network device created"); - return (0); /* and return success */ + return 0; /* and return success */ } /* hysdn_net_create */ /***************************************************************************/ -- cgit v1.2.3-59-g8ed1b From 9fd827c699aaaac8521a3246638850913d140854 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Fri, 2 Aug 2019 16:47:37 -0300 Subject: staging: rtl8712: Add spaces around << Fix checkpatch error "CHECK: spaces preferred around that '<<'". Signed-off-by: Marco Villegas Link: https://lore.kernel.org/r/20190802194737.12252-1-git@marvil07.net Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 4199cb586fb1..c5c55967164b 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -41,7 +41,7 @@ do { \ pattrib_iv[0] = txpn._byte_.TSC0;\ pattrib_iv[1] = txpn._byte_.TSC1;\ pattrib_iv[2] = txpn._byte_.TSC2;\ - pattrib_iv[3] = ((keyidx & 0x3)<<6);\ + pattrib_iv[3] = ((keyidx & 0x3) << 6);\ txpn.val = (txpn.val == 0xffffff) ? 0 : (txpn.val+1);\ } while (0) -- cgit v1.2.3-59-g8ed1b From fe4e6e0368885f77fef81adff486f4f7116e9e8f Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sat, 3 Aug 2019 18:48:42 +0530 Subject: staging: rtl8188eu: core: add spaces around '-', '+', '>>','<<' and '*' in rtw_efuse.c Add spaces around '-', '+', '>>','<<' and '*' to improve readability and follow kernel coding style. Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803131839.GA14077@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 128 ++++++++++++++--------------- 1 file changed, 64 insertions(+), 64 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 533ca1ddffb0..02c476f45b33 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -108,7 +108,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* 1. Read the first byte to check if efuse is empty!!! */ /* */ /* */ - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF) { efuse_utilized++; eFuse_Addr++; @@ -124,10 +124,10 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* Check PG header for section num. */ if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */ u1temp = (rtemp8 & 0xE0) >> 5; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if ((rtemp8 & 0x0F) == 0x0F) { eFuse_Addr++; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) eFuse_Addr++; @@ -147,13 +147,13 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { /* Check word enable condition in the section */ if (!(wren & 0x01)) { - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); eFuse_Addr++; efuse_utilized++; eFuseWord[offset][i] = (rtemp8 & 0xff); if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E) break; - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); eFuse_Addr++; efuse_utilized++; eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00); @@ -165,7 +165,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) } } /* Read next PG header */ - rtemp8 = *(phymap+eFuse_Addr); + rtemp8 = *(phymap + eFuse_Addr); if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) { efuse_utilized++; @@ -178,8 +178,8 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* */ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) { for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff); - efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff); + efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff); } } @@ -187,7 +187,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf) /* 4. Copy from Efuse map to output pointer memory!!! */ /* */ for (i = 0; i < _size_byte; i++) - pbuf[i] = efuseTbl[_offset+i]; + pbuf[i] = efuseTbl[_offset + i]; /* */ /* 5. Calculate Efuse utilization. */ @@ -218,16 +218,16 @@ static void efuse_read_phymap_from_txpktbuf( u8 *pos = content; if (bcnhead < 0) /* if not valid */ - bcnhead = usb_read8(adapter, REG_TDECTRL+1); + bcnhead = usb_read8(adapter, REG_TDECTRL + 1); DBG_88E("%s bcnhead:%d\n", __func__, bcnhead); usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); - dbg_addr = bcnhead*128/8; /* 8-bytes addressing */ + dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */ while (1) { - usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i); + usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i); usb_write8(adapter, REG_TXPKTBUF_DBG, 0); start = jiffies; @@ -246,34 +246,34 @@ static void efuse_read_phymap_from_txpktbuf( u16 aaa; lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L); - lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1); + lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1); aaabak = le16_to_cpup((__le16 *)lenc); lenbak = le16_to_cpu(*((__le16 *)lenc)); aaa = le16_to_cpup((__le16 *)&lo32); len = le16_to_cpu(*((__le16 *)&lo32)); - limit = min_t(u16, len-2, limit); + limit = min_t(u16, len - 2, limit); DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak); - memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count); - count += (limit >= count+2) ? 2 : limit-count; - pos = content+count; + memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count); + count += (limit >= count + 2) ? 2 : limit - count; + pos = content + count; } else { - memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; + memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; } - if (limit > count && len-2 > count) { - memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count); - count += (limit >= count+4) ? 4 : limit-count; - pos = content+count; + if (limit > count && len - 2 > count) { + memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count); + count += (limit >= count + 4) ? 4 : limit - count; + pos = content + count; } - if (limit <= count || len-2 <= count) + if (limit <= count || len - 2 <= count) break; i++; } @@ -288,7 +288,7 @@ static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset u8 physical_map[512]; u16 size = 512; - usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy); + usb_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy); memset(physical_map, 0xFF, 512); usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT); status = iol_execute(padapter, CMD_READ_EFUSE_MAP); @@ -323,7 +323,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[1]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1]); if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) badworden &= (~BIT(0)); } @@ -333,7 +333,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[3]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3]); if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) badworden &= (~BIT(1)); } @@ -343,7 +343,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[5]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5]); if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) badworden &= (~BIT(2)); } @@ -353,7 +353,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e efuse_OneByteWrite(pAdapter, start_addr++, data[7]); efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]); - efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]); + efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7]); if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) badworden &= (~BIT(3)); } @@ -371,7 +371,7 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) while (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && AVAILABLE_EFUSE_ADDR(efuse_addr)) { if (efuse_data != 0xFF) { - if ((efuse_data&0x1F) == 0x0F) { /* extended header */ + if ((efuse_data & 0x1F) == 0x0F) { /* extended header */ hoffset = efuse_data; efuse_addr++; efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data); @@ -383,12 +383,12 @@ static u16 Efuse_GetCurrentSize(struct adapter *pAdapter) hworden = efuse_data & 0x0F; } } else { - hoffset = (efuse_data>>4) & 0x0F; + hoffset = (efuse_data >> 4) & 0x0F; hworden = efuse_data & 0x0F; } word_cnts = Efuse_CalculateWordCnts(hworden); /* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; } else { break; } @@ -439,15 +439,15 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) continue; } } else { - hoffset = (efuse_data>>4) & 0x0F; + hoffset = (efuse_data >> 4) & 0x0F; hworden = efuse_data & 0x0F; } word_cnts = Efuse_CalculateWordCnts(hworden); bDataEmpty = true; if (hoffset == offset) { - for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) { - if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) { + for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) { + if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data)) { tmpdata[tmpidx] = efuse_data; if (efuse_data != 0xff) bDataEmpty = false; @@ -456,11 +456,11 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (!bDataEmpty) { ReadState = PG_STATE_DATA; } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } else {/* read next header */ - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } else { @@ -469,7 +469,7 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) } else if (ReadState & PG_STATE_DATA) { /* Data section Read ------------- */ efuse_WordEnableDataRead(hworden, tmpdata, data); - efuse_addr = efuse_addr + (word_cnts*2)+1; + efuse_addr = efuse_addr + (word_cnts * 2) + 1; ReadState = PG_STATE_HEADER; } } @@ -491,7 +491,7 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { /* check if data exist */ - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata); + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata); if (badworden != 0xf) { /* write fail */ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata); @@ -501,10 +501,10 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st else efuse_addr = Efuse_GetCurrentSize(pAdapter); } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } } else { - efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1; + efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1; } *pAddr = efuse_addr; return true; @@ -601,7 +601,7 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse } else { struct pgpkt fixPkt; - fixPkt.offset = (tmp_header>>4) & 0x0F; + fixPkt.offset = (tmp_header >> 4) & 0x0F; fixPkt.word_en = tmp_header & 0x0F; fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en); if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr)) @@ -619,7 +619,7 @@ static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u u32 PgWriteSuccess = 0; badworden = 0x0f; - badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data); + badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data); if (badworden == 0x0F) { /* write ok */ return true; @@ -681,8 +681,8 @@ static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, bool ret = false; u8 i, efuse_data; - for (i = 0; i < (word_cnts*2); i++) { - if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF)) + for (i = 0; i < (word_cnts * 2); i++) { + if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data) && (efuse_data != 0xFF)) ret = true; } return ret; @@ -721,7 +721,7 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u } } else { cur_header = efuse_data; - curPkt.offset = (cur_header>>4) & 0x0F; + curPkt.offset = (cur_header >> 4) & 0x0F; curPkt.word_en = cur_header & 0x0F; } @@ -729,10 +729,10 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u /* if same header is found but no data followed */ /* write some part of data followed by the header. */ if ((curPkt.offset == pTargetPkt->offset) && - (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) && + (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1)) && wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) { /* Here to write partial data */ - badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data); + badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data); if (badworden != 0x0F) { u32 PgWriteSuccess = 0; /* if write fail on some words, write these bad words again */ @@ -746,13 +746,13 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u } /* partial write ok, update the target packet for later use */ for (i = 0; i < 4; i++) { - if ((matched_wden & (0x1<word_en |= (0x1<word_en |= (0x1 << i); /* disable the word */ } pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en); } /* read from next header */ - startAddr = startAddr + (curPkt.word_cnts*2) + 1; + startAddr = startAddr + (curPkt.word_cnts * 2) + 1; } else { /* not used header, 0xff */ *pAddr = startAddr; @@ -765,7 +765,7 @@ static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt) { - memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8); + memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8); pTargetPkt->offset = offset; pTargetPkt->word_en = word_en; efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data); @@ -815,13 +815,13 @@ u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data) u8 tmpidx = 0; u8 result; - usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff)); - usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) | - (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC)); + usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); + usb_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) | + (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC)); - usb_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */ + usb_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */ - while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) + while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) tmpidx++; if (tmpidx < 100) { *data = usb_read8(pAdapter, EFUSE_CTRL); @@ -838,15 +838,15 @@ u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data) u8 tmpidx = 0; u8 result; - usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff)); - usb_write8(pAdapter, EFUSE_CTRL+2, - (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) | - (u8)((addr>>8) & 0x03)); + usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff)); + usb_write8(pAdapter, EFUSE_CTRL + 2, + (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) | + (u8)((addr >> 8) & 0x03)); usb_write8(pAdapter, EFUSE_CTRL, data);/* data */ - usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */ + usb_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */ - while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100)) + while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100)) tmpidx++; if (tmpidx < 100) -- cgit v1.2.3-59-g8ed1b From 783f9a6a2d2c2b1e5c5bc51f6407e66473385b3a Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sun, 4 Aug 2019 00:00:54 +0530 Subject: staging: rtl8723bs: core: correct spelling mistake in rtw_ap.c Correct spelling mistake in rtw_ap.c Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803183051.GA23151@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 7bd5c61b055c..78b5782fb675 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -94,7 +94,7 @@ static void update_BCNTIM(struct adapter *padapter) } else { tim_ielen = 0; - /* calucate head_len */ + /* calculate head_len */ offset = _FIXED_IE_LENGTH_; /* get ssid_ie len */ @@ -143,7 +143,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = tim_ielen; *dst_ie++ = 0;/* DTIM count */ - *dst_ie++ = 1;/* DTIM peroid */ + *dst_ie++ = 1;/* DTIM period */ if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */ *dst_ie++ = BIT(0);/* bitmap ctrl */ @@ -292,7 +292,7 @@ void expire_timeout_chk(struct adapter *padapter) if (psta->state & WIFI_SLEEP_STATE) { if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - /* to check if alive by another methods if staion is at ps mode. */ + /* to check if alive by another methods if station is at ps mode. */ psta->expire_to = pstapriv->expire_to; psta->state |= WIFI_STA_ALIVE_CHK_STATE; @@ -916,7 +916,7 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) UpdateBrateTbl(padapter, pnetwork->SupportedRates); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); - /* udpate capability after cur_wireless_mode updated */ + /* update capability after cur_wireless_mode updated */ update_capinfo( padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork) @@ -1015,7 +1015,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->Ssid.SsidLength = ie_len; } - /* chnnel */ + /* channel */ channel = 0; pbss_network->Configuration.Length = 0; p = rtw_get_ie( @@ -1827,7 +1827,7 @@ void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) /* op_mode -Set to 0 (HT pure) under the followign conditions +Set to 0 (HT pure) under the following conditions - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - all STAs in the BSS are 20 MHz HT in 20 MHz BSS Set to 1 (HT non-member protection) if there may be non-HT STAs -- cgit v1.2.3-59-g8ed1b From 67ca96bbd0315cc804668d42568934b88fe1d968 Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sun, 4 Aug 2019 00:17:54 +0530 Subject: staging: rtl8723bs: core: Remove Unnecessary parentheses Remove Unnecessary parentheses around padapter->mlmepriv, pmlmeext->mlmext_info and pmlmeinfo->network in rtw_ap.c Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803184750.GA23507@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 78b5782fb675..45a745696af6 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -17,7 +17,7 @@ extern unsigned char WFD_OUI[]; void init_mlme_ap_info(struct adapter *padapter) { - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct sta_priv *pstapriv = &padapter->stapriv; struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; @@ -34,9 +34,9 @@ void init_mlme_ap_info(struct adapter *padapter) void free_mlme_ap_info(struct adapter *padapter) { struct sta_info *psta = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; /* stop_ap_mode(padapter); */ @@ -58,9 +58,9 @@ void free_mlme_ap_info(struct adapter *padapter) static void update_BCNTIM(struct adapter *padapter) { struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; + struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; unsigned char *pie = pnetwork_mlmeext->IEs; /* DBG_871X("%s\n", __func__); */ -- cgit v1.2.3-59-g8ed1b From d8ba499d53d92fbee87638f3313b2281d04300bd Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Sun, 4 Aug 2019 00:55:55 +0530 Subject: staging: rtl8723bs: core: add spaces around '-', '+', '&','|' and '?' Add spaces around '-', '+', '&','|' and '?' to improve readability and follow kernel coding style in rtw_ap.c Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190803192551.GA24041@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 88 ++++++++++++++++----------------- 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 45a745696af6..02f5478845b4 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -83,7 +83,7 @@ static void update_BCNTIM(struct adapter *padapter) if (p != NULL && tim_ielen > 0) { tim_ielen += 2; - premainder_ie = p+tim_ielen; + premainder_ie = p + tim_ielen; tim_ie_offset = (sint)(p - pie); @@ -105,7 +105,7 @@ static void update_BCNTIM(struct adapter *padapter) (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) - offset += tmp_len+2; + offset += tmp_len + 2; /* get supported rates len */ p = rtw_get_ie( @@ -114,7 +114,7 @@ static void update_BCNTIM(struct adapter *padapter) (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) - offset += tmp_len+2; + offset += tmp_len + 2; /* DS Parameter Set IE, len =3 */ offset += 3; @@ -135,7 +135,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = _TIM_IE_; - if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe)) + if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fe)) tim_ielen = 5; else tim_ielen = 4; @@ -145,7 +145,7 @@ static void update_BCNTIM(struct adapter *padapter) *dst_ie++ = 0;/* DTIM count */ *dst_ie++ = 1;/* DTIM period */ - if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */ + if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ *dst_ie++ = BIT(0);/* bitmap ctrl */ else *dst_ie++ = 0; @@ -153,7 +153,7 @@ static void update_BCNTIM(struct adapter *padapter) if (tim_ielen == 4) { __le16 pvb; - if (pstapriv->tim_bitmap&0xff00) + if (pstapriv->tim_bitmap & 0xff00) pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8); else pvb = tim_bitmap_le; @@ -188,8 +188,8 @@ u8 chk_sta_is_alive(struct sta_info *psta) /* STA_RX_PKTS_ARG(psta) */ , STA_RX_PKTS_DIFF_ARG(psta) , psta->expire_to - , psta->state&WIFI_SLEEP_STATE?"PS, ":"" - , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":"" + , psta->state & WIFI_SLEEP_STATE ? "PS, " : "" + , psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : "" , psta->sleepq_len ); #endif @@ -325,10 +325,10 @@ void expire_timeout_chk(struct adapter *padapter) updated = ap_free_sta(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING); } else { /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ - if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt) + if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) && padapter->xmitpriv.free_xmitframe_cnt < (( - NR_XMITFRAME/pstapriv->asoc_list_cnt - )/2) + NR_XMITFRAME / pstapriv->asoc_list_cnt + ) / 2) ) { DBG_871X( "%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", @@ -586,8 +586,8 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; phtpriv_sta->rx_ampdu_min_spacing = ( - phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY - )>>2; + phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY + ) >> 2; /* bwmode */ if (( @@ -782,8 +782,8 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) /* check if there is wps ie, */ /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */ - if (!rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, - pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL)) + if (!rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, + pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; /* todo: update wmm, ht cap */ @@ -861,7 +861,7 @@ void start_bss_network(struct adapter *padapter, u8 *pbuf) (pnetwork->IELength - sizeof(struct ndis_802_11_fix_ie)) ); if (p && ie_len) { - pht_info = (struct HT_info_element *)(p+2); + pht_info = (struct HT_info_element *)(p + 2); if (cur_channel > 14) { if ((pregpriv->bw_mode & 0xf0) > 0) @@ -1037,7 +1037,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) (pbss_network->IELength - _BEACON_IE_OFFSET_) ); if (p != NULL) { - memcpy(supportRate, p+2, ie_len); + memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } @@ -1049,7 +1049,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pbss_network->IELength - _BEACON_IE_OFFSET_ ); if (p != NULL) { - memcpy(supportRate+supportRateNum, p+2, ie_len); + memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } @@ -1088,7 +1088,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (p && ie_len > 0) { if (rtw_parse_wpa2_ie( p, - ie_len+2, + ie_len + 2, &group_cipher, &pairwise_cipher, NULL @@ -1115,10 +1115,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)) ); - if ((p) && (!memcmp(p+2, OUI1, 4))) { + if ((p) && (!memcmp(p + 2, OUI1, 4))) { if (rtw_parse_wpa_ie( p, - ie_len+2, + ie_len + 2, &group_cipher, &pairwise_cipher, NULL @@ -1151,10 +1151,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)) ); - if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) { + if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; - *(p+8) |= BIT(7);/* QoS Info, support U-APSD */ + *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */ /* disable all ACM bits since the WMM admission control is not supported */ *(p + 10) &= ~BIT(4); /* BE */ @@ -1180,7 +1180,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (p && ie_len > 0) { u8 rf_type = 0; u8 max_rx_ampdu_factor = 0; - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2); + struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); pHT_caps_ie = p; @@ -1205,14 +1205,14 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_RX_STBC_3R)); pht_cap->ampdu_params_info &= ~( - IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY + IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY ); if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2)); } else { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); } rtw_hal_get_def_var( @@ -1230,7 +1230,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->supp_mcs_set[1] = 0x0; } - memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); + memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); } /* parsing HT_INFO_IE */ @@ -1265,8 +1265,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pmlmepriv->htpriv.ht_option = false; - if ((psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || - (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP)) { + if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || + (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { /* todo: */ /* ht_cap = false; */ } @@ -1341,7 +1341,7 @@ int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) MAC_ARG(addr) ); - if ((NUM_ACL-1) < pacl_list->num) + if ((NUM_ACL - 1) < pacl_list->num) return (-1); spin_lock_bh(&(pacl_node_q->lock)); @@ -1454,7 +1454,7 @@ u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta) psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); if (psetstakey_para == NULL) { - kfree((u8 *) ph2c); + kfree((u8 *)ph2c); res = _FAIL; goto exit; } @@ -1604,10 +1604,10 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter) struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p; if (pmlmepriv->num_sta_non_erp == 1) - pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION; + pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; else pIE->data[0] &= ~( - RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION + RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION ); if (pmlmepriv->num_sta_no_short_preamble > 0) @@ -1662,8 +1662,8 @@ static void update_bcn_wps_ie(struct adapter *padapter) DBG_871X("%s\n", __func__); pwps_ie = rtw_get_wps_ie( - ie+_FIXED_IE_LENGTH_, - ielen-_FIXED_IE_LENGTH_, + ie + _FIXED_IE_LENGTH_, + ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen ); @@ -1675,7 +1675,7 @@ static void update_bcn_wps_ie(struct adapter *padapter) if (pwps_ie_src == NULL) return; - wps_offset = (uint)(pwps_ie-ie); + wps_offset = (uint)(pwps_ie - ie); premainder_ie = pwps_ie + wps_ielen; @@ -1688,22 +1688,22 @@ static void update_bcn_wps_ie(struct adapter *padapter) } wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ - if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { - memcpy(pwps_ie, pwps_ie_src, wps_ielen+2); + if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { + memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); pwps_ie += (wps_ielen+2); if (pbackup_remainder_ie) memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); /* update IELength */ - pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen; + pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen; } kfree(pbackup_remainder_ie); /* deal with the case without set_tx_beacon_cmd() in update_beacon() */ #if defined(CONFIG_INTERRUPT_BASED_TXBCN) - if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { + if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { u8 sr = 0; rtw_get_wps_attr_content( @@ -2196,7 +2196,7 @@ void rtw_sta_flush(struct adapter *padapter) DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) + if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) return; spin_lock_bh(&pstapriv->asoc_list_lock); @@ -2230,7 +2230,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); /* update wmm cap. */ - if (WLAN_STA_WME&flags) + if (WLAN_STA_WME & flags) psta->qos_option = 1; else psta->qos_option = 0; @@ -2239,7 +2239,7 @@ void sta_info_update(struct adapter *padapter, struct sta_info *psta) psta->qos_option = 0; /* update 802.11n ht cap. */ - if (WLAN_STA_HT&flags) { + if (WLAN_STA_HT & flags) { psta->htpriv.ht_option = true; psta->qos_option = 1; } else { -- cgit v1.2.3-59-g8ed1b From 36d042bd6865ada4fc5b14e2cb5fd325eeb248db Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 4 Aug 2019 08:18:32 +0530 Subject: staging: rtl8192e: Make use kmemdup As kmemdup API does kmalloc + memcpy . We can make use of it instead of calling kmalloc and memcpy independetly. Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190804024832.GA14352@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index e29e8d6f4611..f2f7529e7c80 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -1382,15 +1382,10 @@ rtllib_association_req(struct rtllib_network *beacon, ieee->assocreq_ies = NULL; ies = &(hdr->info_element[0].id); ieee->assocreq_ies_len = (skb->data + skb->len) - ies; - ieee->assocreq_ies = kmalloc(ieee->assocreq_ies_len, GFP_ATOMIC); - if (ieee->assocreq_ies) - memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len); - else { - netdev_info(ieee->dev, - "%s()Warning: can't alloc memory for assocreq_ies\n", - __func__); + ieee->assocreq_ies = kmemdup(ies, ieee->assocreq_ies_len, GFP_ATOMIC); + if (!ieee->assocreq_ies) ieee->assocreq_ies_len = 0; - } + return skb; } @@ -2259,17 +2254,12 @@ rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, ieee->assocresp_ies = NULL; ies = &(assoc_resp->info_element[0].id); ieee->assocresp_ies_len = (skb->data + skb->len) - ies; - ieee->assocresp_ies = kmalloc(ieee->assocresp_ies_len, + ieee->assocresp_ies = kmemdup(ies, + ieee->assocresp_ies_len, GFP_ATOMIC); - if (ieee->assocresp_ies) - memcpy(ieee->assocresp_ies, ies, - ieee->assocresp_ies_len); - else { - netdev_info(ieee->dev, - "%s()Warning: can't alloc memory for assocresp_ies\n", - __func__); + if (!ieee->assocresp_ies) ieee->assocresp_ies_len = 0; - } + rtllib_associate_complete(ieee); } else { /* aid could not been allocated */ -- cgit v1.2.3-59-g8ed1b From b0d525a007b9c954bd2f777174a378eb76cb89e2 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 6 Aug 2019 10:33:49 +0000 Subject: staging: wilc1000: use helper API to pack data for firmware As discussed in [1] use put_unaligned_le16() & put_unaligned_le32() helper to pack the data before sending to firmware. [1]. https://lore.kernel.org/linux-wireless/86bc79ccd379497d56bade79ec8f717603110ef7.camel@sipsolutions.net/ Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20190806103325.14063-1-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan_cfg.c | 74 ++++++++------------------------ 1 file changed, 18 insertions(+), 56 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index f4144f93e4a9..3f53807cee0f 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -52,57 +52,35 @@ static const struct wilc_cfg_str g_cfg_str[] = { static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8) { - u8 *buf; - if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 1; - buf[3] = 0; - buf[4] = val8; + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(1, &frame[offset + 2]); + frame[offset + 4] = val8; return 5; } static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16) { - u8 *buf; - if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 2; - buf[3] = 0; - buf[4] = (u8)val16; - buf[5] = (u8)(val16 >> 8); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(2, &frame[offset + 2]); + put_unaligned_le16(val16, &frame[offset + 4]); return 6; } static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) { - u8 *buf; - if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = 4; - buf[3] = 0; - buf[4] = (u8)val32; - buf[5] = (u8)(val32 >> 8); - buf[6] = (u8)(val32 >> 16); - buf[7] = (u8)(val32 >> 24); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(4, &frame[offset + 2]); + put_unaligned_le32(val32, &frame[offset + 4]); return 8; } @@ -110,46 +88,35 @@ static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, u32 size) { - u8 *buf; - if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = (u8)size; - buf[3] = (u8)(size >> 8); - + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(size, &frame[offset + 2]); if (str && size != 0) - memcpy(&buf[4], str, size); + memcpy(&frame[offset + 4], str, size); return (size + 4); } static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) { - u8 *buf; u32 i; u8 checksum = 0; if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); - buf[2] = (u8)size; - buf[3] = (u8)(size >> 8); + put_unaligned_le16(id, &frame[offset]); + put_unaligned_le16(size, &frame[offset + 2]); if ((b) && size != 0) { - memcpy(&buf[4], b, size); + memcpy(&frame[offset + 4], b, size); for (i = 0; i < size; i++) - checksum += buf[i + 4]; + checksum += frame[offset + i + 4]; } - buf[size + 4] = checksum; + frame[offset + size + 4] = checksum; return (size + 5); } @@ -307,15 +274,10 @@ int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size) int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) { - u8 *buf; - if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE) return 0; - buf = &frame[offset]; - - buf[0] = (u8)id; - buf[1] = (u8)(id >> 8); + put_unaligned_le16(id, &frame[offset]); return 2; } -- cgit v1.2.3-59-g8ed1b From 4f4139e0213516e74cc22fc9787671f325c2b66b Mon Sep 17 00:00:00 2001 From: Merwin Trever Ferrao Date: Tue, 6 Aug 2019 17:58:49 +0530 Subject: Staging: rtl8188eu: core: rtw_security: tidy up crc32_init() This code generates checkpatch warning: WARNING: else is not generally useful after a break or return Moving the declaration to the top of the function we can pull the code back one tab and it makes it more readable. Signed-off-by: Merwin Trever Ferrao Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190806122849.GA25628@IoT-COE Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_security.c | 41 +++++++++++++-------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 2f90f60f1681..435c0fbec54a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -87,29 +87,28 @@ static u8 crc32_reverseBit(u8 data) static void crc32_init(void) { - if (bcrc32initialized == 1) { + int i, j; + u32 c; + u8 *p = (u8 *)&c, *p1; + u8 k; + + if (bcrc32initialized == 1) return; - } else { - int i, j; - u32 c; - u8 *p = (u8 *)&c, *p1; - u8 k; - - c = 0x12340000; - - for (i = 0; i < 256; ++i) { - k = crc32_reverseBit((u8)i); - for (c = ((u32)k) << 24, j = 8; j > 0; --j) - c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); - p1 = (u8 *)&crc32_table[i]; - - p1[0] = crc32_reverseBit(p[3]); - p1[1] = crc32_reverseBit(p[2]); - p1[2] = crc32_reverseBit(p[1]); - p1[3] = crc32_reverseBit(p[0]); - } - bcrc32initialized = 1; + + c = 0x12340000; + + for (i = 0; i < 256; ++i) { + k = crc32_reverseBit((u8)i); + for (c = ((u32)k) << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); + p1 = (u8 *)&crc32_table[i]; + + p1[0] = crc32_reverseBit(p[3]); + p1[1] = crc32_reverseBit(p[2]); + p1[2] = crc32_reverseBit(p[1]); + p1[3] = crc32_reverseBit(p[0]); } + bcrc32initialized = 1; } static __le32 getcrc32(u8 *buf, int len) -- cgit v1.2.3-59-g8ed1b From 5222a8fe6bd0135bd87a629d8d182f951b4ffeae Mon Sep 17 00:00:00 2001 From: Giridhar Prasath R Date: Wed, 7 Aug 2019 07:33:31 +0530 Subject: staging: isdn: hysdn_procconf_init() remove parantheses from return value ERROR: return is not a function, parentheses are not required FILE: git/kernels/staging/drivers/staging/isdn/hysdn/hysdn_procconf.c:385 + return (0); Signed-off-by: Giridhar Prasath R Link: https://lore.kernel.org/r/20190807020331.19729-1-cristianoprasath@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/isdn/hysdn/hysdn_procconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/isdn/hysdn/hysdn_procconf.c b/drivers/staging/isdn/hysdn/hysdn_procconf.c index 73079213ec94..48afd9f5316e 100644 --- a/drivers/staging/isdn/hysdn/hysdn_procconf.c +++ b/drivers/staging/isdn/hysdn/hysdn_procconf.c @@ -382,7 +382,7 @@ hysdn_procconf_init(void) } printk(KERN_NOTICE "HYSDN: procfs initialised\n"); - return (0); + return 0; } /* hysdn_procconf_init */ /*************************************************************************************/ -- cgit v1.2.3-59-g8ed1b From a9ca0c5951ff1cb782cd78dd3eb57afb35f2f841 Mon Sep 17 00:00:00 2001 From: Jose Carlos Cazarin Filho Date: Tue, 6 Aug 2019 20:45:39 -0300 Subject: staging: rtl8723bs: fix brace position in enum declaration Fix two checkpath errors of type: "open brace '{' following enum go on the same line" Signed-off-by: Jose Carlos Cazarin Filho Link: https://lore.kernel.org/r/20190806234539.7513-1-joseespiriki@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/include/rtw_mlme.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index d3c07d1c36e9..2223e1f139f2 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -81,15 +81,13 @@ enum dot11AuthAlgrthmNum { }; /* Scan type including active and passive scan. */ -typedef enum _RT_SCAN_TYPE -{ +typedef enum _RT_SCAN_TYPE { SCAN_PASSIVE, SCAN_ACTIVE, SCAN_MIX, }RT_SCAN_TYPE, *PRT_SCAN_TYPE; -enum _BAND -{ +enum _BAND { GHZ24_50 = 0, GHZ_50, GHZ_24, -- cgit v1.2.3-59-g8ed1b From fc898688aa37c08b872a2228d1f0397d01111652 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:03 +0530 Subject: staging: rtl8712: amsdu_to_msdu(): Change return type Change return type of amsdu_to_msdu from int to void as it always returns _SUCCESS. Remove return statement as well. As this return value was never anything other than _SUCCESS, remove the if-branch that depends on the return value not being _SUCCESS. Remove local variable that was only used in the now-removed if-branch Modify call site to call the function amsdu_to_msdu without expecting a return value. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index eb9a4a5ed740..42372e7e76ac 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -318,7 +318,7 @@ union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter, return prtnframe; } -static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) +static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) { int a_len, padding_len; u16 eth_type, nSubframe_Length; @@ -416,7 +416,6 @@ static int amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe) exit: prframe->u.hdr.len = 0; r8712_free_recvframe(prframe, pfree_recv_queue); - return _SUCCESS; } void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf) @@ -506,7 +505,6 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, union recv_frame *prframe; struct rx_pkt_attrib *pattrib; int bPktInBuf = false; - struct recv_priv *precvpriv = &padapter->recvpriv; struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; @@ -543,10 +541,7 @@ int r8712_recv_indicatepkts_in_order(struct _adapter *padapter, prframe); } } else if (pattrib->amsdu == 1) { - if (amsdu_to_msdu(padapter, prframe) != - _SUCCESS) - r8712_free_recvframe(prframe, - &precvpriv->free_recv_queue); + amsdu_to_msdu(padapter, prframe); } /* Update local variables. */ bPktInBuf = false; -- cgit v1.2.3-59-g8ed1b From 4dbadfaf6a77e3d9ffe7069a8f1a13ae0df00d56 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:04 +0530 Subject: staging: rtl8712: recv_indicatepkt_reorder(): Change return values Change return values of recv_indicatepkt_reorder from _SUCCESS/_FAIL to 0/-ENOMEM and -EINVAL. Within recv_indicatepkt_reorder, modify comparison to true and use the respective value directly. Modify call site of recv_indicatepkt_reorder to check for the new return values. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 42372e7e76ac..3950b2424b64 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -569,9 +569,9 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, if (!padapter->driver_stopped && !padapter->surprise_removed) { r8712_recv_indicatepkt(padapter, prframe); - return _SUCCESS; + return 0; } else { - return _FAIL; + return -EINVAL; } } } @@ -593,8 +593,7 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, * 2. All packets with SeqNum larger than or equal to * WinStart => Buffer it. */ - if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == - true) { + if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) { mod_timer(&preorder_ctrl->reordering_ctrl_timer, jiffies + msecs_to_jiffies(REORDER_WAIT_TIME)); spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); @@ -602,10 +601,10 @@ static int recv_indicatepkt_reorder(struct _adapter *padapter, spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); del_timer(&preorder_ctrl->reordering_ctrl_timer); } - return _SUCCESS; + return 0; _err_exit: spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); - return _FAIL; + return -ENOMEM; } void r8712_reordering_ctrl_timeout_handler(void *pcontext) @@ -631,7 +630,7 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter, struct ht_priv *phtpriv = &pmlmepriv->htpriv; if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ - if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { + if (recv_indicatepkt_reorder(padapter, prframe)) { /* including perform A-MPDU Rx Ordering Buffer Control*/ if (!padapter->driver_stopped && !padapter->surprise_removed) -- cgit v1.2.3-59-g8ed1b From 1bdcb3666a83e533feb35a5a86e4e8e01b44dc18 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:05 +0530 Subject: staging: rtl8712: r8712_wlanhdr_to_ethhdr(): Change return values Change return values of r8712_wlanhdr_to_ethhdr from _SUCCESS/_FAIL to 0/-ENOMEM. Modify the function containing a call site of r8712_wlanhdr_to_ethhdr so that it compares the return value to 0/-ENOMEM instead of _SUCCESS/_FAIL. Change the return type of r8712_wlanhdr_to_ethhdr from sint to int to match its prototype in corresponding .h file. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 4 ++-- drivers/staging/rtl8712/rtl871x_recv.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 3950b2424b64..0c5712898653 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -638,8 +638,8 @@ static int r8712_process_recv_indicatepkts(struct _adapter *padapter, } } else { /*B/G mode*/ retval = r8712_wlanhdr_to_ethhdr(prframe); - if (retval != _SUCCESS) - return retval; + if (retval) + return _FAIL; if (!padapter->driver_stopped && !padapter->surprise_removed) { /* indicate this recv_frame */ r8712_recv_indicatepkt(padapter, prframe); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 79c7a329e9f6..4fae3af36af5 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -585,7 +585,7 @@ sint r8712_validate_recv_frame(struct _adapter *adapter, return retval; } -sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) +int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) { /*remove the wlanhdr and add the eth_hdr*/ sint rmv_len; @@ -628,14 +628,14 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24); if (!ptr) - return _FAIL; + return -ENOMEM; memcpy(ptr, get_rxmem(precvframe), 24); ptr += 24; } else { ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0))); if (!ptr) - return _FAIL; + return -ENOMEM; } memcpy(ptr, pattrib->dst, ETH_ALEN); @@ -645,7 +645,7 @@ sint r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) memcpy(ptr + 12, &be_tmp, 2); } - return _SUCCESS; + return 0; } s32 r8712_recv_entry(union recv_frame *precvframe) -- cgit v1.2.3-59-g8ed1b From af556d30d3387f8b01495b1645d237121b6624d6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:06 +0530 Subject: staging: rtl8712: r8712_recv_entry(): Change return type Change return type of r8712_recv_entry from s32 to void as its return value is never used. Modify or remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/recv_osdep.h | 2 +- drivers/staging/rtl8712/rtl871x_recv.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index 792f9cfbacd9..d8c1fa74f544 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -21,7 +21,7 @@ void _r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter); void _r8712_free_recv_priv(struct recv_priv *precvpriv); -s32 r8712_recv_entry(union recv_frame *precv_frame); +void r8712_recv_entry(union recv_frame *precv_frame); void r8712_recv_indicatepkt(struct _adapter *adapter, union recv_frame *precv_frame); void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup); diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 4fae3af36af5..e5092b6da4bd 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -648,7 +648,7 @@ int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe) return 0; } -s32 r8712_recv_entry(union recv_frame *precvframe) +void r8712_recv_entry(union recv_frame *precvframe) { struct _adapter *padapter; struct recv_priv *precvpriv; @@ -666,9 +666,8 @@ s32 r8712_recv_entry(union recv_frame *precvframe) precvpriv->rx_pkts++; precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail - precvframe->u.hdr.rx_data); - return ret; + return; _recv_entry_drop: precvpriv->rx_drop++; padapter->mppriv.rx_pktloss = precvpriv->rx_drop; - return ret; } -- cgit v1.2.3-59-g8ed1b From 9dca5e687fb05e1b968e5151fd868ed4722863f6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:07 +0530 Subject: staging: rtl8712: recvbuf2recvframe(): Change return type Change return type of recvbuf2recvframe from int to void as its return value is never used. Modify or remove return statements accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 0c5712898653..42cb2c95b40c 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -980,7 +980,7 @@ _exit_recv_func: return retval; } -static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) +static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) { u8 *pbuf, shift_sz = 0; u8 frag, mf; @@ -1007,7 +1007,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) /* In this case, it means the MAX_RECVBUF_SZ is too small to * get the data from 8712u. */ - return _FAIL; + return; } do { prxstat = (struct recv_stat *)pbuf; @@ -1020,13 +1020,13 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16; drvinfo_sz <<= 3; if (pkt_len <= 0) - goto _exit_recvbuf2recvframe; + return; /* Qos data, wireless lan header length is 26 */ if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01) shift_sz = 2; precvframe = r8712_alloc_recvframe(pfree_recv_queue); if (!precvframe) - goto _exit_recvbuf2recvframe; + return; INIT_LIST_HEAD(&precvframe->u.hdr.list); precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/ precvframe->u.hdr.len = 0; @@ -1057,7 +1057,7 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) } else { precvframe->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); if (!precvframe->u.hdr.pkt) - return _FAIL; + return; precvframe->u.hdr.rx_head = pbuf; precvframe->u.hdr.rx_data = pbuf; precvframe->u.hdr.rx_tail = pbuf; @@ -1077,8 +1077,6 @@ static int recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb) precvframe = NULL; pkt_copy = NULL; } while ((transfer_len > 0) && pkt_cnt > 0); -_exit_recvbuf2recvframe: - return _SUCCESS; } static void recv_tasklet(void *priv) -- cgit v1.2.3-59-g8ed1b From 30d83c801d068abbfbb8f6f47e0c1f2a4a36e4b9 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:08 +0530 Subject: staging: rtl8712: init_default_value(): Change return type Change return type of init_default_value from u8 to void as it always returns _SUCCESS. Remove now-unnecessary return statement. Modify call site to simply call the function. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b4059ea17e5c..c98acf4f6fff 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -258,7 +258,7 @@ void r8712_stop_drv_timers(struct _adapter *padapter) del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer); } -static u8 init_default_value(struct _adapter *padapter) +static void init_default_value(struct _adapter *padapter) { struct registry_priv *pregistrypriv = &padapter->registrypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; @@ -292,7 +292,6 @@ static u8 init_default_value(struct _adapter *padapter) r8712_init_registrypriv_dev_network(padapter); r8712_update_registrypriv_dev_network(padapter); /*misc.*/ - return _SUCCESS; } u8 r8712_init_drv_sw(struct _adapter *padapter) @@ -316,8 +315,7 @@ u8 r8712_init_drv_sw(struct _adapter *padapter) r8712_init_bcmc_stainfo(padapter); r8712_init_pwrctrl_priv(padapter); mp871xinit(padapter); - if (init_default_value(padapter) != _SUCCESS) - return _FAIL; + init_default_value(padapter); r8712_InitSwLeds(padapter); return _SUCCESS; } -- cgit v1.2.3-59-g8ed1b From 690407fdc9dd8103a78c251c59513646f1bed50d Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:09 +0530 Subject: staging: rtl8712: init_drv_sw(): Change return values Change return values of init_drv_sw from _SUCCESS and _FAIL to 0 and -ENOMEM. Change return type from u8 to int to allow this. Add a return variable to streamline return of error codes of called functions. Modify call site to check for non-zero return value instead of _FAIL. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 26 ++++++++++++++++---------- drivers/staging/rtl8712/usb_intf.c | 2 +- drivers/staging/rtl8712/usb_osintf.h | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index c98acf4f6fff..be3e5bdea495 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -294,30 +294,36 @@ static void init_default_value(struct _adapter *padapter) /*misc.*/ } -u8 r8712_init_drv_sw(struct _adapter *padapter) +int r8712_init_drv_sw(struct _adapter *padapter) { - if (r8712_init_cmd_priv(&padapter->cmdpriv)) - return _FAIL; + int ret; + + ret = r8712_init_cmd_priv(&padapter->cmdpriv); + if (ret) + return ret; padapter->cmdpriv.padapter = padapter; - if (r8712_init_evt_priv(&padapter->evtpriv)) - return _FAIL; - if (r8712_init_mlme_priv(padapter)) - return _FAIL; + ret = r8712_init_evt_priv(&padapter->evtpriv); + if (ret) + return ret; + ret = r8712_init_mlme_priv(padapter); + if (ret) + return ret; _r8712_init_xmit_priv(&padapter->xmitpriv, padapter); _r8712_init_recv_priv(&padapter->recvpriv, padapter); memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv)); timer_setup(&padapter->securitypriv.tkip_timer, r8712_use_tkipkey_handler, 0); - if (_r8712_init_sta_priv(&padapter->stapriv)) - return _FAIL; + ret = _r8712_init_sta_priv(&padapter->stapriv); + if (ret) + return ret; padapter->stapriv.padapter = padapter; r8712_init_bcmc_stainfo(padapter); r8712_init_pwrctrl_priv(padapter); mp871xinit(padapter); init_default_value(padapter); r8712_InitSwLeds(padapter); - return _SUCCESS; + return ret; } u8 r8712_free_drv_sw(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index d0daae0b8299..ba1288297ee4 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -389,7 +389,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } /* step 4. */ status = r8712_init_drv_sw(padapter); - if (status == _FAIL) + if (status) goto error; /* step 5. read efuse/eeprom data and get mac_addr */ { diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h index ddfa405d0c9b..b649adedfe7c 100644 --- a/drivers/staging/rtl8712/usb_osintf.h +++ b/drivers/staging/rtl8712/usb_osintf.h @@ -28,7 +28,7 @@ void rtl871x_intf_stop(struct _adapter *padapter); void r871x_dev_unload(struct _adapter *padapter); void r8712_stop_drv_threads(struct _adapter *padapter); void r8712_stop_drv_timers(struct _adapter *padapter); -u8 r8712_init_drv_sw(struct _adapter *padapter); +int r8712_init_drv_sw(struct _adapter *padapter); u8 r8712_free_drv_sw(struct _adapter *padapter); struct net_device *r8712_init_netdev(void); -- cgit v1.2.3-59-g8ed1b From 02433a24fe71ba31b8392c2bf98ff9e8a2bce3b6 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:10 +0530 Subject: staging: rtl8712: r8712_free_drv_sw(): Change return type Change return type of r8712_free_drv_sw from u8 to void and remove its return statement as it always returns the same value (_SUCCESS) and even this value is never stored, checked or otherwise used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 3 +-- drivers/staging/rtl8712/usb_osintf.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index be3e5bdea495..0c3ae8495afb 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -326,7 +326,7 @@ int r8712_init_drv_sw(struct _adapter *padapter) return ret; } -u8 r8712_free_drv_sw(struct _adapter *padapter) +void r8712_free_drv_sw(struct _adapter *padapter) { struct net_device *pnetdev = padapter->pnetdev; @@ -341,7 +341,6 @@ u8 r8712_free_drv_sw(struct _adapter *padapter) mp871xdeinit(padapter); if (pnetdev) free_netdev(pnetdev); - return _SUCCESS; } static void enable_video_mode(struct _adapter *padapter, int cbw40_value) diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h index b649adedfe7c..2e512b4a564c 100644 --- a/drivers/staging/rtl8712/usb_osintf.h +++ b/drivers/staging/rtl8712/usb_osintf.h @@ -29,7 +29,7 @@ void r871x_dev_unload(struct _adapter *padapter); void r8712_stop_drv_threads(struct _adapter *padapter); void r8712_stop_drv_timers(struct _adapter *padapter); int r8712_init_drv_sw(struct _adapter *padapter); -u8 r8712_free_drv_sw(struct _adapter *padapter); +void r8712_free_drv_sw(struct _adapter *padapter); struct net_device *r8712_init_netdev(void); #endif -- cgit v1.2.3-59-g8ed1b From 1c8a4f7c84dcb187c076a87e716912053f6ad6ba Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:11 +0530 Subject: staging: rtl8712: Remove while loop and check_cmd_fifo() Remove while loop as it only runs while the function check_cmd_fifo returns _FAIL, whereas check_cmd_fifo always returns _SUCCESS (and hence this loop will never run). Remove now unused function check_cmd_fifo. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190808064012.12661-9-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_cmd.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c index f99fd7cfa445..ff3cb09c57a6 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.c +++ b/drivers/staging/rtl8712/rtl8712_cmd.c @@ -263,11 +263,6 @@ static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter, return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */ } -static u8 check_cmd_fifo(struct _adapter *padapter, uint sz) -{ - return _SUCCESS; -} - u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd) { int pollingcnts = 50; @@ -359,13 +354,6 @@ _next: (pcmdpriv->cmd_seq << 24)); pcmdbuf += 2; /* 8 bytes alignment */ memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz); - while (check_cmd_fifo(padapter, wr_sz) == _FAIL) { - if (padapter->driver_stopped || - padapter->surprise_removed) - break; - msleep(100); - continue; - } if (blnPending) wr_sz += 8; /* Append 8 bytes */ r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz, -- cgit v1.2.3-59-g8ed1b From 3f411e8c99e3354adc10350d0e2ee14914fd1961 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 8 Aug 2019 12:10:12 +0530 Subject: staging: rtl8712: r8712_xmit_classifier(): Change return values and type Change return values of r8712_xmit_classifier from _SUCCESS and _FAIL to 0 and -EINVAL respectively. Modify call site to check for non-zero return values instead of _FAIL. Change return type from sint to int. Signed-off-by: Nishka Dasgupta Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190808064012.12661-10-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 2 +- drivers/staging/rtl8712/rtl871x_xmit.c | 8 ++++---- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index dac79e6dcdcb..3334b03c2548 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -750,7 +750,7 @@ int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) { - if (r8712_xmit_classifier(padapter, pxmitframe) == _FAIL) { + if (r8712_xmit_classifier(padapter, pxmitframe)) { pxmitframe->pkt = NULL; return _FAIL; } diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 0a26d71e5340..f625fd5b9eb3 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -894,8 +894,8 @@ static inline struct tx_servq *get_sta_pending(struct _adapter *padapter, * Will enqueue pxmitframe to the proper queue, and indicate it * to xx_pending list..... */ -sint r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe) +int r8712_xmit_classifier(struct _adapter *padapter, + struct xmit_frame *pxmitframe) { unsigned long irqL0; struct __queue *pstapending; @@ -920,7 +920,7 @@ sint r8712_xmit_classifier(struct _adapter *padapter, } } if (psta == NULL) - return _FAIL; + return -EINVAL; ptxservq = get_sta_pending(padapter, &pstapending, psta, pattrib->priority); spin_lock_irqsave(&pstapending->lock, irqL0); @@ -929,7 +929,7 @@ sint r8712_xmit_classifier(struct _adapter *padapter, list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue); ptxservq->qcnt++; spin_unlock_irqrestore(&pstapending->lock, irqL0); - return _SUCCESS; + return 0; } static void alloc_hwxmits(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index c5c55967164b..d4bc059e6a42 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -258,8 +258,8 @@ void r8712_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe); void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue); -sint r8712_xmit_classifier(struct _adapter *padapter, - struct xmit_frame *pxmitframe); +int r8712_xmit_classifier(struct _adapter *padapter, + struct xmit_frame *pxmitframe); sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe); sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); -- cgit v1.2.3-59-g8ed1b From 0d1b57c1f04cad448eec54dc8de6da3777d3a28d Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Fri, 9 Aug 2019 18:25:18 +0000 Subject: staging: wilc1000: Don't reset WILC CPU disgracefully Send abort request to WILC from wilc_wlan_stop instead of resetting the CPU. The abort request was being sent from wilc_wlan_cleanup after the CPU was reset which wasn't the correct order. The abort request handler in the chip will take care of resetting the CPU. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190809182510.22443-2-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 4 +- drivers/staging/wilc1000/wilc_wlan.c | 75 +++++++++------------------------- drivers/staging/wilc1000/wilc_wlan.h | 5 ++- 3 files changed, 24 insertions(+), 60 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index 57510400f243..cd11c35adcfe 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -475,7 +475,7 @@ static void wilc_wlan_deinitialize(struct net_device *dev) wlan_deinitialize_threads(dev); deinit_irq(dev); - wilc_wlan_stop(wl); + wilc_wlan_stop(wl, vif); wilc_wlan_cleanup(dev); wlan_deinit_locks(dev); @@ -573,7 +573,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) return 0; fail_fw_start: - wilc_wlan_stop(wl); + wilc_wlan_stop(wl, vif); fail_irq_enable: if (!wl->dev_irq_num && diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d4ca6467485c..3d902b499a34 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -968,60 +968,42 @@ int wilc_wlan_start(struct wilc *wilc) return (ret < 0) ? ret : 0; } -int wilc_wlan_stop(struct wilc *wilc) +int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) { u32 reg = 0; int ret; - u8 timeout = 10; acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); + ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); if (!ret) { + netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); return ret; } - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, + (reg | WILC_ABORT_REQ_BIT)); if (!ret) { + netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); return ret; } - do { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_GLB_RESET_0, ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; - } - - if ((reg & BIT(10))) { - reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, - WILC_GLB_RESET_0, - reg); - timeout--; - } else { - ret = wilc->hif_func->hif_read_reg(wilc, - WILC_GLB_RESET_0, - ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; - } - break; - } - - } while (timeout); - reg = (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(8) | BIT(9) | BIT(26) | - BIT(29) | BIT(30) | BIT(31)); - - wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); - reg = (u32)~BIT(10); + ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, ®); + if (!ret) { + netdev_err(vif->ndev, "Error while reading reg\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return ret; + } + reg = BIT(0); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_FW_HOST_COMM, reg); + if (!ret) { + netdev_err(vif->ndev, "Error while writing reg\n"); + release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); + return ret; + } release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); @@ -1032,8 +1014,6 @@ void wilc_wlan_cleanup(struct net_device *dev) { struct txq_entry_t *tqe; struct rxq_entry_t *rqe; - u32 reg = 0; - int ret; struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; @@ -1058,23 +1038,6 @@ void wilc_wlan_cleanup(struct net_device *dev) wilc->rx_buffer = NULL; kfree(wilc->tx_buffer); wilc->tx_buffer = NULL; - - acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); - - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return; - } - - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, - (reg | ABORT_INT)); - if (!ret) { - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return; - } - - release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); wilc->hif_func->hif_deinit(NULL); } diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 802f11807659..f566d040bb72 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -98,6 +98,7 @@ #define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE #define WILC_VMM_TBL_RX_SHADOW_SIZE 256 +#define WILC_FW_HOST_COMM 0x13c0 #define WILC_GP_REG_0 0x149c #define WILC_GP_REG_1 0x14a0 @@ -129,7 +130,7 @@ #define WILC_PLL_TO_SDIO 4 #define WILC_PLL_TO_SPI 2 -#define ABORT_INT BIT(31) +#define WILC_ABORT_REQ_BIT BIT(31) #define WILC_RX_BUFF_SIZE (96 * 1024) #define WILC_TX_BUFF_SIZE (64 * 1024) @@ -280,7 +281,7 @@ struct wilc_vif; int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); int wilc_wlan_start(struct wilc *wilc); -int wilc_wlan_stop(struct wilc *wilc); +int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, u32 buffer_size, void (*tx_complete_fn)(void *, int)); -- cgit v1.2.3-59-g8ed1b From 133716f4ece320691f0052b296df44ed88307da4 Mon Sep 17 00:00:00 2001 From: Adham Abozaeid Date: Fri, 9 Aug 2019 18:25:19 +0000 Subject: staging: wilc1000: return kernel error codes from wilc_wlan_stop return -EIO for bus failures, 0 otherwise. Signed-off-by: Adham Abozaeid Link: https://lore.kernel.org/r/20190809182510.22443-3-adham.abozaeid@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 3d902b499a34..2bbb359d2119 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -979,7 +979,7 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) if (!ret) { netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, @@ -987,14 +987,14 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) if (!ret) { netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } ret = wilc->hif_func->hif_read_reg(wilc, WILC_FW_HOST_COMM, ®); if (!ret) { netdev_err(vif->ndev, "Error while reading reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } reg = BIT(0); @@ -1002,12 +1002,12 @@ int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif) if (!ret) { netdev_err(vif->ndev, "Error while writing reg\n"); release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return -EIO; } release_bus(wilc, WILC_BUS_RELEASE_ALLOW_SLEEP); - return ret; + return 0; } void wilc_wlan_cleanup(struct net_device *dev) -- cgit v1.2.3-59-g8ed1b From ed5d2eaf5f5d59aac17343acebe27b1929e5dcac Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:43 +0530 Subject: staging: rtl8712: _r8712_init_xmit_priv(): Change return values and type Change the return values in _r8712_init_xmit_priv from _SUCCESS/_FAIL to 0/-ENOMEM respectively. Change return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 14 +++++++------- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index f625fd5b9eb3..b9dc8953c6b3 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -49,8 +49,8 @@ void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) INIT_LIST_HEAD(&psta_xmitpriv->apsd); } -sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter) +int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, + struct _adapter *padapter) { sint i; struct xmit_buf *pxmitbuf; @@ -79,7 +79,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4, GFP_ATOMIC); if (!pxmitpriv->pallocated_frame_buf) { pxmitpriv->pxmit_frame_buf = NULL; - return _FAIL; + return -ENOMEM; } pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3); @@ -119,7 +119,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, if (!pxmitpriv->pallocated_xmitbuf) { kfree(pxmitpriv->pallocated_frame_buf); pxmitpriv->pallocated_frame_buf = NULL; - return _FAIL; + return -ENOMEM; } pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3); @@ -129,12 +129,12 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, pxmitbuf->pallocated_buf = kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC); if (!pxmitbuf->pallocated_buf) - return _FAIL; + return -ENOMEM; pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ - ((addr_t) (pxmitbuf->pallocated_buf) & (XMITBUF_ALIGN_SZ - 1)); if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) - return _FAIL; + return -ENOMEM; list_add_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue)); pxmitbuf++; @@ -146,7 +146,7 @@ sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, tasklet_init(&pxmitpriv->xmit_tasklet, (void(*)(unsigned long))r8712_xmit_bh, (unsigned long)padapter); - return _SUCCESS; + return 0; } void _free_xmit_priv(struct xmit_priv *pxmitpriv) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index d4bc059e6a42..6ddf5b6bb633 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -268,8 +268,8 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib); int r8712_txframes_sta_ac_pending(struct _adapter *padapter, struct pkt_attrib *pattrib); -sint _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, - struct _adapter *padapter); +int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, + struct _adapter *padapter); void _free_xmit_priv(struct xmit_priv *pxmitpriv); void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe); -- cgit v1.2.3-59-g8ed1b From b013c5b8ddacdf966392b6197289721a6e4d4ac9 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:44 +0530 Subject: staging: rtl8712: r8712_update_attrib(): Change return values and type Change return values of r8712_update_attrib from _SUCCESS and _FAIL to 0 and -ENOMEM or -EINVAL respectively. Modify call site to check for the new failure conditions. Also modify the return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 16 ++++++++-------- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- drivers/staging/rtl8712/xmit_linux.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index b9dc8953c6b3..40246cdd0911 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -173,8 +173,8 @@ void _free_xmit_priv(struct xmit_priv *pxmitpriv) free_hwxmits(padapter); } -sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib) +int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, + struct pkt_attrib *pattrib) { struct pkt_file pktfile; struct sta_info *psta = NULL; @@ -224,7 +224,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) { /*firstly, filter packet not belongs to mp*/ if (pattrib->ether_type != 0x8712) - return _FAIL; + return -EINVAL; /* for mp storing the txcmd per packet, * according to the info of txcmd to update pattrib */ @@ -271,7 +271,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, } else { psta = r8712_get_stainfo(pstapriv, pattrib->ra); if (psta == NULL) /* drop the pkt */ - return _FAIL; + return -ENOMEM; if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) pattrib->mac_id = 5; else @@ -283,7 +283,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->psta = psta; } else { /* if we cannot get psta => drrp the pkt */ - return _FAIL; + return -ENOMEM; } pattrib->ack_policy = 0; @@ -301,7 +301,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->encrypt = 0; if ((pattrib->ether_type != 0x888e) && !check_fwstate(pmlmepriv, WIFI_MP_STATE)) - return _FAIL; + return -EINVAL; } else { GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); } @@ -315,7 +315,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, pattrib->iv_len = 8; pattrib->icv_len = 4; if (padapter->securitypriv.busetkipkey == _FAIL) - return _FAIL; + return -EINVAL; break; case _AES_: pattrib->iv_len = 8; @@ -339,7 +339,7 @@ sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) pattrib->priority = (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f; - return _SUCCESS; + return 0; } static sint xmitframe_addmic(struct _adapter *padapter, diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 6ddf5b6bb633..291763c310ba 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -264,8 +264,8 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe); sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag); void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv); -sint r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, - struct pkt_attrib *pattrib); +int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, + struct pkt_attrib *pattrib); int r8712_txframes_sta_ac_pending(struct _adapter *padapter, struct pkt_attrib *pattrib); int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv, diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c index 01d713d027b0..1f67d86c606f 100644 --- a/drivers/staging/rtl8712/xmit_linux.c +++ b/drivers/staging/rtl8712/xmit_linux.c @@ -160,7 +160,7 @@ int r8712_xmit_entry(_pkt *pkt, struct net_device *netdev) if (!xmitframe) goto _xmit_entry_drop; - if ((!r8712_update_attrib(adapter, pkt, &xmitframe->attrib))) + if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib)) goto _xmit_entry_drop; adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX); -- cgit v1.2.3-59-g8ed1b From 0d478943e3c5b3f07e48cfa6e9a0d6a0e546dab2 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:46 +0530 Subject: staging: rtl8712: make_wlanhdr(): Change return values and type Change return values of make_wlanhdr from _SUCCESS/_FAIL to 0/-EINVAL. Modify call site to check for non-zero return values instead of _FAIL. Change return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 40246cdd0911..2e63cceff0da 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -469,8 +469,8 @@ static sint xmitframe_swencrypt(struct _adapter *padapter, return _SUCCESS; } -static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) +static int make_wlanhdr(struct _adapter *padapter, u8 *hdr, + struct pkt_attrib *pattrib) { u16 *qc; @@ -509,7 +509,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN); } else { - return _FAIL; + return -EINVAL; } if (pattrib->encrypt) @@ -547,7 +547,7 @@ static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, } } } - return _SUCCESS; + return 0; } static sint r8712_put_snap(u8 *data, u16 h_proto) @@ -605,7 +605,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, pbuf_start = pxmitframe->buf_addr; ptxdesc = pbuf_start; mem_start = pbuf_start + TXDESC_OFFSET; - if (make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) + if (make_wlanhdr(padapter, mem_start, pattrib)) return _FAIL; _r8712_open_pktfile(pkt, &pktfile); _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen); -- cgit v1.2.3-59-g8ed1b From 670b673fa0d0f0abd1f95e5dd26dabdcff5a7be1 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:47 +0530 Subject: staging: rtl8712: r8712_free_xmitbuf(): Change return type Change return type of r8712_free_xmitbuf from int to void (and remove its return values) as its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-5-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 5 ++--- drivers/staging/rtl8712/rtl871x_xmit.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 2e63cceff0da..178f8b96943b 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -753,19 +753,18 @@ struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv) return pxmitbuf; } -int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) +void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) { unsigned long irqL; struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; if (pxmitbuf == NULL) - return _FAIL; + return; spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); list_del_init(&pxmitbuf->list); list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue); pxmitpriv->free_xmitbuf_cnt++; spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - return _SUCCESS; } /* diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index 291763c310ba..d4658c1c4bd4 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -249,8 +249,8 @@ struct xmit_priv { uint free_xmitbuf_cnt; }; -int r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf); +void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, + struct xmit_buf *pxmitbuf); struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv); void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len); struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv); -- cgit v1.2.3-59-g8ed1b From 9958e0e53ba49521323b5ffeafcf996683f6172f Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:48 +0530 Subject: staging: rtl8712: r8712_xmit_direct(): Change return type Change return type of r8712_xmit_direct from int to void as its return value is never used. Remove return statement accordingly. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-6-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 3 +-- drivers/staging/rtl8712/rtl871x_xmit.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 3334b03c2548..d6e8e3fc6527 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -737,7 +737,7 @@ static void dump_xframe(struct _adapter *padapter, } } -int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) +void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) { int res; @@ -745,7 +745,6 @@ int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) pxmitframe->pkt = NULL; if (res == _SUCCESS) dump_xframe(padapter, pxmitframe); - return res; } int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h index d4658c1c4bd4..b14da38bf652 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.h +++ b/drivers/staging/rtl8712/rtl871x_xmit.h @@ -276,7 +276,7 @@ void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv, int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe); int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe); -int r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); +void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe); void r8712_xmit_bh(void *priv); void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe, -- cgit v1.2.3-59-g8ed1b From e7df51e00828c81fe22225da92223eb6a233e91e Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:49 +0530 Subject: staging: rtl8712: r8712_construct_txaggr_cmd_desc(): Change return type Change return type of r8712_construct_txaggr_cmd_desc from u8 to void (and remove its return statement) as it always returns _SUCCESS and its return value is never stored, checked or otherwise used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-7-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index d6e8e3fc6527..87278438bc48 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -246,7 +246,7 @@ void r8712_do_queue_select(struct _adapter *padapter, } #ifdef CONFIG_R8712_TX_AGGR -u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) +void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) { struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; @@ -260,8 +260,6 @@ u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) /* dw1 */ ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); - - return _SUCCESS; } u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) -- cgit v1.2.3-59-g8ed1b From 70deda9dfa6678bcd88020f8fb6614f13ccfb451 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Fri, 9 Aug 2019 10:53:50 +0530 Subject: staging: rtl8712: r8712_construct_txaggr_cmd_hdr(): Change return type Change return type of r8712_construct_txaggr_cmd_hdr from u8 to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190809052353.5308-8-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 87278438bc48..04e70048f0dd 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -262,7 +262,7 @@ void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); } -u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) +void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) { struct xmit_frame *pxmitframe = (struct xmit_frame *) pxmitbuf->priv_data; @@ -276,8 +276,6 @@ u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | (pcmdpriv->cmd_seq << 24)); pcmdpriv->cmd_seq++; - - return _SUCCESS; } u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, -- cgit v1.2.3-59-g8ed1b From 1aee09b8fa5b872d5fde8f23a26bd775aff908f7 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Sun, 11 Aug 2019 15:51:20 -0700 Subject: staging: rtl8192u: fix spacing errors Used checkpatch's --fix-inplace option for types SPACING, OPEN_BRACE, ELSE_AFTER_BRACE. Manually edited the resulting changes to correct for mistaken fixes and complete fixes that were only partially applied. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190811225120.7308-1-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 455 ++++++++++------------ 1 file changed, 200 insertions(+), 255 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 0a3e478fccd6..7ef1e89de269 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -124,7 +124,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, 2 /* alignment */ + 8 /* WEP */ + ETH_ALEN /* WDS */ + - (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); + (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */); if (!skb) return NULL; @@ -145,7 +145,7 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, } else { /* received a fragment of a frame for which the head fragment * should have already been received */ - entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2, + entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, hdr->addr1); if (entry) { entry->last_frag = frag; @@ -169,7 +169,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, struct rtl_80211_hdr_4addrqos *hdr_4addrqos; u8 tid; - if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; tid = UP2AC(tid); @@ -216,7 +216,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct rtl_80211_hdr_3addr *hdr = (struct rtl_80211_hdr_3addr *)skb->data; rx_stats->len = skb->len; - ieee80211_rx_mgt(ieee,(struct rtl_80211_hdr_4addr *)skb->data,rx_stats); + ieee80211_rx_mgt(ieee, (struct rtl_80211_hdr_4addr *)skb->data, rx_stats); /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */ if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))/* use ADDR1 to perform address matching for Management frames */ { @@ -281,11 +281,11 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +static unsigned char rfc1042_header[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +static unsigned char bridge_tunnel_header[] = { + 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; /* No encapsulation header if EtherType < 0x600 (=length) */ /* Called by ieee80211_rx_frame_decrypt */ @@ -300,7 +300,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, if (skb->len < 24) return 0; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; fc = le16_to_cpu(hdr->frame_ctl); /* check that the frame is unicast frame to us */ @@ -341,10 +341,10 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, return 0; if (ieee->hwsec_active) { - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); if (ieee->tkip_countermeasures && @@ -388,11 +388,11 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s return 0; if (ieee->hwsec_active) { - struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); atomic_inc(&crypt->refcnt); @@ -410,7 +410,7 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s /* this function is stolen from ipw2200 driver*/ -#define IEEE_PACKET_RETRY_TIME (5*HZ) +#define IEEE_PACKET_RETRY_TIME (5 * HZ) static int is_duplicate_packet(struct ieee80211_device *ieee, struct rtl_80211_hdr_4addr *header) { @@ -426,12 +426,12 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, //TO2DS and QoS - if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { + if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header; tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; tid = UP2AC(tid); tid++; - } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS + } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header; tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; tid = UP2AC(tid); @@ -507,7 +507,7 @@ drop: static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *pReorderEntry) { struct list_head *pList = &pTS->rx_pending_pkt_list; - while(pList->next != &pTS->rx_pending_pkt_list) + while (pList->next != &pTS->rx_pending_pkt_list) { if (SN_LESS(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) pList = pList->next; @@ -524,17 +524,17 @@ static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *p return true; } -void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray,u8 index) +void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray, u8 index) { - u8 i = 0 , j=0; + u8 i = 0, j = 0; u16 ethertype; // if(index > 1) // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__func__,index); - for(j = 0; jnr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { struct sk_buff *sub_skb = prxb->subframes[i]; /* convert hdr + possible LLC headers into Ethernet header */ @@ -585,7 +585,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, u16 WinEnd = (pTS->rx_indicate_seq + WinSize - 1) % 4096; u8 index = 0; bool bMatchWinStart = false, bPktInBuf = false; - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n",__func__,SeqNum,pTS->rx_indicate_seq,WinSize); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Seq is %d,pTS->rx_indicate_seq is %d, WinSize is %d\n", __func__, SeqNum, pTS->rx_indicate_seq, WinSize); prxbIndicateArray = kmalloc_array(REORDER_WIN_SIZE, sizeof(struct ieee80211_rxb *), @@ -599,12 +599,12 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, /* Drop out the packet which SeqNum is smaller than WinStart */ if (SN_LESS(SeqNum, pTS->rx_indicate_seq)) { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n", + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); pHTInfo->RxReorderDropCounter++; { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -620,16 +620,16 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N */ - if(SN_EQUAL(SeqNum, pTS->rx_indicate_seq)) { + if (SN_EQUAL(SeqNum, pTS->rx_indicate_seq)) { pTS->rx_indicate_seq = (pTS->rx_indicate_seq + 1) % 4096; bMatchWinStart = true; - } else if(SN_LESS(WinEnd, SeqNum)) { - if(SeqNum >= (WinSize - 1)) { - pTS->rx_indicate_seq = SeqNum + 1 -WinSize; + } else if (SN_LESS(WinEnd, SeqNum)) { + if (SeqNum >= (WinSize - 1)) { + pTS->rx_indicate_seq = SeqNum + 1 - WinSize; } else { pTS->rx_indicate_seq = 4095 - (WinSize - (SeqNum + 1)) + 1; } - IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); } /* @@ -641,7 +641,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, * 1. All packets with SeqNum smaller than WinStart => Indicate * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */ - if(bMatchWinStart) { + if (bMatchWinStart) { /* Current packet is going to be indicated.*/ IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\ pTS->rx_indicate_seq, SeqNum); @@ -651,7 +651,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } else { /* Current packet is going to be inserted into pending list.*/ //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to ordered list\n",__func__); - if(!list_empty(&ieee->RxReorder_Unused_List)) { + if (!list_empty(&ieee->RxReorder_Unused_List)) { pReorderEntry = list_entry(ieee->RxReorder_Unused_List.next, struct rx_reorder_entry, List); list_del_init(&pReorderEntry->List); @@ -660,13 +660,13 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, pReorderEntry->prxb = prxb; // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum); - if(!AddReorderEntry(pTS, pReorderEntry)) { + if (!AddReorderEntry(pTS, pReorderEntry)) { IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", __func__, pTS->rx_indicate_seq, SeqNum); - list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -674,10 +674,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } } else { IEEE80211_DEBUG(IEEE80211_DL_REORDER, - "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); } - } - else { + } else { /* * Packets are dropped if there is not enough reorder entries. * This part shall be modified!! We can just indicate all the @@ -686,7 +685,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); { int i; - for(i =0; i < prxb->nr_subframes; i++) { + for (i = 0; i < prxb->nr_subframes; i++) { dev_kfree_skb(prxb->subframes[i]); } kfree(prxb); @@ -696,8 +695,8 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } /* Check if there is any packet need indicate.*/ - while(!list_empty(&pTS->rx_pending_pkt_list)) { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__func__); + while (!list_empty(&pTS->rx_pending_pkt_list)) { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): start RREORDER indicate\n", __func__); pReorderEntry = list_entry(pTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List); if (SN_LESS(pReorderEntry->SeqNum, pTS->rx_indicate_seq) || SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) @@ -711,15 +710,15 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, list_del_init(&pReorderEntry->List); - if(SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) + if (SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) pTS->rx_indicate_seq = (pTS->rx_indicate_seq + 1) % 4096; - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->rx_indicate_seq, SeqNum); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n", pTS->rx_indicate_seq, SeqNum); prxbIndicateArray[index] = pReorderEntry->prxb; // printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__func__,pReorderEntry->SeqNum); index++; - list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); } else { bPktInBuf = true; break; @@ -727,13 +726,13 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, } /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/ - if (index>0) { + if (index > 0) { // Cancel previous pending timer. // del_timer_sync(&pTS->rx_pkt_pending_timer); pTS->rx_timeout_indicate_seq = 0xffff; // Indicate packets - if(index>REORDER_WIN_SIZE){ + if (index > REORDER_WIN_SIZE) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"); kfree(prxbIndicateArray); return; @@ -743,9 +742,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, if (bPktInBuf && pTS->rx_timeout_indicate_seq == 0xffff) { // Set new pending timer. - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __func__); + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): SET rx timeout timer\n", __func__); pTS->rx_timeout_indicate_seq = pTS->rx_indicate_seq; - if(timer_pending(&pTS->rx_pkt_pending_timer)) + if (timer_pending(&pTS->rx_pkt_pending_timer)) del_timer_sync(&pTS->rx_pkt_pending_timer); pTS->rx_pkt_pending_timer.expires = jiffies + msecs_to_jiffies(pHTInfo->RxReorderPendingTime); @@ -762,12 +761,12 @@ static u8 parse_subframe(struct sk_buff *skb, struct rtl_80211_hdr_3addr *hdr = (struct rtl_80211_hdr_3addr *)skb->data; u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 LLCOffset= sizeof(struct rtl_80211_hdr_3addr); + u16 LLCOffset = sizeof(struct rtl_80211_hdr_3addr); u16 ChkLength; bool bIsAggregateFrame = false; u16 nSubframe_Length; u8 nPadding_Length = 0; - u16 SeqNum=0; + u16 SeqNum = 0; struct sk_buff *sub_skb; /* just for debug purpose */ @@ -793,7 +792,7 @@ static u8 parse_subframe(struct sk_buff *skb, skb_pull(skb, LLCOffset); - if(!bIsAggregateFrame) { + if (!bIsAggregateFrame) { rxb->nr_subframes = 1; #ifdef JOHN_NOCPY rxb->subframes[0] = skb; @@ -801,26 +800,26 @@ static u8 parse_subframe(struct sk_buff *skb, rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC); #endif - memcpy(rxb->src,src,ETH_ALEN); - memcpy(rxb->dst,dst,ETH_ALEN); + memcpy(rxb->src, src, ETH_ALEN); + memcpy(rxb->dst, dst, ETH_ALEN); //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len); return 1; } else { rxb->nr_subframes = 0; - memcpy(rxb->src,src,ETH_ALEN); - memcpy(rxb->dst,dst,ETH_ALEN); - while(skb->len > ETHERNET_HEADER_SIZE) { + memcpy(rxb->src, src, ETH_ALEN); + memcpy(rxb->dst, dst, ETH_ALEN); + while (skb->len > ETHERNET_HEADER_SIZE) { /* Offset 12 denote 2 mac address */ nSubframe_Length = *((u16 *)(skb->data + 12)); //==m==>change the length order - nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8); + nSubframe_Length = (nSubframe_Length >> 8) + (nSubframe_Length << 8); - if (skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) { + if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ __func__, rxb->nr_subframes); - printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__func__, nSubframe_Length); - printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length); - printk("The Packet SeqNum is %d\n",SeqNum); + printk("%s: A-MSDU parse error!! Subframe Length: %d\n", __func__, nSubframe_Length); + printk("nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); + printk("The Packet SeqNum is %d\n", SeqNum); return 0; } @@ -925,7 +924,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, if (HTCCheck(ieee, skb->data)) { - if(net_ratelimit()) + if (net_ratelimit()) printk("find HTCControl\n"); hdrlen += 4; rx_stats->bContainHTC = true; @@ -972,7 +971,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * stations that do not support WEP key mapping). */ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) - (void) hostap_handle_sta_crypto(local, hdr, &crypt, + (void)hostap_handle_sta_crypto(local, hdr, &crypt, &sta); #endif @@ -998,18 +997,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; // if QoS enabled, should check the sequence for each of the AC - if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { + if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active || !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { if (is_duplicate_packet(ieee, hdr)) goto rx_dropped; - } - else - { + } else { struct rx_ts_record *pRxTS = NULL; //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__func__, tid); - if(GetTs( + if (GetTs( ieee, - (struct ts_common_info **) &pRxTS, + (struct ts_common_info **)&pRxTS, hdr->addr2, Frame_QoSTID((u8 *)(skb->data)), RX_DIR, @@ -1017,20 +1014,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, { // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->rx_last_frag_num is %d,frag is %d,pRxTS->rx_last_seq_num is %d,seq is %d\n",__func__,pRxTS->rx_last_frag_num,frag,pRxTS->rx_last_seq_num,WLAN_GET_SEQ_SEQ(sc)); - if ((fc & (1<<11)) && + if ((fc & (1 << 11)) && (frag == pRxTS->rx_last_frag_num) && (WLAN_GET_SEQ_SEQ(sc) == pRxTS->rx_last_seq_num)) { goto rx_dropped; - } - else - { + } else { pRxTS->rx_last_frag_num = frag; pRxTS->rx_last_seq_num = WLAN_GET_SEQ_SEQ(sc); } - } - else - { - IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__func__); + } else { + IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n", __func__); goto rx_dropped; } } @@ -1133,7 +1126,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, } - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; /* skb: hdr + (possibly fragmented) plaintext payload */ // PR: FIXME: hostap has additional conditions in the "if" below: @@ -1185,7 +1178,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* this was the last fragment and the frame will be * delivered, so remove skb from fragment cache */ skb = frag_skb; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; ieee80211_frag_cache_invalidate(ieee, hdr); } @@ -1202,7 +1195,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->LinkDetectInfo.NumRecvDataInPeriod++; ieee->LinkDetectInfo.NumRxOkInPeriod++; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { if (/*ieee->ieee802_1x &&*/ ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { @@ -1254,8 +1247,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); - GetTs(ieee,(struct ts_common_info **) &pTS,hdr->addr2,TID,RX_DIR,true); - if (TID !=0 && TID !=3) + GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true); + if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } @@ -1270,7 +1263,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* qos data packets & reserved bit is 1 */ if (parse_subframe(skb, rx_stats, rxb, src, dst) == 0) { /* only to free rxb, and not submit the packets to upper layer */ - for(i =0; i < rxb->nr_subframes; i++) { + for (i = 0; i < rxb->nr_subframes; i++) { dev_kfree_skb(rxb->subframes[i]); } kfree(rxb); @@ -1281,7 +1274,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, //added by amy for reorder if (!ieee->pHTInfo->bCurRxReorderEnable || !pTS) { //added by amy for reorder - for(i = 0; inr_subframes; i++) { + for (i = 0; i < rxb->nr_subframes; i++) { struct sk_buff *sub_skb = rxb->subframes[i]; if (sub_skb) { @@ -1324,10 +1317,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, kfree(rxb); rxb = NULL; - } - else - { - IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__func__); + } else { + IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n", __func__); RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); } #ifndef JOHN_NOCPY @@ -1407,10 +1398,9 @@ static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info /* * Parse a QoS information element */ -static int ieee80211_read_qos_info_element(struct - ieee80211_qos_information_element - *element_info, struct ieee80211_info_element - *info_element) +static int ieee80211_read_qos_info_element( + struct ieee80211_qos_information_element *element_info, + struct ieee80211_info_element *info_element) { int ret = 0; u16 size = sizeof(struct ieee80211_qos_information_element) - 2; @@ -1438,11 +1428,9 @@ static int ieee80211_read_qos_info_element(struct /* * Write QoS parameters from the ac parameters. */ -static int ieee80211_qos_convert_ac_to_parameters(struct - ieee80211_qos_parameter_info - *param_elm, struct - ieee80211_qos_parameters - *qos_param) +static int ieee80211_qos_convert_ac_to_parameters( + struct ieee80211_qos_parameter_info *param_elm, + struct ieee80211_qos_parameters *qos_param) { int i; struct ieee80211_qos_ac_parameter *ac_params; @@ -1455,12 +1443,12 @@ static int ieee80211_qos_convert_ac_to_parameters(struct aci = (ac_params->aci_aifsn & 0x60) >> 5; - if(aci >= QOS_QUEUE_NUM) + if (aci >= QOS_QUEUE_NUM) continue; qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f; /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ - qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci]; + qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci]; qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F); @@ -1563,7 +1551,7 @@ static inline void ieee80211_extract_country_ie( { if (IS_DOT11D_ENABLE(ieee)) { - if (info_element->len!= 0) + if (info_element->len != 0) { memcpy(network->CountryIeBuf, info_element->data, info_element->len); network->CountryIeLen = info_element->len; @@ -1579,7 +1567,7 @@ static inline void ieee80211_extract_country_ie( // some AP (e.g. Cisco 1242) don't include country IE in their // probe response frame. // - if (IS_EQUAL_CIE_SRC(ieee, addr2) ) + if (IS_EQUAL_CIE_SRC(ieee, addr2)) { UPDATE_CIE_WATCHDOG(ieee); } @@ -1595,9 +1583,9 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, { u8 i; short offset; - u16 tmp_htcap_len=0; - u16 tmp_htinfo_len=0; - u16 ht_realtek_agg_len=0; + u16 tmp_htcap_len = 0; + u16 tmp_htinfo_len = 0; + u16 ht_realtek_agg_len = 0; u8 ht_realtek_agg_buf[MAX_IE_LEN]; // u16 broadcom_len = 0; #ifdef CONFIG_IEEE80211_DEBUG @@ -1628,7 +1616,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } network->ssid_len = min(info_element->len, - (u8) IW_ESSID_MAX_SIZE); + (u8)IW_ESSID_MAX_SIZE); memcpy(network->ssid, info_element->data, network->ssid_len); if (network->ssid_len < IW_ESSID_MAX_SIZE) memset(network->ssid + network->ssid_len, 0, @@ -1707,14 +1695,14 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, break; case MFIE_TYPE_TIM: - if(info_element->len < 4) + if (info_element->len < 4) break; network->tim.tim_count = info_element->data[0]; network->tim.tim_period = info_element->data[1]; network->dtim_period = info_element->data[1]; - if(ieee->state != IEEE80211_LINKED) + if (ieee->state != IEEE80211_LINKED) break; network->last_dtim_sta_time[0] = stats->mac_time[0]; @@ -1722,22 +1710,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, network->dtim_data = IEEE80211_DTIM_VALID; - if(info_element->data[0] != 0) + if (info_element->data[0] != 0) break; - if(info_element->data[2] & 1) + if (info_element->data[2] & 1) network->dtim_data |= IEEE80211_DTIM_MBCAST; - offset = (info_element->data[2] >> 1)*2; + offset = (info_element->data[2] >> 1) * 2; - if(ieee->assoc_id < 8*offset || - ieee->assoc_id > 8*(offset + info_element->len -3)) + if (ieee->assoc_id < 8 * offset || + ieee->assoc_id > 8 * (offset + info_element->len - 3)) break; offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ; - if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) + if (info_element->data[3 + offset] & (1 << (ieee->assoc_id % 8))) network->dtim_data |= IEEE80211_DTIM_UCAST; //IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n"); @@ -1790,42 +1778,42 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, #endif //for HTcap and HTinfo parameters - if(tmp_htcap_len == 0){ - if(info_element->len >= 4 && + if (tmp_htcap_len == 0) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x90 && info_element->data[2] == 0x4c && info_element->data[3] == 0x033){ - tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htcap_len != 0){ + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ - sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); } } - if(tmp_htcap_len != 0) + if (tmp_htcap_len != 0) network->bssht.bdSupportHT = true; else network->bssht.bdSupportHT = false; } - if(tmp_htinfo_len == 0){ - if(info_element->len >= 4 && + if (tmp_htinfo_len == 0) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0x90 && info_element->data[2] == 0x4c && info_element->data[3] == 0x034){ - tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htinfo_len != 0){ + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - if(tmp_htinfo_len){ - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ - sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + if (tmp_htinfo_len) { + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } } @@ -1833,22 +1821,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } } - if(ieee->aggregation){ - if(network->bssht.bdSupportHT){ - if(info_element->len >= 4 && + if (ieee->aggregation) { + if (network->bssht.bdSupportHT) { + if (info_element->len >= 4 && info_element->data[0] == 0x00 && info_element->data[1] == 0xe0 && info_element->data[2] == 0x4c && info_element->data[3] == 0x02){ - ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN); - memcpy(ht_realtek_agg_buf,info_element->data,info_element->len); + ht_realtek_agg_len = min(info_element->len, (u8)MAX_IE_LEN); + memcpy(ht_realtek_agg_buf, info_element->data, info_element->len); } - if(ht_realtek_agg_len >= 5){ + if (ht_realtek_agg_len >= 5) { network->bssht.bdRT2RTAggregation = true; - if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) + if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) network->bssht.bdRT2RTLongSlotTime = true; } } @@ -1874,17 +1862,16 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, } } - if(info_element->len >= 3 && + if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x0c && info_element->data[2] == 0x43) { network->ralink_cap_exist = true; - } - else + } else network->ralink_cap_exist = false; //added by amy for atheros AP - if((info_element->len >= 3 && + if ((info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x03 && info_element->data[2] == 0x7f) || @@ -1893,20 +1880,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[1] == 0x13 && info_element->data[2] == 0x74)) { - printk("========>%s(): athros AP is exist\n",__func__); + printk("========>%s(): athros AP is exist\n", __func__); network->atheros_cap_exist = true; - } - else + } else network->atheros_cap_exist = false; - if(info_element->len >= 3 && + if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96) { network->cisco_cap_exist = true; - } - else + } else network->cisco_cap_exist = false; //added by amy for LEAP of cisco if (info_element->len > 4 && @@ -1915,33 +1900,28 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x01) { - if(info_element->len == 6) + if (info_element->len == 6) { memcpy(network->CcxRmState, &info_element[4], 2); - if(network->CcxRmState[0] != 0) + if (network->CcxRmState[0] != 0) { network->bCcxRmEnable = true; - } - else + } else network->bCcxRmEnable = false; // // CCXv4 Table 59-1 MBSSID Masks. // network->MBssidMask = network->CcxRmState[1] & 0x07; - if(network->MBssidMask != 0) + if (network->MBssidMask != 0) { network->bMBssidValid = true; network->MBssidMask = 0xff << (network->MBssidMask); ether_addr_copy(network->MBssid, network->bssid); network->MBssid[5] &= network->MBssidMask; - } - else - { + } else { network->bMBssidValid = false; } - } - else - { + } else { network->bCcxRmEnable = false; } } @@ -1951,13 +1931,10 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x03) { - if(info_element->len == 5) - { + if (info_element->len == 5) { network->bWithCcxVerNum = true; network->BssCcxVerNumber = info_element->data[4]; - } - else - { + } else { network->bWithCcxVerNum = false; network->BssCcxVerNumber = 0; } @@ -1977,19 +1954,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_HT_CAP: IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n", info_element->len); - tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htcap_len != 0){ + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ - sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT() // windows driver will update WMM parameters each beacon received once connected // Linux driver is a bit different. network->bssht.bdSupportHT = true; - } - else + } else network->bssht.bdSupportHT = false; break; @@ -1997,37 +1973,33 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_HT_INFO: IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n", info_element->len); - tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); - if(tmp_htinfo_len){ + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len) { network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE; - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ - sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } break; case MFIE_TYPE_AIRONET: IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", info_element->len); - if(info_element->len >IE_CISCO_FLAG_POSITION) + if (info_element->len > IE_CISCO_FLAG_POSITION) { network->bWithAironetIE = true; // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23): // "A Cisco access point advertises support for CKIP in beacon and probe response packets, // by adding an Aironet element and setting one or both of the CKIP negotiation bits." - if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) || - (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) ) + if ((info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_MIC) || + (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) { network->bCkipSupported = true; - } - else - { + } else { network->bCkipSupported = false; } - } - else - { + } else { network->bWithAironetIE = false; network->bCkipSupported = false; } @@ -2057,13 +2029,10 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, data[info_element->len]; } - if(!network->atheros_cap_exist && !network->broadcom_cap_exist && - !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) - { + if (!network->atheros_cap_exist && !network->broadcom_cap_exist && + !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) { network->unknown_cap_exist = true; - } - else - { + } else { network->unknown_cap_exist = false; } return 0; @@ -2076,44 +2045,25 @@ static inline u8 ieee80211_SignalStrengthTranslate( u8 RetSS; // Step 1. Scale mapping. - if(CurrSS >= 71 && CurrSS <= 100) - { + if (CurrSS >= 71 && CurrSS <= 100) { RetSS = 90 + ((CurrSS - 70) / 3); - } - else if(CurrSS >= 41 && CurrSS <= 70) - { + } else if (CurrSS >= 41 && CurrSS <= 70) { RetSS = 78 + ((CurrSS - 40) / 3); - } - else if(CurrSS >= 31 && CurrSS <= 40) - { + } else if (CurrSS >= 31 && CurrSS <= 40) { RetSS = 66 + (CurrSS - 30); - } - else if(CurrSS >= 21 && CurrSS <= 30) - { + } else if (CurrSS >= 21 && CurrSS <= 30) { RetSS = 54 + (CurrSS - 20); - } - else if(CurrSS >= 5 && CurrSS <= 20) - { + } else if (CurrSS >= 5 && CurrSS <= 20) { RetSS = 42 + (((CurrSS - 5) * 2) / 3); - } - else if(CurrSS == 4) - { + } else if (CurrSS == 4) { RetSS = 36; - } - else if(CurrSS == 3) - { + } else if (CurrSS == 3) { RetSS = 27; - } - else if(CurrSS == 2) - { + } else if (CurrSS == 2) { RetSS = 18; - } - else if(CurrSS == 1) - { + } else if (CurrSS == 1) { RetSS = 9; - } - else - { + } else { RetSS = CurrSS; } //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); @@ -2193,7 +2143,7 @@ static inline int ieee80211_network_init( network->rsn_ie_len = 0; if (ieee80211_parse_info_param - (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats)) + (ieee, beacon->info_element, stats->len - sizeof(*beacon), network, stats)) return 1; network->mode = 0; @@ -2215,10 +2165,10 @@ static inline int ieee80211_network_init( return 1; } - if(network->bssht.bdSupportHT){ - if(network->mode == IEEE_A) + if (network->bssht.bdSupportHT) { + if (network->mode == IEEE_A) network->mode = IEEE_N_5G; - else if(network->mode & (IEEE_G | IEEE_B)) + else if (network->mode & (IEEE_G | IEEE_B)) network->mode = IEEE_N_24G; } if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) @@ -2226,7 +2176,7 @@ static inline int ieee80211_network_init( stats->signal = 30 + (stats->SignalStrength * 70) / 100; //stats->signal = ieee80211_SignalStrengthTranslate(stats->signal); - stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25; + stats->noise = ieee80211_translate_todbm((u8)(100 - stats->signal)) - 25; memcpy(&network->stats, stats, sizeof(network->stats)); @@ -2290,10 +2240,10 @@ static inline void update_network(struct ieee80211_network *dst, dst->bssht.bdSupportHT = src->bssht.bdSupportHT; dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation; - dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen; - memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen); - dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen; - memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen); + dst->bssht.bdHTCapLen = src->bssht.bdHTCapLen; + memcpy(dst->bssht.bdHTCapBuf, src->bssht.bdHTCapBuf, src->bssht.bdHTCapLen); + dst->bssht.bdHTInfoLen = src->bssht.bdHTInfoLen; + memcpy(dst->bssht.bdHTInfoBuf, src->bssht.bdHTInfoBuf, src->bssht.bdHTInfoLen); dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer; dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime; dst->broadcom_cap_exist = src->broadcom_cap_exist; @@ -2312,7 +2262,7 @@ static inline void update_network(struct ieee80211_network *dst, qos_active = dst->qos_data.active; //old_param = dst->qos_data.old_param_count; old_param = dst->qos_data.param_count; - if(dst->flags & NETWORK_HAS_QOS_MASK) + if (dst->flags & NETWORK_HAS_QOS_MASK) memcpy(&dst->qos_data, &src->qos_data, sizeof(struct ieee80211_qos_data)); else { @@ -2322,7 +2272,7 @@ static inline void update_network(struct ieee80211_network *dst, if (dst->qos_data.supported == 1) { dst->QoS_Enable = 1; - if(dst->ssid_len) + if (dst->ssid_len) IEEE80211_DEBUG_QOS ("QoS the network %s is QoS supported\n", dst->ssid); @@ -2335,9 +2285,9 @@ static inline void update_network(struct ieee80211_network *dst, /* dst->last_associate is not overwritten */ dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. - if (src->wmm_param[0].aci_aifsn|| \ - src->wmm_param[1].aci_aifsn|| \ - src->wmm_param[2].aci_aifsn|| \ + if (src->wmm_param[0].aci_aifsn || \ + src->wmm_param[1].aci_aifsn || \ + src->wmm_param[2].aci_aifsn || \ src->wmm_param[3].aci_aifsn) { memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); } @@ -2434,8 +2384,7 @@ static inline void ieee80211_process_probe_response( if (fc == IEEE80211_STYPE_PROBE_RESP) { // Case 1: Country code - if(IS_COUNTRY_IE_VALID(ieee) ) - { + if (IS_COUNTRY_IE_VALID(ieee)) { if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); goto out; @@ -2451,14 +2400,11 @@ static inline void ieee80211_process_probe_response( goto out; } } - } - else - { + } else { // Case 1: Country code - if(IS_COUNTRY_IE_VALID(ieee) ) - { + if (IS_COUNTRY_IE_VALID(ieee)) { if (!is_legal_channel(ieee, network->channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network->channel); + printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); goto out; } } @@ -2468,7 +2414,7 @@ static inline void ieee80211_process_probe_response( // Filter over channel ch12~14 if (network->channel > 14) { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network->channel); + printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); goto out; } } @@ -2491,18 +2437,17 @@ static inline void ieee80211_process_probe_response( update_network(&ieee->current_network, network); if ((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) && ieee->current_network.berp_info_valid){ - if(ieee->current_network.erp_value& ERP_UseProtection) + if (ieee->current_network.erp_value & ERP_UseProtection) ieee->current_network.buseprotection = true; else ieee->current_network.buseprotection = false; } - if(is_beacon(beacon->header.frame_ctl)) + if (is_beacon(beacon->header.frame_ctl)) { - if(ieee->state == IEEE80211_LINKED) + if (ieee->state == IEEE80211_LINKED) ieee->LinkDetectInfo.NumRecvBcnInPeriod++; - } - else //hidden AP - network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); + } else //hidden AP + network->flags = (~NETWORK_EMPTY_ESSID & network->flags) | (NETWORK_EMPTY_ESSID & ieee->current_network.flags); } list_for_each_entry(target, &ieee->network_list, list) { @@ -2543,8 +2488,8 @@ static inline void ieee80211_process_probe_response( #endif memcpy(target, network, sizeof(*target)); list_add_tail(&target->list, &ieee->network_list); - if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) - ieee80211_softmac_new_net(ieee,network); + if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) + ieee80211_softmac_new_net(ieee, network); } else { IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", escape_essid(target->ssid, @@ -2559,26 +2504,26 @@ static inline void ieee80211_process_probe_response( */ renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); //YJ,add,080819,for hidden ap - if(is_beacon(beacon->header.frame_ctl) == 0) - network->flags = (~NETWORK_EMPTY_ESSID & network->flags)|(NETWORK_EMPTY_ESSID & target->flags); + if (is_beacon(beacon->header.frame_ctl) == 0) + network->flags = (~NETWORK_EMPTY_ESSID & network->flags) | (NETWORK_EMPTY_ESSID & target->flags); //if(strncmp(network->ssid, "linksys-c",9) == 0) // printk("====>2 network->ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network->ssid, network->flags, target->ssid, target->flags); - if(((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ + if (((network->flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ && (((network->ssid_len > 0) && (strncmp(target->ssid, network->ssid, network->ssid_len)))\ - ||((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) + || ((ieee->current_network.ssid_len == network->ssid_len) && (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) renew = 1; //YJ,add,080819,for hidden ap,end update_network(target, network); - if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) - ieee80211_softmac_new_net(ieee,network); + if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) + ieee80211_softmac_new_net(ieee, network); } spin_unlock_irqrestore(&ieee->lock, flags); if (is_beacon(beacon->header.frame_ctl) && is_same_network(&ieee->current_network, network, ieee) && \ (ieee->state == IEEE80211_LINKED)) { if (ieee->handle_beacon) - ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); + ieee->handle_beacon(ieee->dev, beacon, &ieee->current_network); } out: -- cgit v1.2.3-59-g8ed1b From 3d2969fac698ef6694e653c192d26ea501b7c3d5 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Tue, 13 Aug 2019 10:30:52 +0800 Subject: staging: erofs: inline erofs_inode_is_data_compressed() As a helper in erofs_fs.h, erofs_inode_is_data_compressed() should be inlined. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190813023054.73126-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/erofs_fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h index e82e833985e4..8dc2a75e478f 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/drivers/staging/erofs/erofs_fs.h @@ -62,7 +62,7 @@ enum { EROFS_INODE_LAYOUT_MAX }; -static bool erofs_inode_is_data_compressed(unsigned int datamode) +static inline bool erofs_inode_is_data_compressed(unsigned int datamode) { if (datamode == EROFS_INODE_FLAT_COMPRESSION) return true; -- cgit v1.2.3-59-g8ed1b From 753a3c80b6afe55012ab49b076d30bfaf0266c46 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Tue, 13 Aug 2019 10:30:53 +0800 Subject: staging: erofs: remove incomplete cleancache cleancache was not fully implemented in EROFS. In addition, it's tend to remove the whole cleancache in related attempt [1]. [1] https://lore.kernel.org/linux-fsdevel/20190527103207.13287-3-jgross@suse.com/ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190813023054.73126-2-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/data.c | 6 ------ drivers/staging/erofs/internal.h | 1 - 2 files changed, 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index 75b859e48084..4cdb743c8b8d 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -201,12 +201,6 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, goto has_updated; } - if (cleancache_get_page(page) == 0) { - err = 0; - SetPageUptodate(page); - goto has_updated; - } - /* note that for readpage case, bio also equals to NULL */ if (bio && /* not continuous */ diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 118e7c7e4d4d..4ce5991c381f 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include "erofs_fs.h" -- cgit v1.2.3-59-g8ed1b From 9ddc7004f6aae68d8c3eee81b4b2a734d25c92e1 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Tue, 13 Aug 2019 10:30:54 +0800 Subject: staging: erofs: xattr.c: avoid BUG_ON Kill all the remaining BUG_ON in EROFS: - one BUG_ON was used to detect xattr on-disk corruption, proper error handling should be added for it instead; - the other BUG_ONs are used to detect potential issues, use DBG_BUGON only in (eng) debugging version. Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190813023054.73126-3-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/xattr.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index b29177a17347..289c7850ec96 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -115,7 +115,7 @@ static int init_inode_xattrs(struct inode *inode) for (i = 0; i < vi->xattr_shared_count; ++i) { if (unlikely(it.ofs >= EROFS_BLKSIZ)) { /* cannot be unaligned */ - BUG_ON(it.ofs != EROFS_BLKSIZ); + DBG_BUGON(it.ofs != EROFS_BLKSIZ); xattr_iter_end(&it, atomic_map); it.page = erofs_get_meta_page(sb, ++it.blkaddr, @@ -191,7 +191,7 @@ static int inline_xattr_iter_begin(struct xattr_iter *it, xattr_header_sz = inlinexattr_header_size(inode); if (unlikely(xattr_header_sz >= vi->xattr_isize)) { - BUG_ON(xattr_header_sz > vi->xattr_isize); + DBG_BUGON(xattr_header_sz > vi->xattr_isize); return -ENOATTR; } @@ -234,7 +234,11 @@ static int xattr_foreach(struct xattr_iter *it, if (tlimit) { unsigned int entry_sz = EROFS_XATTR_ENTRY_SIZE(&entry); - BUG_ON(*tlimit < entry_sz); + /* xattr on-disk corruption: xattr entry beyond xattr_isize */ + if (unlikely(*tlimit < entry_sz)) { + DBG_BUGON(1); + return -EIO; + } *tlimit -= entry_sz; } @@ -253,7 +257,7 @@ static int xattr_foreach(struct xattr_iter *it, while (processed < entry.e_name_len) { if (it->ofs >= EROFS_BLKSIZ) { - BUG_ON(it->ofs > EROFS_BLKSIZ); + DBG_BUGON(it->ofs > EROFS_BLKSIZ); err = xattr_iter_fixup(it); if (err) @@ -288,7 +292,7 @@ static int xattr_foreach(struct xattr_iter *it, while (processed < value_sz) { if (it->ofs >= EROFS_BLKSIZ) { - BUG_ON(it->ofs > EROFS_BLKSIZ); + DBG_BUGON(it->ofs > EROFS_BLKSIZ); err = xattr_iter_fixup(it); if (err) -- cgit v1.2.3-59-g8ed1b From 737d4d9ef6261ffa361fa708fac6047ac720688a Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 13 Aug 2019 12:24:26 +0800 Subject: staging: rtl8723bs: Remove debugging information exposed via procfs The procfs provides many useful information for debugging, but it may be too much for normal usage, routines like proc_get_sec_info() reports various security related information. So let's remove it. Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20190813042426.13733-1-kai.heng.feng@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/Makefile | 1 - drivers/staging/rtl8723bs/core/rtw_cmd.c | 5 - drivers/staging/rtl8723bs/core/rtw_debug.c | 1307 ------------------------ drivers/staging/rtl8723bs/include/autoconf.h | 4 - drivers/staging/rtl8723bs/include/drv_types.h | 2 - drivers/staging/rtl8723bs/include/osdep_intf.h | 2 - drivers/staging/rtl8723bs/include/rtw_debug.h | 77 -- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 8 - drivers/staging/rtl8723bs/os_dep/rtw_proc.c | 779 -------------- drivers/staging/rtl8723bs/os_dep/rtw_proc.h | 37 - drivers/staging/rtl8723bs/os_dep/sdio_intf.c | 3 - 11 files changed, 2225 deletions(-) delete mode 100644 drivers/staging/rtl8723bs/os_dep/rtw_proc.c delete mode 100644 drivers/staging/rtl8723bs/os_dep/rtw_proc.h (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/Makefile b/drivers/staging/rtl8723bs/Makefile index a12cf8dd8ed9..dfe410283ca0 100644 --- a/drivers/staging/rtl8723bs/Makefile +++ b/drivers/staging/rtl8723bs/Makefile @@ -60,7 +60,6 @@ r8723bs-y = \ os_dep/osdep_service.o \ os_dep/os_intfs.o \ os_dep/recv_linux.o \ - os_dep/rtw_proc.o \ os_dep/sdio_intf.o \ os_dep/sdio_ops_linux.o \ os_dep/wifi_regd.o \ diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c index c6565b0e502c..8d93c2f26890 100644 --- a/drivers/staging/rtl8723bs/core/rtw_cmd.c +++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c @@ -1817,11 +1817,6 @@ static void rtw_btinfo_hdl(struct adapter *adapter, u8 *buf, u16 buf_len) len = info->len; } -/* define DBG_PROC_SET_BTINFO_EVT */ -#ifdef DBG_PROC_SET_BTINFO_EVT - btinfo_evt_dump(RTW_DBGDUMP, info); -#endif - /* transform BT-FW btinfo to WiFI-FW C2H format and notify */ if (cmd_idx == BTINFO_WIFI_FETCH) buf[1] = 0; diff --git a/drivers/staging/rtl8723bs/core/rtw_debug.c b/drivers/staging/rtl8723bs/core/rtw_debug.c index 695a85999270..c48a8b80af4c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_debug.c +++ b/drivers/staging/rtl8723bs/core/rtw_debug.c @@ -132,1310 +132,3 @@ void rf_reg_dump(void *sel, struct adapter *adapter) } } } - -#ifdef PROC_DEBUG -ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 addr, val, len; - - if (count < 3) { - DBG_871X("argument size is less than 3\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x %x %x", &addr, &val, &len); - - if (num != 3) { - DBG_871X("invalid write_reg parameter!\n"); - return count; - } - - switch (len) { - case 1: - rtw_write8(padapter, addr, (u8)val); - break; - case 2: - rtw_write16(padapter, addr, (u16)val); - break; - case 4: - rtw_write32(padapter, addr, val); - break; - default: - DBG_871X("error write length =%d", len); - break; - } - - } - - return count; - -} - -static u32 proc_get_read_addr = 0xeeeeeeee; -static u32 proc_get_read_len = 0x4; - -int proc_get_read_reg(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - if (proc_get_read_addr == 0xeeeeeeee) { - DBG_871X_SEL_NL(m, "address not initialized\n"); - return 0; - } - - switch (proc_get_read_len) { - case 1: - DBG_871X_SEL_NL(m, "rtw_read8(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr)); - break; - case 2: - DBG_871X_SEL_NL(m, "rtw_read16(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr)); - break; - case 4: - DBG_871X_SEL_NL(m, "rtw_read32(0x%x) = 0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr)); - break; - default: - DBG_871X_SEL_NL(m, "error read length =%d\n", proc_get_read_len); - break; - } - - return 0; -} - -ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[16]; - u32 addr, len; - - if (count < 2) { - DBG_871X("argument size is less than 2\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x %x", &addr, &len); - - if (num != 2) { - DBG_871X("invalid read_reg parameter!\n"); - return count; - } - - proc_get_read_addr = addr; - - proc_get_read_len = len; - } - - return count; - -} - -int proc_get_fwstate(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - DBG_871X_SEL_NL(m, "fwstate = 0x%x\n", get_fwstate(pmlmepriv)); - - return 0; -} - -int proc_get_sec_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct security_priv *sec = &padapter->securitypriv; - - DBG_871X_SEL_NL(m, "auth_alg = 0x%x, enc_alg = 0x%x, auth_type = 0x%x, enc_type = 0x%x\n", - sec->dot11AuthAlgrthm, sec->dot11PrivacyAlgrthm, - sec->ndisauthtype, sec->ndisencryptstatus); - - DBG_871X_SEL_NL(m, "hw_decrypted =%d\n", sec->hw_decrypted); - -#ifdef DBG_SW_SEC_CNT - DBG_871X_SEL_NL(m, "wep_sw_enc_cnt =%llu, %llu, %llu\n" - , sec->wep_sw_enc_cnt_bc, sec->wep_sw_enc_cnt_mc, sec->wep_sw_enc_cnt_uc); - DBG_871X_SEL_NL(m, "wep_sw_dec_cnt =%llu, %llu, %llu\n" - , sec->wep_sw_dec_cnt_bc, sec->wep_sw_dec_cnt_mc, sec->wep_sw_dec_cnt_uc); - - DBG_871X_SEL_NL(m, "tkip_sw_enc_cnt =%llu, %llu, %llu\n" - , sec->tkip_sw_enc_cnt_bc, sec->tkip_sw_enc_cnt_mc, sec->tkip_sw_enc_cnt_uc); - DBG_871X_SEL_NL(m, "tkip_sw_dec_cnt =%llu, %llu, %llu\n" - , sec->tkip_sw_dec_cnt_bc, sec->tkip_sw_dec_cnt_mc, sec->tkip_sw_dec_cnt_uc); - - DBG_871X_SEL_NL(m, "aes_sw_enc_cnt =%llu, %llu, %llu\n" - , sec->aes_sw_enc_cnt_bc, sec->aes_sw_enc_cnt_mc, sec->aes_sw_enc_cnt_uc); - DBG_871X_SEL_NL(m, "aes_sw_dec_cnt =%llu, %llu, %llu\n" - , sec->aes_sw_dec_cnt_bc, sec->aes_sw_dec_cnt_mc, sec->aes_sw_dec_cnt_uc); -#endif /* DBG_SW_SEC_CNT */ - - return 0; -} - -int proc_get_mlmext_state(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - DBG_871X_SEL_NL(m, "pmlmeinfo->state = 0x%x\n", pmlmeinfo->state); - - return 0; -} - -int proc_get_roam_flags(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, "0x%02x\n", rtw_roam_flags(adapter)); - - return 0; -} - -ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - char tmp[32]; - u8 flags; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhx", &flags); - - if (num == 1) - rtw_assign_roam_flags(adapter, flags); - } - - return count; - -} - -int proc_get_roam_param(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *mlme = &adapter->mlmepriv; - - DBG_871X_SEL_NL(m, "%12s %12s %11s\n", "rssi_diff_th", "scanr_exp_ms", "scan_int_ms"); - DBG_871X_SEL_NL(m, "%-12u %-12u %-11u\n" - , mlme->roam_rssi_diff_th - , mlme->roam_scanr_exp_ms - , mlme->roam_scan_int_ms - ); - - return 0; -} - -ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *mlme = &adapter->mlmepriv; - - char tmp[32]; - u8 rssi_diff_th; - u32 scanr_exp_ms; - u32 scan_int_ms; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhu %u %u", &rssi_diff_th, &scanr_exp_ms, &scan_int_ms); - - if (num >= 1) - mlme->roam_rssi_diff_th = rssi_diff_th; - if (num >= 2) - mlme->roam_scanr_exp_ms = scanr_exp_ms; - if (num >= 3) - mlme->roam_scan_int_ms = scan_int_ms; - } - - return count; - -} - -ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - char tmp[32]; - u8 addr[ETH_ALEN]; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", addr, addr+1, addr+2, addr+3, addr+4, addr+5); - if (num == 6) - memcpy(adapter->mlmepriv.roam_tgt_addr, addr, ETH_ALEN); - - DBG_871X("set roam_tgt_addr to "MAC_FMT"\n", MAC_ARG(adapter->mlmepriv.roam_tgt_addr)); - } - - return count; -} - -int proc_get_qos_option(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - DBG_871X_SEL_NL(m, "qos_option =%d\n", pmlmepriv->qospriv.qos_option); - - return 0; -} - -int proc_get_ht_option(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - DBG_871X_SEL_NL(m, "ht_option =%d\n", pmlmepriv->htpriv.ht_option); - - return 0; -} - -int proc_get_rf_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - DBG_871X_SEL_NL(m, "cur_ch =%d, cur_bw =%d, cur_ch_offet =%d\n", - pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - - DBG_871X_SEL_NL(m, "oper_ch =%d, oper_bw =%d, oper_ch_offet =%d\n", - rtw_get_oper_ch(padapter), rtw_get_oper_bw(padapter), rtw_get_oper_choffset(padapter)); - - return 0; -} - -int proc_get_survey_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct __queue *queue = &(pmlmepriv->scanned_queue); - struct wlan_network *pnetwork = NULL; - struct list_head *plist, *phead; - s32 notify_signal; - s16 notify_noise = 0; - u16 index = 0; - - spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); - phead = get_list_head(queue); - plist = phead ? get_next(phead) : NULL; - if ((!phead) || (!plist)) { - spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); - return 0; - } - - DBG_871X_SEL_NL(m, "%5s %-17s %3s %-3s %-4s %-4s %5s %s\n", "index", "bssid", "ch", "RSSI", "SdBm", "Noise", "age", "ssid"); - while (1) { - if (phead == plist) - break; - - pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); - - if (!pnetwork) - break; - - if (check_fwstate(pmlmepriv, _FW_LINKED) == true && - is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) { - notify_signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);/*dbm*/ - } else { - notify_signal = translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);/*dbm*/ - } - - #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) - rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &(pnetwork->network.Configuration.DSConfig), &(notify_noise)); - #endif - - DBG_871X_SEL_NL(m, "%5d "MAC_FMT" %3d %3d %4d %4d %5d %s\n", - ++index, - MAC_ARG(pnetwork->network.MacAddress), - pnetwork->network.Configuration.DSConfig, - (int)pnetwork->network.Rssi, - notify_signal, - notify_noise, - jiffies_to_msecs(jiffies - pnetwork->last_scanned), - /*translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength),*/ - pnetwork->network.Ssid.Ssid); - plist = get_next(plist); - } - spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); - - return 0; -} - -int proc_get_ap_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct sta_info *psta; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_network *cur_network = &(pmlmepriv->cur_network); - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); - if (psta) { - int i; - struct recv_reorder_ctrl *preorder_ctrl; - - DBG_871X_SEL_NL(m, "SSID =%s\n", cur_network->network.Ssid.Ssid); - DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); - DBG_871X_SEL_NL(m, "cur_channel =%d, cur_bwmode =%d, cur_ch_offset =%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); - DBG_871X_SEL_NL(m, "wireless_mode = 0x%x, rtsen =%d, cts2slef =%d\n", psta->wireless_mode, psta->rtsen, psta->cts2self); - DBG_871X_SEL_NL(m, "state = 0x%x, aid =%d, macid =%d, raid =%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); - DBG_871X_SEL_NL(m, "qos_en =%d, ht_en =%d, init_rate =%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); - DBG_871X_SEL_NL(m, "bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m); - DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); - DBG_871X_SEL_NL(m, "agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); - DBG_871X_SEL_NL(m, "ldpc_cap = 0x%x, stbc_cap = 0x%x, beamform_cap = 0x%x\n", psta->htpriv.ldpc_cap, psta->htpriv.stbc_cap, psta->htpriv.beamform_cap); - - for (i = 0; i < 16; i++) { - preorder_ctrl = &psta->recvreorder_ctrl[i]; - if (preorder_ctrl->enable) { - DBG_871X_SEL_NL(m, "tid =%d, indicate_seq =%d\n", i, preorder_ctrl->indicate_seq); - } - } - - } else { - DBG_871X_SEL_NL(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress)); - } - - return 0; -} - -int proc_get_adapter_state(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, "name =%s, bSurpriseRemoved =%d, bDriverStopped =%d\n", - dev->name, padapter->bSurpriseRemoved, padapter->bDriverStopped); - - return 0; -} - -int proc_get_trx_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct recv_priv *precvpriv = &padapter->recvpriv; - struct hw_xmit *phwxmit; - - DBG_871X_SEL_NL(m, "free_xmitbuf_cnt =%d, free_xmitframe_cnt =%d\n" - , pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt); - DBG_871X_SEL_NL(m, "free_ext_xmitbuf_cnt =%d, free_xframe_ext_cnt =%d\n" - , pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt); - DBG_871X_SEL_NL(m, "free_recvframe_cnt =%d\n" - , precvpriv->free_recvframe_cnt); - - for (i = 0; i < 4; i++) { - phwxmit = pxmitpriv->hwxmits + i; - DBG_871X_SEL_NL(m, "%d, hwq.accnt =%d\n", i, phwxmit->accnt); - } - - return 0; -} - -int proc_get_rate_ctl(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - if (adapter->fix_rate != 0xff) { - DBG_871X_SEL_NL(m, "FIX\n"); - DBG_871X_SEL_NL(m, "0x%02x\n", adapter->fix_rate); - } else { - DBG_871X_SEL_NL(m, "RA\n"); - } - - return 0; -} - -ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u8 fix_rate; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%hhx", &fix_rate); - - if (num >= 1) - adapter->fix_rate = fix_rate; - } - - return count; -} - -ssize_t proc_set_fwdl_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[32]; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%hhu %hhu", &g_fwdl_chksum_fail, &g_fwdl_wintint_rdy_fail); - } - - return count; -} - -ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[32]; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%u", &g_wait_hiq_empty); - } - - return count; -} - -int proc_get_suspend_resume_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *dvobj = padapter->dvobj; - struct debug_priv *pdbgpriv = &dvobj->drv_dbg; - - DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_cnt =%d\n", pdbgpriv->dbg_sdio_alloc_irq_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_cnt =%d\n", pdbgpriv->dbg_sdio_free_irq_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_error_cnt =%d\n", pdbgpriv->dbg_sdio_alloc_irq_error_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_error_cnt =%d\n", pdbgpriv->dbg_sdio_free_irq_error_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_init_error_cnt =%d\n", pdbgpriv->dbg_sdio_init_error_cnt); - DBG_871X_SEL_NL(m, "dbg_sdio_deinit_error_cnt =%d\n", pdbgpriv->dbg_sdio_deinit_error_cnt); - DBG_871X_SEL_NL(m, "dbg_suspend_error_cnt =%d\n", pdbgpriv->dbg_suspend_error_cnt); - DBG_871X_SEL_NL(m, "dbg_suspend_cnt =%d\n", pdbgpriv->dbg_suspend_cnt); - DBG_871X_SEL_NL(m, "dbg_resume_cnt =%d\n", pdbgpriv->dbg_resume_cnt); - DBG_871X_SEL_NL(m, "dbg_resume_error_cnt =%d\n", pdbgpriv->dbg_resume_error_cnt); - DBG_871X_SEL_NL(m, "dbg_deinit_fail_cnt =%d\n", pdbgpriv->dbg_deinit_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_carddisable_cnt =%d\n", pdbgpriv->dbg_carddisable_cnt); - DBG_871X_SEL_NL(m, "dbg_ps_insuspend_cnt =%d\n", pdbgpriv->dbg_ps_insuspend_cnt); - DBG_871X_SEL_NL(m, "dbg_dev_unload_inIPS_cnt =%d\n", pdbgpriv->dbg_dev_unload_inIPS_cnt); - DBG_871X_SEL_NL(m, "dbg_scan_pwr_state_cnt =%d\n", pdbgpriv->dbg_scan_pwr_state_cnt); - DBG_871X_SEL_NL(m, "dbg_downloadfw_pwr_state_cnt =%d\n", pdbgpriv->dbg_downloadfw_pwr_state_cnt); - DBG_871X_SEL_NL(m, "dbg_carddisable_error_cnt =%d\n", pdbgpriv->dbg_carddisable_error_cnt); - DBG_871X_SEL_NL(m, "dbg_fw_read_ps_state_fail_cnt =%d\n", pdbgpriv->dbg_fw_read_ps_state_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_leave_ips_fail_cnt =%d\n", pdbgpriv->dbg_leave_ips_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_leave_lps_fail_cnt =%d\n", pdbgpriv->dbg_leave_lps_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_h2c_leave32k_fail_cnt =%d\n", pdbgpriv->dbg_h2c_leave32k_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_diswow_dload_fw_fail_cnt =%d\n", pdbgpriv->dbg_diswow_dload_fw_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_enwow_dload_fw_fail_cnt =%d\n", pdbgpriv->dbg_enwow_dload_fw_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_ips_drvopen_fail_cnt =%d\n", pdbgpriv->dbg_ips_drvopen_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_poll_fail_cnt =%d\n", pdbgpriv->dbg_poll_fail_cnt); - DBG_871X_SEL_NL(m, "dbg_rpwm_toggle_cnt =%d\n", pdbgpriv->dbg_rpwm_toggle_cnt); - DBG_871X_SEL_NL(m, "dbg_rpwm_timeout_fail_cnt =%d\n", pdbgpriv->dbg_rpwm_timeout_fail_cnt); - - return 0; -} - -#ifdef CONFIG_DBG_COUNTER - -int proc_get_rx_logs(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct rx_logs *rx_logs = &padapter->rx_logs; - - DBG_871X_SEL_NL(m, - "intf_rx =%d\n" - "intf_rx_err_recvframe =%d\n" - "intf_rx_err_skb =%d\n" - "intf_rx_report =%d\n" - "core_rx =%d\n" - "core_rx_pre =%d\n" - "core_rx_pre_ver_err =%d\n" - "core_rx_pre_mgmt =%d\n" - "core_rx_pre_mgmt_err_80211w =%d\n" - "core_rx_pre_mgmt_err =%d\n" - "core_rx_pre_ctrl =%d\n" - "core_rx_pre_ctrl_err =%d\n" - "core_rx_pre_data =%d\n" - "core_rx_pre_data_wapi_seq_err =%d\n" - "core_rx_pre_data_wapi_key_err =%d\n" - "core_rx_pre_data_handled =%d\n" - "core_rx_pre_data_err =%d\n" - "core_rx_pre_data_unknown =%d\n" - "core_rx_pre_unknown =%d\n" - "core_rx_enqueue =%d\n" - "core_rx_dequeue =%d\n" - "core_rx_post =%d\n" - "core_rx_post_decrypt =%d\n" - "core_rx_post_decrypt_wep =%d\n" - "core_rx_post_decrypt_tkip =%d\n" - "core_rx_post_decrypt_aes =%d\n" - "core_rx_post_decrypt_wapi =%d\n" - "core_rx_post_decrypt_hw =%d\n" - "core_rx_post_decrypt_unknown =%d\n" - "core_rx_post_decrypt_err =%d\n" - "core_rx_post_defrag_err =%d\n" - "core_rx_post_portctrl_err =%d\n" - "core_rx_post_indicate =%d\n" - "core_rx_post_indicate_in_oder =%d\n" - "core_rx_post_indicate_reoder =%d\n" - "core_rx_post_indicate_err =%d\n" - "os_indicate =%d\n" - "os_indicate_ap_mcast =%d\n" - "os_indicate_ap_forward =%d\n" - "os_indicate_ap_self =%d\n" - "os_indicate_err =%d\n" - "os_netif_ok =%d\n" - "os_netif_err =%d\n", - rx_logs->intf_rx, - rx_logs->intf_rx_err_recvframe, - rx_logs->intf_rx_err_skb, - rx_logs->intf_rx_report, - rx_logs->core_rx, - rx_logs->core_rx_pre, - rx_logs->core_rx_pre_ver_err, - rx_logs->core_rx_pre_mgmt, - rx_logs->core_rx_pre_mgmt_err_80211w, - rx_logs->core_rx_pre_mgmt_err, - rx_logs->core_rx_pre_ctrl, - rx_logs->core_rx_pre_ctrl_err, - rx_logs->core_rx_pre_data, - rx_logs->core_rx_pre_data_wapi_seq_err, - rx_logs->core_rx_pre_data_wapi_key_err, - rx_logs->core_rx_pre_data_handled, - rx_logs->core_rx_pre_data_err, - rx_logs->core_rx_pre_data_unknown, - rx_logs->core_rx_pre_unknown, - rx_logs->core_rx_enqueue, - rx_logs->core_rx_dequeue, - rx_logs->core_rx_post, - rx_logs->core_rx_post_decrypt, - rx_logs->core_rx_post_decrypt_wep, - rx_logs->core_rx_post_decrypt_tkip, - rx_logs->core_rx_post_decrypt_aes, - rx_logs->core_rx_post_decrypt_wapi, - rx_logs->core_rx_post_decrypt_hw, - rx_logs->core_rx_post_decrypt_unknown, - rx_logs->core_rx_post_decrypt_err, - rx_logs->core_rx_post_defrag_err, - rx_logs->core_rx_post_portctrl_err, - rx_logs->core_rx_post_indicate, - rx_logs->core_rx_post_indicate_in_oder, - rx_logs->core_rx_post_indicate_reoder, - rx_logs->core_rx_post_indicate_err, - rx_logs->os_indicate, - rx_logs->os_indicate_ap_mcast, - rx_logs->os_indicate_ap_forward, - rx_logs->os_indicate_ap_self, - rx_logs->os_indicate_err, - rx_logs->os_netif_ok, - rx_logs->os_netif_err - ); - - return 0; -} - -int proc_get_tx_logs(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct tx_logs *tx_logs = &padapter->tx_logs; - - DBG_871X_SEL_NL(m, - "os_tx =%d\n" - "os_tx_err_up =%d\n" - "os_tx_err_xmit =%d\n" - "os_tx_m2u =%d\n" - "os_tx_m2u_ignore_fw_linked =%d\n" - "os_tx_m2u_ignore_self =%d\n" - "os_tx_m2u_entry =%d\n" - "os_tx_m2u_entry_err_xmit =%d\n" - "os_tx_m2u_entry_err_skb =%d\n" - "os_tx_m2u_stop =%d\n" - "core_tx =%d\n" - "core_tx_err_pxmitframe =%d\n" - "core_tx_err_brtx =%d\n" - "core_tx_upd_attrib =%d\n" - "core_tx_upd_attrib_adhoc =%d\n" - "core_tx_upd_attrib_sta =%d\n" - "core_tx_upd_attrib_ap =%d\n" - "core_tx_upd_attrib_unknown =%d\n" - "core_tx_upd_attrib_dhcp =%d\n" - "core_tx_upd_attrib_icmp =%d\n" - "core_tx_upd_attrib_active =%d\n" - "core_tx_upd_attrib_err_ucast_sta =%d\n" - "core_tx_upd_attrib_err_ucast_ap_link =%d\n" - "core_tx_upd_attrib_err_sta =%d\n" - "core_tx_upd_attrib_err_link =%d\n" - "core_tx_upd_attrib_err_sec =%d\n" - "core_tx_ap_enqueue_warn_fwstate =%d\n" - "core_tx_ap_enqueue_warn_sta =%d\n" - "core_tx_ap_enqueue_warn_nosta =%d\n" - "core_tx_ap_enqueue_warn_link =%d\n" - "core_tx_ap_enqueue_warn_trigger =%d\n" - "core_tx_ap_enqueue_mcast =%d\n" - "core_tx_ap_enqueue_ucast =%d\n" - "core_tx_ap_enqueue =%d\n" - "intf_tx =%d\n" - "intf_tx_pending_ac =%d\n" - "intf_tx_pending_fw_under_survey =%d\n" - "intf_tx_pending_fw_under_linking =%d\n" - "intf_tx_pending_xmitbuf =%d\n" - "intf_tx_enqueue =%d\n" - "core_tx_enqueue =%d\n" - "core_tx_enqueue_class =%d\n" - "core_tx_enqueue_class_err_sta =%d\n" - "core_tx_enqueue_class_err_nosta =%d\n" - "core_tx_enqueue_class_err_fwlink =%d\n" - "intf_tx_direct =%d\n" - "intf_tx_direct_err_coalesce =%d\n" - "intf_tx_dequeue =%d\n" - "intf_tx_dequeue_err_coalesce =%d\n" - "intf_tx_dump_xframe =%d\n" - "intf_tx_dump_xframe_err_txdesc =%d\n" - "intf_tx_dump_xframe_err_port =%d\n", - tx_logs->os_tx, - tx_logs->os_tx_err_up, - tx_logs->os_tx_err_xmit, - tx_logs->os_tx_m2u, - tx_logs->os_tx_m2u_ignore_fw_linked, - tx_logs->os_tx_m2u_ignore_self, - tx_logs->os_tx_m2u_entry, - tx_logs->os_tx_m2u_entry_err_xmit, - tx_logs->os_tx_m2u_entry_err_skb, - tx_logs->os_tx_m2u_stop, - tx_logs->core_tx, - tx_logs->core_tx_err_pxmitframe, - tx_logs->core_tx_err_brtx, - tx_logs->core_tx_upd_attrib, - tx_logs->core_tx_upd_attrib_adhoc, - tx_logs->core_tx_upd_attrib_sta, - tx_logs->core_tx_upd_attrib_ap, - tx_logs->core_tx_upd_attrib_unknown, - tx_logs->core_tx_upd_attrib_dhcp, - tx_logs->core_tx_upd_attrib_icmp, - tx_logs->core_tx_upd_attrib_active, - tx_logs->core_tx_upd_attrib_err_ucast_sta, - tx_logs->core_tx_upd_attrib_err_ucast_ap_link, - tx_logs->core_tx_upd_attrib_err_sta, - tx_logs->core_tx_upd_attrib_err_link, - tx_logs->core_tx_upd_attrib_err_sec, - tx_logs->core_tx_ap_enqueue_warn_fwstate, - tx_logs->core_tx_ap_enqueue_warn_sta, - tx_logs->core_tx_ap_enqueue_warn_nosta, - tx_logs->core_tx_ap_enqueue_warn_link, - tx_logs->core_tx_ap_enqueue_warn_trigger, - tx_logs->core_tx_ap_enqueue_mcast, - tx_logs->core_tx_ap_enqueue_ucast, - tx_logs->core_tx_ap_enqueue, - tx_logs->intf_tx, - tx_logs->intf_tx_pending_ac, - tx_logs->intf_tx_pending_fw_under_survey, - tx_logs->intf_tx_pending_fw_under_linking, - tx_logs->intf_tx_pending_xmitbuf, - tx_logs->intf_tx_enqueue, - tx_logs->core_tx_enqueue, - tx_logs->core_tx_enqueue_class, - tx_logs->core_tx_enqueue_class_err_sta, - tx_logs->core_tx_enqueue_class_err_nosta, - tx_logs->core_tx_enqueue_class_err_fwlink, - tx_logs->intf_tx_direct, - tx_logs->intf_tx_direct_err_coalesce, - tx_logs->intf_tx_dequeue, - tx_logs->intf_tx_dequeue_err_coalesce, - tx_logs->intf_tx_dump_xframe, - tx_logs->intf_tx_dump_xframe_err_txdesc, - tx_logs->intf_tx_dump_xframe_err_port - ); - - return 0; -} - -int proc_get_int_logs(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, - "all =%d\n" - "err =%d\n" - "tbdok =%d\n" - "tbder =%d\n" - "bcnderr =%d\n" - "bcndma =%d\n" - "bcndma_e =%d\n" - "rx =%d\n" - "rx_rdu =%d\n" - "rx_fovw =%d\n" - "txfovw =%d\n" - "mgntok =%d\n" - "highdok =%d\n" - "bkdok =%d\n" - "bedok =%d\n" - "vidok =%d\n" - "vodok =%d\n", - padapter->int_logs.all, - padapter->int_logs.err, - padapter->int_logs.tbdok, - padapter->int_logs.tbder, - padapter->int_logs.bcnderr, - padapter->int_logs.bcndma, - padapter->int_logs.bcndma_e, - padapter->int_logs.rx, - padapter->int_logs.rx_rdu, - padapter->int_logs.rx_fovw, - padapter->int_logs.txfovw, - padapter->int_logs.mgntok, - padapter->int_logs.highdok, - padapter->int_logs.bkdok, - padapter->int_logs.bedok, - padapter->int_logs.vidok, - padapter->int_logs.vodok - ); - - return 0; -} - -#endif /* CONFIG_DBG_COUNTER*/ - -int proc_get_rx_signal(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - DBG_871X_SEL_NL(m, "rssi:%d\n", padapter->recvpriv.rssi); - /*DBG_871X_SEL_NL(m, "rxpwdb:%d\n", padapter->recvpriv.rxpwdb);*/ - DBG_871X_SEL_NL(m, "signal_strength:%u\n", padapter->recvpriv.signal_strength); - DBG_871X_SEL_NL(m, "signal_qual:%u\n", padapter->recvpriv.signal_qual); - DBG_871X_SEL_NL(m, "noise:%d\n", padapter->recvpriv.noise); - rtw_odm_get_perpkt_rssi(m, padapter); - #ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA - rtw_get_raw_rssi_info(m, padapter); - #endif - return 0; -} - - -int proc_get_hw_status(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *dvobj = padapter->dvobj; - struct debug_priv *pdbgpriv = &dvobj->drv_dbg; - - DBG_871X_SEL_NL(m, "RX FIFO full count: last_time =%lld, current_time =%lld, differential =%lld\n" - , pdbgpriv->dbg_rx_fifo_last_overflow, pdbgpriv->dbg_rx_fifo_curr_overflow, pdbgpriv->dbg_rx_fifo_diff_overflow); - - return 0; -} - -ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 is_signal_dbg, signal_strength; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength); - - is_signal_dbg = is_signal_dbg == 0?0:1; - - if (is_signal_dbg && num != 2) - return count; - - signal_strength = signal_strength > 100?100:signal_strength; - - padapter->recvpriv.is_signal_dbg = is_signal_dbg; - padapter->recvpriv.signal_strength_dbg = signal_strength; - - if (is_signal_dbg) - DBG_871X("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength); - else - DBG_871X("set %s\n", "HW_SIGNAL_STRENGTH"); - - } - - return count; - -} - -int proc_get_ht_enable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "%d\n", pregpriv->ht_enable); - - return 0; -} - -ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - pregpriv->ht_enable = mode; - printk("ht_enable =%d\n", pregpriv->ht_enable); - } - } - - return count; - -} - -int proc_get_bw_mode(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "0x%02x\n", pregpriv->bw_mode); - - return 0; -} - -ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - - pregpriv->bw_mode = mode; - printk("bw_mode =%d\n", mode); - - } - } - - return count; - -} - -int proc_get_ampdu_enable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "%d\n", pregpriv->ampdu_enable); - - return 0; -} - -ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 3) { - pregpriv->ampdu_enable = mode; - printk("ampdu_enable =%d\n", mode); - } - - } - - return count; - -} - -int proc_get_rx_ampdu(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (pregpriv) - DBG_871X_SEL_NL(m, - "accept_addba_req = %d , 0:Reject AP's Add BA req, 1:Accept AP's Add BA req.\n", - pmlmeinfo->accept_addba_req - ); - - return 0; -} - -ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - pmlmeinfo->accept_addba_req = mode; - DBG_871X("pmlmeinfo->accept_addba_req =%d\n", - pmlmeinfo->accept_addba_req); - if (mode == 0) { - /*tear down Rx AMPDU*/ - send_delba(padapter, 0, get_my_bssid(&(pmlmeinfo->network)));/* recipient*/ - } - } - - } - - return count; -} - -int proc_get_en_fwps(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "check_fw_ps = %d , 1:enable get FW PS state , 0: disable get FW PS state\n" - , pregpriv->check_fw_ps); - - return 0; -} - -ssize_t proc_set_en_fwps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && mode < 2) { - pregpriv->check_fw_ps = mode; - DBG_871X("pregpriv->check_fw_ps =%d\n", pregpriv->check_fw_ps); - } - } - return count; -} - -int proc_get_rx_stbc(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - - if (pregpriv) - DBG_871X_SEL_NL(m, "%d\n", pregpriv->rx_stbc); - - return 0; -} - -ssize_t proc_set_rx_stbc(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct registry_priv *pregpriv = &padapter->registrypriv; - char tmp[32]; - u32 mode; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &mode); - - if (pregpriv && (mode == 0 || mode == 1 || - mode == 2 || mode == 3)) { - pregpriv->rx_stbc = mode; - printk("rx_stbc =%d\n", mode); - } - } - - return count; - -} - -int proc_get_rssi_disp(struct seq_file *m, void *v) -{ - return 0; -} - -ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 enable = 0; - - if (count < 1) { - DBG_8192C("argument size is less than 1\n"); - return -EFAULT; - } - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - int num = sscanf(tmp, "%x", &enable); - - if (num != 1) { - DBG_8192C("invalid set_rssi_disp parameter!\n"); - return count; - } - - if (enable) { - DBG_8192C("Linked info Function Enable\n"); - padapter->bLinkInfoDump = enable; - } else { - DBG_8192C("Linked info Function Disable\n"); - padapter->bLinkInfoDump = 0; - } - } - return count; -} - -int proc_get_all_sta_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct sta_info *psta; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct sta_priv *pstapriv = &padapter->stapriv; - int i, j; - struct list_head *plist, *phead; - struct recv_reorder_ctrl *preorder_ctrl; - - DBG_871X_SEL_NL(m, "sta_dz_bitmap = 0x%x, tim_bitmap = 0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); - - spin_lock_bh(&pstapriv->sta_hash_lock); - - for (i = 0; i < NUM_STA; i++) { - phead = &(pstapriv->sta_hash[i]); - plist = get_next(phead); - - while (phead != plist) { - psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); - - plist = get_next(plist); - - DBG_871X_SEL_NL(m, "==============================\n"); - DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", - MAC_ARG(psta->hwaddr)); - DBG_871X_SEL_NL(m, "rtsen =%d, cts2slef =%d\n", - psta->rtsen, psta->cts2self); - DBG_871X_SEL_NL(m, "state = 0x%x, aid =%d, macid =%d, raid =%d\n", - psta->state, psta->aid, psta->mac_id, - psta->raid); - DBG_871X_SEL_NL(m, "qos_en =%d, ht_en =%d, init_rate =%d\n", - psta->qos_option, - psta->htpriv.ht_option, - psta->init_rate); - DBG_871X_SEL_NL(m, "bwmode =%d, ch_offset =%d, sgi_20m =%d, sgi_40m =%d\n", - psta->bw_mode, psta->htpriv.ch_offset, - psta->htpriv.sgi_20m, - psta->htpriv.sgi_40m); - DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", - psta->htpriv.ampdu_enable); - DBG_871X_SEL_NL(m, "agg_enable_bitmap =%x, candidate_tid_bitmap =%x\n", - psta->htpriv.agg_enable_bitmap, - psta->htpriv.candidate_tid_bitmap); - DBG_871X_SEL_NL(m, "sleepq_len =%d\n", - psta->sleepq_len); - DBG_871X_SEL_NL(m, "sta_xmitpriv.vo_q_qcnt =%d\n", - psta->sta_xmitpriv.vo_q.qcnt); - DBG_871X_SEL_NL(m, "sta_xmitpriv.vi_q_qcnt =%d\n", - psta->sta_xmitpriv.vi_q.qcnt); - DBG_871X_SEL_NL(m, "sta_xmitpriv.be_q_qcnt =%d\n", - psta->sta_xmitpriv.be_q.qcnt); - DBG_871X_SEL_NL(m, "sta_xmitpriv.bk_q_qcnt =%d\n", - psta->sta_xmitpriv.bk_q.qcnt); - - DBG_871X_SEL_NL(m, "capability = 0x%x\n", - psta->capability); - DBG_871X_SEL_NL(m, "flags = 0x%x\n", psta->flags); - DBG_871X_SEL_NL(m, "wpa_psk = 0x%x\n", psta->wpa_psk); - DBG_871X_SEL_NL(m, "wpa2_group_cipher = 0x%x\n", - psta->wpa2_group_cipher); - DBG_871X_SEL_NL(m, "wpa2_pairwise_cipher = 0x%x\n", - psta->wpa2_pairwise_cipher); - DBG_871X_SEL_NL(m, "qos_info = 0x%x\n", psta->qos_info); - DBG_871X_SEL_NL(m, "dot118021XPrivacy = 0x%x\n", - psta->dot118021XPrivacy); - - for (j = 0; j < 16; j++) { - preorder_ctrl = &psta->recvreorder_ctrl[j]; - if (preorder_ctrl->enable) - DBG_871X_SEL_NL(m, "tid =%d, indicate_seq =%d\n", - j, preorder_ctrl->indicate_seq); - } - DBG_871X_SEL_NL(m, "==============================\n"); - } - } - - spin_unlock_bh(&pstapriv->sta_hash_lock); - - return 0; -} - -int proc_get_btcoex_dbg(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter; - char buf[512] = {0}; - padapter = (struct adapter *)rtw_netdev_priv(dev); - - hal_btcoex_GetDBG(padapter, buf, 512); - - DBG_871X_SEL(m, "%s", buf); - - return 0; -} - -ssize_t proc_set_btcoex_dbg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter; - u8 tmp[80] = {0}; - u32 module[2] = {0}; - u32 num; - - padapter = (struct adapter *)rtw_netdev_priv(dev); - -/* DBG_871X("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));*/ - - if (NULL == buffer) { - DBG_871X(FUNC_ADPT_FMT ": input buffer is NULL!\n", - FUNC_ADPT_ARG(padapter)); - - return -EFAULT; - } - - if (count < 1) { - DBG_871X(FUNC_ADPT_FMT ": input length is 0!\n", - FUNC_ADPT_ARG(padapter)); - - return -EFAULT; - } - - num = count; - if (num > (sizeof(tmp) - 1)) - num = (sizeof(tmp) - 1); - - if (copy_from_user(tmp, buffer, num)) { - DBG_871X(FUNC_ADPT_FMT ": copy buffer from user space FAIL!\n", - FUNC_ADPT_ARG(padapter)); - - return -EFAULT; - } - - num = sscanf(tmp, "%x %x", module, module+1); - if (num == 1) { - if (module[0] == 0) - memset(module, 0, sizeof(module)); - else - memset(module, 0xFF, sizeof(module)); - } else if (num != 2) { - DBG_871X(FUNC_ADPT_FMT ": input(\"%s\") format incorrect!\n", - FUNC_ADPT_ARG(padapter), tmp); - - if (num == 0) - return -EFAULT; - } - - DBG_871X(FUNC_ADPT_FMT ": input 0x%08X 0x%08X\n", - FUNC_ADPT_ARG(padapter), module[0], module[1]); - hal_btcoex_SetDBG(padapter, module); - - return count; -} - -int proc_get_btcoex_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter; - const u32 bufsize = 30*100; - u8 *pbuf = NULL; - - padapter = (struct adapter *)rtw_netdev_priv(dev); - - pbuf = rtw_zmalloc(bufsize); - if (!pbuf) - return -ENOMEM; - - hal_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize); - - DBG_871X_SEL(m, "%s\n", pbuf); - - kfree(pbuf); - - return 0; -} - -#endif diff --git a/drivers/staging/rtl8723bs/include/autoconf.h b/drivers/staging/rtl8723bs/include/autoconf.h index 196aca3aed7b..8f4c1e734473 100644 --- a/drivers/staging/rtl8723bs/include/autoconf.h +++ b/drivers/staging/rtl8723bs/include/autoconf.h @@ -57,9 +57,5 @@ #define DBG 0 /* for ODM & BTCOEX debug */ #endif /* !DEBUG */ -#ifdef CONFIG_PROC_FS -#define PROC_DEBUG -#endif - /* define DBG_XMIT_BUF */ /* define DBG_XMIT_BUF_EXT */ diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index 96346ce064aa..8c1ade44ed81 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -576,8 +576,6 @@ struct adapter { int bup; struct net_device_stats stats; struct iw_statistics iwstats; - struct proc_dir_entry *dir_dev;/* for proc directory */ - struct proc_dir_entry *dir_odm; struct wireless_dev *rtw_wdev; struct rtw_wdev_priv wdev_data; diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h index 40313d17a242..fa16139fcce6 100644 --- a/drivers/staging/rtl8723bs/include/osdep_intf.h +++ b/drivers/staging/rtl8723bs/include/osdep_intf.h @@ -64,8 +64,6 @@ u16 rtw_recv_select_queue(struct sk_buff *skb); int rtw_ndev_notifier_register(void); void rtw_ndev_notifier_unregister(void); -#include "../os_dep/rtw_proc.h" - void rtw_ips_dev_unload(struct adapter *padapter); int rtw_ips_pwr_up(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/include/rtw_debug.h b/drivers/staging/rtl8723bs/include/rtw_debug.h index 216d9492575e..22fc5d730d7b 100644 --- a/drivers/staging/rtl8723bs/include/rtw_debug.h +++ b/drivers/staging/rtl8723bs/include/rtw_debug.h @@ -267,81 +267,4 @@ void mac_reg_dump(void *sel, struct adapter *adapter); void bb_reg_dump(void *sel, struct adapter *adapter); void rf_reg_dump(void *sel, struct adapter *adapter); -#ifdef PROC_DEBUG -ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_read_reg(struct seq_file *m, void *v); -ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_fwstate(struct seq_file *m, void *v); -int proc_get_sec_info(struct seq_file *m, void *v); -int proc_get_mlmext_state(struct seq_file *m, void *v); - -int proc_get_roam_flags(struct seq_file *m, void *v); -ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_roam_param(struct seq_file *m, void *v); -ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_qos_option(struct seq_file *m, void *v); -int proc_get_ht_option(struct seq_file *m, void *v); -int proc_get_rf_info(struct seq_file *m, void *v); -int proc_get_survey_info(struct seq_file *m, void *v); -int proc_get_ap_info(struct seq_file *m, void *v); -int proc_get_adapter_state(struct seq_file *m, void *v); -int proc_get_trx_info(struct seq_file *m, void *v); -int proc_get_rate_ctl(struct seq_file *m, void *v); -ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_suspend_resume_info(struct seq_file *m, void *v); - -ssize_t proc_set_fwdl_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_all_sta_info(struct seq_file *m, void *v); - -int proc_get_rx_signal(struct seq_file *m, void *v); -ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_hw_status(struct seq_file *m, void *v); - -int proc_get_ht_enable(struct seq_file *m, void *v); -ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_bw_mode(struct seq_file *m, void *v); -ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_ampdu_enable(struct seq_file *m, void *v); -ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_rx_ampdu(struct seq_file *m, void *v); -ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_rx_stbc(struct seq_file *m, void *v); -ssize_t proc_set_rx_stbc(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_en_fwps(struct seq_file *m, void *v); -ssize_t proc_set_en_fwps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -/* int proc_get_two_path_rssi(struct seq_file *m, void *v); */ -int proc_get_rssi_disp(struct seq_file *m, void *v); -ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_btcoex_dbg(struct seq_file *m, void *v); -ssize_t proc_set_btcoex_dbg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_btcoex_info(struct seq_file *m, void *v); - -int proc_get_odm_dbg_comp(struct seq_file *m, void *v); -ssize_t proc_set_odm_dbg_comp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -int proc_get_odm_dbg_level(struct seq_file *m, void *v); -ssize_t proc_set_odm_dbg_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -int proc_get_odm_adaptivity(struct seq_file *m, void *v); -ssize_t proc_set_odm_adaptivity(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); - -#ifdef CONFIG_DBG_COUNTER -int proc_get_rx_logs(struct seq_file *m, void *v); -int proc_get_tx_logs(struct seq_file *m, void *v); -int proc_get_int_logs(struct seq_file *m, void *v); -#endif - -#endif /* PROC_DEBUG */ - #endif /* __RTW_DEBUG_H__ */ diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c index 2ddafb07d5b6..ec3a75485233 100644 --- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c @@ -445,12 +445,6 @@ static int rtw_ndev_notifier_call(struct notifier_block *nb, unsigned long state DBG_871X_LEVEL(_drv_info_, FUNC_NDEV_FMT " state:%lu\n", FUNC_NDEV_ARG(dev), state); - switch (state) { - case NETDEV_CHANGENAME: - rtw_adapter_proc_replace(dev); - break; - } - return NOTIFY_DONE; } @@ -475,7 +469,6 @@ static int rtw_ndev_init(struct net_device *dev) DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(adapter)); strncpy(adapter->old_ifname, dev->name, IFNAMSIZ); - rtw_adapter_proc_init(dev); return 0; } @@ -485,7 +478,6 @@ static void rtw_ndev_uninit(struct net_device *dev) struct adapter *adapter = rtw_netdev_priv(dev); DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(adapter)); - rtw_adapter_proc_deinit(dev); } static const struct net_device_ops rtw_netdev_ops = { diff --git a/drivers/staging/rtl8723bs/os_dep/rtw_proc.c b/drivers/staging/rtl8723bs/os_dep/rtw_proc.c deleted file mode 100644 index 5f950fda48ea..000000000000 --- a/drivers/staging/rtl8723bs/os_dep/rtw_proc.c +++ /dev/null @@ -1,779 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/****************************************************************************** - * - * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ - -#include -#include -#include "rtw_proc.h" - -#ifdef PROC_DEBUG - -static struct proc_dir_entry *rtw_proc; - -#define RTW_PROC_NAME "rtl8723bs" - -#define get_proc_net init_net.proc_net - -inline struct proc_dir_entry *rtw_proc_create_dir(const char *name, struct proc_dir_entry *parent, void *data) -{ - struct proc_dir_entry *entry; - - entry = proc_mkdir_data(name, S_IRUGO|S_IXUGO, parent, data); - - return entry; -} - -inline struct proc_dir_entry *rtw_proc_create_entry(const char *name, struct proc_dir_entry *parent, - const struct file_operations *fops, void *data) -{ - struct proc_dir_entry *entry; - - entry = proc_create_data(name, S_IFREG|S_IRUGO, parent, fops, data); - - return entry; -} - -static int proc_get_dummy(struct seq_file *m, void *v) -{ - return 0; -} - -static int proc_get_drv_version(struct seq_file *m, void *v) -{ - dump_drv_version(m); - return 0; -} - -static int proc_get_log_level(struct seq_file *m, void *v) -{ - dump_log_level(m); - return 0; -} - -static ssize_t proc_set_log_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - char tmp[32]; - int log_level; - - if (count < 1) - return -EINVAL; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - sscanf(tmp, "%d ", &log_level); - if (log_level >= _drv_always_ && log_level <= _drv_debug_) { - GlobalDebugLevel = log_level; - printk("%d\n", GlobalDebugLevel); - } - } else { - return -EFAULT; - } - - return count; -} - -/* -* rtw_drv_proc: -* init/deinit when register/unregister driver -*/ -static const struct rtw_proc_hdl drv_proc_hdls[] = { - {"ver_info", proc_get_drv_version, NULL}, - {"log_level", proc_get_log_level, proc_set_log_level}, -}; - -static const int drv_proc_hdls_num = sizeof(drv_proc_hdls) / sizeof(struct rtw_proc_hdl); - -static int rtw_drv_proc_open(struct inode *inode, struct file *file) -{ - /* struct net_device *dev = proc_get_parent_data(inode); */ - ssize_t index = (ssize_t)PDE_DATA(inode); - const struct rtw_proc_hdl *hdl = drv_proc_hdls+index; - - return single_open(file, hdl->show, NULL); -} - -static ssize_t rtw_drv_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) -{ - ssize_t index = (ssize_t)PDE_DATA(file_inode(file)); - const struct rtw_proc_hdl *hdl = drv_proc_hdls+index; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write; - - if (write) - return write(file, buffer, count, pos, NULL); - - return -EROFS; -} - -static const struct file_operations rtw_drv_proc_fops = { - .owner = THIS_MODULE, - .open = rtw_drv_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rtw_drv_proc_write, -}; - -int rtw_drv_proc_init(void) -{ - int ret = _FAIL; - ssize_t i; - struct proc_dir_entry *entry = NULL; - - if (rtw_proc) { - rtw_warn_on(1); - goto exit; - } - - rtw_proc = rtw_proc_create_dir(RTW_PROC_NAME, get_proc_net, NULL); - - if (!rtw_proc) { - rtw_warn_on(1); - goto exit; - } - - for (i = 0; i < drv_proc_hdls_num; i++) { - entry = rtw_proc_create_entry(drv_proc_hdls[i].name, rtw_proc, &rtw_drv_proc_fops, (void *)i); - if (!entry) { - rtw_warn_on(1); - goto exit; - } - } - - ret = _SUCCESS; - -exit: - return ret; -} - -void rtw_drv_proc_deinit(void) -{ - int i; - - if (!rtw_proc) - return; - - for (i = 0; i < drv_proc_hdls_num; i++) - remove_proc_entry(drv_proc_hdls[i].name, rtw_proc); - - remove_proc_entry(RTW_PROC_NAME, get_proc_net); - rtw_proc = NULL; -} - -static int proc_get_sd_f0_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - sd_f0_reg_dump(m, adapter); - - return 0; -} - -static int proc_get_mac_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - mac_reg_dump(m, adapter); - - return 0; -} - -static int proc_get_bb_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - bb_reg_dump(m, adapter); - - return 0; -} - -static int proc_get_rf_reg_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rf_reg_dump(m, adapter); - - return 0; -} -static int proc_get_linked_info_dump(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - if (padapter) - DBG_871X_SEL_NL(m, "linked_info_dump :%s\n", (padapter->bLinkInfoDump)?"enable":"disable"); - - return 0; -} - -static ssize_t proc_set_linked_info_dump(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - char tmp[2]; - int mode = 0; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - if (padapter) { - /* padapter->bLinkInfoDump = mode; */ - /* DBG_871X("linked_info_dump =%s\n", (padapter->bLinkInfoDump)?"enable":"disable"); */ - linked_info_dump(padapter, mode); - } - - } - - return count; - -} - -static int proc_get_rx_info(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *psdpriv = padapter->dvobj; - struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; - - /* Counts of packets whose seq_num is less than preorder_ctrl->indicate_seq, Ex delay, retransmission, redundant packets and so on */ - DBG_871X_SEL_NL(m,"Counts of Packets Whose Seq_Num Less Than Reorder Control Seq_Num: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_drop_count); - /* How many times the Rx Reorder Timer is triggered. */ - DBG_871X_SEL_NL(m,"Rx Reorder Time-out Trigger Counts: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_forced_indicate_count); - /* Total counts of packets loss */ - DBG_871X_SEL_NL(m,"Rx Packet Loss Counts: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_loss_count); - DBG_871X_SEL_NL(m,"Duplicate Management Frame Drop Count: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_dup_mgt_frame_drop_count); - DBG_871X_SEL_NL(m,"AMPDU BA window shift Count: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_ampdu_window_shift_cnt); - return 0; -} - - -static ssize_t proc_reset_rx_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *psdpriv = padapter->dvobj; - struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; - char cmd[32]; - if (buffer && !copy_from_user(cmd, buffer, sizeof(cmd))) { - if ('0' == cmd[0]) { - pdbgpriv->dbg_rx_ampdu_drop_count = 0; - pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0; - pdbgpriv->dbg_rx_ampdu_loss_count = 0; - pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0; - pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0; - } - } - - return count; -} - -static int proc_get_cam(struct seq_file *m, void *v) -{ - return 0; -} - -static ssize_t proc_set_cam(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter; - - char tmp[32]; - char cmd[5]; - u8 id; - - adapter = (struct adapter *)rtw_netdev_priv(dev); - if (!adapter) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - /* c : clear specific cam entry */ - /* wfc : write specific cam entry from cam cache */ - - int num = sscanf(tmp, "%4s %hhu", cmd, &id); - - if (num < 2) - return count; - if (id >= TOTAL_CAM_ENTRY) - return -EINVAL; - - if (strcmp("c", cmd) == 0) { - _clear_cam_entry(adapter, id); - adapter->securitypriv.hw_decrypted = false; /* temporarily set this for TX path to use SW enc */ - } else if (strcmp("wfc", cmd) == 0) { - write_cam_from_cache(adapter, id); - } - } - - return count; -} - -static int proc_get_cam_cache(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - u8 i; - - DBG_871X_SEL_NL(m, "cam bitmap:0x%016llx\n", dvobj->cam_ctl.bitmap); - - DBG_871X_SEL_NL(m, "%-2s %-6s %-17s %-32s %-3s %-7s" - /* %-2s %-2s %-4s %-5s" */ - "\n" - , "id", "ctrl", "addr", "key", "kid", "type" - /* "MK", "GK", "MFB", "valid" */ - ); - - for (i = 0; i < 32; i++) { - if (dvobj->cam_cache[i].ctrl != 0) - DBG_871X_SEL_NL(m, "%2u 0x%04x "MAC_FMT" "KEY_FMT" %3u %-7s" - /* %2u %2u 0x%02x %5u" */ - "\n", i - , dvobj->cam_cache[i].ctrl - , MAC_ARG(dvobj->cam_cache[i].mac) - , KEY_ARG(dvobj->cam_cache[i].key) - , (dvobj->cam_cache[i].ctrl)&0x03 - , security_type_str(((dvobj->cam_cache[i].ctrl)>>2)&0x07) - /* ((dvobj->cam_cache[i].ctrl)>>5)&0x01 */ - /* ((dvobj->cam_cache[i].ctrl)>>6)&0x01 */ - /* ((dvobj->cam_cache[i].ctrl)>>8)&0x7f */ - /* ((dvobj->cam_cache[i].ctrl)>>15)&0x01 */ - ); - } - - return 0; -} - -/* -* rtw_adapter_proc: -* init/deinit when register/unregister net_device -*/ -static const struct rtw_proc_hdl adapter_proc_hdls[] = { - {"write_reg", proc_get_dummy, proc_set_write_reg}, - {"read_reg", proc_get_read_reg, proc_set_read_reg}, - {"fwstate", proc_get_fwstate, NULL}, - {"sec_info", proc_get_sec_info, NULL}, - {"mlmext_state", proc_get_mlmext_state, NULL}, - {"qos_option", proc_get_qos_option, NULL}, - {"ht_option", proc_get_ht_option, NULL}, - {"rf_info", proc_get_rf_info, NULL}, - {"survey_info", proc_get_survey_info, NULL}, - {"ap_info", proc_get_ap_info, NULL}, - {"adapter_state", proc_get_adapter_state, NULL}, - {"trx_info", proc_get_trx_info, NULL}, - {"rate_ctl", proc_get_rate_ctl, proc_set_rate_ctl}, - {"cam", proc_get_cam, proc_set_cam}, - {"cam_cache", proc_get_cam_cache, NULL}, - {"suspend_info", proc_get_suspend_resume_info, NULL}, - {"rx_info", proc_get_rx_info, proc_reset_rx_info}, - - {"roam_flags", proc_get_roam_flags, proc_set_roam_flags}, - {"roam_param", proc_get_roam_param, proc_set_roam_param}, - {"roam_tgt_addr", proc_get_dummy, proc_set_roam_tgt_addr}, - - {"sd_f0_reg_dump", proc_get_sd_f0_reg_dump, NULL}, - - {"fwdl_test_case", proc_get_dummy, proc_set_fwdl_test_case}, - {"wait_hiq_empty", proc_get_dummy, proc_set_wait_hiq_empty}, - - {"mac_reg_dump", proc_get_mac_reg_dump, NULL}, - {"bb_reg_dump", proc_get_bb_reg_dump, NULL}, - {"rf_reg_dump", proc_get_rf_reg_dump, NULL}, - - {"all_sta_info", proc_get_all_sta_info, NULL}, - - {"rx_signal", proc_get_rx_signal, proc_set_rx_signal}, - {"hw_info", proc_get_hw_status, NULL}, - - {"ht_enable", proc_get_ht_enable, proc_set_ht_enable}, - {"bw_mode", proc_get_bw_mode, proc_set_bw_mode}, - {"ampdu_enable", proc_get_ampdu_enable, proc_set_ampdu_enable}, - {"rx_stbc", proc_get_rx_stbc, proc_set_rx_stbc}, - {"rx_ampdu", proc_get_rx_ampdu, proc_set_rx_ampdu}, - - {"en_fwps", proc_get_en_fwps, proc_set_en_fwps}, - - /* path_rssi", proc_get_two_path_rssi, NULL}, */ - {"rssi_disp", proc_get_rssi_disp, proc_set_rssi_disp}, - - {"btcoex_dbg", proc_get_btcoex_dbg, proc_set_btcoex_dbg}, - {"btcoex", proc_get_btcoex_info, NULL}, - - {"linked_info_dump", proc_get_linked_info_dump, proc_set_linked_info_dump}, -#ifdef CONFIG_DBG_COUNTER - {"rx_logs", proc_get_rx_logs, NULL}, - {"tx_logs", proc_get_tx_logs, NULL}, - {"int_logs", proc_get_int_logs, NULL}, -#endif -}; - -static const int adapter_proc_hdls_num = sizeof(adapter_proc_hdls) / sizeof(struct rtw_proc_hdl); - -static int rtw_adapter_proc_open(struct inode *inode, struct file *file) -{ - ssize_t index = (ssize_t)PDE_DATA(inode); - const struct rtw_proc_hdl *hdl = adapter_proc_hdls+index; - - return single_open(file, hdl->show, proc_get_parent_data(inode)); -} - -static ssize_t rtw_adapter_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) -{ - ssize_t index = (ssize_t)PDE_DATA(file_inode(file)); - const struct rtw_proc_hdl *hdl = adapter_proc_hdls+index; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write; - - if (write) - return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private); - - return -EROFS; -} - -static const struct file_operations rtw_adapter_proc_fops = { - .owner = THIS_MODULE, - .open = rtw_adapter_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rtw_adapter_proc_write, -}; - -int proc_get_odm_dbg_comp(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_dbg_comp_msg(m, adapter); - - return 0; -} - -ssize_t proc_set_odm_dbg_comp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - - u64 dbg_comp; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%llx", &dbg_comp); - - if (num != 1) - return count; - - rtw_odm_dbg_comp_set(adapter, dbg_comp); - } - - return count; -} - -int proc_get_odm_dbg_level(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_dbg_level_msg(m, adapter); - - return 0; -} - -ssize_t proc_set_odm_dbg_level(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - - u32 dbg_level; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%u", &dbg_level); - - if (num != 1) - return count; - - rtw_odm_dbg_level_set(adapter, dbg_level); - } - - return count; -} - -static int proc_get_odm_ability(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_ability_msg(m, adapter); - - return 0; -} - -static ssize_t proc_set_odm_ability(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *adapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - - u32 ability; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x", &ability); - - if (num != 1) - return count; - - rtw_odm_ability_set(adapter, ability); - } - - return count; -} - -int proc_get_odm_adaptivity(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - - rtw_odm_adaptivity_parm_msg(m, padapter); - - return 0; -} - -ssize_t proc_set_odm_adaptivity(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data) -{ - struct net_device *dev = data; - struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - char tmp[32]; - u32 TH_L2H_ini; - s8 TH_EDCCA_HL_diff; - u32 IGI_Base; - int ForceEDCCA; - u8 AdapEn_RSSI; - u8 IGI_LowerBound; - - if (count < 1) - return -EFAULT; - - if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { - - int num = sscanf(tmp, "%x %hhd %x %d %hhu %hhu", - &TH_L2H_ini, &TH_EDCCA_HL_diff, &IGI_Base, &ForceEDCCA, &AdapEn_RSSI, &IGI_LowerBound); - - if (num != 6) - return count; - - rtw_odm_adaptivity_parm_set(padapter, (s8)TH_L2H_ini, TH_EDCCA_HL_diff, (s8)IGI_Base, (bool)ForceEDCCA, AdapEn_RSSI, IGI_LowerBound); - } - - return count; -} - -/* -* rtw_odm_proc: -* init/deinit when register/unregister net_device, along with rtw_adapter_proc -*/ -static const struct rtw_proc_hdl odm_proc_hdls[] = { - {"dbg_comp", proc_get_odm_dbg_comp, proc_set_odm_dbg_comp}, - {"dbg_level", proc_get_odm_dbg_level, proc_set_odm_dbg_level}, - {"ability", proc_get_odm_ability, proc_set_odm_ability}, - {"adaptivity", proc_get_odm_adaptivity, proc_set_odm_adaptivity}, -}; - -static const int odm_proc_hdls_num = sizeof(odm_proc_hdls) / sizeof(struct rtw_proc_hdl); - -static int rtw_odm_proc_open(struct inode *inode, struct file *file) -{ - ssize_t index = (ssize_t)PDE_DATA(inode); - const struct rtw_proc_hdl *hdl = odm_proc_hdls+index; - - return single_open(file, hdl->show, proc_get_parent_data(inode)); -} - -static ssize_t rtw_odm_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) -{ - ssize_t index = (ssize_t)PDE_DATA(file_inode(file)); - const struct rtw_proc_hdl *hdl = odm_proc_hdls+index; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *, void *) = hdl->write; - - if (write) - return write(file, buffer, count, pos, ((struct seq_file *)file->private_data)->private); - - return -EROFS; -} - -static const struct file_operations rtw_odm_proc_fops = { - .owner = THIS_MODULE, - .open = rtw_odm_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = rtw_odm_proc_write, -}; - -static struct proc_dir_entry *rtw_odm_proc_init(struct net_device *dev) -{ - struct proc_dir_entry *dir_odm = NULL; - struct proc_dir_entry *entry = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - ssize_t i; - - if (!adapter->dir_dev) { - rtw_warn_on(1); - goto exit; - } - - if (adapter->dir_odm) { - rtw_warn_on(1); - goto exit; - } - - dir_odm = rtw_proc_create_dir("odm", adapter->dir_dev, dev); - if (!dir_odm) { - rtw_warn_on(1); - goto exit; - } - - adapter->dir_odm = dir_odm; - - for (i = 0; i < odm_proc_hdls_num; i++) { - entry = rtw_proc_create_entry(odm_proc_hdls[i].name, dir_odm, &rtw_odm_proc_fops, (void *)i); - if (!entry) { - rtw_warn_on(1); - goto exit; - } - } - -exit: - return dir_odm; -} - -static void rtw_odm_proc_deinit(struct adapter *adapter) -{ - struct proc_dir_entry *dir_odm = NULL; - int i; - - dir_odm = adapter->dir_odm; - - if (!dir_odm) { - rtw_warn_on(1); - return; - } - - for (i = 0; i < odm_proc_hdls_num; i++) - remove_proc_entry(odm_proc_hdls[i].name, dir_odm); - - remove_proc_entry("odm", adapter->dir_dev); - - adapter->dir_odm = NULL; -} - -struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev) -{ - struct proc_dir_entry *drv_proc = rtw_proc; - struct proc_dir_entry *dir_dev = NULL; - struct proc_dir_entry *entry = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - ssize_t i; - - if (!drv_proc) { - rtw_warn_on(1); - goto exit; - } - - if (adapter->dir_dev) { - rtw_warn_on(1); - goto exit; - } - - dir_dev = rtw_proc_create_dir(dev->name, drv_proc, dev); - if (!dir_dev) { - rtw_warn_on(1); - goto exit; - } - - adapter->dir_dev = dir_dev; - - for (i = 0; i < adapter_proc_hdls_num; i++) { - entry = rtw_proc_create_entry(adapter_proc_hdls[i].name, dir_dev, &rtw_adapter_proc_fops, (void *)i); - if (!entry) { - rtw_warn_on(1); - goto exit; - } - } - - rtw_odm_proc_init(dev); - -exit: - return dir_dev; -} - -void rtw_adapter_proc_deinit(struct net_device *dev) -{ - struct proc_dir_entry *drv_proc = rtw_proc; - struct proc_dir_entry *dir_dev = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - int i; - - dir_dev = adapter->dir_dev; - - if (!dir_dev) { - rtw_warn_on(1); - return; - } - - for (i = 0; i < adapter_proc_hdls_num; i++) - remove_proc_entry(adapter_proc_hdls[i].name, dir_dev); - - rtw_odm_proc_deinit(adapter); - - remove_proc_entry(dev->name, drv_proc); - - adapter->dir_dev = NULL; -} - -void rtw_adapter_proc_replace(struct net_device *dev) -{ - struct proc_dir_entry *drv_proc = rtw_proc; - struct proc_dir_entry *dir_dev = NULL; - struct adapter *adapter = rtw_netdev_priv(dev); - int i; - - dir_dev = adapter->dir_dev; - - if (!dir_dev) { - rtw_warn_on(1); - return; - } - - for (i = 0; i < adapter_proc_hdls_num; i++) - remove_proc_entry(adapter_proc_hdls[i].name, dir_dev); - - rtw_odm_proc_deinit(adapter); - - remove_proc_entry(adapter->old_ifname, drv_proc); - - adapter->dir_dev = NULL; - - rtw_adapter_proc_init(dev); - -} - -#endif /* PROC_DEBUG */ diff --git a/drivers/staging/rtl8723bs/os_dep/rtw_proc.h b/drivers/staging/rtl8723bs/os_dep/rtw_proc.h deleted file mode 100644 index c7e6f62b61ef..000000000000 --- a/drivers/staging/rtl8723bs/os_dep/rtw_proc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/****************************************************************************** - * - * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. - * - ******************************************************************************/ -#ifndef __RTW_PROC_H__ -#define __RTW_PROC_H__ - -#include -#include - -struct rtw_proc_hdl { - char *name; - int (*show)(struct seq_file *, void *); - ssize_t (*write)(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data); -}; - -#ifdef PROC_DEBUG - -int rtw_drv_proc_init(void); -void rtw_drv_proc_deinit(void); -struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev); -void rtw_adapter_proc_deinit(struct net_device *dev); -void rtw_adapter_proc_replace(struct net_device *dev); - -#else //!PROC_DEBUG - -static inline int rtw_drv_proc_init(void) {return 0;} -static inline void rtw_drv_proc_deinit(void) {} -static inline struct proc_dir_entry *rtw_adapter_proc_init(struct net_device *dev){return NULL;} -static inline void rtw_adapter_proc_deinit(struct net_device *dev){} -static inline void rtw_adapter_proc_replace(struct net_device *dev){} - -#endif //!PROC_DEBUG - -#endif //__RTW_PROC_H__ diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index 65ffb807eda2..d3784c44f6d0 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -620,12 +620,10 @@ static int __init rtw_drv_entry(void) #endif /* BTCOEXVERSION */ sdio_drvpriv.drv_registered = true; - rtw_drv_proc_init(); ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv); if (ret != 0) { sdio_drvpriv.drv_registered = false; - rtw_drv_proc_deinit(); rtw_ndev_notifier_unregister(); DBG_871X("%s: register driver failed!!(%d)\n", __func__, ret); goto exit; @@ -646,7 +644,6 @@ static void __exit rtw_drv_halt(void) sdio_unregister_driver(&sdio_drvpriv.r871xs_drv); - rtw_drv_proc_deinit(); rtw_ndev_notifier_unregister(); DBG_871X_LEVEL(_drv_always_, "module exit success\n"); -- cgit v1.2.3-59-g8ed1b From 6da2422efbb7f7e11b7f81dcf62817891b311b85 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 13 Aug 2019 10:16:35 +0530 Subject: staging: rtl8712: xmitframe_addmic(): Change return values and type Change return values of xmitframe_addmic from _SUCCESS and _FAIL to 0 and -ENOMEM respectively. Modify call sites to check for non-zero values instead of _FAIL. Also change return type from sint to int. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190813044638.16348-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_xmit.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 178f8b96943b..cc5809e49e35 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -342,8 +342,8 @@ int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt, return 0; } -static sint xmitframe_addmic(struct _adapter *padapter, - struct xmit_frame *pxmitframe) +static int xmitframe_addmic(struct _adapter *padapter, + struct xmit_frame *pxmitframe) { u32 curfragnum, length; u8 *pframe, *payload, mic[8]; @@ -372,7 +372,7 @@ static sint xmitframe_addmic(struct _adapter *padapter, if (!memcmp(psecuritypriv->XGrptxmickey [psecuritypriv->XGrpKeyid].skey, null_key, 16)) - return _FAIL; + return -ENOMEM; /*start to calculate the mic code*/ r8712_secmicsetkey(&micdata, psecuritypriv-> @@ -381,7 +381,7 @@ static sint xmitframe_addmic(struct _adapter *padapter, } else { if (!memcmp(&stainfo->tkiptxmickey.skey[0], null_key, 16)) - return _FAIL; + return -ENOMEM; /* start to calculate the mic code */ r8712_secmicsetkey(&micdata, &stainfo->tkiptxmickey.skey[0]); @@ -442,7 +442,7 @@ static sint xmitframe_addmic(struct _adapter *padapter, payload = payload - pattrib->last_txcmdsz + 8; } } - return _SUCCESS; + return 0; } static sint xmitframe_swencrypt(struct _adapter *padapter, @@ -696,7 +696,7 @@ sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt, memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen); } - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) + if (xmitframe_addmic(padapter, pxmitframe)) return _FAIL; xmitframe_swencrypt(padapter, pxmitframe); return _SUCCESS; -- cgit v1.2.3-59-g8ed1b From bc6132f141b75ea1ee67574bf44adfd0433cad17 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 13 Aug 2019 10:16:36 +0530 Subject: staging: rtl8712: r8712_append_mpdu_unit(): Change return type Change return type of r8712_append_mpdu_unit from u8 to void and remove its return statement as it always returns only _SUCCESS. Modify call sites to simply call this function instead of checking its return value, and execute all the statements in the if-block for when the function returns _SUCCESS. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190813044638.16348-2-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 04e70048f0dd..6f1dbcf25859 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -278,8 +278,8 @@ void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) pcmdpriv->cmd_seq++; } -u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) +void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe) { struct _adapter *padapter = pxmitframe->padapter; struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; @@ -315,8 +315,6 @@ u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, ((ptx_desc->txdw0 & 0x0000ffff) + ((TXDESC_SIZE + last_txcmdsz + padding_sz) & 0x0000ffff))); - - return _SUCCESS; } @@ -332,8 +330,8 @@ u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, /*RTL8712_DMA_H2CCMD */ r8712_construct_txaggr_cmd_desc(pxmitbuf); r8712_construct_txaggr_cmd_hdr(pxmitbuf); - if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) - pxmitbuf->aggr_nr = 1; + r8712_append_mpdu_unit(pxmitbuf, pxmitframe); + pxmitbuf->aggr_nr = 1; return _SUCCESS; } @@ -347,11 +345,10 @@ u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, /* buffer addr assoc */ pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); - if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) { - r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, - pxmitframe); - pxmitbuf->aggr_nr++; - } + r8712_append_mpdu_unit(pxmitbuf, pxmitframe); + r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, + pxmitframe); + pxmitbuf->aggr_nr++; return TXDESC_SIZE + (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); -- cgit v1.2.3-59-g8ed1b From b849e9a4a09f349e37ab936cc082781098b3f48c Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 13 Aug 2019 10:16:37 +0530 Subject: staging: rtl8712: r8712_xmitframe_aggr_1st(): Change return type to void Change return type of r8712_xmitframe_aggr_1st from u8 to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190813044638.16348-3-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 6 ++---- drivers/staging/rtl8712/rtl8712_xmit.h | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 6f1dbcf25859..9152c25c11f8 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -318,8 +318,8 @@ void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, } -u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) +void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe) { /* linux complete context doesn't need to protect */ pxmitframe->pxmitbuf = pxmitbuf; @@ -332,8 +332,6 @@ u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, r8712_construct_txaggr_cmd_hdr(pxmitbuf); r8712_append_mpdu_unit(pxmitbuf, pxmitframe); pxmitbuf->aggr_nr = 1; - - return _SUCCESS; } u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h index 9be8fb70c92e..faf2128285b6 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.h +++ b/drivers/staging/rtl8712/rtl8712_xmit.h @@ -102,8 +102,8 @@ void r8712_do_queue_select(struct _adapter *padapter, struct pkt_attrib *pattrib); #ifdef CONFIG_R8712_TX_AGGR -u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe); +void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe); u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, struct xmit_frame *pxmitframe); #endif -- cgit v1.2.3-59-g8ed1b From ca8a0a4934e0d850c978d17371d2c8acd3ec5ff2 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Tue, 13 Aug 2019 10:16:38 +0530 Subject: staging: rtl8712: r8712_dump_aggr_xframe(): Change type to void Change return type of r8712_dump_aggr_xframe from u8 to void as it always returns _SUCCESS and its return value is never used. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190813044638.16348-4-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_xmit.c | 6 ++---- drivers/staging/rtl8712/rtl8712_xmit.h | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c index 9152c25c11f8..c247f92207f5 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.c +++ b/drivers/staging/rtl8712/rtl8712_xmit.c @@ -352,8 +352,8 @@ u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); } -u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe) +void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe) { struct _adapter *padapter = pxmitframe->padapter; struct dvobj_priv *pdvobj = &padapter->dvobjpriv; @@ -390,8 +390,6 @@ u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, } r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, total_length + TXDESC_SIZE, (u8 *)pxmitframe); - - return _SUCCESS; } #endif diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h index faf2128285b6..0b56bd3ac4d0 100644 --- a/drivers/staging/rtl8712/rtl8712_xmit.h +++ b/drivers/staging/rtl8712/rtl8712_xmit.h @@ -104,8 +104,8 @@ void r8712_do_queue_select(struct _adapter *padapter, #ifdef CONFIG_R8712_TX_AGGR void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, struct xmit_frame *pxmitframe); -u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, - struct xmit_frame *pxmitframe); +void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, + struct xmit_frame *pxmitframe); #endif #endif -- cgit v1.2.3-59-g8ed1b From b1198cca2982f02c27459cfd67d081d7c1460cf9 Mon Sep 17 00:00:00 2001 From: Merwin Trever Ferrao Date: Tue, 13 Aug 2019 12:28:06 +0530 Subject: Staging: rtl8712: rtl8712_recv: fixed 80 character length warning When the checkpatch.pl script was run, it showed lines with length more than 80 characters in rtl8712_recv.c file. Fixed by breaking it up into two lines within 80 characters. Signed-off-by: Merwin Trever Ferrao Link: https://lore.kernel.org/r/20190813065806.GA23606@IoT-COE Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_recv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index 42cb2c95b40c..9901815604f4 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -35,7 +35,8 @@ static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; static void recv_tasklet(void *priv); -void r8712_init_recv_priv(struct recv_priv *precvpriv, struct _adapter *padapter) +void r8712_init_recv_priv(struct recv_priv *precvpriv, + struct _adapter *padapter) { int i; struct recv_buf *precvbuf; -- cgit v1.2.3-59-g8ed1b From 759b2e69238dff3f072e1c8e231aecf662082b6c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 13 Aug 2019 13:48:38 +0100 Subject: staging: rtl8723bs: remove redundant assignment to ret Variable ret is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190813124838.1317-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_io.c b/drivers/staging/rtl8723bs/core/rtw_io.c index a92bc19b196a..57168578663a 100644 --- a/drivers/staging/rtl8723bs/core/rtw_io.c +++ b/drivers/staging/rtl8723bs/core/rtw_io.c @@ -142,7 +142,7 @@ u32 _rtw_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem) u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem); struct io_priv *pio_priv = &adapter->iopriv; struct intf_hdl *pintfhdl = &(pio_priv->intf); - u32 ret = _SUCCESS; + u32 ret; _write_port = pintfhdl->io_ops._write_port; -- cgit v1.2.3-59-g8ed1b From 9d8cfa9d5346b133487a2466b0ebd405c3eb6d07 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:42:58 +0300 Subject: staging: fsl-dpaa2/ethsw: remove IGMP default address Do not add an IGMP multicast address by default since we do not support Rx/Tx ar the moment. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-2-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index aac98ece2335..8032314d5cae 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1506,7 +1506,6 @@ err_close: static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port) { - const char def_mcast[ETH_ALEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01}; struct net_device *netdev = port_priv->netdev; struct ethsw_core *ethsw = port_priv->ethsw_data; struct dpsw_vlan_if_cfg vcfg; @@ -1532,12 +1531,10 @@ static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port) err = dpsw_vlan_remove_if(ethsw->mc_io, 0, ethsw->dpsw_handle, DEFAULT_VLAN_ID, &vcfg); - if (err) { + if (err) netdev_err(netdev, "dpsw_vlan_remove_if err %d\n", err); - return err; - } - return ethsw_port_fdb_add_mc(port_priv, def_mcast); + return err; } static void ethsw_unregister_notifier(struct device *dev) -- cgit v1.2.3-59-g8ed1b From f740eb942b2693bf7516026b4c598cb5e4a26e70 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:42:59 +0300 Subject: staging: fsl-dpaa2/ethsw: enable switch ports only on dev_open At probe time, only the DPSW object should be enabled without the associated ports, which will get enabled on dev_open. Remove the ethsw_open() and ethsw_stop() functions and replace them only with dpsw_enable()/_disable(). Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-3-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 59 ++++----------------------------- 1 file changed, 6 insertions(+), 53 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 8032314d5cae..302842c3bdfe 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1363,48 +1363,6 @@ err_switchdev_nb: return err; } -static int ethsw_open(struct ethsw_core *ethsw) -{ - struct ethsw_port_priv *port_priv = NULL; - int i, err; - - err = dpsw_enable(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) { - dev_err(ethsw->dev, "dpsw_enable err %d\n", err); - return err; - } - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - port_priv = ethsw->ports[i]; - err = dev_open(port_priv->netdev, NULL); - if (err) { - netdev_err(port_priv->netdev, "dev_open err %d\n", err); - return err; - } - } - - return 0; -} - -static int ethsw_stop(struct ethsw_core *ethsw) -{ - struct ethsw_port_priv *port_priv = NULL; - int i, err; - - for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { - port_priv = ethsw->ports[i]; - dev_close(port_priv->netdev); - } - - err = dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); - if (err) { - dev_err(ethsw->dev, "dpsw_disable err %d\n", err); - return err; - } - - return 0; -} - static int ethsw_init(struct fsl_mc_device *sw_dev) { struct device *dev = &sw_dev->dev; @@ -1586,9 +1544,7 @@ static int ethsw_remove(struct fsl_mc_device *sw_dev) destroy_workqueue(ethsw_owq); - rtnl_lock(); - ethsw_stop(ethsw); - rtnl_unlock(); + dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { port_priv = ethsw->ports[i]; @@ -1708,12 +1664,11 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) goto err_free_ports; } - /* Switch starts up enabled */ - rtnl_lock(); - err = ethsw_open(ethsw); - rtnl_unlock(); - if (err) + err = dpsw_enable(ethsw->mc_io, 0, ethsw->dpsw_handle); + if (err) { + dev_err(ethsw->dev, "dpsw_enable err %d\n", err); goto err_free_ports; + } /* Setup IRQs */ err = ethsw_setup_irqs(sw_dev); @@ -1724,9 +1679,7 @@ static int ethsw_probe(struct fsl_mc_device *sw_dev) return 0; err_stop: - rtnl_lock(); - ethsw_stop(ethsw); - rtnl_unlock(); + dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle); err_free_ports: /* Cleanup registered ports only */ -- cgit v1.2.3-59-g8ed1b From 73866324771014136699df73a4cd67e2c47f235c Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:00 +0300 Subject: staging: fsl-dpaa2/ethsw: add line terminator to all formats Add the '\n' line terminator to the string formats missing it. Reported-by: Joe Perches Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-4-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c | 2 +- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c index 926a0c053e18..95e9f1096999 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c @@ -65,7 +65,7 @@ ethsw_get_link_ksettings(struct net_device *netdev, port_priv->idx, &state); if (err) { - netdev_err(netdev, "ERROR %d getting link state", err); + netdev_err(netdev, "ERROR %d getting link state\n", err); goto out; } diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 302842c3bdfe..9ade73928e60 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -722,12 +722,12 @@ static irqreturn_t ethsw_irq0_handler_thread(int irq_num, void *arg) err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, &status); if (err) { - dev_err(dev, "Can't get irq status (err %d)", err); + dev_err(dev, "Can't get irq status (err %d)\n", err); err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, 0xFFFFFFFF); if (err) - dev_err(dev, "Can't clear irq status (err %d)", err); + dev_err(dev, "Can't clear irq status (err %d)\n", err); goto out; } @@ -772,21 +772,21 @@ static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev) IRQF_NO_SUSPEND | IRQF_ONESHOT, dev_name(dev), dev); if (err) { - dev_err(dev, "devm_request_threaded_irq(): %d", err); + dev_err(dev, "devm_request_threaded_irq(): %d\n", err); goto free_irq; } err = dpsw_set_irq_mask(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, mask); if (err) { - dev_err(dev, "dpsw_set_irq_mask(): %d", err); + dev_err(dev, "dpsw_set_irq_mask(): %d\n", err); goto free_devm_irq; } err = dpsw_set_irq_enable(ethsw->mc_io, 0, ethsw->dpsw_handle, DPSW_IRQ_INDEX_IF, 1); if (err) { - dev_err(dev, "dpsw_set_irq_enable(): %d", err); + dev_err(dev, "dpsw_set_irq_enable(): %d\n", err); goto free_devm_irq; } -- cgit v1.2.3-59-g8ed1b From 47980a20a4e257c251eee860e5041f16e2313b26 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:01 +0300 Subject: staging: fsl-dpaa2/ethsw: remove debug message Since ethtool will be loud enough if the .set_link_ksettings() callback fails, remove the debug messages which do not add additional information. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-5-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c index 95e9f1096999..12e33a3a1bf1 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c @@ -91,8 +91,6 @@ ethsw_set_link_ksettings(struct net_device *netdev, struct dpsw_link_cfg cfg = {0}; int err = 0; - netdev_dbg(netdev, "Setting link parameters..."); - /* Due to a temporary MC limitation, the DPSW port must be down * in order to be able to change link settings. Taking steps to let * the user know that. @@ -116,11 +114,6 @@ ethsw_set_link_ksettings(struct net_device *netdev, port_priv->ethsw_data->dpsw_handle, port_priv->idx, &cfg); - if (err) - /* ethtool will be loud enough if we return an error; no point - * in putting our own error message on the console by default - */ - netdev_dbg(netdev, "ERROR %d setting link cfg", err); return err; } -- cgit v1.2.3-59-g8ed1b From 38ec70cc875f1dc9c6afba47dfdd3bea85c7a9ac Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:02 +0300 Subject: staging: fsl-dpaa2/ethsw: use bool when encoding learning/flooding state Use a bool instead of an u8 in ethsw_set_learning() and ethsw_port_set_flood() to encode an binary type property. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-6-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 9ade73928e60..20519af4d804 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -149,12 +149,12 @@ static int ethsw_port_add_vlan(struct ethsw_port_priv *port_priv, return 0; } -static int ethsw_set_learning(struct ethsw_core *ethsw, u8 flag) +static int ethsw_set_learning(struct ethsw_core *ethsw, bool enable) { enum dpsw_fdb_learning_mode learn_mode; int err; - if (flag) + if (enable) learn_mode = DPSW_FDB_LEARNING_MODE_HW; else learn_mode = DPSW_FDB_LEARNING_MODE_DIS; @@ -165,24 +165,24 @@ static int ethsw_set_learning(struct ethsw_core *ethsw, u8 flag) dev_err(ethsw->dev, "dpsw_fdb_set_learning_mode err %d\n", err); return err; } - ethsw->learning = !!flag; + ethsw->learning = enable; return 0; } -static int ethsw_port_set_flood(struct ethsw_port_priv *port_priv, u8 flag) +static int ethsw_port_set_flood(struct ethsw_port_priv *port_priv, bool enable) { int err; err = dpsw_if_set_flooding(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, - port_priv->idx, flag); + port_priv->idx, enable); if (err) { netdev_err(port_priv->netdev, "dpsw_if_set_flooding err %d\n", err); return err; } - port_priv->flood = !!flag; + port_priv->flood = enable; return 0; } -- cgit v1.2.3-59-g8ed1b From 36ec62b7e9e6d2096f01e2df38b309d24ade1abd Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:03 +0300 Subject: staging: fsl-dpaa2/ethsw: remove unnecessary memset The ethtool core already zeroes the memory before calling .get_ethtool_stats() thus making the memset unnecessary. Remove it. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-7-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c index 12e33a3a1bf1..0f9f8345e534 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c @@ -149,9 +149,6 @@ static void ethsw_ethtool_get_stats(struct net_device *netdev, struct ethsw_port_priv *port_priv = netdev_priv(netdev); int i, err; - memset(data, 0, - sizeof(u64) * ETHSW_NUM_COUNTERS); - for (i = 0; i < ETHSW_NUM_COUNTERS; i++) { err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, -- cgit v1.2.3-59-g8ed1b From e76d3d60e3bb918fffb1af3558fe34cd3ea2116b Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:04 +0300 Subject: staging: fsl-dpaa2/ethsw: remove redundant VLAN check The ethsw_add_vlan() function is already called only when the VLAN is not yet configured on the switch. Remove the redundant check. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-8-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 20519af4d804..b69b2b7be972 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -34,11 +34,6 @@ static int ethsw_add_vlan(struct ethsw_core *ethsw, u16 vid) .fdb_id = 0, }; - if (ethsw->vlans[vid]) { - dev_err(ethsw->dev, "VLAN already configured\n"); - return -EEXIST; - } - err = dpsw_vlan_add(ethsw->mc_io, 0, ethsw->dpsw_handle, vid, &vcfg); if (err) { -- cgit v1.2.3-59-g8ed1b From 38fc21369eaaac937a3bbb0a445014731dd32566 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:05 +0300 Subject: staging: fsl-dpaa2/ethsw: reword error message In the current state, the dpaa2-ethsw driver supports only one bridge per DPSW object. Reword the error message so that this information is much more clear. Suggested-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-9-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index b69b2b7be972..28da109aef5e 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1119,8 +1119,7 @@ static int port_bridge_join(struct net_device *netdev, if (ethsw->ports[i]->bridge_dev && (ethsw->ports[i]->bridge_dev != upper_dev)) { netdev_err(netdev, - "Another switch port is connected to %s\n", - ethsw->ports[i]->bridge_dev->name); + "Only one bridge supported per DPSW object!\n"); return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From 18f1296f067e09f1aba8971a2b76b78734a5eb87 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:06 +0300 Subject: staging: fsl-dpaa2/ethsw: register_netdev only when ready The register_netdev() call should be made only when ready to process any user request on the interface. Move the call to be the last one issued in the probe sequence. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-10-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 28da109aef5e..14a9eebf687e 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1588,23 +1588,21 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) port_netdev->min_mtu = ETH_MIN_MTU; port_netdev->max_mtu = ETHSW_MAX_FRAME_LENGTH; + err = ethsw_port_init(port_priv, port_idx); + if (err) + goto err_port_probe; + err = register_netdev(port_netdev); if (err < 0) { dev_err(dev, "register_netdev error %d\n", err); - goto err_register_netdev; + goto err_port_probe; } ethsw->ports[port_idx] = port_priv; - err = ethsw_port_init(port_priv, port_idx); - if (err) - goto err_ethsw_port_init; - return 0; -err_ethsw_port_init: - unregister_netdev(port_netdev); -err_register_netdev: +err_port_probe: free_netdev(port_netdev); return err; -- cgit v1.2.3-59-g8ed1b From c391818a10def7f5aa989842892a4306e75c917d Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Aug 2019 15:43:07 +0300 Subject: staging: fsl-dpaa2/ethsw: do not force user to bring interface down Link settings can be changed only when the interface is down. Disable and re-enable the interface, if necessary, behind the scenes so that we do not force users to an if down/up sequence. Reported-by: Andrew Lunn Signed-off-by: Ioana Ciornei Link: https://lore.kernel.org/r/1565700187-16048-11-git-send-email-ioana.ciornei@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c | 32 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c index 0f9f8345e534..4f0bff86e43e 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c @@ -88,16 +88,21 @@ ethsw_set_link_ksettings(struct net_device *netdev, const struct ethtool_link_ksettings *link_ksettings) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); + struct ethsw_core *ethsw = port_priv->ethsw_data; struct dpsw_link_cfg cfg = {0}; - int err = 0; - - /* Due to a temporary MC limitation, the DPSW port must be down - * in order to be able to change link settings. Taking steps to let - * the user know that. - */ - if (netif_running(netdev)) { - netdev_info(netdev, "Sorry, interface must be brought down first.\n"); - return -EACCES; + bool if_running; + int err = 0, ret; + + /* Interface needs to be down to change link settings */ + if_running = netif_running(netdev); + if (if_running) { + err = dpsw_if_disable(ethsw->mc_io, 0, + ethsw->dpsw_handle, + port_priv->idx); + if (err) { + netdev_err(netdev, "dpsw_if_disable err %d\n", err); + return err; + } } cfg.rate = link_ksettings->base.speed; @@ -115,6 +120,15 @@ ethsw_set_link_ksettings(struct net_device *netdev, port_priv->idx, &cfg); + if (if_running) { + ret = dpsw_if_enable(ethsw->mc_io, 0, + ethsw->dpsw_handle, + port_priv->idx); + if (ret) { + netdev_err(netdev, "dpsw_if_enable err %d\n", ret); + return ret; + } + } return err; } -- cgit v1.2.3-59-g8ed1b From a72553505f11d507ef8d86ea9cb94da68011f417 Mon Sep 17 00:00:00 2001 From: Pratik Shinde Date: Wed, 14 Aug 2019 02:08:40 +0530 Subject: staging: erofs: removing an extra call to iloc() in fill_inode() in fill_inode() we call iloc() twice.Avoiding the extra call by storing the result. Signed-off-by: Pratik Shinde Reviewed-by: Chao Yu Cc: Gao Xiang Link: https://lore.kernel.org/r/20190813203840.13782-1-pratikshinde320@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/inode.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 286729143365..05de0236aa88 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -161,11 +161,12 @@ static int fill_inode(struct inode *inode, int isdir) int err; erofs_blk_t blkaddr; unsigned int ofs; + erofs_off_t inode_loc; trace_erofs_fill_inode(inode, isdir); - - blkaddr = erofs_blknr(iloc(sbi, vi->nid)); - ofs = erofs_blkoff(iloc(sbi, vi->nid)); + inode_loc = iloc(sbi, vi->nid); + blkaddr = erofs_blknr(inode_loc); + ofs = erofs_blkoff(inode_loc); debugln("%s, reading inode nid %llu at %u of blkaddr %u", __func__, vi->nid, ofs, blkaddr); -- cgit v1.2.3-59-g8ed1b From 1548547e1d82532db70a75b9635427a727cd5590 Mon Sep 17 00:00:00 2001 From: Nishka Dasgupta Date: Thu, 15 Aug 2019 11:19:24 +0530 Subject: staging: gasket: apex: Make structure apex_desc constant Static structure apex_desc, of type gasket_driver_desc, is used only as an argument to the functions gasket_register_device() and gasket_unregister_device(). In the definitions of both these functions, their parameter is declared as const. Hence make apex_desc itself constant to protect it from modification. Issue found with Coccinelle. Signed-off-by: Nishka Dasgupta Link: https://lore.kernel.org/r/20190815054924.643-1-nishkadg.linux@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gasket/apex_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/gasket/apex_driver.c b/drivers/staging/gasket/apex_driver.c index 464648ee2036..2973bb920a26 100644 --- a/drivers/staging/gasket/apex_driver.c +++ b/drivers/staging/gasket/apex_driver.c @@ -659,7 +659,7 @@ static void apex_pci_remove(struct pci_dev *pci_dev) pci_disable_device(pci_dev); } -static struct gasket_driver_desc apex_desc = { +static const struct gasket_driver_desc apex_desc = { .name = "apex", .driver_version = APEX_DRIVER_VERSION, .major = 120, -- cgit v1.2.3-59-g8ed1b From 7d5e9e350e60526779e293f32d8c32c4d5090b8b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Aug 2019 09:40:34 +0100 Subject: staging: rtl8192u: fix up indentation of a statement There is a statement that is indented one level too deeply, remove the extraneous tab. Addresses-Coverity: ("Identation does not match nesting level") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190815084034.13885-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8190_rtl8256.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 92de92a3325a..0bedf88525cd 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -289,8 +289,8 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) writeVal = 0x03030303; } else { writeVal = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; - } - rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); + } + rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); } return; -- cgit v1.2.3-59-g8ed1b From d247ceda6ae65968bda1bf7a26b54a257a414c7a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Aug 2019 11:53:14 +0100 Subject: staging: comedi: usbduxsigma: remove redundant assignment to variable fx2delay Variable fx2delay is being initialized with a value that is never read and fx2delay is being re-assigned a little later on. The assignment is redundant and hence can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190815105314.5756-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 3cc40d2544be..54d7605e909f 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1074,7 +1074,7 @@ static int usbduxsigma_pwm_period(struct comedi_device *dev, unsigned int period) { struct usbduxsigma_private *devpriv = dev->private; - int fx2delay = 255; + int fx2delay; if (period < MIN_PWM_PERIOD) return -EAGAIN; -- cgit v1.2.3-59-g8ed1b From a6b9b1d5eae61a68085030e50d56265dec5baa94 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 14 Aug 2019 18:37:03 +0800 Subject: staging: erofs: introduce EFSCORRUPTED and more logs Previously, EROFS uses EIO to indicate that filesystem is corrupted as well. However, as Pavel said [1], other filesystems tend to use EUCLEAN(EFSCORRUPTED) instead, let's follow what others do right now. Also, add some more prints to the syslog. [1] https://lore.kernel.org/lkml/20190813114821.GB11559@amd/ Suggested-by: Pavel Machek Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190814103705.60698-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/data.c | 6 ++++-- drivers/staging/erofs/dir.c | 15 ++++++++------- drivers/staging/erofs/inode.c | 17 ++++++++++++----- drivers/staging/erofs/internal.h | 2 ++ drivers/staging/erofs/namei.c | 6 ++++-- drivers/staging/erofs/xattr.c | 5 +++-- drivers/staging/erofs/zmap.c | 5 +++-- 7 files changed, 36 insertions(+), 20 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c index 4cdb743c8b8d..72c4b4c5296b 100644 --- a/drivers/staging/erofs/data.c +++ b/drivers/staging/erofs/data.c @@ -143,10 +143,12 @@ static int erofs_map_blocks_flatmode(struct inode *inode, vi->xattr_isize + erofs_blkoff(map->m_la); map->m_plen = inode->i_size - offset; - /* inline data should locate in one meta block */ + /* inline data should be located in one meta block */ if (erofs_blkoff(map->m_pa) + map->m_plen > PAGE_SIZE) { + errln("inline data cross block boundary @ nid %llu", + vi->nid); DBG_BUGON(1); - err = -EIO; + err = -EFSCORRUPTED; goto err_out; } diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index 2fbfc4935077..01efc96e1212 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -34,7 +34,7 @@ static void debug_one_dentry(unsigned char d_type, const char *de_name, #endif } -static int erofs_fill_dentries(struct dir_context *ctx, +static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, void *dentry_blk, unsigned int *ofs, unsigned int nameoff, unsigned int maxsize) { @@ -63,8 +63,9 @@ static int erofs_fill_dentries(struct dir_context *ctx, /* a corrupted entry is found */ if (unlikely(nameoff + de_namelen > maxsize || de_namelen > EROFS_NAME_LEN)) { + errln("bogus dirent @ nid %llu", EROFS_V(dir)->nid); DBG_BUGON(1); - return -EIO; + return -EFSCORRUPTED; } debug_one_dentry(d_type, de_name, de_namelen); @@ -104,10 +105,9 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) if (unlikely(nameoff < sizeof(struct erofs_dirent) || nameoff >= PAGE_SIZE)) { - errln("%s, invalid de[0].nameoff %u", - __func__, nameoff); - - err = -EIO; + errln("%s, invalid de[0].nameoff %u @ nid %llu", + __func__, nameoff, EROFS_V(dir)->nid); + err = -EFSCORRUPTED; goto skip_this; } @@ -123,7 +123,8 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) goto skip_this; } - err = erofs_fill_dentries(ctx, de, &ofs, nameoff, maxsize); + err = erofs_fill_dentries(dir, ctx, de, &ofs, + nameoff, maxsize); skip_this: kunmap(dentry_page); diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 05de0236aa88..961c3ab91a8a 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -43,7 +43,7 @@ static int read_inode(struct inode *inode, void *data) else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) inode->i_rdev = 0; else - return -EIO; + goto bogusimode; i_uid_write(inode, le32_to_cpu(v2->i_uid)); i_gid_write(inode, le32_to_cpu(v2->i_gid)); @@ -76,7 +76,7 @@ static int read_inode(struct inode *inode, void *data) else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) inode->i_rdev = 0; else - return -EIO; + goto bogusimode; i_uid_write(inode, le16_to_cpu(v1->i_uid)); i_gid_write(inode, le16_to_cpu(v1->i_gid)); @@ -104,6 +104,11 @@ static int read_inode(struct inode *inode, void *data) else inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; return 0; + +bogusimode: + errln("bogus i_mode (%o) @ nid %llu", inode->i_mode, vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; } /* @@ -137,9 +142,11 @@ static int fill_inline_data(struct inode *inode, void *data, /* inline symlink data shouldn't across page boundary as well */ if (unlikely(m_pofs + inode->i_size > PAGE_SIZE)) { - DBG_BUGON(1); kfree(lnk); - return -EIO; + errln("inline data cross block boundary @ nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; } /* get in-page inline data */ @@ -201,7 +208,7 @@ static int fill_inode(struct inode *inode, int isdir) init_special_inode(inode, inode->i_mode, inode->i_rdev); goto out_unlock; } else { - err = -EIO; + err = -EFSCORRUPTED; goto out_unlock; } diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 4ce5991c381f..12f737cbc0c0 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -548,5 +548,7 @@ static inline int z_erofs_init_zip_subsystem(void) { return 0; } static inline void z_erofs_exit_zip_subsystem(void) {} #endif /* !CONFIG_EROFS_FS_ZIP */ +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ + #endif /* __EROFS_INTERNAL_H */ diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index 8e06526da023..c0963f5a2d22 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -116,10 +116,12 @@ static struct page *find_target_block_classic(struct inode *dir, struct erofs_qstr dname; if (unlikely(!ndirents)) { - DBG_BUGON(1); kunmap_atomic(de); put_page(page); - page = ERR_PTR(-EIO); + errln("corrupted dir block %d @ nid %llu", + mid, EROFS_V(dir)->nid); + DBG_BUGON(1); + page = ERR_PTR(-EFSCORRUPTED); goto out; } diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index 289c7850ec96..c5bfc9be412f 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -75,8 +75,9 @@ static int init_inode_xattrs(struct inode *inode) goto out_unlock; } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { if (unlikely(vi->xattr_isize)) { + errln("bogus xattr ibody @ nid %llu", vi->nid); DBG_BUGON(1); - ret = -EIO; + ret = -EFSCORRUPTED; goto out_unlock; /* xattr ondisk layout error */ } ret = -ENOATTR; @@ -237,7 +238,7 @@ static int xattr_foreach(struct xattr_iter *it, /* xattr on-disk corruption: xattr entry beyond xattr_isize */ if (unlikely(*tlimit < entry_sz)) { DBG_BUGON(1); - return -EIO; + return -EFSCORRUPTED; } *tlimit -= entry_sz; } diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index aeed5c674d9e..16b3625604f4 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -338,8 +338,9 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, int err; if (lcn < lookback_distance) { + errln("bogus lookback distance @ nid %llu", vi->nid); DBG_BUGON(1); - return -EIO; + return -EFSCORRUPTED; } /* load extent head logical cluster if needed */ @@ -419,7 +420,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, if (unlikely(!m.lcn)) { errln("invalid logical cluster 0 at nid %llu", vi->nid); - err = -EIO; + err = -EFSCORRUPTED; goto unmap_out; } end = (m.lcn << lclusterbits) | m.clusterofs; -- cgit v1.2.3-59-g8ed1b From 382329a9d8553a98418a6f6e3425f0c288837897 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 14 Aug 2019 18:37:04 +0800 Subject: staging: erofs: differentiate unsupported on-disk format For some specific fields, use EOPNOTSUPP instead of EIO for values which look sane but aren't supported right now. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190814103705.60698-2-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/inode.c | 4 ++-- drivers/staging/erofs/zmap.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 961c3ab91a8a..cbc2c342a37f 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -24,7 +24,7 @@ static int read_inode(struct inode *inode, void *data) errln("unsupported data mapping %u of nid %llu", vi->datamode, vi->nid); DBG_BUGON(1); - return -EIO; + return -EOPNOTSUPP; } if (__inode_version(advise) == EROFS_INODE_LAYOUT_V2) { @@ -95,7 +95,7 @@ static int read_inode(struct inode *inode, void *data) errln("unsupported on-disk inode version %u of nid %llu", __inode_version(advise), vi->nid); DBG_BUGON(1); - return -EIO; + return -EOPNOTSUPP; } if (!nblks) diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 16b3625604f4..5551e615e8ea 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -178,7 +178,7 @@ static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, break; default: DBG_BUGON(1); - return -EIO; + return -EOPNOTSUPP; } m->type = type; return 0; @@ -362,7 +362,7 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, errln("unknown type %u at lcn %lu of nid %llu", m->type, lcn, vi->nid); DBG_BUGON(1); - return -EIO; + return -EOPNOTSUPP; } return 0; } @@ -436,7 +436,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, default: errln("unknown type %u at offset %llu of nid %llu", m.type, ofs, vi->nid); - err = -EIO; + err = -EOPNOTSUPP; goto unmap_out; } -- cgit v1.2.3-59-g8ed1b From ff784a78af11712c7fa97c292be5390e45b50639 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 14 Aug 2019 18:37:05 +0800 Subject: staging: erofs: correct all misused ENOTSUPP As Chao pointed out [1], ENOTSUPP is used for NFS protocol only, we should use EOPNOTSUPP instead... [1] https://lore.kernel.org/lkml/108ee2f9-75dd-b8ab-8da7-b81c17bafbf6@huawei.com/ Reported-by: Chao Yu Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190814103705.60698-3-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/decompressor.c | 2 +- drivers/staging/erofs/internal.h | 6 +++--- drivers/staging/erofs/xattr.c | 2 +- drivers/staging/erofs/xattr.h | 4 ++-- drivers/staging/erofs/zmap.c | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c index 5361a2bbedb6..32a811ac704a 100644 --- a/drivers/staging/erofs/decompressor.c +++ b/drivers/staging/erofs/decompressor.c @@ -124,7 +124,7 @@ static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) int ret; if (rq->inputsize > PAGE_SIZE) - return -ENOTSUPP; + return -EOPNOTSUPP; src = kmap_atomic(*rq->in); inputmargin = 0; diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 12f737cbc0c0..0e8d58546c52 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -403,12 +403,12 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags); #else -static inline int z_erofs_fill_inode(struct inode *inode) { return -ENOTSUPP; } +static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; } static inline int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, int flags) { - return -ENOTSUPP; + return -EOPNOTSUPP; } #endif /* !CONFIG_EROFS_FS_ZIP */ @@ -516,7 +516,7 @@ void *erofs_get_pcpubuf(unsigned int pagenr); #else static inline void *erofs_get_pcpubuf(unsigned int pagenr) { - return ERR_PTR(-ENOTSUPP); + return ERR_PTR(-EOPNOTSUPP); } #define erofs_put_pcpubuf(buf) do {} while (0) diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c index c5bfc9be412f..e7e5840e3f9d 100644 --- a/drivers/staging/erofs/xattr.c +++ b/drivers/staging/erofs/xattr.c @@ -71,7 +71,7 @@ static int init_inode_xattrs(struct inode *inode) if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) { errln("xattr_isize %d of nid %llu is not supported yet", vi->xattr_isize, vi->nid); - ret = -ENOTSUPP; + ret = -EOPNOTSUPP; goto out_unlock; } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { if (unlikely(vi->xattr_isize)) { diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h index 63cc87e3d3f4..e20249647541 100644 --- a/drivers/staging/erofs/xattr.h +++ b/drivers/staging/erofs/xattr.h @@ -74,13 +74,13 @@ static inline int erofs_getxattr(struct inode *inode, int index, const char *name, void *buffer, size_t buffer_size) { - return -ENOTSUPP; + return -EOPNOTSUPP; } static inline ssize_t erofs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) { - return -ENOTSUPP; + return -EOPNOTSUPP; } #endif /* !CONFIG_EROFS_FS_XATTR */ diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 5551e615e8ea..b61b9b5950ac 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -68,7 +68,7 @@ static int fill_inode_lazy(struct inode *inode) if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) { errln("unknown compression format %u for nid %llu, please upgrade kernel", vi->z_algorithmtype[0], vi->nid); - err = -ENOTSUPP; + err = -EOPNOTSUPP; goto unmap_done; } @@ -79,7 +79,7 @@ static int fill_inode_lazy(struct inode *inode) if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) { errln("unsupported physical clusterbits %u for nid %llu, please upgrade kernel", vi->z_physical_clusterbits[0], vi->nid); - err = -ENOTSUPP; + err = -EOPNOTSUPP; goto unmap_done; } @@ -211,7 +211,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m, else if (1 << amortizedshift == 2 && lclusterbits == 12) vcnt = 16; else - return -ENOTSUPP; + return -EOPNOTSUPP; encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt; base = round_down(eofs, vcnt << amortizedshift); @@ -275,7 +275,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, int err; if (lclusterbits != 12) - return -ENOTSUPP; + return -EOPNOTSUPP; if (lcn >= totalidx) return -EINVAL; -- cgit v1.2.3-59-g8ed1b From 81e0da703fdba1ee126868bf8350592c79cdba13 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 15 Aug 2019 14:30:09 +0200 Subject: staging: sm750fb: fix odd license text There is some "confusing" license text in some of the sm750fb driver files. After discussing it with the company, it turns out to have been a mistake and these lines can be safely removed. The files are all to be licensed under the GPLv2 license. Cc: Sudip Mukherjee Cc: Teddy Wang Cc: linux-fbdev@vger.kernel.org Cc: devel@driverdev.osuosl.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190815123009.16499-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750.h | 3 --- drivers/staging/sm750fb/ddk750_swi2c.c | 3 --- drivers/staging/sm750fb/ddk750_swi2c.h | 3 --- 3 files changed, 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/sm750fb/ddk750.h b/drivers/staging/sm750fb/ddk750.h index 482c1c6ba422..64ef4d258a91 100644 --- a/drivers/staging/sm750fb/ddk750.h +++ b/drivers/staging/sm750fb/ddk750.h @@ -2,9 +2,6 @@ /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * - * All rights are reserved. Reproduction or in part is prohibited - * without the written consent of the copyright owner. - * * RegSC.h --- SM718 SDK * This file contains the definitions for the System Configuration registers. */ diff --git a/drivers/staging/sm750fb/ddk750_swi2c.c b/drivers/staging/sm750fb/ddk750_swi2c.c index 5c0ac747ea2b..0ef8d4ff2ef9 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.c +++ b/drivers/staging/sm750fb/ddk750_swi2c.c @@ -2,9 +2,6 @@ /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * - * All rights are reserved. Reproduction or in part is prohibited - * without the written consent of the copyright owner. - * * swi2c.c --- SM750/SM718 DDK * This file contains the source code for I2C using software * implementation. diff --git a/drivers/staging/sm750fb/ddk750_swi2c.h b/drivers/staging/sm750fb/ddk750_swi2c.h index 5868feea791b..dfa166060da7 100644 --- a/drivers/staging/sm750fb/ddk750_swi2c.h +++ b/drivers/staging/sm750fb/ddk750_swi2c.h @@ -2,9 +2,6 @@ /* * Copyright (c) 2007 by Silicon Motion, Inc. (SMI) * - * All rights are reserved. Reproduction or in part is prohibited - * without the written consent of the copyright owner. - * * swi2c.h --- SM750/SM718 DDK * This file contains the definitions for i2c using software * implementation. -- cgit v1.2.3-59-g8ed1b From eb0e7bf3ca94d71247d5bb2b3925183698741d7d Mon Sep 17 00:00:00 2001 From: Christina Quast Date: Fri, 16 Aug 2019 08:59:35 +0200 Subject: staging: rtl8192u: ieee80211: ieee80211_crypt_ccmp.c: Use crypto API ccm(aes) Use ccm(aes) aead transform instead of invoking the AES block cipher block by block. Signed-off-by: Christina Quast Reviewed-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20190816065936.12214-2-contact@christina-quast.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/Kconfig | 2 + .../rtl8192u/ieee80211/ieee80211_crypt_ccmp.c | 201 +++++++++------------ 2 files changed, 88 insertions(+), 115 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig index 22c2165e8b1c..1edca5c304fb 100644 --- a/drivers/staging/rtl8192u/Kconfig +++ b/drivers/staging/rtl8192u/Kconfig @@ -6,3 +6,5 @@ config RTL8192U select WIRELESS_EXT select WEXT_PRIV select CRYPTO + select CRYPTO_AES + select CRYPTO_CCM diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c index d7188b3f3190..aecee42be95e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c @@ -19,6 +19,7 @@ #include "ieee80211.h" #include +#include #include MODULE_AUTHOR("Jouni Malinen"); @@ -44,20 +45,13 @@ struct ieee80211_ccmp_data { int key_idx; - struct crypto_tfm *tfm; + struct crypto_aead *tfm; /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; + u8 tx_aad[2 * AES_BLOCK_LEN]; + u8 rx_aad[2 * AES_BLOCK_LEN]; }; -static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one((void *)tfm, ct, pt); -} - static void *ieee80211_ccmp_init(int key_idx) { struct ieee80211_ccmp_data *priv; @@ -67,7 +61,7 @@ static void *ieee80211_ccmp_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tfm = (void *)crypto_alloc_cipher("aes", 0, 0); + priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tfm)) { pr_debug("ieee80211_crypt_ccmp: could not allocate crypto API aes\n"); priv->tfm = NULL; @@ -79,7 +73,7 @@ static void *ieee80211_ccmp_init(int key_idx) fail: if (priv) { if (priv->tfm) - crypto_free_cipher((void *)priv->tfm); + crypto_free_aead(priv->tfm); kfree(priv); } @@ -91,28 +85,17 @@ static void ieee80211_ccmp_deinit(void *priv) struct ieee80211_ccmp_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_cipher((void *)_priv->tfm); + crypto_free_aead(_priv->tfm); kfree(priv); } -static inline void xor_block(u8 *b, u8 *a, size_t len) -{ - int i; - - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - -static void ccmp_init_blocks(struct crypto_tfm *tfm, - struct rtl_80211_hdr_4addr *hdr, - u8 *pn, size_t dlen, u8 *b0, u8 *auth, - u8 *s0) +static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr, + u8 *pn, u8 *iv, u8 *aad) { u8 *pos, qc = 0; size_t aad_len; u16 fc; int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; fc = le16_to_cpu(hdr->frame_ctl); a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == @@ -133,18 +116,20 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, qc = *pos & 0x0f; aad_len += 2; } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen + + /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC + * mode authentication are not allowed to collide, yet both are derived + * from the same vector. We only set L := 1 here to indicate that the + * data size can be represented in (L+1) bytes. The CCM layer will take + * care of storing the data length in the top (L+1) bytes and setting + * and clearing the other bits as is required to derive the two IVs. */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; + iv[0] = 0x1; + + /* Nonce: QC | A2 | PN */ + iv[1] = qc; + memcpy(iv + 2, hdr->addr2, ETH_ALEN); + memcpy(iv + 8, pn, CCMP_PN_LEN); /* AAD: * FC with bits 4..6 and 11..13 masked to zero; 14 is always one @@ -154,32 +139,21 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, * QC (if present) */ pos = (u8 *)hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + aad[0] = pos[0] & 0x8f; + aad[1] = pos[1] & 0xc7; + memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN); pos = (u8 *)&hdr->seq_ctl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); + aad[20] = pos[0] & 0x0f; + aad[21] = 0; /* all bits masked */ + memset(aad + 22, 0, 8); if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); + memcpy(aad + 22, hdr->addr4, ETH_ALEN); if (qc_included) { - aad[a4_included ? 30 : 24] = qc; + aad[a4_included ? 28 : 22] = qc; /* rest of QC masked */ } - /* Start with the first block and AAD */ - ieee80211_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = 0; - b0[15] = 0; - ieee80211_ccmp_aes_encrypt(tfm, b0, s0); + return aad_len; } static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) @@ -220,36 +194,34 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tcb_desc->bHwSec) { - int blocks, last, len; - u8 *mic; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; - - /* mic is moved to here by john */ - mic = skb_put(skb, CCMP_MIC_LEN); - - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->tx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; + + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; + aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad); + + skb_put(skb, CCMP_MIC_LEN); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN, + data_len + CCMP_MIC_LEN); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_encrypt(req); + aead_request_free(req); + + return ret; } return 0; } @@ -309,33 +281,31 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return -4; } if (!tcb_desc->bHwSec) { - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; - int i, blocks, last, len; - - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->rx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; + + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], pos, data_len); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_decrypt(req); + aead_request_free(req); - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { + if (ret) { if (net_ratelimit()) { netdev_dbg(skb->dev, "CCMP: decrypt failed: STA=%pM\n", hdr->addr2); @@ -358,12 +328,11 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) { struct ieee80211_ccmp_data *data = priv; int keyidx; - struct crypto_tfm *tfm = data->tfm; + struct crypto_aead *tfm = data->tfm; keyidx = data->key_idx; memset(data, 0, sizeof(*data)); data->key_idx = keyidx; - data->tfm = tfm; if (len == CCMP_TK_LEN) { memcpy(data->key, key, CCMP_TK_LEN); data->key_set = 1; @@ -375,7 +344,9 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) data->rx_pn[4] = seq[1]; data->rx_pn[5] = seq[0]; } - crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); + if (crypto_aead_setauthsize(tfm, CCMP_MIC_LEN) || + crypto_aead_setkey(tfm, data->key, CCMP_TK_LEN)) + return -1; } else if (len == 0) { data->key_set = 0; } else { -- cgit v1.2.3-59-g8ed1b From 5ee5265674ce69db0973e7de6b30016efa1d78fd Mon Sep 17 00:00:00 2001 From: Christina Quast Date: Fri, 16 Aug 2019 08:59:36 +0200 Subject: staging: rtl8192e: rtllib_crypt_ccmp.c: Use crypto API ccm(aes) Use ccm(aes) aead transform instead of invoking the AES block cipher block by block. Signed-off-by: Christina Quast Reviewed-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20190816065936.12214-3-contact@christina-quast.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/Kconfig | 1 + drivers/staging/rtl8192e/rtllib_crypt_ccmp.c | 203 +++++++++++---------------- 2 files changed, 86 insertions(+), 118 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig index 11528d17bb3c..1007eea6c8fc 100644 --- a/drivers/staging/rtl8192e/Kconfig +++ b/drivers/staging/rtl8192e/Kconfig @@ -15,6 +15,7 @@ config RTLLIB_CRYPTO_CCMP tristate "Support for rtllib CCMP crypto" depends on RTLLIB select CRYPTO_AES + select CRYPTO_CCM default y help CCMP crypto driver for rtllib. diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index 2581ed6d14fa..44ec45d5c87f 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -17,6 +17,7 @@ #include "rtllib.h" #include +#include #include @@ -39,20 +40,13 @@ struct rtllib_ccmp_data { int key_idx; - struct crypto_tfm *tfm; + struct crypto_aead *tfm; /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; + u8 tx_aad[2 * AES_BLOCK_LEN]; + u8 rx_aad[2 * AES_BLOCK_LEN]; }; -static void rtllib_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one((void *)tfm, ct, pt); -} - static void *rtllib_ccmp_init(int key_idx) { struct rtllib_ccmp_data *priv; @@ -62,7 +56,7 @@ static void *rtllib_ccmp_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tfm = (void *)crypto_alloc_cipher("aes", 0, 0); + priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tfm)) { pr_debug("Could not allocate crypto API aes\n"); priv->tfm = NULL; @@ -73,7 +67,7 @@ static void *rtllib_ccmp_init(int key_idx) fail: if (priv) { if (priv->tfm) - crypto_free_cipher((void *)priv->tfm); + crypto_free_aead(priv->tfm); kfree(priv); } @@ -86,31 +80,18 @@ static void rtllib_ccmp_deinit(void *priv) struct rtllib_ccmp_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_cipher((void *)_priv->tfm); + crypto_free_aead(_priv->tfm); kfree(priv); } -static inline void xor_block(u8 *b, u8 *a, size_t len) -{ - int i; - - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - - - -static void ccmp_init_blocks(struct crypto_tfm *tfm, - struct rtllib_hdr_4addr *hdr, - u8 *pn, size_t dlen, u8 *b0, u8 *auth, - u8 *s0) +static int ccmp_init_iv_and_aad(struct rtllib_hdr_4addr *hdr, + u8 *pn, u8 *iv, u8 *aad) { u8 *pos, qc = 0; size_t aad_len; u16 fc; int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; fc = le16_to_cpu(hdr->frame_ctl); a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == @@ -128,18 +109,19 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, qc = *pos & 0x0f; aad_len += 2; } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen + /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC + * mode authentication are not allowed to collide, yet both are derived + * from the same vector. We only set L := 1 here to indicate that the + * data size can be represented in (L+1) bytes. The CCM layer will take + * care of storing the data length in the top (L+1) bytes and setting + * and clearing the other bits as is required to derive the two IVs. */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; + iv[0] = 0x1; + + /* Nonce: QC | A2 | PN */ + iv[1] = qc; + memcpy(iv + 2, hdr->addr2, ETH_ALEN); + memcpy(iv + 8, pn, CCMP_PN_LEN); /* AAD: * FC with bits 4..6 and 11..13 masked to zero; 14 is always one @@ -149,31 +131,21 @@ static void ccmp_init_blocks(struct crypto_tfm *tfm, * QC (if present) */ pos = (u8 *) hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + aad[0] = pos[0] & 0x8f; + aad[1] = pos[1] & 0xc7; + memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN); pos = (u8 *) &hdr->seq_ctl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); + aad[20] = pos[0] & 0x0f; + aad[21] = 0; /* all bits masked */ + memset(aad + 22, 0, 8); if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); + memcpy(aad + 22, hdr->addr4, ETH_ALEN); if (qc_included) { - aad[a4_included ? 30 : 24] = qc; + aad[a4_included ? 28 : 22] = qc; /* rest of QC masked */ } - /* Start with the first block and AAD */ - rtllib_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - rtllib_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - rtllib_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = b0[15] = 0; - rtllib_ccmp_aes_encrypt(tfm, b0, s0); + return aad_len; } @@ -213,40 +185,37 @@ static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = key->tx_pn[1]; *pos++ = key->tx_pn[0]; - hdr = (struct rtllib_hdr_4addr *) skb->data; if (!tcb_desc->bHwSec) { - int blocks, last, len; - u8 *mic; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; - - mic = skb_put(skb, CCMP_MIC_LEN); - - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, - b0, b, s0); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - rtllib_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - rtllib_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->tx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + int data_len = skb->len - hdr_len - CCMP_HDR_LEN; - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if (!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad); + + skb_put(skb, CCMP_MIC_LEN); + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN, + data_len + CCMP_MIC_LEN); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_encrypt(req); + aead_request_free(req); + + return ret; } + return 0; } @@ -302,35 +271,31 @@ static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return -4; } if (!tcb_desc->bHwSec) { - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; - int i, blocks, last, len; - - - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - rtllib_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - rtllib_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN; + struct aead_request *req; + struct scatterlist sg[2]; + u8 *aad = key->rx_aad; + u8 iv[AES_BLOCK_LEN]; + int aad_len, ret; + + req = aead_request_alloc(key->tfm, GFP_ATOMIC); + if(!req) + return -ENOMEM; + + aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad); + + sg_init_table(sg, 2); + sg_set_buf(&sg[0], aad, aad_len); + sg_set_buf(&sg[1], pos, data_len); + + aead_request_set_callback(req, 0, NULL, NULL); + aead_request_set_ad(req, aad_len); + aead_request_set_crypt(req, sg, sg, data_len, iv); + + ret = crypto_aead_decrypt(req); + aead_request_free(req); - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { + if (ret) { if (net_ratelimit()) { pr_debug("CCMP: decrypt failed: STA= %pM\n", hdr->addr2); @@ -354,7 +319,7 @@ static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) { struct rtllib_ccmp_data *data = priv; int keyidx; - struct crypto_tfm *tfm = data->tfm; + struct crypto_aead *tfm = data->tfm; keyidx = data->key_idx; memset(data, 0, sizeof(*data)); @@ -371,7 +336,9 @@ static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) data->rx_pn[4] = seq[1]; data->rx_pn[5] = seq[0]; } - crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); + if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) || + crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN)) + return -1; } else if (len == 0) { data->key_set = 0; } else { -- cgit v1.2.3-59-g8ed1b From 1d819c5406d8a01867df55e90af97ee64c03b037 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 16 Aug 2019 15:11:42 +0800 Subject: staging: erofs: use common file type conversion Deduplicate the EROFS file type conversion implementation and remove EROFS_FT_* definitions since it's the same as defined by POSIX, let's follow ext2 as Linus pointed out [1] commit e10892189428 ("ext2: use common file type conversion"). [1] https://lore.kernel.org/r/CAHk-=wiUs+b=iVKM3mVooXgVk7cmmC67KTmnAuL0cd_cMMVAKw@mail.gmail.com/ Reported-by: Linus Torvalds Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190816071142.8633-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/dir.c | 16 +--------------- drivers/staging/erofs/erofs_fs.h | 17 +++++------------ drivers/staging/erofs/namei.c | 2 +- 3 files changed, 7 insertions(+), 28 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index 01efc96e1212..5f38382637e6 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -8,17 +8,6 @@ */ #include "internal.h" -static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = { - [EROFS_FT_UNKNOWN] = DT_UNKNOWN, - [EROFS_FT_REG_FILE] = DT_REG, - [EROFS_FT_DIR] = DT_DIR, - [EROFS_FT_CHRDEV] = DT_CHR, - [EROFS_FT_BLKDEV] = DT_BLK, - [EROFS_FT_FIFO] = DT_FIFO, - [EROFS_FT_SOCK] = DT_SOCK, - [EROFS_FT_SYMLINK] = DT_LNK, -}; - static void debug_one_dentry(unsigned char d_type, const char *de_name, unsigned int de_namelen) { @@ -46,10 +35,7 @@ static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, unsigned int de_namelen; unsigned char d_type; - if (de->file_type < EROFS_FT_MAX) - d_type = erofs_filetype_table[de->file_type]; - else - d_type = DT_UNKNOWN; + d_type = fs_ftype_to_dtype(de->file_type); nameoff = le16_to_cpu(de->nameoff); de_name = (char *)dentry_blk + nameoff; diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h index 8dc2a75e478f..6db70f395937 100644 --- a/drivers/staging/erofs/erofs_fs.h +++ b/drivers/staging/erofs/erofs_fs.h @@ -282,18 +282,11 @@ struct erofs_dirent { __u8 reserved; /* 11, reserved */ } __packed; -/* file types used in inode_info->flags */ -enum { - EROFS_FT_UNKNOWN, - EROFS_FT_REG_FILE, - EROFS_FT_DIR, - EROFS_FT_CHRDEV, - EROFS_FT_BLKDEV, - EROFS_FT_FIFO, - EROFS_FT_SOCK, - EROFS_FT_SYMLINK, - EROFS_FT_MAX -}; +/* + * EROFS file types should match generic FT_* types and + * it seems no need to add BUILD_BUG_ONs since potential + * unmatchness will break other fses as well... + */ #define EROFS_NAME_LEN 255 diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c index c0963f5a2d22..8334a910acef 100644 --- a/drivers/staging/erofs/namei.c +++ b/drivers/staging/erofs/namei.c @@ -237,7 +237,7 @@ static struct dentry *erofs_lookup(struct inode *dir, } else { debugln("%s, %s (nid %llu) found, d_type %u", __func__, dentry->d_name.name, nid, d_type); - inode = erofs_iget(dir->i_sb, nid, d_type == EROFS_FT_DIR); + inode = erofs_iget(dir->i_sb, nid, d_type == FT_DIR); } return d_splice_alias(inode, dentry); } -- cgit v1.2.3-59-g8ed1b From 87b42aa3cb5512036ca98028c6f6b914a96743ba Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Sat, 17 Aug 2019 03:07:02 +0530 Subject: staging: gasket: Remove unnecessary line-breaks in function signatures This patch fixes the function signatures for gasket_read_page_table_size, gasket_read_simple_page_table_size, gasket_partition_page_table, gasket_config_coherent_allocator to avoid the checkpatch.pl warning: CHECK: Lines should not end with a '(' Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190816213702.32116-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gasket/gasket_ioctl.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/gasket/gasket_ioctl.c b/drivers/staging/gasket/gasket_ioctl.c index 7ecfba4f2b06..240f9bb10b71 100644 --- a/drivers/staging/gasket/gasket_ioctl.c +++ b/drivers/staging/gasket/gasket_ioctl.c @@ -39,8 +39,7 @@ static int gasket_set_event_fd(struct gasket_dev *gasket_dev, } /* Read the size of the page table. */ -static int gasket_read_page_table_size( - struct gasket_dev *gasket_dev, +static int gasket_read_page_table_size(struct gasket_dev *gasket_dev, struct gasket_page_table_ioctl __user *argp) { int ret = 0; @@ -66,8 +65,7 @@ static int gasket_read_page_table_size( } /* Read the size of the simple page table. */ -static int gasket_read_simple_page_table_size( - struct gasket_dev *gasket_dev, +static int gasket_read_simple_page_table_size(struct gasket_dev *gasket_dev, struct gasket_page_table_ioctl __user *argp) { int ret = 0; @@ -93,8 +91,7 @@ static int gasket_read_simple_page_table_size( } /* Set the boundary between the simple and extended page tables. */ -static int gasket_partition_page_table( - struct gasket_dev *gasket_dev, +static int gasket_partition_page_table(struct gasket_dev *gasket_dev, struct gasket_page_table_ioctl __user *argp) { int ret; @@ -185,8 +182,7 @@ static int gasket_unmap_buffers(struct gasket_dev *gasket_dev, * Reserve structures for coherent allocation, and allocate or free the * corresponding memory. */ -static int gasket_config_coherent_allocator( - struct gasket_dev *gasket_dev, +static int gasket_config_coherent_allocator(struct gasket_dev *gasket_dev, struct gasket_coherent_alloc_config_ioctl __user *argp) { int ret; -- cgit v1.2.3-59-g8ed1b From 4be27c2a185da8438951620b2822c8547df428ad Mon Sep 17 00:00:00 2001 From: Mircea Caprioru Date: Mon, 12 Aug 2019 12:00:34 +0300 Subject: staging: iio: adc: ad7192: Remove platform data This patch removes the reference voltage entry from the platform_data structure. This is no longer needed since the reference voltage is obtained from the device tree. With this we also remove the entire ad7192.h file. The undefined reference voltage warning is promoted to an error signaling a problem with the device tree. Signed-off-by: Mircea Caprioru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 14 ++------------ drivers/staging/iio/adc/ad7192.h | 37 ------------------------------------- 2 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 drivers/staging/iio/adc/ad7192.h (limited to 'drivers/staging') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index df06e0570f9b..81ea2639c67c 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -25,8 +25,6 @@ #include #include -#include "ad7192.h" - /* Registers */ #define AD7192_REG_COMM 0 /* Communications Register (WO, 8-bit) */ #define AD7192_REG_STAT 0 /* Status Register (RO, 8-bit) */ @@ -666,16 +664,10 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) static int ad7192_probe(struct spi_device *spi) { - const struct ad7192_platform_data *pdata = dev_get_platdata(&spi->dev); struct ad7192_state *st; struct iio_dev *indio_dev; int ret, voltage_uv = 0; - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - if (!spi->irq) { dev_err(&spi->dev, "no IRQ?\n"); return -ENODEV; @@ -713,12 +705,10 @@ static int ad7192_probe(struct spi_device *spi) voltage_uv = regulator_get_voltage(st->avdd); - if (pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) + if (voltage_uv) st->int_vref_mv = voltage_uv / 1000; else - dev_warn(&spi->dev, "reference voltage undefined\n"); + dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); spi_set_drvdata(spi, indio_dev); st->devid = spi_get_device_id(spi)->driver_data; diff --git a/drivers/staging/iio/adc/ad7192.h b/drivers/staging/iio/adc/ad7192.h deleted file mode 100644 index f3669e1df084..000000000000 --- a/drivers/staging/iio/adc/ad7192.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * AD7190 AD7192 AD7195 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ -#ifndef IIO_ADC_AD7192_H_ -#define IIO_ADC_AD7192_H_ - -/* - * TODO: struct ad7192_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad7192_platform_data - platform/board specific information - * @vref_mv: the external reference voltage in millivolt - * @clock_source_sel: [0..3] - * 0 External 4.92 MHz clock connected from MCLK1 to MCLK2 - * 1 External Clock applied to MCLK2 - * 2 Internal 4.92 MHz Clock not available at the MCLK2 pin - * 3 Internal 4.92 MHz Clock available at the MCLK2 pin - * @ext_clk_Hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @refin2_en: REFIN1/REFIN2 Reference Select (AD7190/2 only) - * @rej60_en: 50/60Hz notch filter enable - * @sinc3_en: SINC3 filter enable (default SINC4) - * @chop_en: CHOP mode enable - * @buf_en: buffered input mode enable - * @unipolar_en: unipolar mode enable - * @burnout_curr_en: constant current generators on AIN(+|-) enable - */ - -struct ad7192_platform_data { - u16 vref_mv; -}; - -#endif /* IIO_ADC_AD7192_H_ */ -- cgit v1.2.3-59-g8ed1b From 77f6a23092c0f5fcf85c6c8894ccc436d8d0d9aa Mon Sep 17 00:00:00 2001 From: Mircea Caprioru Date: Wed, 14 Aug 2019 10:31:47 +0300 Subject: staging: iio: adc: ad7192: Add low_pass_3db_filter_frequency By adding this option we are able to remove the sync3 field and dt binding. When setting the required cutoff frequency we also determine the ADC configuration for chop and sync filter. Signed-off-by: Mircea Caprioru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 149 ++++++++++++++++++++++++++++++++++----- 1 file changed, 133 insertions(+), 16 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 81ea2639c67c..e6b660489165 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -143,6 +143,10 @@ #define AD7192_EXT_FREQ_MHZ_MAX 5120000 #define AD7192_INT_FREQ_MHZ 4915200 +#define AD7192_NO_SYNC_FILTER 1 +#define AD7192_SYNC3_FILTER 3 +#define AD7192_SYNC4_FILTER 4 + /* NOTE: * The AD7190/2/5 features a dual use data out ready DOUT/RDY output. * In order to avoid contentions on the SPI bus, it's therefore necessary @@ -250,7 +254,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) static int ad7192_setup(struct ad7192_state *st, struct device_node *np) { struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); - bool rej60_en, sinc3_en, refin2_en, chop_en; + bool rej60_en, refin2_en; bool buf_en, bipolar, burnout_curr_en; unsigned long long scale_uv; int i, ret, id; @@ -282,24 +286,12 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) if (rej60_en) st->mode |= AD7192_MODE_REJ60; - sinc3_en = of_property_read_bool(np, "adi,sinc3-filter-enable"); - if (sinc3_en) - st->mode |= AD7192_MODE_SINC3; - refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable"); if (refin2_en && st->devid != ID_AD7195) st->conf |= AD7192_CONF_REFSEL; - chop_en = of_property_read_bool(np, "adi,chop-enable"); - if (chop_en) { - st->conf |= AD7192_CONF_CHOP; - if (sinc3_en) - st->f_order = 3; /* SINC 3rd order */ - else - st->f_order = 4; /* SINC 4th order */ - } else { - st->f_order = 1; - } + st->conf &= ~AD7192_CONF_CHOP; + st->f_order = AD7192_NO_SYNC_FILTER; buf_en = of_property_read_bool(np, "adi,buffer-enable"); if (buf_en) @@ -311,7 +303,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) burnout_curr_en = of_property_read_bool(np, "adi,burnout-currents-enable"); - if (burnout_curr_en && buf_en && !chop_en) { + if (burnout_curr_en && buf_en) { st->conf |= AD7192_CONF_BURN; } else if (burnout_curr_en) { dev_warn(&st->sd.spi->dev, @@ -409,6 +401,49 @@ static ssize_t ad7192_set(struct device *dev, return ret ? ret : len; } +static void ad7192_get_available_filter_freq(struct ad7192_state *st, + int *freq) +{ + unsigned int fadc; + + /* Formulas for filter at page 25 of the datasheet */ + fadc = DIV_ROUND_CLOSEST(st->fclk, + AD7192_SYNC4_FILTER * AD7192_MODE_RATE(st->mode)); + freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + + fadc = DIV_ROUND_CLOSEST(st->fclk, + AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode)); + freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + + fadc = DIV_ROUND_CLOSEST(st->fclk, AD7192_MODE_RATE(st->mode)); + freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024); + freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024); +} + +static ssize_t ad7192_show_filter_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7192_state *st = iio_priv(indio_dev); + unsigned int freq_avail[4], i; + size_t len = 0; + + ad7192_get_available_filter_freq(st, freq_avail); + + for (i = 0; i < ARRAY_SIZE(freq_avail); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d.%d ", freq_avail[i] / 1000, + freq_avail[i] % 1000); + + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(filter_low_pass_3db_frequency_available, + 0444, ad7192_show_filter_avail, NULL, 0); + static IIO_DEVICE_ATTR(bridge_switch_en, 0644, ad7192_show_bridge_switch, ad7192_set, AD7192_REG_GPOCON); @@ -418,6 +453,7 @@ static IIO_DEVICE_ATTR(ac_excitation_en, 0644, AD7192_REG_MODE); static struct attribute *ad7192_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, &iio_dev_attr_ac_excitation_en.dev_attr.attr, NULL @@ -428,6 +464,7 @@ static const struct attribute_group ad7192_attribute_group = { }; static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, NULL }; @@ -441,6 +478,75 @@ static unsigned int ad7192_get_temp_scale(bool unipolar) return unipolar ? 2815 * 2 : 2815; } +static int ad7192_set_3db_filter_freq(struct ad7192_state *st, + int val, int val2) +{ + int freq_avail[4], i, ret, freq; + unsigned int diff_new, diff_old; + int idx = 0; + + diff_old = U32_MAX; + freq = val * 1000 + val2; + + ad7192_get_available_filter_freq(st, freq_avail); + + for (i = 0; i < ARRAY_SIZE(freq_avail); i++) { + diff_new = abs(freq - freq_avail[i]); + if (diff_new < diff_old) { + diff_old = diff_new; + idx = i; + } + } + + switch (idx) { + case 0: + st->f_order = AD7192_SYNC4_FILTER; + st->mode &= ~AD7192_MODE_SINC3; + + st->conf |= AD7192_CONF_CHOP; + break; + case 1: + st->f_order = AD7192_SYNC3_FILTER; + st->mode |= AD7192_MODE_SINC3; + + st->conf |= AD7192_CONF_CHOP; + break; + case 2: + st->f_order = AD7192_NO_SYNC_FILTER; + st->mode &= ~AD7192_MODE_SINC3; + + st->conf &= ~AD7192_CONF_CHOP; + break; + case 3: + st->f_order = AD7192_NO_SYNC_FILTER; + st->mode |= AD7192_MODE_SINC3; + + st->conf &= ~AD7192_CONF_CHOP; + break; + } + + ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + if (ret < 0) + return ret; + + return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); +} + +static int ad7192_get_3db_filter_freq(struct ad7192_state *st) +{ + unsigned int fadc; + + fadc = DIV_ROUND_CLOSEST(st->fclk, + st->f_order * AD7192_MODE_RATE(st->mode)); + + if (st->conf & AD7192_CONF_CHOP) + return DIV_ROUND_CLOSEST(fadc * 240, 1024); + if (st->mode & AD7192_MODE_SINC3) + return DIV_ROUND_CLOSEST(fadc * 272, 1024); + else + return DIV_ROUND_CLOSEST(fadc * 230, 1024); +} + static int ad7192_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -481,6 +587,10 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, *val = st->fclk / (st->f_order * 1024 * AD7192_MODE_RATE(st->mode)); return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *val = ad7192_get_3db_filter_freq(st); + *val2 = 1000; + return IIO_VAL_FRACTIONAL; } return -EINVAL; @@ -535,6 +645,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, st->mode |= AD7192_MODE_RATE(div); ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); break; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000); + break; default: ret = -EINVAL; } @@ -553,6 +666,8 @@ static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_SAMP_FREQ: return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -653,6 +768,8 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) for (i = 0; i < indio_dev->num_channels; i++) { *chan = channels[i]; + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY); if (chan->type != IIO_TEMP) chan->info_mask_shared_by_type_available |= BIT(IIO_CHAN_INFO_SCALE); -- cgit v1.2.3-59-g8ed1b From b311da85f7944a98fdc45c2fc92d74234e22995c Mon Sep 17 00:00:00 2001 From: Rodrigo Ribeiro Date: Tue, 13 Aug 2019 16:31:01 -0300 Subject: staging: iio: accel: adis16240: Improve readability on write_raw function Replace shift and minus operation by GENMASK macro and remove the local variables used to store intermediate data. Signed-off-by: Rodrigo Ribeiro Carvalho Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16240.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 62f4b3b1b457..82099db4bf0c 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -309,15 +309,12 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, long mask) { struct adis *st = iio_priv(indio_dev); - int bits = 10; - s16 val16; u8 addr; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - val16 = val & ((1 << bits) - 1); addr = adis16240_addresses[chan->scan_index][0]; - return adis_write_reg_16(st, addr, val16); + return adis_write_reg_16(st, addr, val & GENMASK(9, 0)); } return -EINVAL; } -- cgit v1.2.3-59-g8ed1b From a64d9493f587f8ec101d92ec19c7d88d6d3b5567 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Sun, 18 Aug 2019 18:28:24 +0800 Subject: staging: erofs: refuse to mount images with malformed volume name As Richard reminder [1], A valid volume name should be ended in NIL terminator within the length of volume_name. Since this field currently isn't really used, let's fix it to avoid potential bugs in the future. [1] https://lore.kernel.org/r/1133002215.69049.1566119033047.JavaMail.zimbra@nod.at/ Reported-by: Richard Weinberger Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190818102824.22330-1-hsiangkao@aol.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/super.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index f65a1ff9f42f..2da471010a86 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -131,9 +131,14 @@ static int superblock_read(struct super_block *sb) sbi->build_time_nsec = le32_to_cpu(layout->build_time_nsec); memcpy(&sb->s_uuid, layout->uuid, sizeof(layout->uuid)); - memcpy(sbi->volume_name, layout->volume_name, - sizeof(layout->volume_name)); + ret = strscpy(sbi->volume_name, layout->volume_name, + sizeof(layout->volume_name)); + if (ret < 0) { /* -E2BIG */ + errln("bad volume name without NIL terminator"); + ret = -EFSCORRUPTED; + goto out; + } ret = 0; out: brelse(bh); -- cgit v1.2.3-59-g8ed1b From acb383f1dcb4f1e79b66d4be3a0b6f519a957b0d Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Sun, 18 Aug 2019 20:54:57 +0800 Subject: staging: erofs: fix an error handling in erofs_readdir() Richard observed a forever loop of erofs_read_raw_page() [1] which can be generated by forcely setting ->u.i_blkaddr to 0xdeadbeef (as my understanding block layer can handle access beyond end of device correctly). After digging into that, it seems the problem is highly related with directories and then I found the root cause is an improper error handling in erofs_readdir(). Let's fix it now. [1] https://lore.kernel.org/r/1163995781.68824.1566084358245.JavaMail.zimbra@nod.at/ Reported-by: Richard Weinberger Fixes: 3aa8ec716e52 ("staging: erofs: add directory operations") Cc: # 4.19+ Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190818125457.25906-1-hsiangkao@aol.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/dir.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c index 5f38382637e6..77ef856df9f3 100644 --- a/drivers/staging/erofs/dir.c +++ b/drivers/staging/erofs/dir.c @@ -82,8 +82,15 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx) unsigned int nameoff, maxsize; dentry_page = read_mapping_page(mapping, i, NULL); - if (IS_ERR(dentry_page)) - continue; + if (dentry_page == ERR_PTR(-ENOMEM)) { + err = -ENOMEM; + break; + } else if (IS_ERR(dentry_page)) { + errln("fail to readdir of logical block %u of nid %llu", + i, EROFS_V(dir)->nid); + err = -EFSCORRUPTED; + break; + } de = (struct erofs_dirent *)kmap(dentry_page); -- cgit v1.2.3-59-g8ed1b From ee45197c807895e156b2be0abcaebdfc116487c8 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:21 +0800 Subject: staging: erofs: some compressed cluster should be submitted for corrupted images As reported by erofs_utils fuzzer, a logical page can belong to at most 2 compressed clusters, if one compressed cluster is corrupted, but the other has been ready in submitting chain. The chain needs to submit anyway in order to keep the page working properly (page unlocked with PG_error set, PG_uptodate not set). Let's fix it now. Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-2-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 2d7aaf98f7de..87b0c96caf8f 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -1307,19 +1307,18 @@ static int z_erofs_vle_normalaccess_readpage(struct file *file, err = z_erofs_do_read_page(&f, page, &pagepool); (void)z_erofs_collector_end(&f.clt); - if (err) { + /* if some compressed cluster ready, need submit them anyway */ + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); + + if (err) errln("%s, failed to read, err [%d]", __func__, err); - goto out; - } - z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); -out: if (f.map.mpage) put_page(f.map.mpage); /* clean up the remaining free pages */ put_pages_list(&pagepool); - return 0; + return err; } static bool should_decompress_synchronously(struct erofs_sb_info *sbi, -- cgit v1.2.3-59-g8ed1b From 3407a4198faf01c9d7596c45b8606834b8dfc2b7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:22 +0800 Subject: staging: erofs: cannot set EROFS_V_Z_INITED_BIT if fill_inode_lazy fails As reported by erofs-utils fuzzer, unsupported compressed clustersize will make fill_inode_lazy fail, for such case we cannot set EROFS_V_Z_INITED_BIT since we need return failure for each z_erofs_map_blocks_iter(). Fixes: 152a333a5895 ("staging: erofs: add compacted compression indexes support") Cc: # 5.3+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-3-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zmap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index b61b9b5950ac..7408e86823a4 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -85,12 +85,11 @@ static int fill_inode_lazy(struct inode *inode) vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + ((h->h_clusterbits >> 5) & 7); + set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); unmap_done: kunmap_atomic(kaddr); unlock_page(page); put_page(page); - - set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); out_unlock: clear_and_wake_up_bit(EROFS_V_BL_Z_BIT, &vi->flags); return err; -- cgit v1.2.3-59-g8ed1b From 138e1a0990e80db486ab9f6c06bd5c01f9a97999 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:23 +0800 Subject: staging: erofs: add two missing erofs_workgroup_put for corrupted images As reported by erofs-utils fuzzer, these error handling path will be entered to handle corrupted images. Lack of erofs_workgroup_puts will cause unmounting unsuccessfully. Fix these return values to EFSCORRUPTED as well. Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-4-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 87b0c96caf8f..23283c97fd3b 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -357,14 +357,16 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, cl = z_erofs_primarycollection(pcl); if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { DBG_BUGON(1); - return ERR_PTR(-EIO); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } length = READ_ONCE(pcl->length); if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { DBG_BUGON(1); - return ERR_PTR(-EIO); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); } } else { unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; -- cgit v1.2.3-59-g8ed1b From 598bb8913d015150b7734b55443c0e53e7189fc7 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Mon, 19 Aug 2019 18:34:26 +0800 Subject: staging: erofs: avoid endless loop of invalid lookback distance 0 As reported by erofs-utils fuzzer, Lookback distance should be a positive number, so it should be actually looked back rather than spinning. Fixes: 02827e1796b3 ("staging: erofs: add erofs_map_blocks_iter") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190819103426.87579-7-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zmap.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c index 7408e86823a4..774dacbc5b32 100644 --- a/drivers/staging/erofs/zmap.c +++ b/drivers/staging/erofs/zmap.c @@ -350,6 +350,12 @@ static int vle_extent_lookback(struct z_erofs_maprecorder *m, switch (m->type) { case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + if (unlikely(!m->delta[0])) { + errln("invalid lookback distance 0 at nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } return vle_extent_lookback(m, m->delta[0]); case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: map->m_flags &= ~EROFS_MAP_ZIPPED; -- cgit v1.2.3-59-g8ed1b From 88db7fc592559226cda373245770d90af0af3b0a Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 21 Aug 2019 00:33:56 +0900 Subject: staging: comedi: ni_mio_common: Fix a typo in ni_mio_common.c This patch fix a spelling typo in ni_mio_common.c Signed-off-by: Masanari Iida Link: https://lore.kernel.org/r/20190820153356.25189-1-standby24x7@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index c175227009f1..f98e3ae27bff 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -596,7 +596,7 @@ static int ni_request_ao_mite_channel(struct comedi_device *dev) if (!mite_chan) { spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); dev_err(dev->class_dev, - "failed to reserve mite dma channel for analog outut\n"); + "failed to reserve mite dma channel for analog output\n"); return -EBUSY; } mite_chan->dir = COMEDI_OUTPUT; -- cgit v1.2.3-59-g8ed1b From 2cb05d8788f77ed14b99a0fbb2748346071f3a33 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Mon, 19 Aug 2019 22:27:05 +0530 Subject: staging: rtl8723bs: core: Remove unneeded declaration WFD_OUI Remove unneeded declaration "extern unsigned char WFD_OUI" Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20190819165705.GA5782@hari-Inspiron-1545 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ap.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 02f5478845b4..6d18d23acdc0 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -13,7 +13,6 @@ extern unsigned char RTW_WPA_OUI[]; extern unsigned char WMM_OUI[]; extern unsigned char WPS_OUI[]; extern unsigned char P2P_OUI[]; -extern unsigned char WFD_OUI[]; void init_mlme_ap_info(struct adapter *padapter) { -- cgit v1.2.3-59-g8ed1b From bfc4ccb1584129d3ef051f8bf6155835374f132f Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 21 Aug 2019 11:09:08 +0800 Subject: staging: erofs: avoid loop in submit chains As reported by erofs-utils fuzzer, 2 conditions can happen in corrupted images, which can cause unexpected behaviors. - access the same pcluster one more time; - access the tail end pcluster again, e.g. _ access again (will trigger tail merging) | 1 2 3 1 2 -> 1 2 3 1 |_ tail end of the chain \___/ (unexpected behavior) Let's detect and avoid them now. Reviewed-by: Chao Yu Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190821030908.40282-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 23283c97fd3b..4d6faaab04f5 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -132,7 +132,7 @@ enum z_erofs_collectmode { struct z_erofs_collector { struct z_erofs_pagevec_ctor vector; - struct z_erofs_pcluster *pcl; + struct z_erofs_pcluster *pcl, *tailpcl; struct z_erofs_collection *cl; struct page **compressedpages; z_erofs_next_pcluster_t owned_head; @@ -353,6 +353,11 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, return NULL; pcl = container_of(grp, struct z_erofs_pcluster, obj); + if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } cl = z_erofs_primarycollection(pcl); if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { @@ -381,7 +386,13 @@ static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, } } mutex_lock(&cl->lock); + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); + /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = NULL; clt->pcl = pcl; clt->cl = cl; return cl; @@ -434,6 +445,9 @@ static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, kmem_cache_free(pcluster_cachep, pcl); return ERR_PTR(-EAGAIN); } + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; clt->owned_head = &pcl->next; clt->pcl = pcl; clt->cl = cl; -- cgit v1.2.3-59-g8ed1b From f55ef00e0ea2664e1a2a7bd4e8670d27a0bf2b86 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 18 Aug 2019 17:06:09 +0200 Subject: staging: rtl8712: Improve naming of include hearder guards Choose a better name for the include hearder guard used in rtl871x_io.h. '_IO_H_' is to generic and does not match the comment after the #endif. Use '_RTL871X_IO_H_' instead. Also make the comments in the #endif /* XXX */ match the name used in #ifndef. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/20190818150609.3376-1-christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_io.h | 7 +++---- drivers/staging/rtl8712/rtl871x_rf.h | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h index 28941423b7ed..c20dd5a6bbd1 100644 --- a/drivers/staging/rtl8712/rtl871x_io.h +++ b/drivers/staging/rtl8712/rtl871x_io.h @@ -11,8 +11,8 @@ * Larry Finger * ******************************************************************************/ -#ifndef _IO_H_ -#define _IO_H_ +#ifndef _RTL871X_IO_H_ +#define _RTL871X_IO_H_ #include "osdep_service.h" #include "osdep_intf.h" @@ -234,5 +234,4 @@ void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem); uint r8712_alloc_io_queue(struct _adapter *adapter); void r8712_free_io_queue(struct _adapter *adapter); -#endif /*_RTL8711_IO_H_*/ - +#endif /*_RTL871X_IO_H_*/ diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h index cc54453cd424..7d98921a48fa 100644 --- a/drivers/staging/rtl8712/rtl871x_rf.h +++ b/drivers/staging/rtl8712/rtl871x_rf.h @@ -52,5 +52,4 @@ enum { RTL8712_RFC_2T2R = 0x22 }; -#endif /*_RTL8711_RF_H_*/ - +#endif /*__RTL871X_RF_H_*/ -- cgit v1.2.3-59-g8ed1b From be237202ee052ef2885285b4550d9638470ce38d Mon Sep 17 00:00:00 2001 From: Donald Yandt Date: Sun, 18 Aug 2019 11:20:23 -0400 Subject: staging: android: Remove ion device tree bindings from the TODO Commit 23a4388f24f5 ("staging: android: ion: Remove file ion_chunk_heap.c") and eadbf7a34e44 ("staging: android: ion: Remove file ion_carveout_heap.c") removed the chunk and carveout heaps from ion but left behind the device tree bindings for them in the TODO, this patch removes it. Signed-off-by: Donald Yandt Link: https://lore.kernel.org/r/20190818152023.891-1-donald.yandt@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/TODO | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO index fbf015cc6d62..767dd98fd92d 100644 --- a/drivers/staging/android/TODO +++ b/drivers/staging/android/TODO @@ -6,8 +6,6 @@ TODO: ion/ - - Add dt-bindings for remaining heaps (chunk and carveout heaps). This would - involve putting appropriate bindings in a memory node for Ion to find. - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0) - Better test framework (integration with VGEM was suggested) -- cgit v1.2.3-59-g8ed1b From 1327d35ac3c187b3c1ae650d90400f8fe5e41b94 Mon Sep 17 00:00:00 2001 From: Eduardo Barretto Date: Sun, 18 Aug 2019 15:35:55 -0300 Subject: staging: kpc2000: kpc2000_i2c: Fix different address spaces warnings This patch fixes the following sparse warnings: kpc2000_i2c.c:137: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:137: expected void const volatile [noderef] *addr kpc2000_i2c.c:137: got void * kpc2000_i2c.c:146: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:146: expected void volatile [noderef] *addr kpc2000_i2c.c:146: got void * kpc2000_i2c.c:147: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:147: expected void const volatile [noderef] *addr kpc2000_i2c.c:147: got void * kpc2000_i2c.c:166: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:166: expected void const volatile [noderef] *addr kpc2000_i2c.c:166: got void * kpc2000_i2c.c:166: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:166: expected void volatile [noderef] *addr kpc2000_i2c.c:166: got void * kpc2000_i2c.c:168: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:168: expected void const volatile [noderef] *addr kpc2000_i2c.c:168: got void * kpc2000_i2c.c:168: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:168: expected void volatile [noderef] *addr kpc2000_i2c.c:168: got void * kpc2000_i2c.c:171: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:171: expected void const volatile [noderef] *addr kpc2000_i2c.c:171: got void * kpc2000_i2c.c:174: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:174: expected void volatile [noderef] *addr kpc2000_i2c.c:174: got void * kpc2000_i2c.c:193: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:193: expected void volatile [noderef] *addr kpc2000_i2c.c:193: got void * kpc2000_i2c.c:194: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:194: expected void const volatile [noderef] *addr kpc2000_i2c.c:194: got void * kpc2000_i2c.c:214: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:214: expected void volatile [noderef] *addr kpc2000_i2c.c:214: got void * kpc2000_i2c.c:219: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:219: expected void const volatile [noderef] *addr kpc2000_i2c.c:219: got void * kpc2000_i2c.c:226: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:226: expected void volatile [noderef] *addr kpc2000_i2c.c:226: got void * kpc2000_i2c.c:238: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:238: expected void const volatile [noderef] *addr kpc2000_i2c.c:238: got void * kpc2000_i2c.c:244: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:244: expected void volatile [noderef] *addr kpc2000_i2c.c:244: got void * kpc2000_i2c.c:252: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:252: expected void const volatile [noderef] *addr kpc2000_i2c.c:252: got void * kpc2000_i2c.c:257: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:257: expected void volatile [noderef] *addr kpc2000_i2c.c:257: got void * kpc2000_i2c.c:259: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:259: expected void volatile [noderef] *addr kpc2000_i2c.c:259: got void * kpc2000_i2c.c:267: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:267: expected void const volatile [noderef] *addr kpc2000_i2c.c:267: got void * kpc2000_i2c.c:273: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:273: expected void const volatile [noderef] *addr kpc2000_i2c.c:273: got void * kpc2000_i2c.c:293: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:293: expected void volatile [noderef] *addr kpc2000_i2c.c:293: got void * kpc2000_i2c.c:294: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:294: expected void volatile [noderef] *addr kpc2000_i2c.c:294: got void * kpc2000_i2c.c:309: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:309: expected void volatile [noderef] *addr kpc2000_i2c.c:309: got void * kpc2000_i2c.c:312: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:312: expected void volatile [noderef] *addr kpc2000_i2c.c:312: got void * kpc2000_i2c.c:317: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:317: expected void const volatile [noderef] *addr kpc2000_i2c.c:317: got void * kpc2000_i2c.c:324: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:324: expected void const volatile [noderef] *addr kpc2000_i2c.c:324: got void * kpc2000_i2c.c:328: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:328: expected void const volatile [noderef] *addr kpc2000_i2c.c:328: got void * kpc2000_i2c.c:329: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:329: expected void volatile [noderef] *addr kpc2000_i2c.c:329: got void * kpc2000_i2c.c:330: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:330: expected void volatile [noderef] *addr kpc2000_i2c.c:330: got void * kpc2000_i2c.c:338: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:338: expected void const volatile [noderef] *addr kpc2000_i2c.c:338: got void * kpc2000_i2c.c:340: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:340: expected void volatile [noderef] *addr kpc2000_i2c.c:340: got void * kpc2000_i2c.c:342: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:342: expected void volatile [noderef] *addr kpc2000_i2c.c:342: got void * kpc2000_i2c.c:350: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:350: expected void const volatile [noderef] *addr kpc2000_i2c.c:350: got void * kpc2000_i2c.c:350: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:350: expected void volatile [noderef] *addr kpc2000_i2c.c:350: got void * kpc2000_i2c.c:351: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:351: expected void const volatile [noderef] *addr kpc2000_i2c.c:351: got void * kpc2000_i2c.c:414: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:414: expected void volatile [noderef] *addr kpc2000_i2c.c:414: got void * kpc2000_i2c.c:420: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:420: expected void volatile [noderef] *addr kpc2000_i2c.c:420: got void * kpc2000_i2c.c:422: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:422: expected void volatile [noderef] *addr kpc2000_i2c.c:422: got void * kpc2000_i2c.c:427: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:427: expected void volatile [noderef] *addr kpc2000_i2c.c:427: got void * kpc2000_i2c.c:428: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:428: expected void volatile [noderef] *addr kpc2000_i2c.c:428: got void * kpc2000_i2c.c:430: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:430: expected void volatile [noderef] *addr kpc2000_i2c.c:430: got void * kpc2000_i2c.c:435: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:435: expected void volatile [noderef] *addr kpc2000_i2c.c:435: got void * kpc2000_i2c.c:436: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:436: expected void volatile [noderef] *addr kpc2000_i2c.c:436: got void * kpc2000_i2c.c:438: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:438: expected void volatile [noderef] *addr kpc2000_i2c.c:438: got void * kpc2000_i2c.c:439: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:439: expected void volatile [noderef] *addr kpc2000_i2c.c:439: got void * kpc2000_i2c.c:445: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:445: expected void volatile [noderef] *addr kpc2000_i2c.c:445: got void * kpc2000_i2c.c:446: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:446: expected void volatile [noderef] *addr kpc2000_i2c.c:446: got void * kpc2000_i2c.c:454: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:454: expected void volatile [noderef] *addr kpc2000_i2c.c:454: got void * kpc2000_i2c.c:459: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:459: expected void volatile [noderef] *addr kpc2000_i2c.c:459: got void * kpc2000_i2c.c:461: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:461: expected void volatile [noderef] *addr kpc2000_i2c.c:461: got void * kpc2000_i2c.c:472: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:472: expected void const volatile [noderef] *addr kpc2000_i2c.c:472: got void * kpc2000_i2c.c:472: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:472: expected void volatile [noderef] *addr kpc2000_i2c.c:472: got void * kpc2000_i2c.c:475: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:475: expected void const volatile [noderef] *addr kpc2000_i2c.c:475: got void * kpc2000_i2c.c:475: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:475: expected void volatile [noderef] *addr kpc2000_i2c.c:475: got void * kpc2000_i2c.c:493: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:493: expected void const volatile [noderef] *addr kpc2000_i2c.c:493: got void * kpc2000_i2c.c:493: warning: incorrect type in argument 2 (different address spaces) kpc2000_i2c.c:493: expected void volatile [noderef] *addr kpc2000_i2c.c:493: got void * kpc2000_i2c.c:512: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:512: expected void const volatile [noderef] *addr kpc2000_i2c.c:512: got void * kpc2000_i2c.c:516: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:516: expected void const volatile [noderef] *addr kpc2000_i2c.c:516: got void * kpc2000_i2c.c:516: warning: incorrect type in argument 1 (different address spaces) kpc2000_i2c.c:516: expected void const volatile [noderef] *addr kpc2000_i2c.c:516: got void * Signed-off-by: Eduardo Barretto Link: https://lore.kernel.org/r/20190818183555.7167-1-edusbarretto@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index b108da4ac633..bc02534d8dc3 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -123,9 +123,9 @@ struct i2c_device { // FIXME! #undef inb_p -#define inb_p(a) readq((void *)a) +#define inb_p(a) readq((void __iomem *)a) #undef outb_p -#define outb_p(d, a) writeq(d, (void *)a) +#define outb_p(d, a) writeq(d, (void __iomem *)a) /* Make sure the SMBus host is ready to start transmitting. * Return 0 if it is, -EBUSY if it is not. -- cgit v1.2.3-59-g8ed1b From 8467c3b456b57fcb4b3179c34c20cbc9c88956c5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 18 Aug 2019 19:46:49 +0100 Subject: staging: rts5208: remove redundant assignment to retval Variable retval is initialized to a value that is never read and it is re-assigned later. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190818184649.13828-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/ms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index 1128eec3bd08..e853fa9cc950 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -3842,7 +3842,7 @@ int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip) int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip) { - int retval = STATUS_FAIL; + int retval; int bufflen; unsigned int lun = SCSI_LUN(srb); u8 *buf = NULL; -- cgit v1.2.3-59-g8ed1b From e12a0ce2fa69798194f3a8628baf6edfbd5c548f Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Wed, 21 Aug 2019 22:01:52 +0800 Subject: staging: erofs: detect potential multiref due to corrupted images As reported by erofs-utils fuzzer, currently, multiref (ondisk deduplication) hasn't been supported for now, we should forbid it properly. Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support") Cc: # 4.19+ Signed-off-by: Gao Xiang Reviewed-by: Chao Yu Link: https://lore.kernel.org/r/20190821140152.229648-1-gaoxiang25@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/erofs/zdata.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c index 4d6faaab04f5..60d7c20db87d 100644 --- a/drivers/staging/erofs/zdata.c +++ b/drivers/staging/erofs/zdata.c @@ -798,6 +798,7 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, for (i = 0; i < nr_pages; ++i) pages[i] = NULL; + err = 0; z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, cl->pagevec, 0); @@ -819,8 +820,17 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, pagenr = z_erofs_onlinepage_index(page); DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); + /* + * currently EROFS doesn't support multiref(dedup), + * so here erroring out one multiref page. + */ + if (unlikely(pages[pagenr])) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } pages[pagenr] = page; } z_erofs_pagevec_ctor_exit(&ctor, true); @@ -828,7 +838,6 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, overlapped = false; compressed_pages = pcl->compressed_pages; - err = 0; for (i = 0; i < clusterpages; ++i) { unsigned int pagenr; @@ -852,7 +861,12 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, pagenr = z_erofs_onlinepage_index(page); DBG_BUGON(pagenr >= nr_pages); - DBG_BUGON(pages[pagenr]); + if (unlikely(pages[pagenr])) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } pages[pagenr] = page; overlapped = true; -- cgit v1.2.3-59-g8ed1b From 68772c84f7e0380033ce560802b0d179d76be392 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:22:50 +0800 Subject: staging: rtl8192u: ieee80211: remove set but not used variable 'data_len' Fixes gcc '-Wunused-but-set-variable' warning: drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c: In function ieee80211_ccmp_encrypt: drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c:162:6: warning: variable data_len set but not used [-Wunused-but-set-variable] It is not used since commit eb0e7bf3ca94 ("staging: rtl8192u: ieee80211: ieee80211_crypt_ccmp.c: Use crypto API ccm(aes)") Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190821122250.71404-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c index aecee42be95e..a43a5d617bd9 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c @@ -159,7 +159,7 @@ static int ccmp_init_iv_and_aad(struct rtl_80211_hdr_4addr *hdr, static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct ieee80211_ccmp_data *key = priv; - int data_len, i; + int i; u8 *pos; struct rtl_80211_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); @@ -169,7 +169,6 @@ static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - data_len = skb->len - hdr_len; pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; -- cgit v1.2.3-59-g8ed1b From 4a67342ea9c7c34903f4068f21c98385f9f62b8d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:25:56 +0800 Subject: staging: rtl8192e: remove two set but not used variables Fixes gcc '-Wunused-but-set-variable' warning: In function '_rtl92e_dm_tx_power_tracking_callback_tssi': drivers/staging/rtl8192e/rtl8192e/rtl_dm.c:621:7: warning: variable 'bHighpowerstate' set but not used [-Wunused-but-set-variable] In function '_rtl92e_dm_rx_path_sel_byrssi': drivers/staging/rtl8192e/rtl8192e/rtl_dm.c:1904:32: warning: variable 'cck_rx_ver2_min_index' set but not used [-Wunused-but-set-variable] They are never used, so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190821122556.37636-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 1b7e3fda7905..20e494186c9e 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -618,7 +618,7 @@ static void _rtl92e_dm_tx_update_tssi_strong_signal(struct net_device *dev, static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) { struct r8192_priv *priv = rtllib_priv(dev); - bool bHighpowerstate, viviflag = false; + bool viviflag = false; struct dcmd_txcmd tx_cmd; u8 powerlevelOFDM24G; int i = 0, j = 0, k = 0; @@ -632,7 +632,6 @@ static void _rtl92e_dm_tx_power_tracking_callback_tssi(struct net_device *dev) rtl92e_writeb(dev, Pw_Track_Flag, 0); rtl92e_writeb(dev, FW_Busy_Flag, 0); priv->rtllib->bdynamic_txpower_enable = false; - bHighpowerstate = priv->bDynamicTxHighPower; powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24); RF_Type = priv->rf_type; @@ -1901,7 +1900,7 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) u8 cck_default_Rx = 0x2; u8 cck_optional_Rx = 0x3; long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0; - u8 cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0; + u8 cck_rx_ver2_max_index = 0; u8 cck_rx_ver2_sec_index = 0; u8 cur_rf_rssi; long cur_cck_pwdb; @@ -1984,7 +1983,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) if (rf_num == 1) { cck_rx_ver2_max_index = i; - cck_rx_ver2_min_index = i; cck_rx_ver2_sec_index = i; tmp_cck_max_pwdb = cur_cck_pwdb; tmp_cck_min_pwdb = cur_cck_pwdb; @@ -1997,7 +1995,6 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) tmp_cck_sec_pwdb = cur_cck_pwdb; tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - cck_rx_ver2_min_index = i; } } else { if (cur_cck_pwdb > tmp_cck_max_pwdb) { @@ -2027,13 +2024,10 @@ static void _rtl92e_dm_rx_path_sel_byrssi(struct net_device *dev) (cur_cck_pwdb > tmp_cck_min_pwdb)) { ; } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; - } } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; } } -- cgit v1.2.3-59-g8ed1b From 6808f8cf57f10c1491074572eb247e7fc2a60f47 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 21 Aug 2019 20:28:02 +0800 Subject: staging: rtl8192e: remove set but not used variable 'data_len' Fixes gcc '-Wunused-but-set-variable' warning: In function ieee80211_ccmp_encrypt: drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c:162:6: warning: variable data_len set but not used [-Wunused-but-set-variable] It is not used since commit 5ee5265674ce ("staging: rtl8192e: rtllib_crypt_ccmp.c: Use crypto API ccm(aes)") Reported-by: Hulk Robot Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190821122802.44028-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_ccmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c index 44ec45d5c87f..0cbf4a1a326b 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c @@ -153,7 +153,7 @@ static int ccmp_init_iv_and_aad(struct rtllib_hdr_4addr *hdr, static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct rtllib_ccmp_data *key = priv; - int data_len, i; + int i; u8 *pos; struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + @@ -163,7 +163,6 @@ static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - data_len = skb->len - hdr_len; pos = skb_push(skb, CCMP_HDR_LEN); memmove(pos, pos + CCMP_HDR_LEN, hdr_len); pos += hdr_len; -- cgit v1.2.3-59-g8ed1b From ee16d7d3e0128b347210b27214043e245d03c256 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Wed, 21 Aug 2019 07:35:38 -0700 Subject: staging: rtl8192u: fix OPEN_BRACE errors in ieee80211 Checkpatch emits several errors regarding braces being on the incorrect line. These can be fixed by moving the brace, do this. In a few cases, some comments were moved to facilitate this. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190821143540.4501-2-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 3 +- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 116 ++++++++-------------- drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c | 81 ++++++--------- drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c | 3 +- drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h | 3 +- 5 files changed, 73 insertions(+), 133 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 3963a08b9eb2..129dcb5a0f2e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -458,8 +458,7 @@ do { if (ieee80211_debug_level & (level)) \ int i; \ u8 *pdata = (u8 *) data; \ printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ - for (i = 0; i < (int)(datalen); i++) \ - { \ + for (i = 0; i < (int)(datalen); i++) { \ printk("%2x ", pdata[i]); \ if ((i + 1) % 16 == 0) printk("\n"); \ } \ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 7ef1e89de269..9d8b2ff700fe 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -218,8 +218,8 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, rx_stats->len = skb->len; ieee80211_rx_mgt(ieee, (struct rtl_80211_hdr_4addr *)skb->data, rx_stats); /* if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) */ - if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))/* use ADDR1 to perform address matching for Management frames */ - { + if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) { + /* use ADDR1 to perform address matching for Management frames */ dev_kfree_skb_any(skb); return 0; } @@ -339,8 +339,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, if (!crypt || !crypt->ops->decrypt_mpdu) return 0; - if (ieee->hwsec_active) - { + if (ieee->hwsec_active) { struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } @@ -386,8 +385,7 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, struct sk_buff *s if (!crypt || !crypt->ops->decrypt_msdu) return 0; - if (ieee->hwsec_active) - { + if (ieee->hwsec_active) { struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bHwSec = 1; } @@ -507,8 +505,7 @@ drop: static bool AddReorderEntry(struct rx_ts_record *pTS, struct rx_reorder_entry *pReorderEntry) { struct list_head *pList = &pTS->rx_pending_pkt_list; - while (pList->next != &pTS->rx_pending_pkt_list) - { + while (pList->next != &pTS->rx_pending_pkt_list) { if (SN_LESS(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) pList = pList->next; else if (SN_EQUAL(pReorderEntry->SeqNum, list_entry(pList->next, struct rx_reorder_entry, List)->SeqNum)) @@ -530,8 +527,7 @@ void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_ u16 ethertype; // if(index > 1) // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__func__,index); - for (j = 0; j < index; j++) - { + for (j = 0; j < index; j++) { //added by amy for reorder struct ieee80211_rxb *prxb = prxbIndicateArray[j]; for (i = 0; i < prxb->nr_subframes; i++) { @@ -699,8 +695,7 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): start RREORDER indicate\n", __func__); pReorderEntry = list_entry(pTS->rx_pending_pkt_list.prev, struct rx_reorder_entry, List); if (SN_LESS(pReorderEntry->SeqNum, pTS->rx_indicate_seq) || - SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) - { + SN_EQUAL(pReorderEntry->SeqNum, pTS->rx_indicate_seq)) { /* This protect buffer from overflow. */ if (index >= REORDER_WIN_SIZE) { IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n"); @@ -922,8 +917,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, frag = WLAN_GET_SEQ_FRAG(sc); hdrlen = ieee80211_get_hdrlen(fc); - if (HTCCheck(ieee, skb->data)) - { + if (HTCCheck(ieee, skb->data)) { if (net_ratelimit()) printk("find HTCControl\n"); hdrlen += 4; @@ -1010,8 +1004,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, hdr->addr2, Frame_QoSTID((u8 *)(skb->data)), RX_DIR, - true)) - { + true)) { // IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->rx_last_frag_num is %d,frag is %d,pRxTS->rx_last_seq_num is %d,seq is %d\n",__func__,pRxTS->rx_last_frag_num,frag,pRxTS->rx_last_seq_num,WLAN_GET_SEQ_SEQ(sc)); if ((fc & (1 << 11)) && @@ -1119,8 +1112,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) - { + (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) { printk("decrypt frame error\n"); goto rx_dropped; } @@ -1185,8 +1177,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* skb: hdr + (possible reassembled) full MSDU payload; possibly still * encrypted/authenticated */ if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) - { + ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) { printk("==>decrypt msdu error\n"); goto rx_dropped; } @@ -1243,13 +1234,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, */ //added by amy for reorder if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) - && !is_multicast_ether_addr(hdr->addr1)) - { + && !is_multicast_ether_addr(hdr->addr1)) { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true); - if (TID != 0 && TID != 3) - { + if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } } @@ -1549,15 +1538,12 @@ static inline void ieee80211_extract_country_ie( u8 *addr2 ) { - if (IS_DOT11D_ENABLE(ieee)) - { - if (info_element->len != 0) - { + if (IS_DOT11D_ENABLE(ieee)) { + if (info_element->len != 0) { memcpy(network->CountryIeBuf, info_element->data, info_element->len); network->CountryIeLen = info_element->len; - if (!IS_COUNTRY_IE_VALID(ieee)) - { + if (!IS_COUNTRY_IE_VALID(ieee)) { dot11d_update_country_ie(ieee, addr2, info_element->len, info_element->data); } } @@ -1567,8 +1553,7 @@ static inline void ieee80211_extract_country_ie( // some AP (e.g. Cisco 1242) don't include country IE in their // probe response frame. // - if (IS_EQUAL_CIE_SRC(ieee, addr2)) - { + if (IS_EQUAL_CIE_SRC(ieee, addr2)) { UPDATE_CIE_WATCHDOG(ieee); } } @@ -1865,8 +1850,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x0c && - info_element->data[2] == 0x43) - { + info_element->data[2] == 0x43) { network->ralink_cap_exist = true; } else network->ralink_cap_exist = false; @@ -1878,8 +1862,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x13 && - info_element->data[2] == 0x74)) - { + info_element->data[2] == 0x74)) { printk("========>%s(): athros AP is exist\n", __func__); network->atheros_cap_exist = true; } else @@ -1888,8 +1871,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, if (info_element->len >= 3 && info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && - info_element->data[2] == 0x96) - { + info_element->data[2] == 0x96) { network->cisco_cap_exist = true; } else network->cisco_cap_exist = false; @@ -1898,22 +1880,18 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96 && - info_element->data[3] == 0x01) - { - if (info_element->len == 6) - { + info_element->data[3] == 0x01) { + if (info_element->len == 6) { memcpy(network->CcxRmState, &info_element[4], 2); if (network->CcxRmState[0] != 0) - { network->bCcxRmEnable = true; - } else + else network->bCcxRmEnable = false; // // CCXv4 Table 59-1 MBSSID Masks. // network->MBssidMask = network->CcxRmState[1] & 0x07; - if (network->MBssidMask != 0) - { + if (network->MBssidMask != 0) { network->bMBssidValid = true; network->MBssidMask = 0xff << (network->MBssidMask); ether_addr_copy(network->MBssid, network->bssid); @@ -1929,8 +1907,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[0] == 0x00 && info_element->data[1] == 0x40 && info_element->data[2] == 0x96 && - info_element->data[3] == 0x03) - { + info_element->data[3] == 0x03) { if (info_element->len == 5) { network->bWithCcxVerNum = true; network->BssCcxVerNumber = info_element->data[4]; @@ -1985,16 +1962,14 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, case MFIE_TYPE_AIRONET: IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", info_element->len); - if (info_element->len > IE_CISCO_FLAG_POSITION) - { + if (info_element->len > IE_CISCO_FLAG_POSITION) { network->bWithAironetIE = true; // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23): // "A Cisco access point advertises support for CKIP in beacon and probe response packets, // by adding an Aironet element and setting one or both of the CKIP negotiation bits." if ((info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_MIC) || - (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) - { + (info_element->data[IE_CISCO_FLAG_POSITION] & SUPPORT_CKIP_PK)) { network->bCkipSupported = true; } else { network->bCkipSupported = false; @@ -2214,8 +2189,7 @@ static inline void update_network(struct ieee80211_network *dst, dst->rates_len = src->rates_len; memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); dst->rates_ex_len = src->rates_ex_len; - if (src->ssid_len > 0) - { + if (src->ssid_len > 0) { memset(dst->ssid, 0, dst->ssid_len); dst->ssid_len = src->ssid_len; memcpy(dst->ssid, src->ssid, src->ssid_len); @@ -2224,8 +2198,7 @@ static inline void update_network(struct ieee80211_network *dst, dst->flags = src->flags; dst->time_stamp[0] = src->time_stamp[0]; dst->time_stamp[1] = src->time_stamp[1]; - if (src->flags & NETWORK_HAS_ERP_VALUE) - { + if (src->flags & NETWORK_HAS_ERP_VALUE) { dst->erp_value = src->erp_value; dst->berp_info_valid = src->berp_info_valid = true; } @@ -2379,41 +2352,33 @@ static inline void ieee80211_process_probe_response( if (!is_legal_channel(ieee, network->channel)) goto out; - if (ieee->bGlobalDomain) - { - if (fc == IEEE80211_STYPE_PROBE_RESP) - { - // Case 1: Country code + if (ieee->bGlobalDomain) { + if (fc == IEEE80211_STYPE_PROBE_RESP) { if (IS_COUNTRY_IE_VALID(ieee)) { + // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network->channel); goto out; } - } - // Case 2: No any country code. - else - { + } else { + // Case 2: No any country code. // Filter over channel ch12~14 - if (network->channel > 11) - { + if (network->channel > 11) { printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); goto out; } } } else { - // Case 1: Country code if (IS_COUNTRY_IE_VALID(ieee)) { + // Case 1: Country code if (!is_legal_channel(ieee, network->channel)) { printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network->channel); goto out; } - } - // Case 2: No any country code. - else - { + } else { + // Case 2: No any country code. // Filter over channel ch12~14 - if (network->channel > 14) - { + if (network->channel > 14) { printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network->channel); goto out; } @@ -2442,8 +2407,7 @@ static inline void ieee80211_process_probe_response( else ieee->current_network.buseprotection = false; } - if (is_beacon(beacon->header.frame_ctl)) - { + if (is_beacon(beacon->header.frame_ctl)) { if (ieee->state == IEEE80211_LINKED) ieee->LinkDetectInfo.NumRecvBcnInPeriod++; } else //hidden AP diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index fc6eb97801e1..c49357067735 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -214,7 +214,8 @@ int ieee80211_encrypt_fragment( } -void ieee80211_txb_free(struct ieee80211_txb *txb) { +void ieee80211_txb_free(struct ieee80211_txb *txb) +{ //int i; if (unlikely(!txb)) return; @@ -333,8 +334,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, } } FORCED_AGG_SETTING: - switch (pHTInfo->ForcedAMPDUMode ) - { + switch (pHTInfo->ForcedAMPDUMode ) { case HT_AGG_AUTO: break; @@ -424,19 +424,15 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. return; - if (ieee->mode < IEEE_N_24G) //b, g mode - { + if (ieee->mode < IEEE_N_24G) /* b, g mode */ { // (1) RTS_Threshold is compared to the MPDU, not MSDU. // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. // Other fragments are protected by previous fragment. // So we only need to check the length of first fragment. - if (skb->len > ieee->rts) - { + if (skb->len > ieee->rts) { tcb_desc->bRTSEnable = true; tcb_desc->rts_rate = MGN_24M; - } - else if (ieee->current_network.buseprotection) - { + } else if (ieee->current_network.buseprotection) { // Use CTS-to-SELF in protection mode. tcb_desc->bRTSEnable = true; tcb_desc->bCTSEnable = true; @@ -444,43 +440,35 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, } //otherwise return; return; - } - else - {// 11n High throughput case. + } else { // 11n High throughput case. PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; - while (true) - { + while (true) { //check ERP protection - if (ieee->current_network.buseprotection) - {// CTS-to-SELF + if (ieee->current_network.buseprotection) {// CTS-to-SELF tcb_desc->bRTSEnable = true; tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; break; } //check HT op mode - if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) - { + if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { u8 HTOpMode = pHTInfo->CurrentOpMode; if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || - (!pHTInfo->bCurBW40MHz && HTOpMode == 3) ) - { + (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; break; } } //check rts - if (skb->len > ieee->rts) - { + if (skb->len > ieee->rts) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; break; } //to do list: check MIMO power save condition. //check AMPDU aggregation for TXOP - if(tcb_desc->bAMPDUEnable) - { + if(tcb_desc->bAMPDUEnable) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily @@ -488,8 +476,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check IOT action - if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) - { + if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; tcb_desc->bRTSEnable = true; @@ -541,8 +528,7 @@ static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, if (ieee->bTxUseDriverAssingedRate) tcb_desc->bTxUseDriverAssingedRate = true; - if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) - { + if (!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) { if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) tcb_desc->RATRIndex = 0; } @@ -553,11 +539,9 @@ static void ieee80211_query_seqnum(struct ieee80211_device *ieee, { if (is_multicast_ether_addr(dst)) return; - if (IsQoSDataFrame(skb->data)) //we deal qos data only - { + if (IsQoSDataFrame(skb->data)) /* we deal qos data only */ { struct tx_ts_record *pTS = NULL; - if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) - { + if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst, skb->priority, TX_DIR, true)) { return; } pTS->tx_cur_seq = (pTS->tx_cur_seq + 1) % 4096; @@ -749,15 +733,13 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } skb_reserve(skb_frag, ieee->tx_headroom); - if (encrypt){ + if (encrypt) { if (ieee->hwsec_active) tcb_desc->bHwSec = 1; else tcb_desc->bHwSec = 0; skb_reserve(skb_frag, crypt->ops->extra_prefix_len); - } - else - { + } else { tcb_desc->bHwSec = 0; } frag_hdr = skb_put_data(skb_frag, &header, hdr_len); @@ -775,8 +757,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) - if(qos_actived) - { + if(qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); } else { @@ -806,17 +787,16 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) skb_put(skb_frag, 4); } - if(qos_actived) - { - if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) - ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; - else - ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; + if (qos_actived) { + if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) + ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; + else + ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; } else { - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; } } else { if (unlikely(skb->len < sizeof(struct rtl_80211_hdr_3addr))) { @@ -839,8 +819,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) success: //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place. - if (txb) - { + if (txb) { struct cb_desc *tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); tcb_desc->bTxEnableFwCalcDur = 1; if (is_multicast_ether_addr(header.addr1)) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index be08cd1d37a7..8ad85331f020 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -130,8 +130,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, max_rate = rate; } - if (network->mode >= IEEE_N_24G)//add N rate here; - { + if (network->mode >= IEEE_N_24G) /* add N rate here */ { struct ht_capability_ele *ht_cap = NULL; bool is40M = false, isShortGI = false; u8 max_mcs = 0; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index b7769bca9740..3fca0d3a1d05 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -273,8 +273,7 @@ typedef enum _HT_AGGRE_SIZE { }HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; /* Indicate different AP vendor for IOT issue */ -typedef enum _HT_IOT_PEER -{ +typedef enum _HT_IOT_PEER { HT_IOT_PEER_UNKNOWN = 0, HT_IOT_PEER_REALTEK = 1, HT_IOT_PEER_BROADCOM = 2, -- cgit v1.2.3-59-g8ed1b From 2b1d4c425ae548f3f8da11238abf59a08f1626b7 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Wed, 21 Aug 2019 07:35:39 -0700 Subject: staging: rtl8192u: fix macro alignment in ieee80211 Several macros display unaligned, due to mixes of tabs and spaces. These can be fixed by making spacing consistent, do this. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190821143540.4501-3-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 35 +++++++++++++------------ drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h | 8 +++--- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 129dcb5a0f2e..6b7828a9e71d 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -169,9 +169,9 @@ struct cb_desc { #define MGN_MCS14 0x8e #define MGN_MCS15 0x8f -#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \ +#define aSifsTime ((priv->ieee80211->current_network.mode == IEEE_A || \ priv->ieee80211->current_network.mode == IEEE_N_24G || \ - priv->ieee80211->current_network.mode == IEEE_N_5G) ? \ + priv->ieee80211->current_network.mode == IEEE_N_5G) ? \ 16 : 10) #define MGMT_QUEUE_NUM 5 @@ -387,7 +387,7 @@ struct ieee_param { #define IEEE80211_STYPE_ACK 0x00D0 #define IEEE80211_STYPE_CFEND 0x00E0 #define IEEE80211_STYPE_CFENDACK 0x00F0 -#define IEEE80211_STYPE_BLOCKACK 0x0094 +#define IEEE80211_STYPE_BLOCKACK 0x0094 /* data */ #define IEEE80211_STYPE_DATA 0x0000 @@ -452,18 +452,19 @@ do { if (ieee80211_debug_level & (level)) \ printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0) //wb added to debug out data buf //if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA -#define IEEE80211_DEBUG_DATA(level, data, datalen) \ - do { if ((ieee80211_debug_level & (level)) == (level)) \ - { \ - int i; \ - u8 *pdata = (u8 *) data; \ - printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ - for (i = 0; i < (int)(datalen); i++) { \ - printk("%2x ", pdata[i]); \ - if ((i + 1) % 16 == 0) printk("\n"); \ - } \ - printk("\n"); \ - } \ +#define IEEE80211_DEBUG_DATA(level, data, datalen) \ + do { if ((ieee80211_debug_level & (level)) == (level)) \ + { \ + int i; \ + u8 *pdata = (u8 *) data; \ + printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ + for (i = 0; i < (int)(datalen); i++) { \ + printk("%2x ", pdata[i]); \ + if ((i + 1) % 16 == 0) \ + printk("\n"); \ + } \ + printk("\n"); \ + } \ } while (0) #else #define IEEE80211_DEBUG (level, fmt, args...) do {} while (0) @@ -2014,8 +2015,8 @@ struct ieee80211_device { #define IEEE_A (1<<0) #define IEEE_B (1<<1) #define IEEE_G (1<<2) -#define IEEE_N_24G (1<<4) -#define IEEE_N_5G (1<<5) +#define IEEE_N_24G (1<<4) +#define IEEE_N_5G (1<<5) #define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G) /* Generate a 802.11 header */ diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index 3fca0d3a1d05..586d93720e37 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -253,10 +253,10 @@ extern u8 MCS_FILTER_1SS[16]; /* 2007/07/12 MH We only define legacy and HT wireless mode now. */ #define LEGACY_WIRELESS_MODE IEEE_MODE_MASK -#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ - ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ?\ - (LegacyRate) :\ - (PICK_RATE(LegacyRate, HTRate)) +#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ + ((WirelessMode & (LEGACY_WIRELESS_MODE)) != 0) ? \ + (LegacyRate) : \ + (PICK_RATE(LegacyRate, HTRate)) // MCS Bw 40 {1~7, 12~15,32} #define RATE_ADPT_1SS_MASK 0xFF -- cgit v1.2.3-59-g8ed1b From f401441deda68326852560bf70d59e95f585bbb3 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Wed, 21 Aug 2019 07:35:40 -0700 Subject: staging: rtl8192u: fix spacing in ieee80211 Checkpatch emits several errors, warnings, and checks about spacing. Apply checkpatch's suggested spacing rules. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190821143540.4501-4-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/dot11d.c | 10 ++--- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 4 +- .../staging/rtl8192u/ieee80211/ieee80211_crypt.c | 2 +- .../rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 22 +++++----- .../rtl8192u/ieee80211/ieee80211_crypt_wep.c | 4 +- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 2 +- .../rtl8192u/ieee80211/ieee80211_softmac_wx.c | 14 +++--- drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c | 50 +++++++++++----------- drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c | 32 +++++++------- .../staging/rtl8192u/ieee80211/rtl819x_BAProc.c | 12 +++--- drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h | 6 +-- .../staging/rtl8192u/ieee80211/rtl819x_TSProc.c | 14 +++--- 12 files changed, 86 insertions(+), 86 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/dot11d.c b/drivers/staging/rtl8192u/ieee80211/dot11d.c index 130ddfe9868f..bc642076b96f 100644 --- a/drivers/staging/rtl8192u/ieee80211/dot11d.c +++ b/drivers/staging/rtl8192u/ieee80211/dot11d.c @@ -12,7 +12,7 @@ void rtl8192u_dot11d_init(struct ieee80211_device *ieee) dot11d_info->state = DOT11D_STATE_NONE; dot11d_info->country_ie_len = 0; memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); RESET_CIE_WATCHDOG(ieee); netdev_info(ieee->dev, "rtl8192u_dot11d_init()\n"); @@ -25,8 +25,8 @@ void dot11d_reset(struct ieee80211_device *ieee) u32 i; struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee); /* Clear old channel map */ - memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); /* Set new channel map */ for (i = 1; i <= 11; i++) (dot11d_info->channel_map)[i] = 1; @@ -56,8 +56,8 @@ void dot11d_update_country_ie(struct ieee80211_device *dev, u8 *pTaddr, u8 i, j, NumTriples, MaxChnlNum; struct chnl_txpower_triple *pTriple; - memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER+1); + memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); + memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1); MaxChnlNum = 0; NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */ pTriple = (struct chnl_txpower_triple *)(pCoutryIe + 3); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 6b7828a9e71d..daebbbd8f4dd 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -456,7 +456,7 @@ do { if (ieee80211_debug_level & (level)) \ do { if ((ieee80211_debug_level & (level)) == (level)) \ { \ int i; \ - u8 *pdata = (u8 *) data; \ + u8 *pdata = (u8 *)data; \ printk(KERN_DEBUG "ieee80211: %s()\n", __func__); \ for (i = 0; i < (int)(datalen); i++) { \ printk("%2x ", pdata[i]); \ @@ -468,7 +468,7 @@ do { if (ieee80211_debug_level & (level)) \ } while (0) #else #define IEEE80211_DEBUG (level, fmt, args...) do {} while (0) -#define IEEE80211_DEBUG_DATA (level, data, datalen) do {} while(0) +#define IEEE80211_DEBUG_DATA (level, data, datalen) do {} while (0) #endif /* CONFIG_IEEE80211_DEBUG */ /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c index 36987fccac5d..01012dddcd73 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c @@ -176,7 +176,7 @@ struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) } -static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } +static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; } static void ieee80211_crypt_null_deinit(void *priv) {} static struct ieee80211_crypto_ops ieee80211_crypt_null = { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c index 0927b2b15151..6f4710171151 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -160,7 +160,7 @@ static inline u16 Hi16(u32 val) static inline u16 Mk16(u8 hi, u8 lo) { - return lo | (((u16) hi) << 8); + return lo | (((u16)hi) << 8); } static const u16 Sbox[256] = { @@ -238,7 +238,7 @@ static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, * Make temporary area overlap WEP seed so that the final copy can be * avoided on little endian hosts. */ - u16 *PPK = (u16 *) &WEPSeed[4]; + u16 *PPK = (u16 *)&WEPSeed[4]; /* Step 1 - make copy of TTAK and bring in TSC */ PPK[0] = TTAK[0]; @@ -299,7 +299,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) skb->len < hdr_len) return -1; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tcb_desc->bHwSec) { if (!tkey->tx_phase1_done) { @@ -343,7 +343,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; crypto_sync_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, len+4); + sg_init_one(&sg, pos, len + 4); skcipher_request_set_sync_tfm(req, tkey->tx_tfm_arc4); skcipher_request_set_callback(req, 0, NULL, NULL); skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); @@ -383,7 +383,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) if (skb->len < hdr_len + 8 + 4) return -1; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; pos = skb->data + hdr_len; keyidx = pos[3]; if (!(keyidx & BIT(5))) { @@ -435,7 +435,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; crypto_sync_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, plen+4); + sg_init_one(&sg, pos, plen + 4); skcipher_request_set_sync_tfm(req, tkey->rx_tfm_arc4); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -523,7 +523,7 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) { struct rtl_80211_hdr_4addr *hdr11; - hdr11 = (struct rtl_80211_hdr_4addr *) skb->data; + hdr11 = (struct rtl_80211_hdr_4addr *)skb->data; switch (le16_to_cpu(hdr11->frame_ctl) & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { case IEEE80211_FCTL_TODS: @@ -556,7 +556,7 @@ static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *pri u8 *pos; struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { printk(KERN_DEBUG "Invalid packet for Michael MIC add " @@ -599,7 +599,7 @@ static void ieee80211_michael_mic_failure(struct net_device *dev, memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = sizeof(ev); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *)&ev); } static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, @@ -609,7 +609,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, u8 mic[8]; struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; if (!tkey->key_set) return -1; @@ -626,7 +626,7 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, return -1; if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { struct rtl_80211_hdr_4addr *hdr; - hdr = (struct rtl_80211_hdr_4addr *) skb->data; + hdr = (struct rtl_80211_hdr_4addr *)skb->data; printk(KERN_DEBUG "%s: Michael MIC verification failed for " "MSDU from %pM keyidx=%d\n", diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c index 805493a0870d..26482c3dcd1c 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -135,7 +135,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; crypto_sync_skcipher_setkey(wep->tx_tfm, key, klen); - sg_init_one(&sg, pos, len+4); + sg_init_one(&sg, pos, len + 4); skcipher_request_set_sync_tfm(req, wep->tx_tfm); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -192,7 +192,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) SYNC_SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); crypto_sync_skcipher_setkey(wep->rx_tfm, key, klen); - sg_init_one(&sg, pos, plen+4); + sg_init_one(&sg, pos, plen + 4); skcipher_request_set_sync_tfm(req, wep->rx_tfm); skcipher_request_set_callback(req, 0, NULL, NULL); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 9d8b2ff700fe..a1462ec55767 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -1237,7 +1237,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, && !is_multicast_ether_addr(hdr->addr1)) { TID = Frame_QoSTID(skb->data); SeqNum = WLAN_GET_SEQ_SEQ(sc); - GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true); + GetTs(ieee, (struct ts_common_info **)&pTS, hdr->addr2, TID, RX_DIR, true); if (TID != 0 && TID != 3) { ieee->bis_any_nonbepkts = true; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c index 4a8d16a45fc5..b1baaa18b129 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c @@ -42,8 +42,8 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info /* if setting by freq convert to channel */ if (fwrq->e == 1) { - if ((fwrq->m >= (int) 2.412e8 && - fwrq->m <= (int) 2.487e8)) { + if ((fwrq->m >= (int)2.412e8 && + fwrq->m <= (int)2.487e8)) { int f = fwrq->m / 100000; int c = 0; @@ -92,7 +92,7 @@ int ieee80211_wx_get_freq(struct ieee80211_device *ieee, if (ieee->current_network.channel == 0) return -1; /* NM 0.7.0 will not accept channel any more. */ - fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000; + fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel - 1] * 100000; fwrq->e = 1; /* fwrq->m = ieee->current_network.channel; */ /* fwrq->e = 0; */ @@ -220,7 +220,7 @@ int ieee80211_wx_set_rate(struct ieee80211_device *ieee, u32 target_rate = wrqu->bitrate.value; - ieee->rate = target_rate/100000; + ieee->rate = target_rate / 100000; /* FIXME: we might want to limit rate also in management protocols. */ return 0; } @@ -415,9 +415,9 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee, if (wrqu->essid.flags && wrqu->essid.length) { /* first flush current network.ssid */ - len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; - strncpy(ieee->current_network.ssid, extra, len+1); - ieee->current_network.ssid_len = len+1; + len = ((wrqu->essid.length - 1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length - 1) : IW_ESSID_MAX_SIZE; + strncpy(ieee->current_network.ssid, extra, len + 1); + ieee->current_network.ssid_len = len + 1; ieee->ssid_set = 1; } else { ieee->ssid_set = 0; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index c49357067735..e76bdedc8409 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -294,7 +294,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, struct tx_ts_record *pTxTs = NULL; struct rtl_80211_hdr_1addr *hdr = (struct rtl_80211_hdr_1addr *)skb->data; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (!IsQoSDataFrame(skb->data)) return; @@ -334,7 +334,7 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, } } FORCED_AGG_SETTING: - switch (pHTInfo->ForcedAMPDUMode ) { + switch (pHTInfo->ForcedAMPDUMode) { case HT_AGG_AUTO: break; @@ -372,7 +372,7 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_ tcb_desc->bUseShortGI = false; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (pHTInfo->bForcedShortGI) { @@ -380,9 +380,9 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, struct cb_desc *tcb_ return; } - if ((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz) + if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz) tcb_desc->bUseShortGI = true; - else if ((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz) + else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz) tcb_desc->bUseShortGI = true; } @@ -393,16 +393,16 @@ static void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, tcb_desc->bPacketBW = false; - if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT) return; if (tcb_desc->bMulticast || tcb_desc->bBroadcast) return; - if ((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel. + if ((tcb_desc->data_rate & 0x80) == 0) // If using legacy rate, it shall use 20MHz channel. return; //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance - if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) + if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) tcb_desc->bPacketBW = true; return; } @@ -418,10 +418,10 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate. tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz - if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts + if (tcb_desc->bBroadcast || tcb_desc->bMulticast) //only unicast frame will use rts/cts return; - if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA. + if (is_broadcast_ether_addr(skb->data + 16)) //check addr3 as infrastructure add3 is DA. return; if (ieee->mode < IEEE_N_24G) /* b, g mode */ { @@ -451,9 +451,9 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check HT op mode - if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { + if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) { u8 HTOpMode = pHTInfo->CurrentOpMode; - if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || + if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. tcb_desc->bRTSEnable = true; @@ -468,7 +468,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, } //to do list: check MIMO power save condition. //check AMPDU aggregation for TXOP - if(tcb_desc->bAMPDUEnable) { + if (tcb_desc->bAMPDUEnable) { tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps. // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily @@ -476,7 +476,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, break; } //check IOT action - if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { + if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) { tcb_desc->bCTSEnable = true; tcb_desc->rts_rate = MGN_24M; tcb_desc->bRTSEnable = true; @@ -517,7 +517,7 @@ static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, return; } - if (pMgntInfo->ForcedDataRate!= 0) { + if (pMgntInfo->ForcedDataRate != 0) { pTcb->bTxDisableRateFallBack = true; pTcb->bTxUseDriverAssingedRate = true; return; @@ -576,7 +576,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* If there is no driver handler to take the TXB, dont' bother * creating it... */ - if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| + if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) || ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); @@ -615,7 +615,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) /* Save source and destination addresses */ memcpy(&dest, skb->data, ETH_ALEN); - memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); + memcpy(&src, skb->data + ETH_ALEN, ETH_ALEN); /* Advance the SKB to the start of the payload */ skb_pull(skb, sizeof(struct ethhdr)); @@ -630,7 +630,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) fc = IEEE80211_FTYPE_DATA; //if(ieee->current_network.QoS_Enable) - if(qos_actived) + if (qos_actived) fc |= IEEE80211_STYPE_QOS_DATA; else fc |= IEEE80211_STYPE_DATA; @@ -724,7 +724,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) for (i = 0; i < nr_frags; i++) { skb_frag = txb->fragments[i]; tcb_desc = (struct cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); - if(qos_actived){ + if (qos_actived) { skb_frag->priority = skb->priority;//UP2AC(skb->priority); tcb_desc->queue_index = UP2AC(skb->priority); } else { @@ -757,11 +757,11 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) bytes = bytes_last_frag; } //if(ieee->current_network.QoS_Enable) - if(qos_actived) { + if (qos_actived) { // add 1 only indicate to corresponding seq number control 2006/7/12 - frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority) + 1] << 4 | i); } else { - frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4 | i); } /* Put a SNAP header on the first fragment */ @@ -806,7 +806,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); - if(!txb){ + if (!txb) { printk(KERN_WARNING "%s: Could not allocate TXB\n", ieee->dev->name); goto failed; @@ -841,9 +841,9 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&ieee->lock, flags); dev_kfree_skb_any(skb); if (txb) { - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { ieee80211_softmac_xmit(txb, ieee); - }else{ + } else { if ((*ieee->hard_start_xmit)(txb, dev) == 0) { stats->tx_packets++; stats->tx_bytes += __le16_to_cpu(txb->payload_size); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index 8ad85331f020..8ca7a7fd74f9 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -70,10 +70,10 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; - for(i=0; imode & BIT(i)) { - sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size); - pname +=ieee80211_modes[i].mode_size; + sprintf(pname, ieee80211_modes[i].mode_string, ieee80211_modes[i].mode_size); + pname += ieee80211_modes[i].mode_size; } } *pname = '\0'; @@ -138,13 +138,13 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[4]; else ht_cap = (struct ht_capability_ele *)&network->bssht.bdHTCapBuf[0]; - is40M = (ht_cap->ChlWidth)?1:0; - isShortGI = (ht_cap->ChlWidth)? - ((ht_cap->ShortGI40Mhz)?1:0): - ((ht_cap->ShortGI20Mhz)?1:0); + is40M = (ht_cap->ChlWidth) ? 1 : 0; + isShortGI = (ht_cap->ChlWidth) ? + ((ht_cap->ShortGI40Mhz) ? 1 : 0) : + ((ht_cap->ShortGI20Mhz) ? 1 : 0); max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL); - rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f]; + rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f]; if (rate > max_rate) max_rate = rate; } @@ -242,7 +242,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, list_for_each_entry(network, &ieee->network_list, list) { i++; - if((stop-ev)<200) { + if ((stop - ev) < 200) { err = -E2BIG; break; } @@ -453,7 +453,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee, IEEE80211_DEBUG_WX("GET_ENCODE\n"); - if(ieee->iw_mode == IW_MODE_MONITOR) + if (ieee->iw_mode == IW_MODE_MONITOR) return -1; key = erq->flags & IW_ENCODE_INDEX; @@ -570,7 +570,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, ret = -EINVAL; goto done; } - printk("alg name:%s\n",alg); + printk("alg name:%s\n", alg); ops = try_then_request_module(ieee80211_get_crypto_ops(alg), module); if (!ops) { @@ -687,7 +687,7 @@ int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee, ext->key_len = 0; encoding->flags |= IW_ENCODE_DISABLED; } else { - if (strcmp(crypt->ops->name, "WEP") == 0 ) + if (strcmp(crypt->ops->name, "WEP") == 0) ext->alg = IW_ENCODE_ALG_WEP; else if (strcmp(crypt->ops->name, "TKIP")) ext->alg = IW_ENCODE_ALG_TKIP; @@ -711,7 +711,7 @@ int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - struct iw_mlme *mlme = (struct iw_mlme *) extra; + struct iw_mlme *mlme = (struct iw_mlme *)extra; switch (mlme->cmd) { case IW_MLME_DEAUTH: case IW_MLME_DISASSOC: @@ -764,7 +764,7 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee, break; case IW_AUTH_WPA_ENABLED: - ieee->wpa_enabled = (data->value)?1:0; + ieee->wpa_enabled = (data->value) ? 1 : 0; break; case IW_AUTH_RX_UNENCRYPTED_EAPOL: @@ -784,14 +784,14 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) { u8 *buf; - if (len>MAX_WPA_IE_LEN || (len && !ie)) { + if (len > MAX_WPA_IE_LEN || (len && !ie)) { // printk("return error out, len:%d\n", len); return -EINVAL; } if (len) { - if (len != ie[1]+2) { + if (len != ie[1] + 2) { printk("len:%zu, ie:%d\n", len, ie[1]); return -EINVAL; } diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 53869b3c985c..379a2ccf4d9f 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -162,7 +162,7 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, s tag += 2; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); return skb; //return NULL; } @@ -229,7 +229,7 @@ static struct sk_buff *ieee80211_DELBA( put_unaligned_le16(ReasonCode, tag); tag += 2; - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); if (net_ratelimit()) IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __func__); @@ -331,9 +331,9 @@ int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb) return -1; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); - req = (struct rtl_80211_hdr_3addr *) skb->data; + req = (struct rtl_80211_hdr_3addr *)skb->data; tag = (u8 *)req; dst = &req->addr2[0]; tag += sizeof(struct rtl_80211_hdr_3addr); @@ -556,7 +556,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb) return -1; } - IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); + IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_BA, skb->data, skb->len); delba = (struct rtl_80211_hdr_3addr *)skb->data; dst = &delba->addr2[0]; pDelBaParamSet = (union delba_param_set *)&delba->payload[2]; @@ -643,7 +643,7 @@ TsInitDelBA(struct ieee80211_device *ieee, struct ts_common_info *pTsCommonInfo, ieee80211_send_DELBA( ieee, pTsCommonInfo->addr, - (pTxTs->tx_admitted_ba_record.valid)?(&pTxTs->tx_admitted_ba_record):(&pTxTs->tx_pending_ba_record), + (pTxTs->tx_admitted_ba_record.valid) ? (&pTxTs->tx_admitted_ba_record) : (&pTxTs->tx_pending_ba_record), TxRxSelect, DELBA_REASON_END_BA); } else if (TxRxSelect == RX_DIR) { diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h index 586d93720e37..79346a00af09 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h @@ -270,7 +270,7 @@ typedef enum _HT_AGGRE_SIZE { HT_AGG_SIZE_16K = 1, HT_AGG_SIZE_32K = 2, HT_AGG_SIZE_64K = 3, -}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; +} HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; /* Indicate different AP vendor for IOT issue */ typedef enum _HT_IOT_PEER { @@ -281,7 +281,7 @@ typedef enum _HT_IOT_PEER { HT_IOT_PEER_ATHEROS = 4, HT_IOT_PEER_CISCO = 5, HT_IOT_PEER_MAX = 6 -}HT_IOT_PEER_E, *PHTIOT_PEER_E; +} HT_IOT_PEER_E, *PHTIOT_PEER_E; /* * IOT Action for different AP @@ -297,6 +297,6 @@ typedef enum _HT_IOT_ACTION { HT_IOT_ACT_CDD_FSYNC = 0x00000080, HT_IOT_ACT_PURE_N_MODE = 0x00000100, HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200, -}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; +} HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; #endif //_RTL819XU_HTTYPE_H_ diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index 59d179ae7ad2..f4e5aa07421f 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -105,7 +105,7 @@ static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo) { eth_zero_addr(pTsCommonInfo->addr); memset(&pTsCommonInfo->t_spec, 0, sizeof(struct tspec_body)); - memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas)*TCLAS_NUM); + memset(&pTsCommonInfo->t_class, 0, sizeof(union qos_tclas) * TCLAS_NUM); pTsCommonInfo->t_clas_proc = 0; pTsCommonInfo->t_clas_num = 0; } @@ -183,9 +183,9 @@ void TSInitialize(struct ieee80211_device *ieee) //#ifdef TO_DO_LIST for (count = 0; count < REORDER_ENTRY_NUM; count++) { list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List); - if (count == (REORDER_ENTRY_NUM-1)) + if (count == (REORDER_ENTRY_NUM - 1)) break; - pRxReorderEntry = &ieee->RxReorderEntry[count+1]; + pRxReorderEntry = &ieee->RxReorderEntry[count + 1]; } //#endif } @@ -259,7 +259,7 @@ static struct ts_common_info *SearchAdmitTRStream(struct ieee80211_device *ieee, } if (&pRet->list != psearch_list) - return pRet ; + return pRet; else return NULL; } @@ -367,8 +367,8 @@ bool GetTs( (&ieee->Rx_TS_Admit_List); enum direction_value Dir = (ieee->iw_mode == IW_MODE_MASTER) ? - ((TxRxSelect == TX_DIR)?DIR_DOWN:DIR_UP) : - ((TxRxSelect == TX_DIR)?DIR_UP:DIR_DOWN); + ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) : + ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN); IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n"); if (!list_empty(pUnusedList)) { (*ppTS) = list_entry(pUnusedList->next, struct ts_common_info, list); @@ -530,7 +530,7 @@ void TsStartAddBaProcess(struct ieee80211_device *ieee, struct tx_ts_record *pTx jiffies + msecs_to_jiffies(TS_ADDBA_DELAY)); } else { IEEE80211_DEBUG(IEEE80211_DL_BA, "%s: Immediately Start ADDBA now!!\n", __func__); - mod_timer(&pTxTS->ts_add_ba_timer, jiffies+10); //set 10 ticks + mod_timer(&pTxTS->ts_add_ba_timer, jiffies + 10); //set 10 ticks } } else { IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __func__); -- cgit v1.2.3-59-g8ed1b From 47e4937a4a7ca4184fd282791dfee76c6799966a Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 23 Aug 2019 05:36:59 +0800 Subject: erofs: move erofs out of staging EROFS filesystem has been merged into linux-staging for a year. EROFS is designed to be a better solution of saving extra storage space with guaranteed end-to-end performance for read-only files with the help of reduced metadata, fixed-sized output compression and decompression inplace technologies. In the past year, EROFS was greatly improved by many people as a staging driver, self-tested, betaed by a large number of our internal users, successfully applied to almost all in-service HUAWEI smartphones as the part of EMUI 9.1 and proven to be stable enough to be moved out of staging. EROFS is a self-contained filesystem driver. Although there are still some TODOs to be more generic, we have a dedicated team actively keeping on working on EROFS in order to make it better with the evolution of Linux kernel as the other in-kernel filesystems. As Pavel suggested, it's better to do as one commit since git can do moves and all histories will be saved in this way. Let's promote it from staging and enhance it more actively as a "real" part of kernel for more wider scenarios! Cc: Greg Kroah-Hartman Cc: Alexander Viro Cc: Andrew Morton Cc: Stephen Rothwell Cc: Theodore Ts'o Cc: Pavel Machek Cc: David Sterba Cc: Amir Goldstein Cc: Christoph Hellwig Cc: Darrick J . Wong Cc: Dave Chinner Cc: Jaegeuk Kim Cc: Jan Kara Cc: Richard Weinberger Cc: Linus Torvalds Cc: Chao Yu Cc: Miao Xie Cc: Li Guifu Cc: Fang Wei Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20190822213659.5501-1-hsiangkao@aol.com Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/erofs.txt | 219 +++ MAINTAINERS | 14 +- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - .../erofs/Documentation/filesystems/erofs.txt | 223 --- drivers/staging/erofs/Kconfig | 98 -- drivers/staging/erofs/Makefile | 13 - drivers/staging/erofs/TODO | 46 - drivers/staging/erofs/compress.h | 62 - drivers/staging/erofs/data.c | 425 ------ drivers/staging/erofs/decompressor.c | 360 ----- drivers/staging/erofs/dir.c | 141 -- drivers/staging/erofs/erofs_fs.h | 310 ----- drivers/staging/erofs/include/trace/events/erofs.h | 256 ---- drivers/staging/erofs/inode.c | 334 ----- drivers/staging/erofs/internal.h | 554 -------- drivers/staging/erofs/namei.c | 253 ---- drivers/staging/erofs/super.c | 671 --------- drivers/staging/erofs/tagptr.h | 110 -- drivers/staging/erofs/utils.c | 335 ----- drivers/staging/erofs/xattr.c | 705 ---------- drivers/staging/erofs/xattr.h | 94 -- drivers/staging/erofs/zdata.c | 1434 -------------------- drivers/staging/erofs/zdata.h | 195 --- drivers/staging/erofs/zmap.c | 468 ------- drivers/staging/erofs/zpvec.h | 159 --- fs/Kconfig | 1 + fs/Makefile | 1 + fs/erofs/Kconfig | 98 ++ fs/erofs/Makefile | 11 + fs/erofs/compress.h | 60 + fs/erofs/data.c | 423 ++++++ fs/erofs/decompressor.c | 358 +++++ fs/erofs/dir.c | 139 ++ fs/erofs/erofs_fs.h | 307 +++++ fs/erofs/inode.c | 332 +++++ fs/erofs/internal.h | 553 ++++++++ fs/erofs/namei.c | 251 ++++ fs/erofs/super.c | 669 +++++++++ fs/erofs/tagptr.h | 110 ++ fs/erofs/utils.c | 333 +++++ fs/erofs/xattr.c | 703 ++++++++++ fs/erofs/xattr.h | 92 ++ fs/erofs/zdata.c | 1432 +++++++++++++++++++ fs/erofs/zdata.h | 193 +++ fs/erofs/zmap.c | 466 +++++++ fs/erofs/zpvec.h | 157 +++ include/trace/events/erofs.h | 256 ++++ include/uapi/linux/magic.h | 1 + 49 files changed, 7172 insertions(+), 7256 deletions(-) create mode 100644 Documentation/filesystems/erofs.txt delete mode 100644 drivers/staging/erofs/Documentation/filesystems/erofs.txt delete mode 100644 drivers/staging/erofs/Kconfig delete mode 100644 drivers/staging/erofs/Makefile delete mode 100644 drivers/staging/erofs/TODO delete mode 100644 drivers/staging/erofs/compress.h delete mode 100644 drivers/staging/erofs/data.c delete mode 100644 drivers/staging/erofs/decompressor.c delete mode 100644 drivers/staging/erofs/dir.c delete mode 100644 drivers/staging/erofs/erofs_fs.h delete mode 100644 drivers/staging/erofs/include/trace/events/erofs.h delete mode 100644 drivers/staging/erofs/inode.c delete mode 100644 drivers/staging/erofs/internal.h delete mode 100644 drivers/staging/erofs/namei.c delete mode 100644 drivers/staging/erofs/super.c delete mode 100644 drivers/staging/erofs/tagptr.h delete mode 100644 drivers/staging/erofs/utils.c delete mode 100644 drivers/staging/erofs/xattr.c delete mode 100644 drivers/staging/erofs/xattr.h delete mode 100644 drivers/staging/erofs/zdata.c delete mode 100644 drivers/staging/erofs/zdata.h delete mode 100644 drivers/staging/erofs/zmap.c delete mode 100644 drivers/staging/erofs/zpvec.h create mode 100644 fs/erofs/Kconfig create mode 100644 fs/erofs/Makefile create mode 100644 fs/erofs/compress.h create mode 100644 fs/erofs/data.c create mode 100644 fs/erofs/decompressor.c create mode 100644 fs/erofs/dir.c create mode 100644 fs/erofs/erofs_fs.h create mode 100644 fs/erofs/inode.c create mode 100644 fs/erofs/internal.h create mode 100644 fs/erofs/namei.c create mode 100644 fs/erofs/super.c create mode 100644 fs/erofs/tagptr.h create mode 100644 fs/erofs/utils.c create mode 100644 fs/erofs/xattr.c create mode 100644 fs/erofs/xattr.h create mode 100644 fs/erofs/zdata.c create mode 100644 fs/erofs/zdata.h create mode 100644 fs/erofs/zmap.c create mode 100644 fs/erofs/zpvec.h create mode 100644 include/trace/events/erofs.h (limited to 'drivers/staging') diff --git a/Documentation/filesystems/erofs.txt b/Documentation/filesystems/erofs.txt new file mode 100644 index 000000000000..38aa9126ec98 --- /dev/null +++ b/Documentation/filesystems/erofs.txt @@ -0,0 +1,219 @@ +Overview +======== + +EROFS file-system stands for Enhanced Read-Only File System. Different +from other read-only file systems, it aims to be designed for flexibility, +scalability, but be kept simple and high performance. + +It is designed as a better filesystem solution for the following scenarios: + - read-only storage media or + + - part of a fully trusted read-only solution, which means it needs to be + immutable and bit-for-bit identical to the official golden image for + their releases due to security and other considerations and + + - hope to save some extra storage space with guaranteed end-to-end performance + by using reduced metadata and transparent file compression, especially + for those embedded devices with limited memory (ex, smartphone); + +Here is the main features of EROFS: + - Little endian on-disk design; + + - Currently 4KB block size (nobh) and therefore maximum 16TB address space; + + - Metadata & data could be mixed by design; + + - 2 inode versions for different requirements: + v1 v2 + Inode metadata size: 32 bytes 64 bytes + Max file size: 4 GB 16 EB (also limited by max. vol size) + Max uids/gids: 65536 4294967296 + File creation time: no yes (64 + 32-bit timestamp) + Max hardlinks: 65536 4294967296 + Metadata reserved: 4 bytes 14 bytes + + - Support extended attributes (xattrs) as an option; + + - Support xattr inline and tail-end data inline for all files; + + - Support POSIX.1e ACLs by using xattrs; + + - Support transparent file compression as an option: + LZ4 algorithm with 4 KB fixed-output compression for high performance; + +The following git tree provides the file system user-space tools under +development (ex, formatting tool mkfs.erofs): +>> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git + +Bugs and patches are welcome, please kindly help us and send to the following +linux-erofs mailing list: +>> linux-erofs mailing list + +Mount options +============= + +fault_injection=%d Enable fault injection in all supported types with + specified injection rate. Supported injection type: + Type_Name Type_Value + FAULT_KMALLOC 0x000000001 + FAULT_READ_IO 0x000000002 +(no)user_xattr Setup Extended User Attributes. Note: xattr is enabled + by default if CONFIG_EROFS_FS_XATTR is selected. +(no)acl Setup POSIX Access Control List. Note: acl is enabled + by default if CONFIG_EROFS_FS_POSIX_ACL is selected. +cache_strategy=%s Select a strategy for cached decompression from now on: + disabled: In-place I/O decompression only; + readahead: Cache the last incomplete compressed physical + cluster for further reading. It still does + in-place I/O decompression for the rest + compressed physical clusters; + readaround: Cache the both ends of incomplete compressed + physical clusters for further reading. + It still does in-place I/O decompression + for the rest compressed physical clusters. + +Module parameters +================= +use_vmap=[0|1] Use vmap() instead of vm_map_ram() (default 0). + +On-disk details +=============== + +Summary +------- +Different from other read-only file systems, an EROFS volume is designed +to be as simple as possible: + + |-> aligned with the block size + ____________________________________________________________ + | |SB| | ... | Metadata | ... | Data | Metadata | ... | Data | + |_|__|_|_____|__________|_____|______|__________|_____|______| + 0 +1K + +All data areas should be aligned with the block size, but metadata areas +may not. All metadatas can be now observed in two different spaces (views): + 1. Inode metadata space + Each valid inode should be aligned with an inode slot, which is a fixed + value (32 bytes) and designed to be kept in line with v1 inode size. + + Each inode can be directly found with the following formula: + inode offset = meta_blkaddr * block_size + 32 * nid + + |-> aligned with 8B + |-> followed closely + + meta_blkaddr blocks |-> another slot + _____________________________________________________________________ + | ... | inode | xattrs | extents | data inline | ... | inode ... + |________|_______|(optional)|(optional)|__(optional)_|_____|__________ + |-> aligned with the inode slot size + . . + . . + . . + . . + . . + . . + .____________________________________________________|-> aligned with 4B + | xattr_ibody_header | shared xattrs | inline xattrs | + |____________________|_______________|_______________| + |-> 12 bytes <-|->x * 4 bytes<-| . + . . . + . . . + . . . + ._______________________________.______________________. + | id | id | id | id | ... | id | ent | ... | ent| ... | + |____|____|____|____|______|____|_____|_____|____|_____| + |-> aligned with 4B + |-> aligned with 4B + + Inode could be 32 or 64 bytes, which can be distinguished from a common + field which all inode versions have -- i_advise: + + __________________ __________________ + | i_advise | | i_advise | + |__________________| |__________________| + | ... | | ... | + | | | | + |__________________| 32 bytes | | + | | + |__________________| 64 bytes + + Xattrs, extents, data inline are followed by the corresponding inode with + proper alignes, and they could be optional for different data mappings, + _currently_ there are totally 3 valid data mappings supported: + + 1) flat file data without data inline (no extent); + 2) fixed-output size data compression (must have extents); + 3) flat file data with tail-end data inline (no extent); + + The size of the optional xattrs is indicated by i_xattr_count in inode + header. Large xattrs or xattrs shared by many different files can be + stored in shared xattrs metadata rather than inlined right after inode. + + 2. Shared xattrs metadata space + Shared xattrs space is similar to the above inode space, started with + a specific block indicated by xattr_blkaddr, organized one by one with + proper align. + + Each share xattr can also be directly found by the following formula: + xattr offset = xattr_blkaddr * block_size + 4 * xattr_id + + |-> aligned by 4 bytes + + xattr_blkaddr blocks |-> aligned with 4 bytes + _________________________________________________________________________ + | ... | xattr_entry | xattr data | ... | xattr_entry | xattr data ... + |________|_____________|_____________|_____|______________|_______________ + +Directories +----------- +All directories are now organized in a compact on-disk format. Note that +each directory block is divided into index and name areas in order to support +random file lookup, and all directory entries are _strictly_ recorded in +alphabetical order in order to support improved prefix binary search +algorithm (could refer to the related source code). + + ___________________________ + / | + / ______________|________________ + / / | nameoff1 | nameoffN-1 + ____________.______________._______________v________________v__________ +| dirent | dirent | ... | dirent | filename | filename | ... | filename | +|___.0___|____1___|_____|___N-1__|____0_____|____1_____|_____|___N-1____| + \ ^ + \ | * could have + \ | trailing '\0' + \________________________| nameoff0 + + Directory block + +Note that apart from the offset of the first filename, nameoff0 also indicates +the total number of directory entries in this block since it is no need to +introduce another on-disk field at all. + +Compression +----------- +Currently, EROFS supports 4KB fixed-output clustersize transparent file +compression, as illustrated below: + + |---- Variant-Length Extent ----|-------- VLE --------|----- VLE ----- + clusterofs clusterofs clusterofs + | | | logical data +_________v_______________________________v_____________________v_______________ +... | . | | . | | . | ... +____|____.________|_____________|________.____|_____________|__.__________|____ + |-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-| + size size size size size + . . . . + . . . . + . . . . + _______._____________._____________._____________._____________________ + ... | | | | ... physical data + _______|_____________|_____________|_____________|_____________________ + |-> cluster <-|-> cluster <-|-> cluster <-| + size size size + +Currently each on-disk physical cluster can contain 4KB (un)compressed data +at most. For each logical cluster, there is a corresponding on-disk index to +describe its cluster type, physical cluster address, etc. + +See "struct z_erofs_vle_decompressed_index" in erofs_fs.h for more details. + diff --git a/MAINTAINERS b/MAINTAINERS index 6847372cfab8..0f38cba2c581 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6046,6 +6046,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: drivers/video/fbdev/s1d13xxxfb.c F: include/video/s1d13xxxfb.h +EROFS FILE SYSTEM +M: Gao Xiang +M: Chao Yu +L: linux-erofs@lists.ozlabs.org +S: Maintained +F: fs/erofs/ + ERRSEQ ERROR TRACKING INFRASTRUCTURE M: Jeff Layton S: Maintained @@ -15229,13 +15236,6 @@ M: H Hartley Sweeten S: Odd Fixes F: drivers/staging/comedi/ -STAGING - EROFS FILE SYSTEM -M: Gao Xiang -M: Chao Yu -L: linux-erofs@lists.ozlabs.org -S: Maintained -F: drivers/staging/erofs/ - STAGING - FIELDBUS SUBSYSTEM M: Sven Van Asbroeck S: Maintained diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 7c96a01eef6c..d972ec8e71fb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -112,8 +112,6 @@ source "drivers/staging/gasket/Kconfig" source "drivers/staging/axis-fifo/Kconfig" -source "drivers/staging/erofs/Kconfig" - source "drivers/staging/fieldbus/Kconfig" source "drivers/staging/kpc2000/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index fcaac9693b83..6018b9a4a077 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_DMA_RALINK) += ralink-gdma/ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ -obj-$(CONFIG_EROFS_FS) += erofs/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_ISDN_CAPI) += isdn/ diff --git a/drivers/staging/erofs/Documentation/filesystems/erofs.txt b/drivers/staging/erofs/Documentation/filesystems/erofs.txt deleted file mode 100644 index 0eab600ca7ca..000000000000 --- a/drivers/staging/erofs/Documentation/filesystems/erofs.txt +++ /dev/null @@ -1,223 +0,0 @@ -Overview -======== - -EROFS file-system stands for Enhanced Read-Only File System. Different -from other read-only file systems, it aims to be designed for flexibility, -scalability, but be kept simple and high performance. - -It is designed as a better filesystem solution for the following scenarios: - - read-only storage media or - - - part of a fully trusted read-only solution, which means it needs to be - immutable and bit-for-bit identical to the official golden image for - their releases due to security and other considerations and - - - hope to save some extra storage space with guaranteed end-to-end performance - by using reduced metadata and transparent file compression, especially - for those embedded devices with limited memory (ex, smartphone); - -Here is the main features of EROFS: - - Little endian on-disk design; - - - Currently 4KB block size (nobh) and therefore maximum 16TB address space; - - - Metadata & data could be mixed by design; - - - 2 inode versions for different requirements: - v1 v2 - Inode metadata size: 32 bytes 64 bytes - Max file size: 4 GB 16 EB (also limited by max. vol size) - Max uids/gids: 65536 4294967296 - File creation time: no yes (64 + 32-bit timestamp) - Max hardlinks: 65536 4294967296 - Metadata reserved: 4 bytes 14 bytes - - - Support extended attributes (xattrs) as an option; - - - Support xattr inline and tail-end data inline for all files; - - - Support POSIX.1e ACLs by using xattrs; - - - Support transparent file compression as an option: - LZ4 algorithm with 4 KB fixed-output compression for high performance; - -The following git tree provides the file system user-space tools under -development (ex, formatting tool mkfs.erofs): ->> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git - -Bugs and patches are welcome, please kindly help us and send to the following -linux-erofs mailing list: ->> linux-erofs mailing list - -Note that EROFS is still working in progress as a Linux staging driver, -Cc the staging mailing list as well is highly recommended: ->> Linux Driver Project Developer List - -Mount options -============= - -fault_injection=%d Enable fault injection in all supported types with - specified injection rate. Supported injection type: - Type_Name Type_Value - FAULT_KMALLOC 0x000000001 - FAULT_READ_IO 0x000000002 -(no)user_xattr Setup Extended User Attributes. Note: xattr is enabled - by default if CONFIG_EROFS_FS_XATTR is selected. -(no)acl Setup POSIX Access Control List. Note: acl is enabled - by default if CONFIG_EROFS_FS_POSIX_ACL is selected. -cache_strategy=%s Select a strategy for cached decompression from now on: - disabled: In-place I/O decompression only; - readahead: Cache the last incomplete compressed physical - cluster for further reading. It still does - in-place I/O decompression for the rest - compressed physical clusters; - readaround: Cache the both ends of incomplete compressed - physical clusters for further reading. - It still does in-place I/O decompression - for the rest compressed physical clusters. - -Module parameters -================= -use_vmap=[0|1] Use vmap() instead of vm_map_ram() (default 0). - -On-disk details -=============== - -Summary -------- -Different from other read-only file systems, an EROFS volume is designed -to be as simple as possible: - - |-> aligned with the block size - ____________________________________________________________ - | |SB| | ... | Metadata | ... | Data | Metadata | ... | Data | - |_|__|_|_____|__________|_____|______|__________|_____|______| - 0 +1K - -All data areas should be aligned with the block size, but metadata areas -may not. All metadatas can be now observed in two different spaces (views): - 1. Inode metadata space - Each valid inode should be aligned with an inode slot, which is a fixed - value (32 bytes) and designed to be kept in line with v1 inode size. - - Each inode can be directly found with the following formula: - inode offset = meta_blkaddr * block_size + 32 * nid - - |-> aligned with 8B - |-> followed closely - + meta_blkaddr blocks |-> another slot - _____________________________________________________________________ - | ... | inode | xattrs | extents | data inline | ... | inode ... - |________|_______|(optional)|(optional)|__(optional)_|_____|__________ - |-> aligned with the inode slot size - . . - . . - . . - . . - . . - . . - .____________________________________________________|-> aligned with 4B - | xattr_ibody_header | shared xattrs | inline xattrs | - |____________________|_______________|_______________| - |-> 12 bytes <-|->x * 4 bytes<-| . - . . . - . . . - . . . - ._______________________________.______________________. - | id | id | id | id | ... | id | ent | ... | ent| ... | - |____|____|____|____|______|____|_____|_____|____|_____| - |-> aligned with 4B - |-> aligned with 4B - - Inode could be 32 or 64 bytes, which can be distinguished from a common - field which all inode versions have -- i_advise: - - __________________ __________________ - | i_advise | | i_advise | - |__________________| |__________________| - | ... | | ... | - | | | | - |__________________| 32 bytes | | - | | - |__________________| 64 bytes - - Xattrs, extents, data inline are followed by the corresponding inode with - proper alignes, and they could be optional for different data mappings, - _currently_ there are totally 3 valid data mappings supported: - - 1) flat file data without data inline (no extent); - 2) fixed-output size data compression (must have extents); - 3) flat file data with tail-end data inline (no extent); - - The size of the optional xattrs is indicated by i_xattr_count in inode - header. Large xattrs or xattrs shared by many different files can be - stored in shared xattrs metadata rather than inlined right after inode. - - 2. Shared xattrs metadata space - Shared xattrs space is similar to the above inode space, started with - a specific block indicated by xattr_blkaddr, organized one by one with - proper align. - - Each share xattr can also be directly found by the following formula: - xattr offset = xattr_blkaddr * block_size + 4 * xattr_id - - |-> aligned by 4 bytes - + xattr_blkaddr blocks |-> aligned with 4 bytes - _________________________________________________________________________ - | ... | xattr_entry | xattr data | ... | xattr_entry | xattr data ... - |________|_____________|_____________|_____|______________|_______________ - -Directories ------------ -All directories are now organized in a compact on-disk format. Note that -each directory block is divided into index and name areas in order to support -random file lookup, and all directory entries are _strictly_ recorded in -alphabetical order in order to support improved prefix binary search -algorithm (could refer to the related source code). - - ___________________________ - / | - / ______________|________________ - / / | nameoff1 | nameoffN-1 - ____________.______________._______________v________________v__________ -| dirent | dirent | ... | dirent | filename | filename | ... | filename | -|___.0___|____1___|_____|___N-1__|____0_____|____1_____|_____|___N-1____| - \ ^ - \ | * could have - \ | trailing '\0' - \________________________| nameoff0 - - Directory block - -Note that apart from the offset of the first filename, nameoff0 also indicates -the total number of directory entries in this block since it is no need to -introduce another on-disk field at all. - -Compression ------------ -Currently, EROFS supports 4KB fixed-output clustersize transparent file -compression, as illustrated below: - - |---- Variant-Length Extent ----|-------- VLE --------|----- VLE ----- - clusterofs clusterofs clusterofs - | | | logical data -_________v_______________________________v_____________________v_______________ -... | . | | . | | . | ... -____|____.________|_____________|________.____|_____________|__.__________|____ - |-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-|-> cluster <-| - size size size size size - . . . . - . . . . - . . . . - _______._____________._____________._____________._____________________ - ... | | | | ... physical data - _______|_____________|_____________|_____________|_____________________ - |-> cluster <-|-> cluster <-|-> cluster <-| - size size size - -Currently each on-disk physical cluster can contain 4KB (un)compressed data -at most. For each logical cluster, there is a corresponding on-disk index to -describe its cluster type, physical cluster address, etc. - -See "struct z_erofs_vle_decompressed_index" in erofs_fs.h for more details. - diff --git a/drivers/staging/erofs/Kconfig b/drivers/staging/erofs/Kconfig deleted file mode 100644 index 16316d1adca3..000000000000 --- a/drivers/staging/erofs/Kconfig +++ /dev/null @@ -1,98 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -config EROFS_FS - tristate "EROFS filesystem support" - depends on BLOCK - help - EROFS (Enhanced Read-Only File System) is a lightweight - read-only file system with modern designs (eg. page-sized - blocks, inline xattrs/data, etc.) for scenarios which need - high-performance read-only requirements, e.g. Android OS - for mobile phones and LIVECDs. - - It also provides fixed-sized output compression support, - which improves storage density, keeps relatively higher - compression ratios, which is more useful to achieve high - performance for embedded devices with limited memory. - - If unsure, say N. - -config EROFS_FS_DEBUG - bool "EROFS debugging feature" - depends on EROFS_FS - help - Print debugging messages and enable more BUG_ONs which check - filesystem consistency and find potential issues aggressively, - which can be used for Android eng build, for example. - - For daily use, say N. - -config EROFS_FAULT_INJECTION - bool "EROFS fault injection facility" - depends on EROFS_FS - help - Test EROFS to inject faults such as ENOMEM, EIO, and so on. - If unsure, say N. - -config EROFS_FS_XATTR - bool "EROFS extended attributes" - depends on EROFS_FS - default y - help - Extended attributes are name:value pairs associated with inodes by - the kernel or by users (see the attr(5) manual page, or visit - for details). - - If unsure, say N. - -config EROFS_FS_POSIX_ACL - bool "EROFS Access Control Lists" - depends on EROFS_FS_XATTR - select FS_POSIX_ACL - default y - help - Posix Access Control Lists (ACLs) support permissions for users and - groups beyond the owner/group/world scheme. - - To learn more about Access Control Lists, visit the POSIX ACLs for - Linux website . - - If you don't know what Access Control Lists are, say N. - -config EROFS_FS_SECURITY - bool "EROFS Security Labels" - depends on EROFS_FS_XATTR - default y - help - Security labels provide an access control facility to support Linux - Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO - Linux. This option enables an extended attribute handler for file - security labels in the erofs filesystem, so that it requires enabling - the extended attribute support in advance. - - If you are not using a security module, say N. - -config EROFS_FS_ZIP - bool "EROFS Data Compression Support" - depends on EROFS_FS - select LZ4_DECOMPRESS - default y - help - Enable fixed-sized output compression for EROFS. - - If you don't want to enable compression feature, say N. - -config EROFS_FS_CLUSTER_PAGE_LIMIT - int "EROFS Cluster Pages Hard Limit" - depends on EROFS_FS_ZIP - range 1 256 - default "1" - help - Indicates maximum # of pages of a compressed - physical cluster. - - For example, if files in a image were compressed - into 8k-unit, hard limit should not be configured - less than 2. Otherwise, the image will be refused - to mount on this kernel. - diff --git a/drivers/staging/erofs/Makefile b/drivers/staging/erofs/Makefile deleted file mode 100644 index 5cdae21cb5af..000000000000 --- a/drivers/staging/erofs/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only - -EROFS_VERSION = "1.0pre1" - -ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" - -obj-$(CONFIG_EROFS_FS) += erofs.o -# staging requirement: to be self-contained in its own directory -ccflags-y += -I $(srctree)/$(src)/include -erofs-objs := super.o inode.o data.o namei.o dir.o utils.o -erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o -erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o - diff --git a/drivers/staging/erofs/TODO b/drivers/staging/erofs/TODO deleted file mode 100644 index a8608b2f72bd..000000000000 --- a/drivers/staging/erofs/TODO +++ /dev/null @@ -1,46 +0,0 @@ - -EROFS is still working in progress, thus it is not suitable -for all productive uses. play at your own risk :) - -TODO List: - - add the missing error handling code - (mainly existed in xattr and decompression submodules); - - - finalize erofs ondisk format design (which means that - minor on-disk revisions could happen later); - - - documentation and detailed technical analysis; - - - general code review and clean up - (including confusing variable names and code snippets); - - - support larger compressed clustersizes for selection - (currently erofs only works as expected with the page-sized - compressed cluster configuration, usually 4KB); - - - support more lossless data compression algorithms - in addition to LZ4 algorithms in VLE approach; - - - data deduplication and other useful features. - -The following git tree provides the file system user-space -tools under development (ex, formatting tool mkfs.erofs): ->> git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git - -The open-source development of erofs-utils is at the early stage. -Contact the original author Li Guifu and -the co-maintainer Fang Wei for the latest news -and more details. - -Code, suggestions, etc, are welcome. Please feel free to -ask and send patches, - -To: - linux-erofs mailing list - Gao Xiang - Chao Yu - -Cc: (for linux-kernel upstream patches) - Greg Kroah-Hartman - linux-staging mailing list - diff --git a/drivers/staging/erofs/compress.h b/drivers/staging/erofs/compress.h deleted file mode 100644 index 043013f9ef1b..000000000000 --- a/drivers/staging/erofs/compress.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/compress.h - * - * Copyright (C) 2019 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_FS_COMPRESS_H -#define __EROFS_FS_COMPRESS_H - -#include "internal.h" - -enum { - Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX, - Z_EROFS_COMPRESSION_RUNTIME_MAX -}; - -struct z_erofs_decompress_req { - struct super_block *sb; - struct page **in, **out; - - unsigned short pageofs_out; - unsigned int inputsize, outputsize; - - /* indicate the algorithm will be used for decompression */ - unsigned int alg; - bool inplace_io, partial_decoding; -}; - -/* - * - 0x5A110C8D ('sallocated', Z_EROFS_MAPPING_STAGING) - - * used to mark temporary allocated pages from other - * file/cached pages and NULL mapping pages. - */ -#define Z_EROFS_MAPPING_STAGING ((void *)0x5A110C8D) - -/* check if a page is marked as staging */ -static inline bool z_erofs_page_is_staging(struct page *page) -{ - return page->mapping == Z_EROFS_MAPPING_STAGING; -} - -static inline bool z_erofs_put_stagingpage(struct list_head *pagepool, - struct page *page) -{ - if (!z_erofs_page_is_staging(page)) - return false; - - /* staging pages should not be used by others at the same time */ - if (page_ref_count(page) > 1) - put_page(page); - else - list_add(&page->lru, pagepool); - return true; -} - -int z_erofs_decompress(struct z_erofs_decompress_req *rq, - struct list_head *pagepool); - -#endif - diff --git a/drivers/staging/erofs/data.c b/drivers/staging/erofs/data.c deleted file mode 100644 index 72c4b4c5296b..000000000000 --- a/drivers/staging/erofs/data.c +++ /dev/null @@ -1,425 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/data.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "internal.h" -#include - -#include - -static inline void read_endio(struct bio *bio) -{ - struct super_block *const sb = bio->bi_private; - struct bio_vec *bvec; - blk_status_t err = bio->bi_status; - struct bvec_iter_all iter_all; - - if (time_to_inject(EROFS_SB(sb), FAULT_READ_IO)) { - erofs_show_injection_info(FAULT_READ_IO); - err = BLK_STS_IOERR; - } - - bio_for_each_segment_all(bvec, bio, iter_all) { - struct page *page = bvec->bv_page; - - /* page is already locked */ - DBG_BUGON(PageUptodate(page)); - - if (unlikely(err)) - SetPageError(page); - else - SetPageUptodate(page); - - unlock_page(page); - /* page could be reclaimed now */ - } - bio_put(bio); -} - -/* prio -- true is used for dir */ -struct page *__erofs_get_meta_page(struct super_block *sb, - erofs_blk_t blkaddr, bool prio, bool nofail) -{ - struct inode *const bd_inode = sb->s_bdev->bd_inode; - struct address_space *const mapping = bd_inode->i_mapping; - /* prefer retrying in the allocator to blindly looping below */ - const gfp_t gfp = mapping_gfp_constraint(mapping, ~__GFP_FS) | - (nofail ? __GFP_NOFAIL : 0); - unsigned int io_retries = nofail ? EROFS_IO_MAX_RETRIES_NOFAIL : 0; - struct page *page; - int err; - -repeat: - page = find_or_create_page(mapping, blkaddr, gfp); - if (unlikely(!page)) { - DBG_BUGON(nofail); - return ERR_PTR(-ENOMEM); - } - DBG_BUGON(!PageLocked(page)); - - if (!PageUptodate(page)) { - struct bio *bio; - - bio = erofs_grab_bio(sb, blkaddr, 1, sb, read_endio, nofail); - if (IS_ERR(bio)) { - DBG_BUGON(nofail); - err = PTR_ERR(bio); - goto err_out; - } - - err = bio_add_page(bio, page, PAGE_SIZE, 0); - if (unlikely(err != PAGE_SIZE)) { - err = -EFAULT; - goto err_out; - } - - __submit_bio(bio, REQ_OP_READ, - REQ_META | (prio ? REQ_PRIO : 0)); - - lock_page(page); - - /* this page has been truncated by others */ - if (unlikely(page->mapping != mapping)) { -unlock_repeat: - unlock_page(page); - put_page(page); - goto repeat; - } - - /* more likely a read error */ - if (unlikely(!PageUptodate(page))) { - if (io_retries) { - --io_retries; - goto unlock_repeat; - } - err = -EIO; - goto err_out; - } - } - return page; - -err_out: - unlock_page(page); - put_page(page); - return ERR_PTR(err); -} - -static int erofs_map_blocks_flatmode(struct inode *inode, - struct erofs_map_blocks *map, - int flags) -{ - int err = 0; - erofs_blk_t nblocks, lastblk; - u64 offset = map->m_la; - struct erofs_vnode *vi = EROFS_V(inode); - - trace_erofs_map_blocks_flatmode_enter(inode, map, flags); - - nblocks = DIV_ROUND_UP(inode->i_size, PAGE_SIZE); - lastblk = nblocks - is_inode_flat_inline(inode); - - if (unlikely(offset >= inode->i_size)) { - /* leave out-of-bound access unmapped */ - map->m_flags = 0; - map->m_plen = 0; - goto out; - } - - /* there is no hole in flatmode */ - map->m_flags = EROFS_MAP_MAPPED; - - if (offset < blknr_to_addr(lastblk)) { - map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la; - map->m_plen = blknr_to_addr(lastblk) - offset; - } else if (is_inode_flat_inline(inode)) { - /* 2 - inode inline B: inode, [xattrs], inline last blk... */ - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - - map->m_pa = iloc(sbi, vi->nid) + vi->inode_isize + - vi->xattr_isize + erofs_blkoff(map->m_la); - map->m_plen = inode->i_size - offset; - - /* inline data should be located in one meta block */ - if (erofs_blkoff(map->m_pa) + map->m_plen > PAGE_SIZE) { - errln("inline data cross block boundary @ nid %llu", - vi->nid); - DBG_BUGON(1); - err = -EFSCORRUPTED; - goto err_out; - } - - map->m_flags |= EROFS_MAP_META; - } else { - errln("internal error @ nid: %llu (size %llu), m_la 0x%llx", - vi->nid, inode->i_size, map->m_la); - DBG_BUGON(1); - err = -EIO; - goto err_out; - } - -out: - map->m_llen = map->m_plen; - -err_out: - trace_erofs_map_blocks_flatmode_exit(inode, map, flags, 0); - return err; -} - -int erofs_map_blocks(struct inode *inode, - struct erofs_map_blocks *map, int flags) -{ - if (unlikely(is_inode_layout_compression(inode))) { - int err = z_erofs_map_blocks_iter(inode, map, flags); - - if (map->mpage) { - put_page(map->mpage); - map->mpage = NULL; - } - return err; - } - return erofs_map_blocks_flatmode(inode, map, flags); -} - -static inline struct bio *erofs_read_raw_page(struct bio *bio, - struct address_space *mapping, - struct page *page, - erofs_off_t *last_block, - unsigned int nblocks, - bool ra) -{ - struct inode *const inode = mapping->host; - struct super_block *const sb = inode->i_sb; - erofs_off_t current_block = (erofs_off_t)page->index; - int err; - - DBG_BUGON(!nblocks); - - if (PageUptodate(page)) { - err = 0; - goto has_updated; - } - - /* note that for readpage case, bio also equals to NULL */ - if (bio && - /* not continuous */ - *last_block + 1 != current_block) { -submit_bio_retry: - __submit_bio(bio, REQ_OP_READ, 0); - bio = NULL; - } - - if (!bio) { - struct erofs_map_blocks map = { - .m_la = blknr_to_addr(current_block), - }; - erofs_blk_t blknr; - unsigned int blkoff; - - err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); - if (unlikely(err)) - goto err_out; - - /* zero out the holed page */ - if (unlikely(!(map.m_flags & EROFS_MAP_MAPPED))) { - zero_user_segment(page, 0, PAGE_SIZE); - SetPageUptodate(page); - - /* imply err = 0, see erofs_map_blocks */ - goto has_updated; - } - - /* for RAW access mode, m_plen must be equal to m_llen */ - DBG_BUGON(map.m_plen != map.m_llen); - - blknr = erofs_blknr(map.m_pa); - blkoff = erofs_blkoff(map.m_pa); - - /* deal with inline page */ - if (map.m_flags & EROFS_MAP_META) { - void *vsrc, *vto; - struct page *ipage; - - DBG_BUGON(map.m_plen > PAGE_SIZE); - - ipage = erofs_get_meta_page(inode->i_sb, blknr, 0); - - if (IS_ERR(ipage)) { - err = PTR_ERR(ipage); - goto err_out; - } - - vsrc = kmap_atomic(ipage); - vto = kmap_atomic(page); - memcpy(vto, vsrc + blkoff, map.m_plen); - memset(vto + map.m_plen, 0, PAGE_SIZE - map.m_plen); - kunmap_atomic(vto); - kunmap_atomic(vsrc); - flush_dcache_page(page); - - SetPageUptodate(page); - /* TODO: could we unlock the page earlier? */ - unlock_page(ipage); - put_page(ipage); - - /* imply err = 0, see erofs_map_blocks */ - goto has_updated; - } - - /* pa must be block-aligned for raw reading */ - DBG_BUGON(erofs_blkoff(map.m_pa)); - - /* max # of continuous pages */ - if (nblocks > DIV_ROUND_UP(map.m_plen, PAGE_SIZE)) - nblocks = DIV_ROUND_UP(map.m_plen, PAGE_SIZE); - if (nblocks > BIO_MAX_PAGES) - nblocks = BIO_MAX_PAGES; - - bio = erofs_grab_bio(sb, blknr, nblocks, sb, - read_endio, false); - if (IS_ERR(bio)) { - err = PTR_ERR(bio); - bio = NULL; - goto err_out; - } - } - - err = bio_add_page(bio, page, PAGE_SIZE, 0); - /* out of the extent or bio is full */ - if (err < PAGE_SIZE) - goto submit_bio_retry; - - *last_block = current_block; - - /* shift in advance in case of it followed by too many gaps */ - if (bio->bi_iter.bi_size >= bio->bi_max_vecs * PAGE_SIZE) { - /* err should reassign to 0 after submitting */ - err = 0; - goto submit_bio_out; - } - - return bio; - -err_out: - /* for sync reading, set page error immediately */ - if (!ra) { - SetPageError(page); - ClearPageUptodate(page); - } -has_updated: - unlock_page(page); - - /* if updated manually, continuous pages has a gap */ - if (bio) -submit_bio_out: - __submit_bio(bio, REQ_OP_READ, 0); - - return unlikely(err) ? ERR_PTR(err) : NULL; -} - -/* - * since we dont have write or truncate flows, so no inode - * locking needs to be held at the moment. - */ -static int erofs_raw_access_readpage(struct file *file, struct page *page) -{ - erofs_off_t last_block; - struct bio *bio; - - trace_erofs_readpage(page, true); - - bio = erofs_read_raw_page(NULL, page->mapping, - page, &last_block, 1, false); - - if (IS_ERR(bio)) - return PTR_ERR(bio); - - DBG_BUGON(bio); /* since we have only one bio -- must be NULL */ - return 0; -} - -static int erofs_raw_access_readpages(struct file *filp, - struct address_space *mapping, - struct list_head *pages, - unsigned int nr_pages) -{ - erofs_off_t last_block; - struct bio *bio = NULL; - gfp_t gfp = readahead_gfp_mask(mapping); - struct page *page = list_last_entry(pages, struct page, lru); - - trace_erofs_readpages(mapping->host, page, nr_pages, true); - - for (; nr_pages; --nr_pages) { - page = list_entry(pages->prev, struct page, lru); - - prefetchw(&page->flags); - list_del(&page->lru); - - if (!add_to_page_cache_lru(page, mapping, page->index, gfp)) { - bio = erofs_read_raw_page(bio, mapping, page, - &last_block, nr_pages, true); - - /* all the page errors are ignored when readahead */ - if (IS_ERR(bio)) { - pr_err("%s, readahead error at page %lu of nid %llu\n", - __func__, page->index, - EROFS_V(mapping->host)->nid); - - bio = NULL; - } - } - - /* pages could still be locked */ - put_page(page); - } - DBG_BUGON(!list_empty(pages)); - - /* the rare case (end in gaps) */ - if (unlikely(bio)) - __submit_bio(bio, REQ_OP_READ, 0); - return 0; -} - -static int erofs_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh, int create) -{ - struct erofs_map_blocks map = { - .m_la = iblock << 9, - }; - int err; - - err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); - if (err) - return err; - - if (map.m_flags & EROFS_MAP_MAPPED) - bh->b_blocknr = erofs_blknr(map.m_pa); - - return err; -} - -static sector_t erofs_bmap(struct address_space *mapping, sector_t block) -{ - struct inode *inode = mapping->host; - - if (is_inode_flat_inline(inode)) { - erofs_blk_t blks = i_size_read(inode) >> LOG_BLOCK_SIZE; - - if (block >> LOG_SECTORS_PER_BLOCK >= blks) - return 0; - } - - return generic_block_bmap(mapping, block, erofs_get_block); -} - -/* for uncompressed (aligned) files and raw access for other files */ -const struct address_space_operations erofs_raw_access_aops = { - .readpage = erofs_raw_access_readpage, - .readpages = erofs_raw_access_readpages, - .bmap = erofs_bmap, -}; - diff --git a/drivers/staging/erofs/decompressor.c b/drivers/staging/erofs/decompressor.c deleted file mode 100644 index 32a811ac704a..000000000000 --- a/drivers/staging/erofs/decompressor.c +++ /dev/null @@ -1,360 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/decompressor.c - * - * Copyright (C) 2019 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "compress.h" -#include -#include - -#ifndef LZ4_DISTANCE_MAX /* history window size */ -#define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */ -#endif - -#define LZ4_MAX_DISTANCE_PAGES (DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE) + 1) -#ifndef LZ4_DECOMPRESS_INPLACE_MARGIN -#define LZ4_DECOMPRESS_INPLACE_MARGIN(srcsize) (((srcsize) >> 8) + 32) -#endif - -struct z_erofs_decompressor { - /* - * if destpages have sparsed pages, fill them with bounce pages. - * it also check whether destpages indicate continuous physical memory. - */ - int (*prepare_destpages)(struct z_erofs_decompress_req *rq, - struct list_head *pagepool); - int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out); - char *name; -}; - -static bool use_vmap; -module_param(use_vmap, bool, 0444); -MODULE_PARM_DESC(use_vmap, "Use vmap() instead of vm_map_ram() (default 0)"); - -static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, - struct list_head *pagepool) -{ - const unsigned int nr = - PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; - struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL }; - unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES, - BITS_PER_LONG)] = { 0 }; - void *kaddr = NULL; - unsigned int i, j, top; - - top = 0; - for (i = j = 0; i < nr; ++i, ++j) { - struct page *const page = rq->out[i]; - struct page *victim; - - if (j >= LZ4_MAX_DISTANCE_PAGES) - j = 0; - - /* 'valid' bounced can only be tested after a complete round */ - if (test_bit(j, bounced)) { - DBG_BUGON(i < LZ4_MAX_DISTANCE_PAGES); - DBG_BUGON(top >= LZ4_MAX_DISTANCE_PAGES); - availables[top++] = rq->out[i - LZ4_MAX_DISTANCE_PAGES]; - } - - if (page) { - __clear_bit(j, bounced); - if (kaddr) { - if (kaddr + PAGE_SIZE == page_address(page)) - kaddr += PAGE_SIZE; - else - kaddr = NULL; - } else if (!i) { - kaddr = page_address(page); - } - continue; - } - kaddr = NULL; - __set_bit(j, bounced); - - if (top) { - victim = availables[--top]; - get_page(victim); - } else { - victim = erofs_allocpage(pagepool, GFP_KERNEL, false); - if (unlikely(!victim)) - return -ENOMEM; - victim->mapping = Z_EROFS_MAPPING_STAGING; - } - rq->out[i] = victim; - } - return kaddr ? 1 : 0; -} - -static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq, - u8 *src, unsigned int pageofs_in) -{ - /* - * if in-place decompression is ongoing, those decompressed - * pages should be copied in order to avoid being overlapped. - */ - struct page **in = rq->in; - u8 *const tmp = erofs_get_pcpubuf(0); - u8 *tmpp = tmp; - unsigned int inlen = rq->inputsize - pageofs_in; - unsigned int count = min_t(uint, inlen, PAGE_SIZE - pageofs_in); - - while (tmpp < tmp + inlen) { - if (!src) - src = kmap_atomic(*in); - memcpy(tmpp, src + pageofs_in, count); - kunmap_atomic(src); - src = NULL; - tmpp += count; - pageofs_in = 0; - count = PAGE_SIZE; - ++in; - } - return tmp; -} - -static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) -{ - unsigned int inputmargin, inlen; - u8 *src; - bool copied, support_0padding; - int ret; - - if (rq->inputsize > PAGE_SIZE) - return -EOPNOTSUPP; - - src = kmap_atomic(*rq->in); - inputmargin = 0; - support_0padding = false; - - /* decompression inplace is only safe when 0padding is enabled */ - if (EROFS_SB(rq->sb)->requirements & EROFS_REQUIREMENT_LZ4_0PADDING) { - support_0padding = true; - - while (!src[inputmargin & ~PAGE_MASK]) - if (!(++inputmargin & ~PAGE_MASK)) - break; - - if (inputmargin >= rq->inputsize) { - kunmap_atomic(src); - return -EIO; - } - } - - copied = false; - inlen = rq->inputsize - inputmargin; - if (rq->inplace_io) { - const uint oend = (rq->pageofs_out + - rq->outputsize) & ~PAGE_MASK; - const uint nr = PAGE_ALIGN(rq->pageofs_out + - rq->outputsize) >> PAGE_SHIFT; - - if (rq->partial_decoding || !support_0padding || - rq->out[nr - 1] != rq->in[0] || - rq->inputsize - oend < - LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) { - src = generic_copy_inplace_data(rq, src, inputmargin); - inputmargin = 0; - copied = true; - } - } - - ret = LZ4_decompress_safe_partial(src + inputmargin, out, - inlen, rq->outputsize, - rq->outputsize); - if (ret < 0) { - errln("%s, failed to decompress, in[%p, %u, %u] out[%p, %u]", - __func__, src + inputmargin, inlen, inputmargin, - out, rq->outputsize); - WARN_ON(1); - print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, - 16, 1, src + inputmargin, inlen, true); - print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, - 16, 1, out, rq->outputsize, true); - ret = -EIO; - } - - if (copied) - erofs_put_pcpubuf(src); - else - kunmap_atomic(src); - return ret; -} - -static struct z_erofs_decompressor decompressors[] = { - [Z_EROFS_COMPRESSION_SHIFTED] = { - .name = "shifted" - }, - [Z_EROFS_COMPRESSION_LZ4] = { - .prepare_destpages = lz4_prepare_destpages, - .decompress = lz4_decompress, - .name = "lz4" - }, -}; - -static void copy_from_pcpubuf(struct page **out, const char *dst, - unsigned short pageofs_out, - unsigned int outputsize) -{ - const char *end = dst + outputsize; - const unsigned int righthalf = PAGE_SIZE - pageofs_out; - const char *cur = dst - pageofs_out; - - while (cur < end) { - struct page *const page = *out++; - - if (page) { - char *buf = kmap_atomic(page); - - if (cur >= dst) { - memcpy(buf, cur, min_t(uint, PAGE_SIZE, - end - cur)); - } else { - memcpy(buf + pageofs_out, cur + pageofs_out, - min_t(uint, righthalf, end - cur)); - } - kunmap_atomic(buf); - } - cur += PAGE_SIZE; - } -} - -static void *erofs_vmap(struct page **pages, unsigned int count) -{ - int i = 0; - - if (use_vmap) - return vmap(pages, count, VM_MAP, PAGE_KERNEL); - - while (1) { - void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); - - /* retry two more times (totally 3 times) */ - if (addr || ++i >= 3) - return addr; - vm_unmap_aliases(); - } - return NULL; -} - -static void erofs_vunmap(const void *mem, unsigned int count) -{ - if (!use_vmap) - vm_unmap_ram(mem, count); - else - vunmap(mem); -} - -static int decompress_generic(struct z_erofs_decompress_req *rq, - struct list_head *pagepool) -{ - const unsigned int nrpages_out = - PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; - const struct z_erofs_decompressor *alg = decompressors + rq->alg; - unsigned int dst_maptype; - void *dst; - int ret; - - if (nrpages_out == 1 && !rq->inplace_io) { - DBG_BUGON(!*rq->out); - dst = kmap_atomic(*rq->out); - dst_maptype = 0; - goto dstmap_out; - } - - /* - * For the case of small output size (especially much less - * than PAGE_SIZE), memcpy the decompressed data rather than - * compressed data is preferred. - */ - if (rq->outputsize <= PAGE_SIZE * 7 / 8) { - dst = erofs_get_pcpubuf(0); - if (IS_ERR(dst)) - return PTR_ERR(dst); - - rq->inplace_io = false; - ret = alg->decompress(rq, dst); - if (!ret) - copy_from_pcpubuf(rq->out, dst, rq->pageofs_out, - rq->outputsize); - - erofs_put_pcpubuf(dst); - return ret; - } - - ret = alg->prepare_destpages(rq, pagepool); - if (ret < 0) { - return ret; - } else if (ret) { - dst = page_address(*rq->out); - dst_maptype = 1; - goto dstmap_out; - } - - dst = erofs_vmap(rq->out, nrpages_out); - if (!dst) - return -ENOMEM; - dst_maptype = 2; - -dstmap_out: - ret = alg->decompress(rq, dst + rq->pageofs_out); - - if (!dst_maptype) - kunmap_atomic(dst); - else if (dst_maptype == 2) - erofs_vunmap(dst, nrpages_out); - return ret; -} - -static int shifted_decompress(const struct z_erofs_decompress_req *rq, - struct list_head *pagepool) -{ - const unsigned int nrpages_out = - PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; - const unsigned int righthalf = PAGE_SIZE - rq->pageofs_out; - unsigned char *src, *dst; - - if (nrpages_out > 2) { - DBG_BUGON(1); - return -EIO; - } - - if (rq->out[0] == *rq->in) { - DBG_BUGON(nrpages_out != 1); - return 0; - } - - src = kmap_atomic(*rq->in); - if (!rq->out[0]) { - dst = NULL; - } else { - dst = kmap_atomic(rq->out[0]); - memcpy(dst + rq->pageofs_out, src, righthalf); - } - - if (rq->out[1] == *rq->in) { - memmove(src, src + righthalf, rq->pageofs_out); - } else if (nrpages_out == 2) { - if (dst) - kunmap_atomic(dst); - DBG_BUGON(!rq->out[1]); - dst = kmap_atomic(rq->out[1]); - memcpy(dst, src + righthalf, rq->pageofs_out); - } - if (dst) - kunmap_atomic(dst); - kunmap_atomic(src); - return 0; -} - -int z_erofs_decompress(struct z_erofs_decompress_req *rq, - struct list_head *pagepool) -{ - if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) - return shifted_decompress(rq, pagepool); - return decompress_generic(rq, pagepool); -} - diff --git a/drivers/staging/erofs/dir.c b/drivers/staging/erofs/dir.c deleted file mode 100644 index 77ef856df9f3..000000000000 --- a/drivers/staging/erofs/dir.c +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/dir.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "internal.h" - -static void debug_one_dentry(unsigned char d_type, const char *de_name, - unsigned int de_namelen) -{ -#ifdef CONFIG_EROFS_FS_DEBUG - /* since the on-disk name could not have the trailing '\0' */ - unsigned char dbg_namebuf[EROFS_NAME_LEN + 1]; - - memcpy(dbg_namebuf, de_name, de_namelen); - dbg_namebuf[de_namelen] = '\0'; - - debugln("found dirent %s de_len %u d_type %d", dbg_namebuf, - de_namelen, d_type); -#endif -} - -static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, - void *dentry_blk, unsigned int *ofs, - unsigned int nameoff, unsigned int maxsize) -{ - struct erofs_dirent *de = dentry_blk + *ofs; - const struct erofs_dirent *end = dentry_blk + nameoff; - - while (de < end) { - const char *de_name; - unsigned int de_namelen; - unsigned char d_type; - - d_type = fs_ftype_to_dtype(de->file_type); - - nameoff = le16_to_cpu(de->nameoff); - de_name = (char *)dentry_blk + nameoff; - - /* the last dirent in the block? */ - if (de + 1 >= end) - de_namelen = strnlen(de_name, maxsize - nameoff); - else - de_namelen = le16_to_cpu(de[1].nameoff) - nameoff; - - /* a corrupted entry is found */ - if (unlikely(nameoff + de_namelen > maxsize || - de_namelen > EROFS_NAME_LEN)) { - errln("bogus dirent @ nid %llu", EROFS_V(dir)->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; - } - - debug_one_dentry(d_type, de_name, de_namelen); - if (!dir_emit(ctx, de_name, de_namelen, - le64_to_cpu(de->nid), d_type)) - /* stopped by some reason */ - return 1; - ++de; - *ofs += sizeof(struct erofs_dirent); - } - *ofs = maxsize; - return 0; -} - -static int erofs_readdir(struct file *f, struct dir_context *ctx) -{ - struct inode *dir = file_inode(f); - struct address_space *mapping = dir->i_mapping; - const size_t dirsize = i_size_read(dir); - unsigned int i = ctx->pos / EROFS_BLKSIZ; - unsigned int ofs = ctx->pos % EROFS_BLKSIZ; - int err = 0; - bool initial = true; - - while (ctx->pos < dirsize) { - struct page *dentry_page; - struct erofs_dirent *de; - unsigned int nameoff, maxsize; - - dentry_page = read_mapping_page(mapping, i, NULL); - if (dentry_page == ERR_PTR(-ENOMEM)) { - err = -ENOMEM; - break; - } else if (IS_ERR(dentry_page)) { - errln("fail to readdir of logical block %u of nid %llu", - i, EROFS_V(dir)->nid); - err = -EFSCORRUPTED; - break; - } - - de = (struct erofs_dirent *)kmap(dentry_page); - - nameoff = le16_to_cpu(de->nameoff); - - if (unlikely(nameoff < sizeof(struct erofs_dirent) || - nameoff >= PAGE_SIZE)) { - errln("%s, invalid de[0].nameoff %u @ nid %llu", - __func__, nameoff, EROFS_V(dir)->nid); - err = -EFSCORRUPTED; - goto skip_this; - } - - maxsize = min_t(unsigned int, - dirsize - ctx->pos + ofs, PAGE_SIZE); - - /* search dirents at the arbitrary position */ - if (unlikely(initial)) { - initial = false; - - ofs = roundup(ofs, sizeof(struct erofs_dirent)); - if (unlikely(ofs >= nameoff)) - goto skip_this; - } - - err = erofs_fill_dentries(dir, ctx, de, &ofs, - nameoff, maxsize); -skip_this: - kunmap(dentry_page); - - put_page(dentry_page); - - ctx->pos = blknr_to_addr(i) + ofs; - - if (unlikely(err)) - break; - ++i; - ofs = 0; - } - return err < 0 ? err : 0; -} - -const struct file_operations erofs_dir_fops = { - .llseek = generic_file_llseek, - .read = generic_read_dir, - .iterate_shared = erofs_readdir, -}; - diff --git a/drivers/staging/erofs/erofs_fs.h b/drivers/staging/erofs/erofs_fs.h deleted file mode 100644 index 6db70f395937..000000000000 --- a/drivers/staging/erofs/erofs_fs.h +++ /dev/null @@ -1,310 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ -/* - * linux/drivers/staging/erofs/erofs_fs.h - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_FS_H -#define __EROFS_FS_H - -/* Enhanced(Extended) ROM File System */ -#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 -#define EROFS_SUPER_OFFSET 1024 - -/* - * Any bits that aren't in EROFS_ALL_REQUIREMENTS should be - * incompatible with this kernel version. - */ -#define EROFS_REQUIREMENT_LZ4_0PADDING 0x00000001 -#define EROFS_ALL_REQUIREMENTS EROFS_REQUIREMENT_LZ4_0PADDING - -struct erofs_super_block { -/* 0 */__le32 magic; /* in the little endian */ -/* 4 */__le32 checksum; /* crc32c(super_block) */ -/* 8 */__le32 features; /* (aka. feature_compat) */ -/* 12 */__u8 blkszbits; /* support block_size == PAGE_SIZE only */ -/* 13 */__u8 reserved; - -/* 14 */__le16 root_nid; -/* 16 */__le64 inos; /* total valid ino # (== f_files - f_favail) */ - -/* 24 */__le64 build_time; /* inode v1 time derivation */ -/* 32 */__le32 build_time_nsec; -/* 36 */__le32 blocks; /* used for statfs */ -/* 40 */__le32 meta_blkaddr; -/* 44 */__le32 xattr_blkaddr; -/* 48 */__u8 uuid[16]; /* 128-bit uuid for volume */ -/* 64 */__u8 volume_name[16]; /* volume name */ -/* 80 */__le32 requirements; /* (aka. feature_incompat) */ - -/* 84 */__u8 reserved2[44]; -} __packed; /* 128 bytes */ - -/* - * erofs inode data mapping: - * 0 - inode plain without inline data A: - * inode, [xattrs], ... | ... | no-holed data - * 1 - inode VLE compression B (legacy): - * inode, [xattrs], extents ... | ... - * 2 - inode plain with inline data C: - * inode, [xattrs], last_inline_data, ... | ... | no-holed data - * 3 - inode compression D: - * inode, [xattrs], map_header, extents ... | ... - * 4~7 - reserved - */ -enum { - EROFS_INODE_FLAT_PLAIN, - EROFS_INODE_FLAT_COMPRESSION_LEGACY, - EROFS_INODE_FLAT_INLINE, - EROFS_INODE_FLAT_COMPRESSION, - EROFS_INODE_LAYOUT_MAX -}; - -static inline bool erofs_inode_is_data_compressed(unsigned int datamode) -{ - if (datamode == EROFS_INODE_FLAT_COMPRESSION) - return true; - return datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY; -} - -/* bit definitions of inode i_advise */ -#define EROFS_I_VERSION_BITS 1 -#define EROFS_I_DATA_MAPPING_BITS 3 - -#define EROFS_I_VERSION_BIT 0 -#define EROFS_I_DATA_MAPPING_BIT 1 - -struct erofs_inode_v1 { -/* 0 */__le16 i_advise; - -/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ -/* 2 */__le16 i_xattr_icount; -/* 4 */__le16 i_mode; -/* 6 */__le16 i_nlink; -/* 8 */__le32 i_size; -/* 12 */__le32 i_reserved; -/* 16 */union { - /* file total compressed blocks for data mapping 1 */ - __le32 compressed_blocks; - __le32 raw_blkaddr; - - /* for device files, used to indicate old/new device # */ - __le32 rdev; - } i_u __packed; -/* 20 */__le32 i_ino; /* only used for 32-bit stat compatibility */ -/* 24 */__le16 i_uid; -/* 26 */__le16 i_gid; -/* 28 */__le32 i_reserved2; -} __packed; - -/* 32 bytes on-disk inode */ -#define EROFS_INODE_LAYOUT_V1 0 -/* 64 bytes on-disk inode */ -#define EROFS_INODE_LAYOUT_V2 1 - -struct erofs_inode_v2 { -/* 0 */__le16 i_advise; - -/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ -/* 2 */__le16 i_xattr_icount; -/* 4 */__le16 i_mode; -/* 6 */__le16 i_reserved; -/* 8 */__le64 i_size; -/* 16 */union { - /* file total compressed blocks for data mapping 1 */ - __le32 compressed_blocks; - __le32 raw_blkaddr; - - /* for device files, used to indicate old/new device # */ - __le32 rdev; - } i_u __packed; - - /* only used for 32-bit stat compatibility */ -/* 20 */__le32 i_ino; - -/* 24 */__le32 i_uid; -/* 28 */__le32 i_gid; -/* 32 */__le64 i_ctime; -/* 40 */__le32 i_ctime_nsec; -/* 44 */__le32 i_nlink; -/* 48 */__u8 i_reserved2[16]; -} __packed; /* 64 bytes */ - -#define EROFS_MAX_SHARED_XATTRS (128) -/* h_shared_count between 129 ... 255 are special # */ -#define EROFS_SHARED_XATTR_EXTENT (255) - -/* - * inline xattrs (n == i_xattr_icount): - * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes - * 12 bytes / \ - * / \ - * /-----------------------\ - * | erofs_xattr_entries+ | - * +-----------------------+ - * inline xattrs must starts in erofs_xattr_ibody_header, - * for read-only fs, no need to introduce h_refcount - */ -struct erofs_xattr_ibody_header { - __le32 h_reserved; - __u8 h_shared_count; - __u8 h_reserved2[7]; - __le32 h_shared_xattrs[0]; /* shared xattr id array */ -} __packed; - -/* Name indexes */ -#define EROFS_XATTR_INDEX_USER 1 -#define EROFS_XATTR_INDEX_POSIX_ACL_ACCESS 2 -#define EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -#define EROFS_XATTR_INDEX_TRUSTED 4 -#define EROFS_XATTR_INDEX_LUSTRE 5 -#define EROFS_XATTR_INDEX_SECURITY 6 - -/* xattr entry (for both inline & shared xattrs) */ -struct erofs_xattr_entry { - __u8 e_name_len; /* length of name */ - __u8 e_name_index; /* attribute name index */ - __le16 e_value_size; /* size of attribute value */ - /* followed by e_name and e_value */ - char e_name[0]; /* attribute name */ -} __packed; - -#define ondisk_xattr_ibody_size(count) ({\ - u32 __count = le16_to_cpu(count); \ - ((__count) == 0) ? 0 : \ - sizeof(struct erofs_xattr_ibody_header) + \ - sizeof(__u32) * ((__count) - 1); }) - -#define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry)) -#define EROFS_XATTR_ENTRY_SIZE(entry) EROFS_XATTR_ALIGN( \ - sizeof(struct erofs_xattr_entry) + \ - (entry)->e_name_len + le16_to_cpu((entry)->e_value_size)) - -/* available compression algorithm types */ -enum { - Z_EROFS_COMPRESSION_LZ4, - Z_EROFS_COMPRESSION_MAX -}; - -/* - * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) - * e.g. for 4k logical cluster size, 4B if compacted 2B is off; - * (4B) + 2B + (4B) if compacted 2B is on. - */ -#define Z_EROFS_ADVISE_COMPACTED_2B_BIT 0 - -#define Z_EROFS_ADVISE_COMPACTED_2B (1 << Z_EROFS_ADVISE_COMPACTED_2B_BIT) - -struct z_erofs_map_header { - __le32 h_reserved1; - __le16 h_advise; - /* - * bit 0-3 : algorithm type of head 1 (logical cluster type 01); - * bit 4-7 : algorithm type of head 2 (logical cluster type 11). - */ - __u8 h_algorithmtype; - /* - * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; - * bit 3-4 : (physical - logical) cluster bits of head 1: - * For example, if logical clustersize = 4096, 1 for 8192. - * bit 5-7 : (physical - logical) cluster bits of head 2. - */ - __u8 h_clusterbits; -}; - -#define Z_EROFS_VLE_LEGACY_HEADER_PADDING 8 - -/* - * Z_EROFS Variable-sized Logical Extent cluster type: - * 0 - literal (uncompressed) cluster - * 1 - compressed cluster (for the head logical cluster) - * 2 - compressed cluster (for the other logical clusters) - * - * In detail, - * 0 - literal (uncompressed) cluster, - * di_advise = 0 - * di_clusterofs = the literal data offset of the cluster - * di_blkaddr = the blkaddr of the literal cluster - * - * 1 - compressed cluster (for the head logical cluster) - * di_advise = 1 - * di_clusterofs = the decompressed data offset of the cluster - * di_blkaddr = the blkaddr of the compressed cluster - * - * 2 - compressed cluster (for the other logical clusters) - * di_advise = 2 - * di_clusterofs = - * the decompressed data offset in its own head cluster - * di_u.delta[0] = distance to its corresponding head cluster - * di_u.delta[1] = distance to its corresponding tail cluster - * (di_advise could be 0, 1 or 2) - */ -enum { - Z_EROFS_VLE_CLUSTER_TYPE_PLAIN, - Z_EROFS_VLE_CLUSTER_TYPE_HEAD, - Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD, - Z_EROFS_VLE_CLUSTER_TYPE_RESERVED, - Z_EROFS_VLE_CLUSTER_TYPE_MAX -}; - -#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2 -#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0 - -struct z_erofs_vle_decompressed_index { - __le16 di_advise; - /* where to decompress in the head cluster */ - __le16 di_clusterofs; - - union { - /* for the head cluster */ - __le32 blkaddr; - /* - * for the rest clusters - * eg. for 4k page-sized cluster, maximum 4K*64k = 256M) - * [0] - pointing to the head cluster - * [1] - pointing to the tail cluster - */ - __le16 delta[2]; - } di_u __packed; /* 8 bytes */ -} __packed; - -#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \ - (round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \ - sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING) - -/* dirent sorts in alphabet order, thus we can do binary search */ -struct erofs_dirent { - __le64 nid; /* 0, node number */ - __le16 nameoff; /* 8, start offset of file name */ - __u8 file_type; /* 10, file type */ - __u8 reserved; /* 11, reserved */ -} __packed; - -/* - * EROFS file types should match generic FT_* types and - * it seems no need to add BUILD_BUG_ONs since potential - * unmatchness will break other fses as well... - */ - -#define EROFS_NAME_LEN 255 - -/* check the EROFS on-disk layout strictly at compile time */ -static inline void erofs_check_ondisk_layout_definitions(void) -{ - BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); - BUILD_BUG_ON(sizeof(struct erofs_inode_v1) != 32); - BUILD_BUG_ON(sizeof(struct erofs_inode_v2) != 64); - BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); - BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); - BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); - BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8); - BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); - - BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) < - Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1); -} - -#endif - diff --git a/drivers/staging/erofs/include/trace/events/erofs.h b/drivers/staging/erofs/include/trace/events/erofs.h deleted file mode 100644 index bfb2da9c4eee..000000000000 --- a/drivers/staging/erofs/include/trace/events/erofs.h +++ /dev/null @@ -1,256 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM erofs - -#if !defined(_TRACE_EROFS_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_EROFS_H - -#include - -#define show_dev(dev) MAJOR(dev), MINOR(dev) -#define show_dev_nid(entry) show_dev(entry->dev), entry->nid - -#define show_file_type(type) \ - __print_symbolic(type, \ - { 0, "FILE" }, \ - { 1, "DIR" }) - -#define show_map_flags(flags) __print_flags(flags, "|", \ - { EROFS_GET_BLOCKS_RAW, "RAW" }) - -#define show_mflags(flags) __print_flags(flags, "", \ - { EROFS_MAP_MAPPED, "M" }, \ - { EROFS_MAP_META, "I" }, \ - { EROFS_MAP_ZIPPED, "Z" }) - -TRACE_EVENT(erofs_lookup, - - TP_PROTO(struct inode *dir, struct dentry *dentry, unsigned int flags), - - TP_ARGS(dir, dentry, flags), - - TP_STRUCT__entry( - __field(dev_t, dev ) - __field(erofs_nid_t, nid ) - __field(const char *, name ) - __field(unsigned int, flags ) - ), - - TP_fast_assign( - __entry->dev = dir->i_sb->s_dev; - __entry->nid = EROFS_V(dir)->nid; - __entry->name = dentry->d_name.name; - __entry->flags = flags; - ), - - TP_printk("dev = (%d,%d), pnid = %llu, name:%s, flags:%x", - show_dev_nid(__entry), - __entry->name, - __entry->flags) -); - -TRACE_EVENT(erofs_fill_inode, - TP_PROTO(struct inode *inode, int isdir), - TP_ARGS(inode, isdir), - - TP_STRUCT__entry( - __field(dev_t, dev ) - __field(erofs_nid_t, nid ) - __field(erofs_blk_t, blkaddr ) - __field(unsigned int, ofs ) - __field(int, isdir ) - ), - - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; - __entry->blkaddr = erofs_blknr(iloc(EROFS_I_SB(inode), __entry->nid)); - __entry->ofs = erofs_blkoff(iloc(EROFS_I_SB(inode), __entry->nid)); - __entry->isdir = isdir; - ), - - TP_printk("dev = (%d,%d), nid = %llu, blkaddr %u ofs %u, isdir %d", - show_dev_nid(__entry), - __entry->blkaddr, __entry->ofs, - __entry->isdir) -); - -TRACE_EVENT(erofs_readpage, - - TP_PROTO(struct page *page, bool raw), - - TP_ARGS(page, raw), - - TP_STRUCT__entry( - __field(dev_t, dev ) - __field(erofs_nid_t, nid ) - __field(int, dir ) - __field(pgoff_t, index ) - __field(int, uptodate) - __field(bool, raw ) - ), - - TP_fast_assign( - __entry->dev = page->mapping->host->i_sb->s_dev; - __entry->nid = EROFS_V(page->mapping->host)->nid; - __entry->dir = S_ISDIR(page->mapping->host->i_mode); - __entry->index = page->index; - __entry->uptodate = PageUptodate(page); - __entry->raw = raw; - ), - - TP_printk("dev = (%d,%d), nid = %llu, %s, index = %lu, uptodate = %d " - "raw = %d", - show_dev_nid(__entry), - show_file_type(__entry->dir), - (unsigned long)__entry->index, - __entry->uptodate, - __entry->raw) -); - -TRACE_EVENT(erofs_readpages, - - TP_PROTO(struct inode *inode, struct page *page, unsigned int nrpage, - bool raw), - - TP_ARGS(inode, page, nrpage, raw), - - TP_STRUCT__entry( - __field(dev_t, dev ) - __field(erofs_nid_t, nid ) - __field(pgoff_t, start ) - __field(unsigned int, nrpage ) - __field(bool, raw ) - ), - - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; - __entry->start = page->index; - __entry->nrpage = nrpage; - __entry->raw = raw; - ), - - TP_printk("dev = (%d,%d), nid = %llu, start = %lu nrpage = %u raw = %d", - show_dev_nid(__entry), - (unsigned long)__entry->start, - __entry->nrpage, - __entry->raw) -); - -DECLARE_EVENT_CLASS(erofs__map_blocks_enter, - TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, - unsigned int flags), - - TP_ARGS(inode, map, flags), - - TP_STRUCT__entry( - __field( dev_t, dev ) - __field( erofs_nid_t, nid ) - __field( erofs_off_t, la ) - __field( u64, llen ) - __field( unsigned int, flags ) - ), - - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; - __entry->la = map->m_la; - __entry->llen = map->m_llen; - __entry->flags = flags; - ), - - TP_printk("dev = (%d,%d), nid = %llu, la %llu llen %llu flags %s", - show_dev_nid(__entry), - __entry->la, __entry->llen, - __entry->flags ? show_map_flags(__entry->flags) : "NULL") -); - -DEFINE_EVENT(erofs__map_blocks_enter, erofs_map_blocks_flatmode_enter, - TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, - unsigned flags), - - TP_ARGS(inode, map, flags) -); - -DEFINE_EVENT(erofs__map_blocks_enter, z_erofs_map_blocks_iter_enter, - TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, - unsigned int flags), - - TP_ARGS(inode, map, flags) -); - -DECLARE_EVENT_CLASS(erofs__map_blocks_exit, - TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, - unsigned int flags, int ret), - - TP_ARGS(inode, map, flags, ret), - - TP_STRUCT__entry( - __field( dev_t, dev ) - __field( erofs_nid_t, nid ) - __field( unsigned int, flags ) - __field( erofs_off_t, la ) - __field( erofs_off_t, pa ) - __field( u64, llen ) - __field( u64, plen ) - __field( unsigned int, mflags ) - __field( int, ret ) - ), - - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; - __entry->flags = flags; - __entry->la = map->m_la; - __entry->pa = map->m_pa; - __entry->llen = map->m_llen; - __entry->plen = map->m_plen; - __entry->mflags = map->m_flags; - __entry->ret = ret; - ), - - TP_printk("dev = (%d,%d), nid = %llu, flags %s " - "la %llu pa %llu llen %llu plen %llu mflags %s ret %d", - show_dev_nid(__entry), - __entry->flags ? show_map_flags(__entry->flags) : "NULL", - __entry->la, __entry->pa, __entry->llen, __entry->plen, - show_mflags(__entry->mflags), __entry->ret) -); - -DEFINE_EVENT(erofs__map_blocks_exit, erofs_map_blocks_flatmode_exit, - TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, - unsigned flags, int ret), - - TP_ARGS(inode, map, flags, ret) -); - -DEFINE_EVENT(erofs__map_blocks_exit, z_erofs_map_blocks_iter_exit, - TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, - unsigned int flags, int ret), - - TP_ARGS(inode, map, flags, ret) -); - -TRACE_EVENT(erofs_destroy_inode, - TP_PROTO(struct inode *inode), - - TP_ARGS(inode), - - TP_STRUCT__entry( - __field( dev_t, dev ) - __field( erofs_nid_t, nid ) - ), - - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->nid = EROFS_V(inode)->nid; - ), - - TP_printk("dev = (%d,%d), nid = %llu", show_dev_nid(__entry)) -); - -#endif /* _TRACE_EROFS_H */ - - /* This part must be outside protection */ -#include diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c deleted file mode 100644 index cbc2c342a37f..000000000000 --- a/drivers/staging/erofs/inode.c +++ /dev/null @@ -1,334 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/inode.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "xattr.h" - -#include - -/* no locking */ -static int read_inode(struct inode *inode, void *data) -{ - struct erofs_vnode *vi = EROFS_V(inode); - struct erofs_inode_v1 *v1 = data; - const unsigned int advise = le16_to_cpu(v1->i_advise); - erofs_blk_t nblks = 0; - - vi->datamode = __inode_data_mapping(advise); - - if (unlikely(vi->datamode >= EROFS_INODE_LAYOUT_MAX)) { - errln("unsupported data mapping %u of nid %llu", - vi->datamode, vi->nid); - DBG_BUGON(1); - return -EOPNOTSUPP; - } - - if (__inode_version(advise) == EROFS_INODE_LAYOUT_V2) { - struct erofs_inode_v2 *v2 = data; - - vi->inode_isize = sizeof(struct erofs_inode_v2); - vi->xattr_isize = ondisk_xattr_ibody_size(v2->i_xattr_icount); - - inode->i_mode = le16_to_cpu(v2->i_mode); - if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) - vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); - else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - inode->i_rdev = - new_decode_dev(le32_to_cpu(v2->i_u.rdev)); - else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) - inode->i_rdev = 0; - else - goto bogusimode; - - i_uid_write(inode, le32_to_cpu(v2->i_uid)); - i_gid_write(inode, le32_to_cpu(v2->i_gid)); - set_nlink(inode, le32_to_cpu(v2->i_nlink)); - - /* ns timestamp */ - inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = - le64_to_cpu(v2->i_ctime); - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = - le32_to_cpu(v2->i_ctime_nsec); - - inode->i_size = le64_to_cpu(v2->i_size); - - /* total blocks for compressed files */ - if (is_inode_layout_compression(inode)) - nblks = le32_to_cpu(v2->i_u.compressed_blocks); - } else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) { - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - - vi->inode_isize = sizeof(struct erofs_inode_v1); - vi->xattr_isize = ondisk_xattr_ibody_size(v1->i_xattr_icount); - - inode->i_mode = le16_to_cpu(v1->i_mode); - if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode)) - vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); - else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - inode->i_rdev = - new_decode_dev(le32_to_cpu(v1->i_u.rdev)); - else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) - inode->i_rdev = 0; - else - goto bogusimode; - - i_uid_write(inode, le16_to_cpu(v1->i_uid)); - i_gid_write(inode, le16_to_cpu(v1->i_gid)); - set_nlink(inode, le16_to_cpu(v1->i_nlink)); - - /* use build time to derive all file time */ - inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = - sbi->build_time; - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = - sbi->build_time_nsec; - - inode->i_size = le32_to_cpu(v1->i_size); - if (is_inode_layout_compression(inode)) - nblks = le32_to_cpu(v1->i_u.compressed_blocks); - } else { - errln("unsupported on-disk inode version %u of nid %llu", - __inode_version(advise), vi->nid); - DBG_BUGON(1); - return -EOPNOTSUPP; - } - - if (!nblks) - /* measure inode.i_blocks as generic filesystems */ - inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; - else - inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; - return 0; - -bogusimode: - errln("bogus i_mode (%o) @ nid %llu", inode->i_mode, vi->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; -} - -/* - * try_lock can be required since locking order is: - * file data(fs_inode) - * meta(bd_inode) - * but the majority of the callers is "iget", - * in that case we are pretty sure no deadlock since - * no data operations exist. However I tend to - * try_lock since it takes no much overhead and - * will success immediately. - */ -static int fill_inline_data(struct inode *inode, void *data, - unsigned int m_pofs) -{ - struct erofs_vnode *vi = EROFS_V(inode); - struct erofs_sb_info *sbi = EROFS_I_SB(inode); - - /* should be inode inline C */ - if (!is_inode_flat_inline(inode)) - return 0; - - /* fast symlink (following ext4) */ - if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) { - char *lnk = erofs_kmalloc(sbi, inode->i_size + 1, GFP_KERNEL); - - if (unlikely(!lnk)) - return -ENOMEM; - - m_pofs += vi->inode_isize + vi->xattr_isize; - - /* inline symlink data shouldn't across page boundary as well */ - if (unlikely(m_pofs + inode->i_size > PAGE_SIZE)) { - kfree(lnk); - errln("inline data cross block boundary @ nid %llu", - vi->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; - } - - /* get in-page inline data */ - memcpy(lnk, data + m_pofs, inode->i_size); - lnk[inode->i_size] = '\0'; - - inode->i_link = lnk; - set_inode_fast_symlink(inode); - } - return 0; -} - -static int fill_inode(struct inode *inode, int isdir) -{ - struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); - struct erofs_vnode *vi = EROFS_V(inode); - struct page *page; - void *data; - int err; - erofs_blk_t blkaddr; - unsigned int ofs; - erofs_off_t inode_loc; - - trace_erofs_fill_inode(inode, isdir); - inode_loc = iloc(sbi, vi->nid); - blkaddr = erofs_blknr(inode_loc); - ofs = erofs_blkoff(inode_loc); - - debugln("%s, reading inode nid %llu at %u of blkaddr %u", - __func__, vi->nid, ofs, blkaddr); - - page = erofs_get_meta_page(inode->i_sb, blkaddr, isdir); - - if (IS_ERR(page)) { - errln("failed to get inode (nid: %llu) page, err %ld", - vi->nid, PTR_ERR(page)); - return PTR_ERR(page); - } - - DBG_BUGON(!PageUptodate(page)); - data = page_address(page); - - err = read_inode(inode, data + ofs); - if (!err) { - /* setup the new inode */ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &erofs_generic_iops; - inode->i_fop = &generic_ro_fops; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &erofs_dir_iops; - inode->i_fop = &erofs_dir_fops; - } else if (S_ISLNK(inode->i_mode)) { - /* by default, page_get_link is used for symlink */ - inode->i_op = &erofs_symlink_iops; - inode_nohighmem(inode); - } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || - S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - inode->i_op = &erofs_generic_iops; - init_special_inode(inode, inode->i_mode, inode->i_rdev); - goto out_unlock; - } else { - err = -EFSCORRUPTED; - goto out_unlock; - } - - if (is_inode_layout_compression(inode)) { - err = z_erofs_fill_inode(inode); - goto out_unlock; - } - - inode->i_mapping->a_ops = &erofs_raw_access_aops; - - /* fill last page if inline data is available */ - err = fill_inline_data(inode, data, ofs); - } - -out_unlock: - unlock_page(page); - put_page(page); - return err; -} - -/* - * erofs nid is 64bits, but i_ino is 'unsigned long', therefore - * we should do more for 32-bit platform to find the right inode. - */ -#if BITS_PER_LONG == 32 -static int erofs_ilookup_test_actor(struct inode *inode, void *opaque) -{ - const erofs_nid_t nid = *(erofs_nid_t *)opaque; - - return EROFS_V(inode)->nid == nid; -} - -static int erofs_iget_set_actor(struct inode *inode, void *opaque) -{ - const erofs_nid_t nid = *(erofs_nid_t *)opaque; - - inode->i_ino = erofs_inode_hash(nid); - return 0; -} -#endif - -static inline struct inode *erofs_iget_locked(struct super_block *sb, - erofs_nid_t nid) -{ - const unsigned long hashval = erofs_inode_hash(nid); - -#if BITS_PER_LONG >= 64 - /* it is safe to use iget_locked for >= 64-bit platform */ - return iget_locked(sb, hashval); -#else - return iget5_locked(sb, hashval, erofs_ilookup_test_actor, - erofs_iget_set_actor, &nid); -#endif -} - -struct inode *erofs_iget(struct super_block *sb, - erofs_nid_t nid, - bool isdir) -{ - struct inode *inode = erofs_iget_locked(sb, nid); - - if (unlikely(!inode)) - return ERR_PTR(-ENOMEM); - - if (inode->i_state & I_NEW) { - int err; - struct erofs_vnode *vi = EROFS_V(inode); - - vi->nid = nid; - - err = fill_inode(inode, isdir); - if (likely(!err)) - unlock_new_inode(inode); - else { - iget_failed(inode); - inode = ERR_PTR(err); - } - } - return inode; -} - -int erofs_getattr(const struct path *path, struct kstat *stat, - u32 request_mask, unsigned int query_flags) -{ - struct inode *const inode = d_inode(path->dentry); - - if (is_inode_layout_compression(inode)) - stat->attributes |= STATX_ATTR_COMPRESSED; - - stat->attributes |= STATX_ATTR_IMMUTABLE; - stat->attributes_mask |= (STATX_ATTR_COMPRESSED | - STATX_ATTR_IMMUTABLE); - - generic_fillattr(inode, stat); - return 0; -} - -const struct inode_operations erofs_generic_iops = { - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - -const struct inode_operations erofs_symlink_iops = { - .get_link = page_get_link, - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - -const struct inode_operations erofs_fast_symlink_iops = { - .get_link = simple_get_link, - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h deleted file mode 100644 index 0e8d58546c52..000000000000 --- a/drivers/staging/erofs/internal.h +++ /dev/null @@ -1,554 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/internal.h - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_INTERNAL_H -#define __EROFS_INTERNAL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include "erofs_fs.h" - -/* redefine pr_fmt "erofs: " */ -#undef pr_fmt -#define pr_fmt(fmt) "erofs: " fmt - -#define errln(x, ...) pr_err(x "\n", ##__VA_ARGS__) -#define infoln(x, ...) pr_info(x "\n", ##__VA_ARGS__) -#ifdef CONFIG_EROFS_FS_DEBUG -#define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__) -#define DBG_BUGON BUG_ON -#else -#define debugln(x, ...) ((void)0) -#define DBG_BUGON(x) ((void)(x)) -#endif /* !CONFIG_EROFS_FS_DEBUG */ - -enum { - FAULT_KMALLOC, - FAULT_READ_IO, - FAULT_MAX, -}; - -#ifdef CONFIG_EROFS_FAULT_INJECTION -extern const char *erofs_fault_name[FAULT_MAX]; -#define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type))) - -struct erofs_fault_info { - atomic_t inject_ops; - unsigned int inject_rate; - unsigned int inject_type; -}; -#endif /* CONFIG_EROFS_FAULT_INJECTION */ - -/* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ -#define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 - -typedef u64 erofs_nid_t; -typedef u64 erofs_off_t; -/* data type for filesystem-wide blocks number */ -typedef u32 erofs_blk_t; - -struct erofs_sb_info { -#ifdef CONFIG_EROFS_FS_ZIP - /* list for all registered superblocks, mainly for shrinker */ - struct list_head list; - struct mutex umount_mutex; - - /* the dedicated workstation for compression */ - struct radix_tree_root workstn_tree; - - /* threshold for decompression synchronously */ - unsigned int max_sync_decompress_pages; - - unsigned int shrinker_run_no; - - /* current strategy of how to use managed cache */ - unsigned char cache_strategy; - - /* pseudo inode to manage cached pages */ - struct inode *managed_cache; -#endif /* CONFIG_EROFS_FS_ZIP */ - u32 blocks; - u32 meta_blkaddr; -#ifdef CONFIG_EROFS_FS_XATTR - u32 xattr_blkaddr; -#endif - - /* inode slot unit size in bit shift */ - unsigned char islotbits; - - u32 build_time_nsec; - u64 build_time; - - /* what we really care is nid, rather than ino.. */ - erofs_nid_t root_nid; - /* used for statfs, f_files - f_favail */ - u64 inos; - - u8 uuid[16]; /* 128-bit uuid for volume */ - u8 volume_name[16]; /* volume name */ - u32 requirements; - - unsigned int mount_opt; - -#ifdef CONFIG_EROFS_FAULT_INJECTION - struct erofs_fault_info fault_info; /* For fault injection */ -#endif -}; - -#ifdef CONFIG_EROFS_FAULT_INJECTION -#define erofs_show_injection_info(type) \ - infoln("inject %s in %s of %pS", erofs_fault_name[type], \ - __func__, __builtin_return_address(0)) - -static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) -{ - struct erofs_fault_info *ffi = &sbi->fault_info; - - if (!ffi->inject_rate) - return false; - - if (!IS_FAULT_SET(ffi, type)) - return false; - - atomic_inc(&ffi->inject_ops); - if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) { - atomic_set(&ffi->inject_ops, 0); - return true; - } - return false; -} -#else -static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) -{ - return false; -} - -static inline void erofs_show_injection_info(int type) -{ -} -#endif /* !CONFIG_EROFS_FAULT_INJECTION */ - -static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, - size_t size, gfp_t flags) -{ - if (time_to_inject(sbi, FAULT_KMALLOC)) { - erofs_show_injection_info(FAULT_KMALLOC); - return NULL; - } - return kmalloc(size, flags); -} - -#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) -#define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info) - -/* Mount flags set via mount options or defaults */ -#define EROFS_MOUNT_XATTR_USER 0x00000010 -#define EROFS_MOUNT_POSIX_ACL 0x00000020 -#define EROFS_MOUNT_FAULT_INJECTION 0x00000040 - -#define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) -#define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) -#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) - -#ifdef CONFIG_EROFS_FS_ZIP -enum { - EROFS_ZIP_CACHE_DISABLED, - EROFS_ZIP_CACHE_READAHEAD, - EROFS_ZIP_CACHE_READAROUND -}; - -#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) - -/* basic unit of the workstation of a super_block */ -struct erofs_workgroup { - /* the workgroup index in the workstation */ - pgoff_t index; - - /* overall workgroup reference count */ - atomic_t refcount; -}; - -#if defined(CONFIG_SMP) -static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, - int val) -{ - preempt_disable(); - if (val != atomic_cmpxchg(&grp->refcount, val, EROFS_LOCKED_MAGIC)) { - preempt_enable(); - return false; - } - return true; -} - -static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp, - int orig_val) -{ - /* - * other observers should notice all modifications - * in the freezing period. - */ - smp_mb(); - atomic_set(&grp->refcount, orig_val); - preempt_enable(); -} - -static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) -{ - return atomic_cond_read_relaxed(&grp->refcount, - VAL != EROFS_LOCKED_MAGIC); -} -#else -static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, - int val) -{ - preempt_disable(); - /* no need to spin on UP platforms, let's just disable preemption. */ - if (val != atomic_read(&grp->refcount)) { - preempt_enable(); - return false; - } - return true; -} - -static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp, - int orig_val) -{ - preempt_enable(); -} - -static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) -{ - int v = atomic_read(&grp->refcount); - - /* workgroup is never freezed on uniprocessor systems */ - DBG_BUGON(v == EROFS_LOCKED_MAGIC); - return v; -} -#endif /* !CONFIG_SMP */ - -/* hard limit of pages per compressed cluster */ -#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) -#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES -#else -#define EROFS_PCPUBUF_NR_PAGES 0 -#endif /* !CONFIG_EROFS_FS_ZIP */ - -/* we strictly follow PAGE_SIZE and no buffer head yet */ -#define LOG_BLOCK_SIZE PAGE_SHIFT - -#undef LOG_SECTORS_PER_BLOCK -#define LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) - -#undef SECTORS_PER_BLOCK -#define SECTORS_PER_BLOCK (1 << SECTORS_PER_BLOCK) - -#define EROFS_BLKSIZ (1 << LOG_BLOCK_SIZE) - -#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ) -#error erofs cannot be used in this platform -#endif - -#define EROFS_IO_MAX_RETRIES_NOFAIL 5 - -#define ROOT_NID(sb) ((sb)->root_nid) - -#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) -#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) -#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) - -static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) -{ - return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits); -} - -/* atomic flag definitions */ -#define EROFS_V_EA_INITED_BIT 0 -#define EROFS_V_Z_INITED_BIT 1 - -/* bitlock definitions (arranged in reverse order) */ -#define EROFS_V_BL_XATTR_BIT (BITS_PER_LONG - 1) -#define EROFS_V_BL_Z_BIT (BITS_PER_LONG - 2) - -struct erofs_vnode { - erofs_nid_t nid; - - /* atomic flags (including bitlocks) */ - unsigned long flags; - - unsigned char datamode; - unsigned char inode_isize; - unsigned short xattr_isize; - - unsigned int xattr_shared_count; - unsigned int *xattr_shared_xattrs; - - union { - erofs_blk_t raw_blkaddr; -#ifdef CONFIG_EROFS_FS_ZIP - struct { - unsigned short z_advise; - unsigned char z_algorithmtype[2]; - unsigned char z_logical_clusterbits; - unsigned char z_physical_clusterbits[2]; - }; -#endif /* CONFIG_EROFS_FS_ZIP */ - }; - /* the corresponding vfs inode */ - struct inode vfs_inode; -}; - -#define EROFS_V(ptr) \ - container_of(ptr, struct erofs_vnode, vfs_inode) - -#define __inode_advise(x, bit, bits) \ - (((x) >> (bit)) & ((1 << (bits)) - 1)) - -#define __inode_version(advise) \ - __inode_advise(advise, EROFS_I_VERSION_BIT, \ - EROFS_I_VERSION_BITS) - -#define __inode_data_mapping(advise) \ - __inode_advise(advise, EROFS_I_DATA_MAPPING_BIT,\ - EROFS_I_DATA_MAPPING_BITS) - -static inline unsigned long inode_datablocks(struct inode *inode) -{ - /* since i_size cannot be changed */ - return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); -} - -static inline bool is_inode_layout_compression(struct inode *inode) -{ - return erofs_inode_is_data_compressed(EROFS_V(inode)->datamode); -} - -static inline bool is_inode_flat_inline(struct inode *inode) -{ - return EROFS_V(inode)->datamode == EROFS_INODE_FLAT_INLINE; -} - -extern const struct super_operations erofs_sops; - -extern const struct address_space_operations erofs_raw_access_aops; -#ifdef CONFIG_EROFS_FS_ZIP -extern const struct address_space_operations z_erofs_vle_normalaccess_aops; -#endif - -/* - * Logical to physical block mapping, used by erofs_map_blocks() - * - * Different with other file systems, it is used for 2 access modes: - * - * 1) RAW access mode: - * - * Users pass a valid (m_lblk, m_lofs -- usually 0) pair, - * and get the valid m_pblk, m_pofs and the longest m_len(in bytes). - * - * Note that m_lblk in the RAW access mode refers to the number of - * the compressed ondisk block rather than the uncompressed - * in-memory block for the compressed file. - * - * m_pofs equals to m_lofs except for the inline data page. - * - * 2) Normal access mode: - * - * If the inode is not compressed, it has no difference with - * the RAW access mode. However, if the inode is compressed, - * users should pass a valid (m_lblk, m_lofs) pair, and get - * the needed m_pblk, m_pofs, m_len to get the compressed data - * and the updated m_lblk, m_lofs which indicates the start - * of the corresponding uncompressed data in the file. - */ -enum { - BH_Zipped = BH_PrivateStart, - BH_FullMapped, -}; - -/* Has a disk mapping */ -#define EROFS_MAP_MAPPED (1 << BH_Mapped) -/* Located in metadata (could be copied from bd_inode) */ -#define EROFS_MAP_META (1 << BH_Meta) -/* The extent has been compressed */ -#define EROFS_MAP_ZIPPED (1 << BH_Zipped) -/* The length of extent is full */ -#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped) - -struct erofs_map_blocks { - erofs_off_t m_pa, m_la; - u64 m_plen, m_llen; - - unsigned int m_flags; - - struct page *mpage; -}; - -/* Flags used by erofs_map_blocks() */ -#define EROFS_GET_BLOCKS_RAW 0x0001 - -/* zmap.c */ -#ifdef CONFIG_EROFS_FS_ZIP -int z_erofs_fill_inode(struct inode *inode); -int z_erofs_map_blocks_iter(struct inode *inode, - struct erofs_map_blocks *map, - int flags); -#else -static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; } -static inline int z_erofs_map_blocks_iter(struct inode *inode, - struct erofs_map_blocks *map, - int flags) -{ - return -EOPNOTSUPP; -} -#endif /* !CONFIG_EROFS_FS_ZIP */ - -/* data.c */ -static inline struct bio *erofs_grab_bio(struct super_block *sb, - erofs_blk_t blkaddr, - unsigned int nr_pages, - void *bi_private, bio_end_io_t endio, - bool nofail) -{ - const gfp_t gfp = GFP_NOIO; - struct bio *bio; - - do { - if (nr_pages == 1) { - bio = bio_alloc(gfp | (nofail ? __GFP_NOFAIL : 0), 1); - if (unlikely(!bio)) { - DBG_BUGON(nofail); - return ERR_PTR(-ENOMEM); - } - break; - } - bio = bio_alloc(gfp, nr_pages); - nr_pages /= 2; - } while (unlikely(!bio)); - - bio->bi_end_io = endio; - bio_set_dev(bio, sb->s_bdev); - bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK; - bio->bi_private = bi_private; - return bio; -} - -static inline void __submit_bio(struct bio *bio, unsigned int op, - unsigned int op_flags) -{ - bio_set_op_attrs(bio, op, op_flags); - submit_bio(bio); -} - -struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, - bool prio, bool nofail); - -static inline struct page *erofs_get_meta_page(struct super_block *sb, - erofs_blk_t blkaddr, bool prio) -{ - return __erofs_get_meta_page(sb, blkaddr, prio, false); -} - -int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); - -static inline struct page *erofs_get_inline_page(struct inode *inode, - erofs_blk_t blkaddr) -{ - return erofs_get_meta_page(inode->i_sb, blkaddr, - S_ISDIR(inode->i_mode)); -} - -/* inode.c */ -static inline unsigned long erofs_inode_hash(erofs_nid_t nid) -{ -#if BITS_PER_LONG == 32 - return (nid >> 32) ^ (nid & 0xffffffff); -#else - return nid; -#endif -} - -extern const struct inode_operations erofs_generic_iops; -extern const struct inode_operations erofs_symlink_iops; -extern const struct inode_operations erofs_fast_symlink_iops; - -static inline void set_inode_fast_symlink(struct inode *inode) -{ - inode->i_op = &erofs_fast_symlink_iops; -} - -static inline bool is_inode_fast_symlink(struct inode *inode) -{ - return inode->i_op == &erofs_fast_symlink_iops; -} - -struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir); -int erofs_getattr(const struct path *path, struct kstat *stat, - u32 request_mask, unsigned int query_flags); - -/* namei.c */ -extern const struct inode_operations erofs_dir_iops; - -int erofs_namei(struct inode *dir, struct qstr *name, - erofs_nid_t *nid, unsigned int *d_type); - -/* dir.c */ -extern const struct file_operations erofs_dir_fops; - -/* utils.c / zdata.c */ -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); - -#if (EROFS_PCPUBUF_NR_PAGES > 0) -void *erofs_get_pcpubuf(unsigned int pagenr); -#define erofs_put_pcpubuf(buf) do { \ - (void)&(buf); \ - preempt_enable(); \ -} while (0) -#else -static inline void *erofs_get_pcpubuf(unsigned int pagenr) -{ - return ERR_PTR(-EOPNOTSUPP); -} - -#define erofs_put_pcpubuf(buf) do {} while (0) -#endif - -#ifdef CONFIG_EROFS_FS_ZIP -int erofs_workgroup_put(struct erofs_workgroup *grp); -struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag); -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, bool tag); -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); -void erofs_shrinker_register(struct super_block *sb); -void erofs_shrinker_unregister(struct super_block *sb); -int __init erofs_init_shrinker(void); -void erofs_exit_shrinker(void); -int __init z_erofs_init_zip_subsystem(void); -void z_erofs_exit_zip_subsystem(void); -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *egrp); -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page); -#else -static inline void erofs_shrinker_register(struct super_block *sb) {} -static inline void erofs_shrinker_unregister(struct super_block *sb) {} -static inline int erofs_init_shrinker(void) { return 0; } -static inline void erofs_exit_shrinker(void) {} -static inline int z_erofs_init_zip_subsystem(void) { return 0; } -static inline void z_erofs_exit_zip_subsystem(void) {} -#endif /* !CONFIG_EROFS_FS_ZIP */ - -#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ - -#endif /* __EROFS_INTERNAL_H */ - diff --git a/drivers/staging/erofs/namei.c b/drivers/staging/erofs/namei.c deleted file mode 100644 index 8334a910acef..000000000000 --- a/drivers/staging/erofs/namei.c +++ /dev/null @@ -1,253 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/namei.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "xattr.h" - -#include - -struct erofs_qstr { - const unsigned char *name; - const unsigned char *end; -}; - -/* based on the end of qn is accurate and it must have the trailing '\0' */ -static inline int dirnamecmp(const struct erofs_qstr *qn, - const struct erofs_qstr *qd, - unsigned int *matched) -{ - unsigned int i = *matched; - - /* - * on-disk error, let's only BUG_ON in the debugging mode. - * otherwise, it will return 1 to just skip the invalid name - * and go on (in consideration of the lookup performance). - */ - DBG_BUGON(qd->name > qd->end); - - /* qd could not have trailing '\0' */ - /* However it is absolutely safe if < qd->end */ - while (qd->name + i < qd->end && qd->name[i] != '\0') { - if (qn->name[i] != qd->name[i]) { - *matched = i; - return qn->name[i] > qd->name[i] ? 1 : -1; - } - ++i; - } - *matched = i; - /* See comments in __d_alloc on the terminating NUL character */ - return qn->name[i] == '\0' ? 0 : 1; -} - -#define nameoff_from_disk(off, sz) (le16_to_cpu(off) & ((sz) - 1)) - -static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name, - u8 *data, - unsigned int dirblksize, - const int ndirents) -{ - int head, back; - unsigned int startprfx, endprfx; - struct erofs_dirent *const de = (struct erofs_dirent *)data; - - /* since the 1st dirent has been evaluated previously */ - head = 1; - back = ndirents - 1; - startprfx = endprfx = 0; - - while (head <= back) { - const int mid = head + (back - head) / 2; - const int nameoff = nameoff_from_disk(de[mid].nameoff, - dirblksize); - unsigned int matched = min(startprfx, endprfx); - struct erofs_qstr dname = { - .name = data + nameoff, - .end = unlikely(mid >= ndirents - 1) ? - data + dirblksize : - data + nameoff_from_disk(de[mid + 1].nameoff, - dirblksize) - }; - - /* string comparison without already matched prefix */ - int ret = dirnamecmp(name, &dname, &matched); - - if (unlikely(!ret)) { - return de + mid; - } else if (ret > 0) { - head = mid + 1; - startprfx = matched; - } else { - back = mid - 1; - endprfx = matched; - } - } - - return ERR_PTR(-ENOENT); -} - -static struct page *find_target_block_classic(struct inode *dir, - struct erofs_qstr *name, - int *_ndirents) -{ - unsigned int startprfx, endprfx; - int head, back; - struct address_space *const mapping = dir->i_mapping; - struct page *candidate = ERR_PTR(-ENOENT); - - startprfx = endprfx = 0; - head = 0; - back = inode_datablocks(dir) - 1; - - while (head <= back) { - const int mid = head + (back - head) / 2; - struct page *page = read_mapping_page(mapping, mid, NULL); - - if (!IS_ERR(page)) { - struct erofs_dirent *de = kmap_atomic(page); - const int nameoff = nameoff_from_disk(de->nameoff, - EROFS_BLKSIZ); - const int ndirents = nameoff / sizeof(*de); - int diff; - unsigned int matched; - struct erofs_qstr dname; - - if (unlikely(!ndirents)) { - kunmap_atomic(de); - put_page(page); - errln("corrupted dir block %d @ nid %llu", - mid, EROFS_V(dir)->nid); - DBG_BUGON(1); - page = ERR_PTR(-EFSCORRUPTED); - goto out; - } - - matched = min(startprfx, endprfx); - - dname.name = (u8 *)de + nameoff; - if (ndirents == 1) - dname.end = (u8 *)de + EROFS_BLKSIZ; - else - dname.end = (u8 *)de + - nameoff_from_disk(de[1].nameoff, - EROFS_BLKSIZ); - - /* string comparison without already matched prefix */ - diff = dirnamecmp(name, &dname, &matched); - kunmap_atomic(de); - - if (unlikely(!diff)) { - *_ndirents = 0; - goto out; - } else if (diff > 0) { - head = mid + 1; - startprfx = matched; - - if (!IS_ERR(candidate)) - put_page(candidate); - candidate = page; - *_ndirents = ndirents; - } else { - put_page(page); - - back = mid - 1; - endprfx = matched; - } - continue; - } -out: /* free if the candidate is valid */ - if (!IS_ERR(candidate)) - put_page(candidate); - return page; - } - return candidate; -} - -int erofs_namei(struct inode *dir, - struct qstr *name, - erofs_nid_t *nid, unsigned int *d_type) -{ - int ndirents; - struct page *page; - void *data; - struct erofs_dirent *de; - struct erofs_qstr qn; - - if (unlikely(!dir->i_size)) - return -ENOENT; - - qn.name = name->name; - qn.end = name->name + name->len; - - ndirents = 0; - page = find_target_block_classic(dir, &qn, &ndirents); - - if (IS_ERR(page)) - return PTR_ERR(page); - - data = kmap_atomic(page); - /* the target page has been mapped */ - if (ndirents) - de = find_target_dirent(&qn, data, EROFS_BLKSIZ, ndirents); - else - de = (struct erofs_dirent *)data; - - if (!IS_ERR(de)) { - *nid = le64_to_cpu(de->nid); - *d_type = de->file_type; - } - - kunmap_atomic(data); - put_page(page); - - return PTR_ERR_OR_ZERO(de); -} - -/* NOTE: i_mutex is already held by vfs */ -static struct dentry *erofs_lookup(struct inode *dir, - struct dentry *dentry, - unsigned int flags) -{ - int err; - erofs_nid_t nid; - unsigned int d_type; - struct inode *inode; - - DBG_BUGON(!d_really_is_negative(dentry)); - /* dentry must be unhashed in lookup, no need to worry about */ - DBG_BUGON(!d_unhashed(dentry)); - - trace_erofs_lookup(dir, dentry, flags); - - /* file name exceeds fs limit */ - if (unlikely(dentry->d_name.len > EROFS_NAME_LEN)) - return ERR_PTR(-ENAMETOOLONG); - - /* false uninitialized warnings on gcc 4.8.x */ - err = erofs_namei(dir, &dentry->d_name, &nid, &d_type); - - if (err == -ENOENT) { - /* negative dentry */ - inode = NULL; - } else if (unlikely(err)) { - inode = ERR_PTR(err); - } else { - debugln("%s, %s (nid %llu) found, d_type %u", __func__, - dentry->d_name.name, nid, d_type); - inode = erofs_iget(dir->i_sb, nid, d_type == FT_DIR); - } - return d_splice_alias(inode, dentry); -} - -const struct inode_operations erofs_dir_iops = { - .lookup = erofs_lookup, - .getattr = erofs_getattr, -#ifdef CONFIG_EROFS_FS_XATTR - .listxattr = erofs_listxattr, -#endif - .get_acl = erofs_get_acl, -}; - diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c deleted file mode 100644 index 2da471010a86..000000000000 --- a/drivers/staging/erofs/super.c +++ /dev/null @@ -1,671 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/super.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include -#include -#include -#include -#include -#include "xattr.h" - -#define CREATE_TRACE_POINTS -#include - -static struct kmem_cache *erofs_inode_cachep __read_mostly; - -static void init_once(void *ptr) -{ - struct erofs_vnode *vi = ptr; - - inode_init_once(&vi->vfs_inode); -} - -static int __init erofs_init_inode_cache(void) -{ - erofs_inode_cachep = kmem_cache_create("erofs_inode", - sizeof(struct erofs_vnode), 0, - SLAB_RECLAIM_ACCOUNT, - init_once); - - return erofs_inode_cachep ? 0 : -ENOMEM; -} - -static void erofs_exit_inode_cache(void) -{ - kmem_cache_destroy(erofs_inode_cachep); -} - -static struct inode *alloc_inode(struct super_block *sb) -{ - struct erofs_vnode *vi = - kmem_cache_alloc(erofs_inode_cachep, GFP_KERNEL); - - if (!vi) - return NULL; - - /* zero out everything except vfs_inode */ - memset(vi, 0, offsetof(struct erofs_vnode, vfs_inode)); - return &vi->vfs_inode; -} - -static void free_inode(struct inode *inode) -{ - struct erofs_vnode *vi = EROFS_V(inode); - - /* be careful RCU symlink path (see ext4_inode_info->i_data)! */ - if (is_inode_fast_symlink(inode)) - kfree(inode->i_link); - - kfree(vi->xattr_shared_xattrs); - - kmem_cache_free(erofs_inode_cachep, vi); -} - -static bool check_layout_compatibility(struct super_block *sb, - struct erofs_super_block *layout) -{ - const unsigned int requirements = le32_to_cpu(layout->requirements); - - EROFS_SB(sb)->requirements = requirements; - - /* check if current kernel meets all mandatory requirements */ - if (requirements & (~EROFS_ALL_REQUIREMENTS)) { - errln("unidentified requirements %x, please upgrade kernel version", - requirements & ~EROFS_ALL_REQUIREMENTS); - return false; - } - return true; -} - -static int superblock_read(struct super_block *sb) -{ - struct erofs_sb_info *sbi; - struct buffer_head *bh; - struct erofs_super_block *layout; - unsigned int blkszbits; - int ret; - - bh = sb_bread(sb, 0); - - if (!bh) { - errln("cannot read erofs superblock"); - return -EIO; - } - - sbi = EROFS_SB(sb); - layout = (struct erofs_super_block *)((u8 *)bh->b_data - + EROFS_SUPER_OFFSET); - - ret = -EINVAL; - if (le32_to_cpu(layout->magic) != EROFS_SUPER_MAGIC_V1) { - errln("cannot find valid erofs superblock"); - goto out; - } - - blkszbits = layout->blkszbits; - /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ - if (unlikely(blkszbits != LOG_BLOCK_SIZE)) { - errln("blksize %u isn't supported on this platform", - 1 << blkszbits); - goto out; - } - - if (!check_layout_compatibility(sb, layout)) - goto out; - - sbi->blocks = le32_to_cpu(layout->blocks); - sbi->meta_blkaddr = le32_to_cpu(layout->meta_blkaddr); -#ifdef CONFIG_EROFS_FS_XATTR - sbi->xattr_blkaddr = le32_to_cpu(layout->xattr_blkaddr); -#endif - sbi->islotbits = ffs(sizeof(struct erofs_inode_v1)) - 1; - sbi->root_nid = le16_to_cpu(layout->root_nid); - sbi->inos = le64_to_cpu(layout->inos); - - sbi->build_time = le64_to_cpu(layout->build_time); - sbi->build_time_nsec = le32_to_cpu(layout->build_time_nsec); - - memcpy(&sb->s_uuid, layout->uuid, sizeof(layout->uuid)); - - ret = strscpy(sbi->volume_name, layout->volume_name, - sizeof(layout->volume_name)); - if (ret < 0) { /* -E2BIG */ - errln("bad volume name without NIL terminator"); - ret = -EFSCORRUPTED; - goto out; - } - ret = 0; -out: - brelse(bh); - return ret; -} - -#ifdef CONFIG_EROFS_FAULT_INJECTION -const char *erofs_fault_name[FAULT_MAX] = { - [FAULT_KMALLOC] = "kmalloc", - [FAULT_READ_IO] = "read IO error", -}; - -static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, - unsigned int rate) -{ - struct erofs_fault_info *ffi = &sbi->fault_info; - - if (rate) { - atomic_set(&ffi->inject_ops, 0); - ffi->inject_rate = rate; - ffi->inject_type = (1 << FAULT_MAX) - 1; - } else { - memset(ffi, 0, sizeof(struct erofs_fault_info)); - } - - set_opt(sbi, FAULT_INJECTION); -} - -static int erofs_build_fault_attr(struct erofs_sb_info *sbi, - substring_t *args) -{ - int rate = 0; - - if (args->from && match_int(args, &rate)) - return -EINVAL; - - __erofs_build_fault_attr(sbi, rate); - return 0; -} - -static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) -{ - return sbi->fault_info.inject_rate; -} -#else -static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, - unsigned int rate) -{ -} - -static int erofs_build_fault_attr(struct erofs_sb_info *sbi, - substring_t *args) -{ - infoln("fault_injection options not supported"); - return 0; -} - -static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) -{ - return 0; -} -#endif - -#ifdef CONFIG_EROFS_FS_ZIP -static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, - substring_t *args) -{ - const char *cs = match_strdup(args); - int err = 0; - - if (!cs) { - errln("Not enough memory to store cache strategy"); - return -ENOMEM; - } - - if (!strcmp(cs, "disabled")) { - sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; - } else if (!strcmp(cs, "readahead")) { - sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; - } else if (!strcmp(cs, "readaround")) { - sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; - } else { - errln("Unrecognized cache strategy \"%s\"", cs); - err = -EINVAL; - } - kfree(cs); - return err; -} -#else -static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, - substring_t *args) -{ - infoln("EROFS compression is disabled, so cache strategy is ignored"); - return 0; -} -#endif - -/* set up default EROFS parameters */ -static void default_options(struct erofs_sb_info *sbi) -{ -#ifdef CONFIG_EROFS_FS_ZIP - sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; - sbi->max_sync_decompress_pages = 3; -#endif -#ifdef CONFIG_EROFS_FS_XATTR - set_opt(sbi, XATTR_USER); -#endif -#ifdef CONFIG_EROFS_FS_POSIX_ACL - set_opt(sbi, POSIX_ACL); -#endif -} - -enum { - Opt_user_xattr, - Opt_nouser_xattr, - Opt_acl, - Opt_noacl, - Opt_fault_injection, - Opt_cache_strategy, - Opt_err -}; - -static match_table_t erofs_tokens = { - {Opt_user_xattr, "user_xattr"}, - {Opt_nouser_xattr, "nouser_xattr"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, - {Opt_fault_injection, "fault_injection=%u"}, - {Opt_cache_strategy, "cache_strategy=%s"}, - {Opt_err, NULL} -}; - -static int parse_options(struct super_block *sb, char *options) -{ - substring_t args[MAX_OPT_ARGS]; - char *p; - int err; - - if (!options) - return 0; - - while ((p = strsep(&options, ","))) { - int token; - - if (!*p) - continue; - - args[0].to = args[0].from = NULL; - token = match_token(p, erofs_tokens, args); - - switch (token) { -#ifdef CONFIG_EROFS_FS_XATTR - case Opt_user_xattr: - set_opt(EROFS_SB(sb), XATTR_USER); - break; - case Opt_nouser_xattr: - clear_opt(EROFS_SB(sb), XATTR_USER); - break; -#else - case Opt_user_xattr: - infoln("user_xattr options not supported"); - break; - case Opt_nouser_xattr: - infoln("nouser_xattr options not supported"); - break; -#endif -#ifdef CONFIG_EROFS_FS_POSIX_ACL - case Opt_acl: - set_opt(EROFS_SB(sb), POSIX_ACL); - break; - case Opt_noacl: - clear_opt(EROFS_SB(sb), POSIX_ACL); - break; -#else - case Opt_acl: - infoln("acl options not supported"); - break; - case Opt_noacl: - infoln("noacl options not supported"); - break; -#endif - case Opt_fault_injection: - err = erofs_build_fault_attr(EROFS_SB(sb), args); - if (err) - return err; - break; - case Opt_cache_strategy: - err = erofs_build_cache_strategy(EROFS_SB(sb), args); - if (err) - return err; - break; - default: - errln("Unrecognized mount option \"%s\" or missing value", p); - return -EINVAL; - } - } - return 0; -} - -#ifdef CONFIG_EROFS_FS_ZIP -static const struct address_space_operations managed_cache_aops; - -static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask) -{ - int ret = 1; /* 0 - busy */ - struct address_space *const mapping = page->mapping; - - DBG_BUGON(!PageLocked(page)); - DBG_BUGON(mapping->a_ops != &managed_cache_aops); - - if (PagePrivate(page)) - ret = erofs_try_to_free_cached_page(mapping, page); - - return ret; -} - -static void managed_cache_invalidatepage(struct page *page, - unsigned int offset, - unsigned int length) -{ - const unsigned int stop = length + offset; - - DBG_BUGON(!PageLocked(page)); - - /* Check for potential overflow in debug mode */ - DBG_BUGON(stop > PAGE_SIZE || stop < length); - - if (offset == 0 && stop == PAGE_SIZE) - while (!managed_cache_releasepage(page, GFP_NOFS)) - cond_resched(); -} - -static const struct address_space_operations managed_cache_aops = { - .releasepage = managed_cache_releasepage, - .invalidatepage = managed_cache_invalidatepage, -}; - -static int erofs_init_managed_cache(struct super_block *sb) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - struct inode *const inode = new_inode(sb); - - if (unlikely(!inode)) - return -ENOMEM; - - set_nlink(inode, 1); - inode->i_size = OFFSET_MAX; - - inode->i_mapping->a_ops = &managed_cache_aops; - mapping_set_gfp_mask(inode->i_mapping, - GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE); - sbi->managed_cache = inode; - return 0; -} -#else -static int erofs_init_managed_cache(struct super_block *sb) { return 0; } -#endif - -static int erofs_fill_super(struct super_block *sb, void *data, int silent) -{ - struct inode *inode; - struct erofs_sb_info *sbi; - int err; - - infoln("fill_super, device -> %s", sb->s_id); - infoln("options -> %s", (char *)data); - - sb->s_magic = EROFS_SUPER_MAGIC; - - if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { - errln("failed to set erofs blksize"); - return -EINVAL; - } - - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (unlikely(!sbi)) - return -ENOMEM; - - sb->s_fs_info = sbi; - err = superblock_read(sb); - if (err) - return err; - - sb->s_flags |= SB_RDONLY | SB_NOATIME; - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_time_gran = 1; - - sb->s_op = &erofs_sops; - -#ifdef CONFIG_EROFS_FS_XATTR - sb->s_xattr = erofs_xattr_handlers; -#endif - /* set erofs default mount options */ - default_options(sbi); - - err = parse_options(sb, data); - if (unlikely(err)) - return err; - - if (!silent) - infoln("root inode @ nid %llu", ROOT_NID(sbi)); - - if (test_opt(sbi, POSIX_ACL)) - sb->s_flags |= SB_POSIXACL; - else - sb->s_flags &= ~SB_POSIXACL; - -#ifdef CONFIG_EROFS_FS_ZIP - INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); -#endif - - /* get the root inode */ - inode = erofs_iget(sb, ROOT_NID(sbi), true); - if (IS_ERR(inode)) - return PTR_ERR(inode); - - if (unlikely(!S_ISDIR(inode->i_mode))) { - errln("rootino(nid %llu) is not a directory(i_mode %o)", - ROOT_NID(sbi), inode->i_mode); - iput(inode); - return -EINVAL; - } - - sb->s_root = d_make_root(inode); - if (unlikely(!sb->s_root)) - return -ENOMEM; - - erofs_shrinker_register(sb); - /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ - err = erofs_init_managed_cache(sb); - if (unlikely(err)) - return err; - - if (!silent) - infoln("mounted on %s with opts: %s.", sb->s_id, (char *)data); - return 0; -} - -static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); -} - -/* - * could be triggered after deactivate_locked_super() - * is called, thus including umount and failed to initialize. - */ -static void erofs_kill_sb(struct super_block *sb) -{ - struct erofs_sb_info *sbi; - - WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); - infoln("unmounting for %s", sb->s_id); - - kill_block_super(sb); - - sbi = EROFS_SB(sb); - if (!sbi) - return; - kfree(sbi); - sb->s_fs_info = NULL; -} - -/* called when ->s_root is non-NULL */ -static void erofs_put_super(struct super_block *sb) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - - DBG_BUGON(!sbi); - - erofs_shrinker_unregister(sb); -#ifdef CONFIG_EROFS_FS_ZIP - iput(sbi->managed_cache); - sbi->managed_cache = NULL; -#endif -} - -static struct file_system_type erofs_fs_type = { - .owner = THIS_MODULE, - .name = "erofs", - .mount = erofs_mount, - .kill_sb = erofs_kill_sb, - .fs_flags = FS_REQUIRES_DEV, -}; -MODULE_ALIAS_FS("erofs"); - -static int __init erofs_module_init(void) -{ - int err; - - erofs_check_ondisk_layout_definitions(); - infoln("initializing erofs " EROFS_VERSION); - - err = erofs_init_inode_cache(); - if (err) - goto icache_err; - - err = erofs_init_shrinker(); - if (err) - goto shrinker_err; - - err = z_erofs_init_zip_subsystem(); - if (err) - goto zip_err; - - err = register_filesystem(&erofs_fs_type); - if (err) - goto fs_err; - - infoln("successfully to initialize erofs"); - return 0; - -fs_err: - z_erofs_exit_zip_subsystem(); -zip_err: - erofs_exit_shrinker(); -shrinker_err: - erofs_exit_inode_cache(); -icache_err: - return err; -} - -static void __exit erofs_module_exit(void) -{ - unregister_filesystem(&erofs_fs_type); - z_erofs_exit_zip_subsystem(); - erofs_exit_shrinker(); - erofs_exit_inode_cache(); - infoln("successfully finalize erofs"); -} - -/* get filesystem statistics */ -static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct super_block *sb = dentry->d_sb; - struct erofs_sb_info *sbi = EROFS_SB(sb); - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); - - buf->f_type = sb->s_magic; - buf->f_bsize = EROFS_BLKSIZ; - buf->f_blocks = sbi->blocks; - buf->f_bfree = buf->f_bavail = 0; - - buf->f_files = ULLONG_MAX; - buf->f_ffree = ULLONG_MAX - sbi->inos; - - buf->f_namelen = EROFS_NAME_LEN; - - buf->f_fsid.val[0] = (u32)id; - buf->f_fsid.val[1] = (u32)(id >> 32); - return 0; -} - -static int erofs_show_options(struct seq_file *seq, struct dentry *root) -{ - struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); - -#ifdef CONFIG_EROFS_FS_XATTR - if (test_opt(sbi, XATTR_USER)) - seq_puts(seq, ",user_xattr"); - else - seq_puts(seq, ",nouser_xattr"); -#endif -#ifdef CONFIG_EROFS_FS_POSIX_ACL - if (test_opt(sbi, POSIX_ACL)) - seq_puts(seq, ",acl"); - else - seq_puts(seq, ",noacl"); -#endif - if (test_opt(sbi, FAULT_INJECTION)) - seq_printf(seq, ",fault_injection=%u", - erofs_get_fault_rate(sbi)); -#ifdef CONFIG_EROFS_FS_ZIP - if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { - seq_puts(seq, ",cache_strategy=disabled"); - } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { - seq_puts(seq, ",cache_strategy=readahead"); - } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { - seq_puts(seq, ",cache_strategy=readaround"); - } else { - seq_puts(seq, ",cache_strategy=(unknown)"); - DBG_BUGON(1); - } -#endif - return 0; -} - -static int erofs_remount(struct super_block *sb, int *flags, char *data) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - unsigned int org_mnt_opt = sbi->mount_opt; - unsigned int org_inject_rate = erofs_get_fault_rate(sbi); - int err; - - DBG_BUGON(!sb_rdonly(sb)); - err = parse_options(sb, data); - if (err) - goto out; - - if (test_opt(sbi, POSIX_ACL)) - sb->s_flags |= SB_POSIXACL; - else - sb->s_flags &= ~SB_POSIXACL; - - *flags |= SB_RDONLY; - return 0; -out: - __erofs_build_fault_attr(sbi, org_inject_rate); - sbi->mount_opt = org_mnt_opt; - - return err; -} - -const struct super_operations erofs_sops = { - .put_super = erofs_put_super, - .alloc_inode = alloc_inode, - .free_inode = free_inode, - .statfs = erofs_statfs, - .show_options = erofs_show_options, - .remount_fs = erofs_remount, -}; - -module_init(erofs_module_init); -module_exit(erofs_module_exit); - -MODULE_DESCRIPTION("Enhanced ROM File System"); -MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); -MODULE_LICENSE("GPL"); - diff --git a/drivers/staging/erofs/tagptr.h b/drivers/staging/erofs/tagptr.h deleted file mode 100644 index a72897c86744..000000000000 --- a/drivers/staging/erofs/tagptr.h +++ /dev/null @@ -1,110 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * A tagged pointer implementation - * - * Copyright (C) 2018 Gao Xiang - */ -#ifndef __EROFS_FS_TAGPTR_H -#define __EROFS_FS_TAGPTR_H - -#include -#include - -/* - * the name of tagged pointer types are tagptr{1, 2, 3...}_t - * avoid directly using the internal structs __tagptr{1, 2, 3...} - */ -#define __MAKE_TAGPTR(n) \ -typedef struct __tagptr##n { \ - uintptr_t v; \ -} tagptr##n##_t; - -__MAKE_TAGPTR(1) -__MAKE_TAGPTR(2) -__MAKE_TAGPTR(3) -__MAKE_TAGPTR(4) - -#undef __MAKE_TAGPTR - -extern void __compiletime_error("bad tagptr tags") - __bad_tagptr_tags(void); - -extern void __compiletime_error("bad tagptr type") - __bad_tagptr_type(void); - -/* fix the broken usage of "#define tagptr2_t tagptr3_t" by users */ -#define __tagptr_mask_1(ptr, n) \ - __builtin_types_compatible_p(typeof(ptr), struct __tagptr##n) ? \ - (1UL << (n)) - 1 : - -#define __tagptr_mask(ptr) (\ - __tagptr_mask_1(ptr, 1) ( \ - __tagptr_mask_1(ptr, 2) ( \ - __tagptr_mask_1(ptr, 3) ( \ - __tagptr_mask_1(ptr, 4) ( \ - __bad_tagptr_type(), 0))))) - -/* generate a tagged pointer from a raw value */ -#define tagptr_init(type, val) \ - ((typeof(type)){ .v = (uintptr_t)(val) }) - -/* - * directly cast a tagged pointer to the native pointer type, which - * could be used for backward compatibility of existing code. - */ -#define tagptr_cast_ptr(tptr) ((void *)(tptr).v) - -/* encode tagged pointers */ -#define tagptr_fold(type, ptr, _tags) ({ \ - const typeof(_tags) tags = (_tags); \ - if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(type))) \ - __bad_tagptr_tags(); \ -tagptr_init(type, (uintptr_t)(ptr) | tags); }) - -/* decode tagged pointers */ -#define tagptr_unfold_ptr(tptr) \ - ((void *)((tptr).v & ~__tagptr_mask(tptr))) - -#define tagptr_unfold_tags(tptr) \ - ((tptr).v & __tagptr_mask(tptr)) - -/* operations for the tagger pointer */ -#define tagptr_eq(_tptr1, _tptr2) ({ \ - typeof(_tptr1) tptr1 = (_tptr1); \ - typeof(_tptr2) tptr2 = (_tptr2); \ - (void)(&tptr1 == &tptr2); \ -(tptr1).v == (tptr2).v; }) - -/* lock-free CAS operation */ -#define tagptr_cmpxchg(_ptptr, _o, _n) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - typeof(_o) o = (_o); \ - typeof(_n) n = (_n); \ - (void)(&o == &n); \ - (void)(&o == ptptr); \ -tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) - -/* wrap WRITE_ONCE if atomic update is needed */ -#define tagptr_replace_tags(_ptptr, tags) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - *ptptr = tagptr_fold(*ptptr, tagptr_unfold_ptr(*ptptr), tags); \ -*ptptr; }) - -#define tagptr_set_tags(_ptptr, _tags) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - const typeof(_tags) tags = (_tags); \ - if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ - __bad_tagptr_tags(); \ - ptptr->v |= tags; \ -*ptptr; }) - -#define tagptr_clear_tags(_ptptr, _tags) ({ \ - typeof(_ptptr) ptptr = (_ptptr); \ - const typeof(_tags) tags = (_tags); \ - if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ - __bad_tagptr_tags(); \ - ptptr->v &= ~tags; \ -*ptptr; }) - -#endif /* __EROFS_FS_TAGPTR_H */ - diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c deleted file mode 100644 index 814c2ee037ae..000000000000 --- a/drivers/staging/erofs/utils.c +++ /dev/null @@ -1,335 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/utils.c - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "internal.h" -#include - -struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) -{ - struct page *page; - - if (!list_empty(pool)) { - page = lru_to_page(pool); - DBG_BUGON(page_ref_count(page) != 1); - list_del(&page->lru); - } else { - page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); - } - return page; -} - -#if (EROFS_PCPUBUF_NR_PAGES > 0) -static struct { - u8 data[PAGE_SIZE * EROFS_PCPUBUF_NR_PAGES]; -} ____cacheline_aligned_in_smp erofs_pcpubuf[NR_CPUS]; - -void *erofs_get_pcpubuf(unsigned int pagenr) -{ - preempt_disable(); - return &erofs_pcpubuf[smp_processor_id()].data[pagenr * PAGE_SIZE]; -} -#endif - -#ifdef CONFIG_EROFS_FS_ZIP -/* global shrink count (for all mounted EROFS instances) */ -static atomic_long_t erofs_global_shrink_cnt; - -#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) -#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) - -static int erofs_workgroup_get(struct erofs_workgroup *grp) -{ - int o; - -repeat: - o = erofs_wait_on_workgroup_freezed(grp); - if (unlikely(o <= 0)) - return -1; - - if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o)) - goto repeat; - - /* decrease refcount paired by erofs_workgroup_put */ - if (unlikely(o == 1)) - atomic_long_dec(&erofs_global_shrink_cnt); - return 0; -} - -struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, - pgoff_t index, bool *tag) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - struct erofs_workgroup *grp; - -repeat: - rcu_read_lock(); - grp = radix_tree_lookup(&sbi->workstn_tree, index); - if (grp) { - *tag = xa_pointer_tag(grp); - grp = xa_untag_pointer(grp); - - if (erofs_workgroup_get(grp)) { - /* prefer to relax rcu read side */ - rcu_read_unlock(); - goto repeat; - } - - DBG_BUGON(index != grp->index); - } - rcu_read_unlock(); - return grp; -} - -int erofs_register_workgroup(struct super_block *sb, - struct erofs_workgroup *grp, - bool tag) -{ - struct erofs_sb_info *sbi; - int err; - - /* grp shouldn't be broken or used before */ - if (unlikely(atomic_read(&grp->refcount) != 1)) { - DBG_BUGON(1); - return -EINVAL; - } - - err = radix_tree_preload(GFP_NOFS); - if (err) - return err; - - sbi = EROFS_SB(sb); - xa_lock(&sbi->workstn_tree); - - grp = xa_tag_pointer(grp, tag); - - /* - * Bump up reference count before making this workgroup - * visible to other users in order to avoid potential UAF - * without serialized by workstn_lock. - */ - __erofs_workgroup_get(grp); - - err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); - if (unlikely(err)) - /* - * it's safe to decrease since the workgroup isn't visible - * and refcount >= 2 (cannot be freezed). - */ - __erofs_workgroup_put(grp); - - xa_unlock(&sbi->workstn_tree); - radix_tree_preload_end(); - return err; -} - -static void __erofs_workgroup_free(struct erofs_workgroup *grp) -{ - atomic_long_dec(&erofs_global_shrink_cnt); - erofs_workgroup_free_rcu(grp); -} - -int erofs_workgroup_put(struct erofs_workgroup *grp) -{ - int count = atomic_dec_return(&grp->refcount); - - if (count == 1) - atomic_long_inc(&erofs_global_shrink_cnt); - else if (!count) - __erofs_workgroup_free(grp); - return count; -} - -static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) -{ - erofs_workgroup_unfreeze(grp, 0); - __erofs_workgroup_free(grp); -} - -static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp, - bool cleanup) -{ - /* - * If managed cache is on, refcount of workgroups - * themselves could be < 0 (freezed). In other words, - * there is no guarantee that all refcounts > 0. - */ - if (!erofs_workgroup_try_to_freeze(grp, 1)) - return false; - - /* - * Note that all cached pages should be unattached - * before deleted from the radix tree. Otherwise some - * cached pages could be still attached to the orphan - * old workgroup when the new one is available in the tree. - */ - if (erofs_try_to_free_all_cached_pages(sbi, grp)) { - erofs_workgroup_unfreeze(grp, 1); - return false; - } - - /* - * It's impossible to fail after the workgroup is freezed, - * however in order to avoid some race conditions, add a - * DBG_BUGON to observe this in advance. - */ - DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, - grp->index)) != grp); - - /* - * If managed cache is on, last refcount should indicate - * the related workstation. - */ - erofs_workgroup_unfreeze_final(grp); - return true; -} - -static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, - unsigned long nr_shrink, - bool cleanup) -{ - pgoff_t first_index = 0; - void *batch[PAGEVEC_SIZE]; - unsigned int freed = 0; - - int i, found; -repeat: - xa_lock(&sbi->workstn_tree); - - found = radix_tree_gang_lookup(&sbi->workstn_tree, - batch, first_index, PAGEVEC_SIZE); - - for (i = 0; i < found; ++i) { - struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); - - first_index = grp->index + 1; - - /* try to shrink each valid workgroup */ - if (!erofs_try_to_release_workgroup(sbi, grp, cleanup)) - continue; - - ++freed; - if (unlikely(!--nr_shrink)) - break; - } - xa_unlock(&sbi->workstn_tree); - - if (i && nr_shrink) - goto repeat; - return freed; -} - -/* protected by 'erofs_sb_list_lock' */ -static unsigned int shrinker_run_no; - -/* protects the mounted 'erofs_sb_list' */ -static DEFINE_SPINLOCK(erofs_sb_list_lock); -static LIST_HEAD(erofs_sb_list); - -void erofs_shrinker_register(struct super_block *sb) -{ - struct erofs_sb_info *sbi = EROFS_SB(sb); - - mutex_init(&sbi->umount_mutex); - - spin_lock(&erofs_sb_list_lock); - list_add(&sbi->list, &erofs_sb_list); - spin_unlock(&erofs_sb_list_lock); -} - -void erofs_shrinker_unregister(struct super_block *sb) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - - mutex_lock(&sbi->umount_mutex); - erofs_shrink_workstation(sbi, ~0UL, true); - - spin_lock(&erofs_sb_list_lock); - list_del(&sbi->list); - spin_unlock(&erofs_sb_list_lock); - mutex_unlock(&sbi->umount_mutex); -} - -static unsigned long erofs_shrink_count(struct shrinker *shrink, - struct shrink_control *sc) -{ - return atomic_long_read(&erofs_global_shrink_cnt); -} - -static unsigned long erofs_shrink_scan(struct shrinker *shrink, - struct shrink_control *sc) -{ - struct erofs_sb_info *sbi; - struct list_head *p; - - unsigned long nr = sc->nr_to_scan; - unsigned int run_no; - unsigned long freed = 0; - - spin_lock(&erofs_sb_list_lock); - do { - run_no = ++shrinker_run_no; - } while (run_no == 0); - - /* Iterate over all mounted superblocks and try to shrink them */ - p = erofs_sb_list.next; - while (p != &erofs_sb_list) { - sbi = list_entry(p, struct erofs_sb_info, list); - - /* - * We move the ones we do to the end of the list, so we stop - * when we see one we have already done. - */ - if (sbi->shrinker_run_no == run_no) - break; - - if (!mutex_trylock(&sbi->umount_mutex)) { - p = p->next; - continue; - } - - spin_unlock(&erofs_sb_list_lock); - sbi->shrinker_run_no = run_no; - - freed += erofs_shrink_workstation(sbi, nr, false); - - spin_lock(&erofs_sb_list_lock); - /* Get the next list element before we move this one */ - p = p->next; - - /* - * Move this one to the end of the list to provide some - * fairness. - */ - list_move_tail(&sbi->list, &erofs_sb_list); - mutex_unlock(&sbi->umount_mutex); - - if (freed >= nr) - break; - } - spin_unlock(&erofs_sb_list_lock); - return freed; -} - -static struct shrinker erofs_shrinker_info = { - .scan_objects = erofs_shrink_scan, - .count_objects = erofs_shrink_count, - .seeks = DEFAULT_SEEKS, -}; - -int __init erofs_init_shrinker(void) -{ - return register_shrinker(&erofs_shrinker_info); -} - -void erofs_exit_shrinker(void) -{ - unregister_shrinker(&erofs_shrinker_info); -} -#endif /* !CONFIG_EROFS_FS_ZIP */ - diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c deleted file mode 100644 index e7e5840e3f9d..000000000000 --- a/drivers/staging/erofs/xattr.c +++ /dev/null @@ -1,705 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/xattr.c - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include -#include "xattr.h" - -struct xattr_iter { - struct super_block *sb; - struct page *page; - void *kaddr; - - erofs_blk_t blkaddr; - unsigned int ofs; -}; - -static inline void xattr_iter_end(struct xattr_iter *it, bool atomic) -{ - /* the only user of kunmap() is 'init_inode_xattrs' */ - if (unlikely(!atomic)) - kunmap(it->page); - else - kunmap_atomic(it->kaddr); - - unlock_page(it->page); - put_page(it->page); -} - -static inline void xattr_iter_end_final(struct xattr_iter *it) -{ - if (!it->page) - return; - - xattr_iter_end(it, true); -} - -static int init_inode_xattrs(struct inode *inode) -{ - struct erofs_vnode *const vi = EROFS_V(inode); - struct xattr_iter it; - unsigned int i; - struct erofs_xattr_ibody_header *ih; - struct super_block *sb; - struct erofs_sb_info *sbi; - bool atomic_map; - int ret = 0; - - /* the most case is that xattrs of this inode are initialized. */ - if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags)) - return 0; - - if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_XATTR_BIT, TASK_KILLABLE)) - return -ERESTARTSYS; - - /* someone has initialized xattrs for us? */ - if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags)) - goto out_unlock; - - /* - * bypass all xattr operations if ->xattr_isize is not greater than - * sizeof(struct erofs_xattr_ibody_header), in detail: - * 1) it is not enough to contain erofs_xattr_ibody_header then - * ->xattr_isize should be 0 (it means no xattr); - * 2) it is just to contain erofs_xattr_ibody_header, which is on-disk - * undefined right now (maybe use later with some new sb feature). - */ - if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) { - errln("xattr_isize %d of nid %llu is not supported yet", - vi->xattr_isize, vi->nid); - ret = -EOPNOTSUPP; - goto out_unlock; - } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { - if (unlikely(vi->xattr_isize)) { - errln("bogus xattr ibody @ nid %llu", vi->nid); - DBG_BUGON(1); - ret = -EFSCORRUPTED; - goto out_unlock; /* xattr ondisk layout error */ - } - ret = -ENOATTR; - goto out_unlock; - } - - sb = inode->i_sb; - sbi = EROFS_SB(sb); - it.blkaddr = erofs_blknr(iloc(sbi, vi->nid) + vi->inode_isize); - it.ofs = erofs_blkoff(iloc(sbi, vi->nid) + vi->inode_isize); - - it.page = erofs_get_inline_page(inode, it.blkaddr); - if (IS_ERR(it.page)) { - ret = PTR_ERR(it.page); - goto out_unlock; - } - - /* read in shared xattr array (non-atomic, see kmalloc below) */ - it.kaddr = kmap(it.page); - atomic_map = false; - - ih = (struct erofs_xattr_ibody_header *)(it.kaddr + it.ofs); - - vi->xattr_shared_count = ih->h_shared_count; - vi->xattr_shared_xattrs = kmalloc_array(vi->xattr_shared_count, - sizeof(uint), GFP_KERNEL); - if (!vi->xattr_shared_xattrs) { - xattr_iter_end(&it, atomic_map); - ret = -ENOMEM; - goto out_unlock; - } - - /* let's skip ibody header */ - it.ofs += sizeof(struct erofs_xattr_ibody_header); - - for (i = 0; i < vi->xattr_shared_count; ++i) { - if (unlikely(it.ofs >= EROFS_BLKSIZ)) { - /* cannot be unaligned */ - DBG_BUGON(it.ofs != EROFS_BLKSIZ); - xattr_iter_end(&it, atomic_map); - - it.page = erofs_get_meta_page(sb, ++it.blkaddr, - S_ISDIR(inode->i_mode)); - if (IS_ERR(it.page)) { - kfree(vi->xattr_shared_xattrs); - vi->xattr_shared_xattrs = NULL; - ret = PTR_ERR(it.page); - goto out_unlock; - } - - it.kaddr = kmap_atomic(it.page); - atomic_map = true; - it.ofs = 0; - } - vi->xattr_shared_xattrs[i] = - le32_to_cpu(*(__le32 *)(it.kaddr + it.ofs)); - it.ofs += sizeof(__le32); - } - xattr_iter_end(&it, atomic_map); - - set_bit(EROFS_V_EA_INITED_BIT, &vi->flags); - -out_unlock: - clear_and_wake_up_bit(EROFS_V_BL_XATTR_BIT, &vi->flags); - return ret; -} - -/* - * the general idea for these return values is - * if 0 is returned, go on processing the current xattr; - * 1 (> 0) is returned, skip this round to process the next xattr; - * -err (< 0) is returned, an error (maybe ENOXATTR) occurred - * and need to be handled - */ -struct xattr_iter_handlers { - int (*entry)(struct xattr_iter *_it, struct erofs_xattr_entry *entry); - int (*name)(struct xattr_iter *_it, unsigned int processed, char *buf, - unsigned int len); - int (*alloc_buffer)(struct xattr_iter *_it, unsigned int value_sz); - void (*value)(struct xattr_iter *_it, unsigned int processed, char *buf, - unsigned int len); -}; - -static inline int xattr_iter_fixup(struct xattr_iter *it) -{ - if (it->ofs < EROFS_BLKSIZ) - return 0; - - xattr_iter_end(it, true); - - it->blkaddr += erofs_blknr(it->ofs); - - it->page = erofs_get_meta_page(it->sb, it->blkaddr, false); - if (IS_ERR(it->page)) { - int err = PTR_ERR(it->page); - - it->page = NULL; - return err; - } - - it->kaddr = kmap_atomic(it->page); - it->ofs = erofs_blkoff(it->ofs); - return 0; -} - -static int inline_xattr_iter_begin(struct xattr_iter *it, - struct inode *inode) -{ - struct erofs_vnode *const vi = EROFS_V(inode); - struct erofs_sb_info *const sbi = EROFS_SB(inode->i_sb); - unsigned int xattr_header_sz, inline_xattr_ofs; - - xattr_header_sz = inlinexattr_header_size(inode); - if (unlikely(xattr_header_sz >= vi->xattr_isize)) { - DBG_BUGON(xattr_header_sz > vi->xattr_isize); - return -ENOATTR; - } - - inline_xattr_ofs = vi->inode_isize + xattr_header_sz; - - it->blkaddr = erofs_blknr(iloc(sbi, vi->nid) + inline_xattr_ofs); - it->ofs = erofs_blkoff(iloc(sbi, vi->nid) + inline_xattr_ofs); - - it->page = erofs_get_inline_page(inode, it->blkaddr); - if (IS_ERR(it->page)) - return PTR_ERR(it->page); - - it->kaddr = kmap_atomic(it->page); - return vi->xattr_isize - xattr_header_sz; -} - -/* - * Regardless of success or failure, `xattr_foreach' will end up with - * `ofs' pointing to the next xattr item rather than an arbitrary position. - */ -static int xattr_foreach(struct xattr_iter *it, - const struct xattr_iter_handlers *op, - unsigned int *tlimit) -{ - struct erofs_xattr_entry entry; - unsigned int value_sz, processed, slice; - int err; - - /* 0. fixup blkaddr, ofs, ipage */ - err = xattr_iter_fixup(it); - if (err) - return err; - - /* - * 1. read xattr entry to the memory, - * since we do EROFS_XATTR_ALIGN - * therefore entry should be in the page - */ - entry = *(struct erofs_xattr_entry *)(it->kaddr + it->ofs); - if (tlimit) { - unsigned int entry_sz = EROFS_XATTR_ENTRY_SIZE(&entry); - - /* xattr on-disk corruption: xattr entry beyond xattr_isize */ - if (unlikely(*tlimit < entry_sz)) { - DBG_BUGON(1); - return -EFSCORRUPTED; - } - *tlimit -= entry_sz; - } - - it->ofs += sizeof(struct erofs_xattr_entry); - value_sz = le16_to_cpu(entry.e_value_size); - - /* handle entry */ - err = op->entry(it, &entry); - if (err) { - it->ofs += entry.e_name_len + value_sz; - goto out; - } - - /* 2. handle xattr name (ofs will finally be at the end of name) */ - processed = 0; - - while (processed < entry.e_name_len) { - if (it->ofs >= EROFS_BLKSIZ) { - DBG_BUGON(it->ofs > EROFS_BLKSIZ); - - err = xattr_iter_fixup(it); - if (err) - goto out; - it->ofs = 0; - } - - slice = min_t(unsigned int, PAGE_SIZE - it->ofs, - entry.e_name_len - processed); - - /* handle name */ - err = op->name(it, processed, it->kaddr + it->ofs, slice); - if (err) { - it->ofs += entry.e_name_len - processed + value_sz; - goto out; - } - - it->ofs += slice; - processed += slice; - } - - /* 3. handle xattr value */ - processed = 0; - - if (op->alloc_buffer) { - err = op->alloc_buffer(it, value_sz); - if (err) { - it->ofs += value_sz; - goto out; - } - } - - while (processed < value_sz) { - if (it->ofs >= EROFS_BLKSIZ) { - DBG_BUGON(it->ofs > EROFS_BLKSIZ); - - err = xattr_iter_fixup(it); - if (err) - goto out; - it->ofs = 0; - } - - slice = min_t(unsigned int, PAGE_SIZE - it->ofs, - value_sz - processed); - op->value(it, processed, it->kaddr + it->ofs, slice); - it->ofs += slice; - processed += slice; - } - -out: - /* xattrs should be 4-byte aligned (on-disk constraint) */ - it->ofs = EROFS_XATTR_ALIGN(it->ofs); - return err < 0 ? err : 0; -} - -struct getxattr_iter { - struct xattr_iter it; - - char *buffer; - int buffer_size, index; - struct qstr name; -}; - -static int xattr_entrymatch(struct xattr_iter *_it, - struct erofs_xattr_entry *entry) -{ - struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); - - return (it->index != entry->e_name_index || - it->name.len != entry->e_name_len) ? -ENOATTR : 0; -} - -static int xattr_namematch(struct xattr_iter *_it, - unsigned int processed, char *buf, unsigned int len) -{ - struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); - - return memcmp(buf, it->name.name + processed, len) ? -ENOATTR : 0; -} - -static int xattr_checkbuffer(struct xattr_iter *_it, - unsigned int value_sz) -{ - struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); - int err = it->buffer_size < value_sz ? -ERANGE : 0; - - it->buffer_size = value_sz; - return !it->buffer ? 1 : err; -} - -static void xattr_copyvalue(struct xattr_iter *_it, - unsigned int processed, - char *buf, unsigned int len) -{ - struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); - - memcpy(it->buffer + processed, buf, len); -} - -static const struct xattr_iter_handlers find_xattr_handlers = { - .entry = xattr_entrymatch, - .name = xattr_namematch, - .alloc_buffer = xattr_checkbuffer, - .value = xattr_copyvalue -}; - -static int inline_getxattr(struct inode *inode, struct getxattr_iter *it) -{ - int ret; - unsigned int remaining; - - ret = inline_xattr_iter_begin(&it->it, inode); - if (ret < 0) - return ret; - - remaining = ret; - while (remaining) { - ret = xattr_foreach(&it->it, &find_xattr_handlers, &remaining); - if (ret != -ENOATTR) - break; - } - xattr_iter_end_final(&it->it); - - return ret ? ret : it->buffer_size; -} - -static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) -{ - struct erofs_vnode *const vi = EROFS_V(inode); - struct super_block *const sb = inode->i_sb; - struct erofs_sb_info *const sbi = EROFS_SB(sb); - unsigned int i; - int ret = -ENOATTR; - - for (i = 0; i < vi->xattr_shared_count; ++i) { - erofs_blk_t blkaddr = - xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]); - - it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]); - - if (!i || blkaddr != it->it.blkaddr) { - if (i) - xattr_iter_end(&it->it, true); - - it->it.page = erofs_get_meta_page(sb, blkaddr, false); - if (IS_ERR(it->it.page)) - return PTR_ERR(it->it.page); - - it->it.kaddr = kmap_atomic(it->it.page); - it->it.blkaddr = blkaddr; - } - - ret = xattr_foreach(&it->it, &find_xattr_handlers, NULL); - if (ret != -ENOATTR) - break; - } - if (vi->xattr_shared_count) - xattr_iter_end_final(&it->it); - - return ret ? ret : it->buffer_size; -} - -static bool erofs_xattr_user_list(struct dentry *dentry) -{ - return test_opt(EROFS_SB(dentry->d_sb), XATTR_USER); -} - -static bool erofs_xattr_trusted_list(struct dentry *dentry) -{ - return capable(CAP_SYS_ADMIN); -} - -int erofs_getxattr(struct inode *inode, int index, - const char *name, - void *buffer, size_t buffer_size) -{ - int ret; - struct getxattr_iter it; - - if (unlikely(!name)) - return -EINVAL; - - ret = init_inode_xattrs(inode); - if (ret) - return ret; - - it.index = index; - - it.name.len = strlen(name); - if (it.name.len > EROFS_NAME_LEN) - return -ERANGE; - it.name.name = name; - - it.buffer = buffer; - it.buffer_size = buffer_size; - - it.it.sb = inode->i_sb; - ret = inline_getxattr(inode, &it); - if (ret == -ENOATTR) - ret = shared_getxattr(inode, &it); - return ret; -} - -static int erofs_xattr_generic_get(const struct xattr_handler *handler, - struct dentry *unused, struct inode *inode, - const char *name, void *buffer, size_t size) -{ - struct erofs_sb_info *const sbi = EROFS_I_SB(inode); - - switch (handler->flags) { - case EROFS_XATTR_INDEX_USER: - if (!test_opt(sbi, XATTR_USER)) - return -EOPNOTSUPP; - break; - case EROFS_XATTR_INDEX_TRUSTED: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - break; - case EROFS_XATTR_INDEX_SECURITY: - break; - default: - return -EINVAL; - } - - return erofs_getxattr(inode, handler->flags, name, buffer, size); -} - -const struct xattr_handler erofs_xattr_user_handler = { - .prefix = XATTR_USER_PREFIX, - .flags = EROFS_XATTR_INDEX_USER, - .list = erofs_xattr_user_list, - .get = erofs_xattr_generic_get, -}; - -const struct xattr_handler erofs_xattr_trusted_handler = { - .prefix = XATTR_TRUSTED_PREFIX, - .flags = EROFS_XATTR_INDEX_TRUSTED, - .list = erofs_xattr_trusted_list, - .get = erofs_xattr_generic_get, -}; - -#ifdef CONFIG_EROFS_FS_SECURITY -const struct xattr_handler __maybe_unused erofs_xattr_security_handler = { - .prefix = XATTR_SECURITY_PREFIX, - .flags = EROFS_XATTR_INDEX_SECURITY, - .get = erofs_xattr_generic_get, -}; -#endif - -const struct xattr_handler *erofs_xattr_handlers[] = { - &erofs_xattr_user_handler, -#ifdef CONFIG_EROFS_FS_POSIX_ACL - &posix_acl_access_xattr_handler, - &posix_acl_default_xattr_handler, -#endif - &erofs_xattr_trusted_handler, -#ifdef CONFIG_EROFS_FS_SECURITY - &erofs_xattr_security_handler, -#endif - NULL, -}; - -struct listxattr_iter { - struct xattr_iter it; - - struct dentry *dentry; - char *buffer; - int buffer_size, buffer_ofs; -}; - -static int xattr_entrylist(struct xattr_iter *_it, - struct erofs_xattr_entry *entry) -{ - struct listxattr_iter *it = - container_of(_it, struct listxattr_iter, it); - unsigned int prefix_len; - const char *prefix; - - const struct xattr_handler *h = - erofs_xattr_handler(entry->e_name_index); - - if (!h || (h->list && !h->list(it->dentry))) - return 1; - - prefix = xattr_prefix(h); - prefix_len = strlen(prefix); - - if (!it->buffer) { - it->buffer_ofs += prefix_len + entry->e_name_len + 1; - return 1; - } - - if (it->buffer_ofs + prefix_len - + entry->e_name_len + 1 > it->buffer_size) - return -ERANGE; - - memcpy(it->buffer + it->buffer_ofs, prefix, prefix_len); - it->buffer_ofs += prefix_len; - return 0; -} - -static int xattr_namelist(struct xattr_iter *_it, - unsigned int processed, char *buf, unsigned int len) -{ - struct listxattr_iter *it = - container_of(_it, struct listxattr_iter, it); - - memcpy(it->buffer + it->buffer_ofs, buf, len); - it->buffer_ofs += len; - return 0; -} - -static int xattr_skipvalue(struct xattr_iter *_it, - unsigned int value_sz) -{ - struct listxattr_iter *it = - container_of(_it, struct listxattr_iter, it); - - it->buffer[it->buffer_ofs++] = '\0'; - return 1; -} - -static const struct xattr_iter_handlers list_xattr_handlers = { - .entry = xattr_entrylist, - .name = xattr_namelist, - .alloc_buffer = xattr_skipvalue, - .value = NULL -}; - -static int inline_listxattr(struct listxattr_iter *it) -{ - int ret; - unsigned int remaining; - - ret = inline_xattr_iter_begin(&it->it, d_inode(it->dentry)); - if (ret < 0) - return ret; - - remaining = ret; - while (remaining) { - ret = xattr_foreach(&it->it, &list_xattr_handlers, &remaining); - if (ret) - break; - } - xattr_iter_end_final(&it->it); - return ret ? ret : it->buffer_ofs; -} - -static int shared_listxattr(struct listxattr_iter *it) -{ - struct inode *const inode = d_inode(it->dentry); - struct erofs_vnode *const vi = EROFS_V(inode); - struct super_block *const sb = inode->i_sb; - struct erofs_sb_info *const sbi = EROFS_SB(sb); - unsigned int i; - int ret = 0; - - for (i = 0; i < vi->xattr_shared_count; ++i) { - erofs_blk_t blkaddr = - xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]); - - it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]); - if (!i || blkaddr != it->it.blkaddr) { - if (i) - xattr_iter_end(&it->it, true); - - it->it.page = erofs_get_meta_page(sb, blkaddr, false); - if (IS_ERR(it->it.page)) - return PTR_ERR(it->it.page); - - it->it.kaddr = kmap_atomic(it->it.page); - it->it.blkaddr = blkaddr; - } - - ret = xattr_foreach(&it->it, &list_xattr_handlers, NULL); - if (ret) - break; - } - if (vi->xattr_shared_count) - xattr_iter_end_final(&it->it); - - return ret ? ret : it->buffer_ofs; -} - -ssize_t erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) -{ - int ret; - struct listxattr_iter it; - - ret = init_inode_xattrs(d_inode(dentry)); - if (ret) - return ret; - - it.dentry = dentry; - it.buffer = buffer; - it.buffer_size = buffer_size; - it.buffer_ofs = 0; - - it.it.sb = dentry->d_sb; - - ret = inline_listxattr(&it); - if (ret < 0 && ret != -ENOATTR) - return ret; - return shared_listxattr(&it); -} - -#ifdef CONFIG_EROFS_FS_POSIX_ACL -struct posix_acl *erofs_get_acl(struct inode *inode, int type) -{ - struct posix_acl *acl; - int prefix, rc; - char *value = NULL; - - switch (type) { - case ACL_TYPE_ACCESS: - prefix = EROFS_XATTR_INDEX_POSIX_ACL_ACCESS; - break; - case ACL_TYPE_DEFAULT: - prefix = EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT; - break; - default: - return ERR_PTR(-EINVAL); - } - - rc = erofs_getxattr(inode, prefix, "", NULL, 0); - if (rc > 0) { - value = kmalloc(rc, GFP_KERNEL); - if (!value) - return ERR_PTR(-ENOMEM); - rc = erofs_getxattr(inode, prefix, "", value, rc); - } - - if (rc == -ENOATTR) - acl = NULL; - else if (rc < 0) - acl = ERR_PTR(rc); - else - acl = posix_acl_from_xattr(&init_user_ns, value, rc); - kfree(value); - return acl; -} -#endif - diff --git a/drivers/staging/erofs/xattr.h b/drivers/staging/erofs/xattr.h deleted file mode 100644 index e20249647541..000000000000 --- a/drivers/staging/erofs/xattr.h +++ /dev/null @@ -1,94 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/xattr.h - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_XATTR_H -#define __EROFS_XATTR_H - -#include "internal.h" -#include -#include - -/* Attribute not found */ -#define ENOATTR ENODATA - -static inline unsigned int inlinexattr_header_size(struct inode *inode) -{ - return sizeof(struct erofs_xattr_ibody_header) - + sizeof(u32) * EROFS_V(inode)->xattr_shared_count; -} - -static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi, - unsigned int xattr_id) -{ -#ifdef CONFIG_EROFS_FS_XATTR - return sbi->xattr_blkaddr + - xattr_id * sizeof(__u32) / EROFS_BLKSIZ; -#else - return 0; -#endif -} - -static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, - unsigned int xattr_id) -{ - return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; -} - -#ifdef CONFIG_EROFS_FS_XATTR -extern const struct xattr_handler erofs_xattr_user_handler; -extern const struct xattr_handler erofs_xattr_trusted_handler; -#ifdef CONFIG_EROFS_FS_SECURITY -extern const struct xattr_handler erofs_xattr_security_handler; -#endif - -static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) -{ -static const struct xattr_handler *xattr_handler_map[] = { - [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, -#ifdef CONFIG_EROFS_FS_POSIX_ACL - [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler, - [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = - &posix_acl_default_xattr_handler, -#endif - [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler, -#ifdef CONFIG_EROFS_FS_SECURITY - [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, -#endif -}; - - return idx && idx < ARRAY_SIZE(xattr_handler_map) ? - xattr_handler_map[idx] : NULL; -} - -extern const struct xattr_handler *erofs_xattr_handlers[]; - -int erofs_getxattr(struct inode *, int, const char *, void *, size_t); -ssize_t erofs_listxattr(struct dentry *, char *, size_t); -#else -static inline int erofs_getxattr(struct inode *inode, int index, - const char *name, void *buffer, - size_t buffer_size) -{ - return -EOPNOTSUPP; -} - -static inline ssize_t erofs_listxattr(struct dentry *dentry, - char *buffer, size_t buffer_size) -{ - return -EOPNOTSUPP; -} -#endif /* !CONFIG_EROFS_FS_XATTR */ - -#ifdef CONFIG_EROFS_FS_POSIX_ACL -struct posix_acl *erofs_get_acl(struct inode *inode, int type); -#else -#define erofs_get_acl (NULL) -#endif - -#endif - diff --git a/drivers/staging/erofs/zdata.c b/drivers/staging/erofs/zdata.c deleted file mode 100644 index 60d7c20db87d..000000000000 --- a/drivers/staging/erofs/zdata.c +++ /dev/null @@ -1,1434 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/zdata.c - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "zdata.h" -#include "compress.h" -#include - -#include - -/* - * a compressed_pages[] placeholder in order to avoid - * being filled with file pages for in-place decompression. - */ -#define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) - -/* how to allocate cached pages for a pcluster */ -enum z_erofs_cache_alloctype { - DONTALLOC, /* don't allocate any cached pages */ - DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ -}; - -/* - * tagged pointer with 1-bit tag for all compressed pages - * tag 0 - the page is just found with an extra page reference - */ -typedef tagptr1_t compressed_page_t; - -#define tag_compressed_page_justfound(page) \ - tagptr_fold(compressed_page_t, page, 1) - -static struct workqueue_struct *z_erofs_workqueue __read_mostly; -static struct kmem_cache *pcluster_cachep __read_mostly; - -void z_erofs_exit_zip_subsystem(void) -{ - destroy_workqueue(z_erofs_workqueue); - kmem_cache_destroy(pcluster_cachep); -} - -static inline int init_unzip_workqueue(void) -{ - const unsigned int onlinecpus = num_possible_cpus(); - const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; - - /* - * no need to spawn too many threads, limiting threads could minimum - * scheduling overhead, perhaps per-CPU threads should be better? - */ - z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, - onlinecpus + onlinecpus / 4); - return z_erofs_workqueue ? 0 : -ENOMEM; -} - -static void init_once(void *ptr) -{ - struct z_erofs_pcluster *pcl = ptr; - struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); - unsigned int i; - - mutex_init(&cl->lock); - cl->nr_pages = 0; - cl->vcnt = 0; - for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) - pcl->compressed_pages[i] = NULL; -} - -static void init_always(struct z_erofs_pcluster *pcl) -{ - struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); - - atomic_set(&pcl->obj.refcount, 1); - - DBG_BUGON(cl->nr_pages); - DBG_BUGON(cl->vcnt); -} - -int __init z_erofs_init_zip_subsystem(void) -{ - pcluster_cachep = kmem_cache_create("erofs_compress", - Z_EROFS_WORKGROUP_SIZE, 0, - SLAB_RECLAIM_ACCOUNT, init_once); - if (pcluster_cachep) { - if (!init_unzip_workqueue()) - return 0; - - kmem_cache_destroy(pcluster_cachep); - } - return -ENOMEM; -} - -enum z_erofs_collectmode { - COLLECT_SECONDARY, - COLLECT_PRIMARY, - /* - * The current collection was the tail of an exist chain, in addition - * that the previous processed chained collections are all decided to - * be hooked up to it. - * A new chain will be created for the remaining collections which are - * not processed yet, therefore different from COLLECT_PRIMARY_FOLLOWED, - * the next collection cannot reuse the whole page safely in - * the following scenario: - * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (belongs to the next cl) | (belongs to the current cl) | - * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| - */ - COLLECT_PRIMARY_HOOKED, - COLLECT_PRIMARY_FOLLOWED_NOINPLACE, - /* - * The current collection has been linked with the owned chain, and - * could also be linked with the remaining collections, which means - * if the processing page is the tail page of the collection, thus - * the current collection can safely use the whole page (since - * the previous collection is under control) for in-place I/O, as - * illustrated below: - * ________________________________________________________________ - * | tail (partial) page | head (partial) page | - * | (of the current cl) | (of the previous collection) | - * | PRIMARY_FOLLOWED or | | - * |_____PRIMARY_HOOKED___|____________PRIMARY_FOLLOWED____________| - * - * [ (*) the above page can be used as inplace I/O. ] - */ - COLLECT_PRIMARY_FOLLOWED, -}; - -struct z_erofs_collector { - struct z_erofs_pagevec_ctor vector; - - struct z_erofs_pcluster *pcl, *tailpcl; - struct z_erofs_collection *cl; - struct page **compressedpages; - z_erofs_next_pcluster_t owned_head; - - enum z_erofs_collectmode mode; -}; - -struct z_erofs_decompress_frontend { - struct inode *const inode; - - struct z_erofs_collector clt; - struct erofs_map_blocks map; - - /* used for applying cache strategy on the fly */ - bool backmost; - erofs_off_t headoffset; -}; - -#define COLLECTOR_INIT() { \ - .owned_head = Z_EROFS_PCLUSTER_TAIL, \ - .mode = COLLECT_PRIMARY_FOLLOWED } - -#define DECOMPRESS_FRONTEND_INIT(__i) { \ - .inode = __i, .clt = COLLECTOR_INIT(), \ - .backmost = true, } - -static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; -static DEFINE_MUTEX(z_pagemap_global_lock); - -static void preload_compressed_pages(struct z_erofs_collector *clt, - struct address_space *mc, - enum z_erofs_cache_alloctype type, - struct list_head *pagepool) -{ - const struct z_erofs_pcluster *pcl = clt->pcl; - const unsigned int clusterpages = BIT(pcl->clusterbits); - struct page **pages = clt->compressedpages; - pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); - bool standalone = true; - - if (clt->mode < COLLECT_PRIMARY_FOLLOWED) - return; - - for (; pages < pcl->compressed_pages + clusterpages; ++pages) { - struct page *page; - compressed_page_t t; - - /* the compressed page was loaded before */ - if (READ_ONCE(*pages)) - continue; - - page = find_get_page(mc, index); - - if (page) { - t = tag_compressed_page_justfound(page); - } else if (type == DELAYEDALLOC) { - t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); - } else { /* DONTALLOC */ - if (standalone) - clt->compressedpages = pages; - standalone = false; - continue; - } - - if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) - continue; - - if (page) - put_page(page); - } - - if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ - clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; -} - -/* called by erofs_shrinker to get rid of all compressed_pages */ -int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, - struct erofs_workgroup *grp) -{ - struct z_erofs_pcluster *const pcl = - container_of(grp, struct z_erofs_pcluster, obj); - struct address_space *const mapping = MNGD_MAPPING(sbi); - const unsigned int clusterpages = BIT(pcl->clusterbits); - int i; - - /* - * refcount of workgroup is now freezed as 1, - * therefore no need to worry about available decompression users. - */ - for (i = 0; i < clusterpages; ++i) { - struct page *page = pcl->compressed_pages[i]; - - if (!page) - continue; - - /* block other users from reclaiming or migrating the page */ - if (!trylock_page(page)) - return -EBUSY; - - if (unlikely(page->mapping != mapping)) - continue; - - /* barrier is implied in the following 'unlock_page' */ - WRITE_ONCE(pcl->compressed_pages[i], NULL); - set_page_private(page, 0); - ClearPagePrivate(page); - - unlock_page(page); - put_page(page); - } - return 0; -} - -int erofs_try_to_free_cached_page(struct address_space *mapping, - struct page *page) -{ - struct z_erofs_pcluster *const pcl = (void *)page_private(page); - const unsigned int clusterpages = BIT(pcl->clusterbits); - int ret = 0; /* 0 - busy */ - - if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { - unsigned int i; - - for (i = 0; i < clusterpages; ++i) { - if (pcl->compressed_pages[i] == page) { - WRITE_ONCE(pcl->compressed_pages[i], NULL); - ret = 1; - break; - } - } - erofs_workgroup_unfreeze(&pcl->obj, 1); - - if (ret) { - ClearPagePrivate(page); - put_page(page); - } - } - return ret; -} - -/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ -static inline bool try_inplace_io(struct z_erofs_collector *clt, - struct page *page) -{ - struct z_erofs_pcluster *const pcl = clt->pcl; - const unsigned int clusterpages = BIT(pcl->clusterbits); - - while (clt->compressedpages < pcl->compressed_pages + clusterpages) { - if (!cmpxchg(clt->compressedpages++, NULL, page)) - return true; - } - return false; -} - -/* callers must be with collection lock held */ -static int z_erofs_attach_page(struct z_erofs_collector *clt, - struct page *page, - enum z_erofs_page_type type) -{ - int ret; - bool occupied; - - /* give priority for inplaceio */ - if (clt->mode >= COLLECT_PRIMARY && - type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && - try_inplace_io(clt, page)) - return 0; - - ret = z_erofs_pagevec_enqueue(&clt->vector, - page, type, &occupied); - clt->cl->vcnt += (unsigned int)ret; - - return ret ? 0 : -EAGAIN; -} - -static enum z_erofs_collectmode -try_to_claim_pcluster(struct z_erofs_pcluster *pcl, - z_erofs_next_pcluster_t *owned_head) -{ - /* let's claim these following types of pclusters */ -retry: - if (pcl->next == Z_EROFS_PCLUSTER_NIL) { - /* type 1, nil pcluster */ - if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_NIL, - *owned_head) != Z_EROFS_PCLUSTER_NIL) - goto retry; - - *owned_head = &pcl->next; - /* lucky, I am the followee :) */ - return COLLECT_PRIMARY_FOLLOWED; - } else if (pcl->next == Z_EROFS_PCLUSTER_TAIL) { - /* - * type 2, link to the end of a existing open chain, - * be careful that its submission itself is governed - * by the original owned chain. - */ - if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, - *owned_head) != Z_EROFS_PCLUSTER_TAIL) - goto retry; - *owned_head = Z_EROFS_PCLUSTER_TAIL; - return COLLECT_PRIMARY_HOOKED; - } - return COLLECT_PRIMARY; /* :( better luck next time */ -} - -static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) -{ - struct erofs_workgroup *grp; - struct z_erofs_pcluster *pcl; - struct z_erofs_collection *cl; - unsigned int length; - bool tag; - - grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); - if (!grp) - return NULL; - - pcl = container_of(grp, struct z_erofs_pcluster, obj); - if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { - DBG_BUGON(1); - erofs_workgroup_put(grp); - return ERR_PTR(-EFSCORRUPTED); - } - - cl = z_erofs_primarycollection(pcl); - if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { - DBG_BUGON(1); - erofs_workgroup_put(grp); - return ERR_PTR(-EFSCORRUPTED); - } - - length = READ_ONCE(pcl->length); - if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { - if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { - DBG_BUGON(1); - erofs_workgroup_put(grp); - return ERR_PTR(-EFSCORRUPTED); - } - } else { - unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; - - if (map->m_flags & EROFS_MAP_FULL_MAPPED) - llen |= Z_EROFS_PCLUSTER_FULL_LENGTH; - - while (llen > length && - length != cmpxchg_relaxed(&pcl->length, length, llen)) { - cpu_relax(); - length = READ_ONCE(pcl->length); - } - } - mutex_lock(&cl->lock); - /* used to check tail merging loop due to corrupted images */ - if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) - clt->tailpcl = pcl; - clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); - /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ - if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) - clt->tailpcl = NULL; - clt->pcl = pcl; - clt->cl = cl; - return cl; -} - -static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) -{ - struct z_erofs_pcluster *pcl; - struct z_erofs_collection *cl; - int err; - - /* no available workgroup, let's allocate one */ - pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); - if (unlikely(!pcl)) - return ERR_PTR(-ENOMEM); - - init_always(pcl); - pcl->obj.index = map->m_pa >> PAGE_SHIFT; - - pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | - (map->m_flags & EROFS_MAP_FULL_MAPPED ? - Z_EROFS_PCLUSTER_FULL_LENGTH : 0); - - if (map->m_flags & EROFS_MAP_ZIPPED) - pcl->algorithmformat = Z_EROFS_COMPRESSION_LZ4; - else - pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; - - pcl->clusterbits = EROFS_V(inode)->z_physical_clusterbits[0]; - pcl->clusterbits -= PAGE_SHIFT; - - /* new pclusters should be claimed as type 1, primary and followed */ - pcl->next = clt->owned_head; - clt->mode = COLLECT_PRIMARY_FOLLOWED; - - cl = z_erofs_primarycollection(pcl); - cl->pageofs = map->m_la & ~PAGE_MASK; - - /* - * lock all primary followed works before visible to others - * and mutex_trylock *never* fails for a new pcluster. - */ - mutex_trylock(&cl->lock); - - err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); - if (err) { - mutex_unlock(&cl->lock); - kmem_cache_free(pcluster_cachep, pcl); - return ERR_PTR(-EAGAIN); - } - /* used to check tail merging loop due to corrupted images */ - if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) - clt->tailpcl = pcl; - clt->owned_head = &pcl->next; - clt->pcl = pcl; - clt->cl = cl; - return cl; -} - -static int z_erofs_collector_begin(struct z_erofs_collector *clt, - struct inode *inode, - struct erofs_map_blocks *map) -{ - struct z_erofs_collection *cl; - - DBG_BUGON(clt->cl); - - /* must be Z_EROFS_PCLUSTER_TAIL or pointed to previous collection */ - DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_NIL); - DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); - - if (!PAGE_ALIGNED(map->m_pa)) { - DBG_BUGON(1); - return -EINVAL; - } - -repeat: - cl = cllookup(clt, inode, map); - if (!cl) { - cl = clregister(clt, inode, map); - - if (unlikely(cl == ERR_PTR(-EAGAIN))) - goto repeat; - } - - if (IS_ERR(cl)) - return PTR_ERR(cl); - - z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, - cl->pagevec, cl->vcnt); - - clt->compressedpages = clt->pcl->compressed_pages; - if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ - clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; - return 0; -} - -/* - * keep in mind that no referenced pclusters will be freed - * only after a RCU grace period. - */ -static void z_erofs_rcu_callback(struct rcu_head *head) -{ - struct z_erofs_collection *const cl = - container_of(head, struct z_erofs_collection, rcu); - - kmem_cache_free(pcluster_cachep, - container_of(cl, struct z_erofs_pcluster, - primary_collection)); -} - -void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) -{ - struct z_erofs_pcluster *const pcl = - container_of(grp, struct z_erofs_pcluster, obj); - struct z_erofs_collection *const cl = z_erofs_primarycollection(pcl); - - call_rcu(&cl->rcu, z_erofs_rcu_callback); -} - -static void z_erofs_collection_put(struct z_erofs_collection *cl) -{ - struct z_erofs_pcluster *const pcl = - container_of(cl, struct z_erofs_pcluster, primary_collection); - - erofs_workgroup_put(&pcl->obj); -} - -static bool z_erofs_collector_end(struct z_erofs_collector *clt) -{ - struct z_erofs_collection *cl = clt->cl; - - if (!cl) - return false; - - z_erofs_pagevec_ctor_exit(&clt->vector, false); - mutex_unlock(&cl->lock); - - /* - * if all pending pages are added, don't hold its reference - * any longer if the pcluster isn't hosted by ourselves. - */ - if (clt->mode < COLLECT_PRIMARY_FOLLOWED_NOINPLACE) - z_erofs_collection_put(cl); - - clt->cl = NULL; - return true; -} - -static inline struct page *__stagingpage_alloc(struct list_head *pagepool, - gfp_t gfp) -{ - struct page *page = erofs_allocpage(pagepool, gfp, true); - - page->mapping = Z_EROFS_MAPPING_STAGING; - return page; -} - -static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, - unsigned int cachestrategy, - erofs_off_t la) -{ - if (cachestrategy <= EROFS_ZIP_CACHE_DISABLED) - return false; - - if (fe->backmost) - return true; - - return cachestrategy >= EROFS_ZIP_CACHE_READAROUND && - la < fe->headoffset; -} - -static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, - struct page *page, - struct list_head *pagepool) -{ - struct inode *const inode = fe->inode; - struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); - struct erofs_map_blocks *const map = &fe->map; - struct z_erofs_collector *const clt = &fe->clt; - const loff_t offset = page_offset(page); - bool tight = (clt->mode >= COLLECT_PRIMARY_HOOKED); - - enum z_erofs_cache_alloctype cache_strategy; - enum z_erofs_page_type page_type; - unsigned int cur, end, spiltted, index; - int err = 0; - - /* register locked file pages as online pages in pack */ - z_erofs_onlinepage_init(page); - - spiltted = 0; - end = PAGE_SIZE; -repeat: - cur = end - 1; - - /* lucky, within the range of the current map_blocks */ - if (offset + cur >= map->m_la && - offset + cur < map->m_la + map->m_llen) { - /* didn't get a valid collection previously (very rare) */ - if (!clt->cl) - goto restart_now; - goto hitted; - } - - /* go ahead the next map_blocks */ - debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); - - if (z_erofs_collector_end(clt)) - fe->backmost = false; - - map->m_la = offset + cur; - map->m_llen = 0; - err = z_erofs_map_blocks_iter(inode, map, 0); - if (unlikely(err)) - goto err_out; - -restart_now: - if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) - goto hitted; - - err = z_erofs_collector_begin(clt, inode, map); - if (unlikely(err)) - goto err_out; - - /* preload all compressed pages (maybe downgrade role if necessary) */ - if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) - cache_strategy = DELAYEDALLOC; - else - cache_strategy = DONTALLOC; - - preload_compressed_pages(clt, MNGD_MAPPING(sbi), - cache_strategy, pagepool); - - tight &= (clt->mode >= COLLECT_PRIMARY_HOOKED); -hitted: - cur = end - min_t(unsigned int, offset + end - map->m_la, end); - if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { - zero_user_segment(page, cur, end); - goto next_part; - } - - /* let's derive page type */ - page_type = cur ? Z_EROFS_VLE_PAGE_TYPE_HEAD : - (!spiltted ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : - (tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : - Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); - - if (cur) - tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); - -retry: - err = z_erofs_attach_page(clt, page, page_type); - /* should allocate an additional staging page for pagevec */ - if (err == -EAGAIN) { - struct page *const newpage = - __stagingpage_alloc(pagepool, GFP_NOFS); - - err = z_erofs_attach_page(clt, newpage, - Z_EROFS_PAGE_TYPE_EXCLUSIVE); - if (likely(!err)) - goto retry; - } - - if (unlikely(err)) - goto err_out; - - index = page->index - (map->m_la >> PAGE_SHIFT); - - z_erofs_onlinepage_fixup(page, index, true); - - /* bump up the number of spiltted parts of a page */ - ++spiltted; - /* also update nr_pages */ - clt->cl->nr_pages = max_t(pgoff_t, clt->cl->nr_pages, index + 1); -next_part: - /* can be used for verification */ - map->m_llen = offset + cur - map->m_la; - - end = cur; - if (end > 0) - goto repeat; - -out: - z_erofs_onlinepage_endio(page); - - debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", - __func__, page, spiltted, map->m_llen); - return err; - - /* if some error occurred while processing this page */ -err_out: - SetPageError(page); - goto out; -} - -static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) -{ - tagptr1_t t = tagptr_init(tagptr1_t, ptr); - struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); - bool background = tagptr_unfold_tags(t); - - if (!background) { - unsigned long flags; - - spin_lock_irqsave(&io->u.wait.lock, flags); - if (!atomic_add_return(bios, &io->pending_bios)) - wake_up_locked(&io->u.wait); - spin_unlock_irqrestore(&io->u.wait.lock, flags); - return; - } - - if (!atomic_add_return(bios, &io->pending_bios)) - queue_work(z_erofs_workqueue, &io->u.work); -} - -static inline void z_erofs_vle_read_endio(struct bio *bio) -{ - struct erofs_sb_info *sbi = NULL; - blk_status_t err = bio->bi_status; - struct bio_vec *bvec; - struct bvec_iter_all iter_all; - - bio_for_each_segment_all(bvec, bio, iter_all) { - struct page *page = bvec->bv_page; - bool cachemngd = false; - - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!page->mapping); - - if (unlikely(!sbi && !z_erofs_page_is_staging(page))) { - sbi = EROFS_SB(page->mapping->host->i_sb); - - if (time_to_inject(sbi, FAULT_READ_IO)) { - erofs_show_injection_info(FAULT_READ_IO); - err = BLK_STS_IOERR; - } - } - - /* sbi should already be gotten if the page is managed */ - if (sbi) - cachemngd = erofs_page_is_managed(sbi, page); - - if (unlikely(err)) - SetPageError(page); - else if (cachemngd) - SetPageUptodate(page); - - if (cachemngd) - unlock_page(page); - } - - z_erofs_vle_unzip_kickoff(bio->bi_private, -1); - bio_put(bio); -} - -static int z_erofs_decompress_pcluster(struct super_block *sb, - struct z_erofs_pcluster *pcl, - struct list_head *pagepool) -{ - struct erofs_sb_info *const sbi = EROFS_SB(sb); - const unsigned int clusterpages = BIT(pcl->clusterbits); - struct z_erofs_pagevec_ctor ctor; - unsigned int i, outputsize, llen, nr_pages; - struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; - struct page **pages, **compressed_pages, *page; - - enum z_erofs_page_type page_type; - bool overlapped, partial; - struct z_erofs_collection *cl; - int err; - - might_sleep(); - cl = z_erofs_primarycollection(pcl); - DBG_BUGON(!READ_ONCE(cl->nr_pages)); - - mutex_lock(&cl->lock); - nr_pages = cl->nr_pages; - - if (likely(nr_pages <= Z_EROFS_VMAP_ONSTACK_PAGES)) { - pages = pages_onstack; - } else if (nr_pages <= Z_EROFS_VMAP_GLOBAL_PAGES && - mutex_trylock(&z_pagemap_global_lock)) { - pages = z_pagemap_global; - } else { - gfp_t gfp_flags = GFP_KERNEL; - - if (nr_pages > Z_EROFS_VMAP_GLOBAL_PAGES) - gfp_flags |= __GFP_NOFAIL; - - pages = kvmalloc_array(nr_pages, sizeof(struct page *), - gfp_flags); - - /* fallback to global pagemap for the lowmem scenario */ - if (unlikely(!pages)) { - mutex_lock(&z_pagemap_global_lock); - pages = z_pagemap_global; - } - } - - for (i = 0; i < nr_pages; ++i) - pages[i] = NULL; - - err = 0; - z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, - cl->pagevec, 0); - - for (i = 0; i < cl->vcnt; ++i) { - unsigned int pagenr; - - page = z_erofs_pagevec_dequeue(&ctor, &page_type); - - /* all pages in pagevec ought to be valid */ - DBG_BUGON(!page); - DBG_BUGON(!page->mapping); - - if (z_erofs_put_stagingpage(pagepool, page)) - continue; - - if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) - pagenr = 0; - else - pagenr = z_erofs_onlinepage_index(page); - - DBG_BUGON(pagenr >= nr_pages); - - /* - * currently EROFS doesn't support multiref(dedup), - * so here erroring out one multiref page. - */ - if (unlikely(pages[pagenr])) { - DBG_BUGON(1); - SetPageError(pages[pagenr]); - z_erofs_onlinepage_endio(pages[pagenr]); - err = -EFSCORRUPTED; - } - pages[pagenr] = page; - } - z_erofs_pagevec_ctor_exit(&ctor, true); - - overlapped = false; - compressed_pages = pcl->compressed_pages; - - for (i = 0; i < clusterpages; ++i) { - unsigned int pagenr; - - page = compressed_pages[i]; - - /* all compressed pages ought to be valid */ - DBG_BUGON(!page); - DBG_BUGON(!page->mapping); - - if (!z_erofs_page_is_staging(page)) { - if (erofs_page_is_managed(sbi, page)) { - if (unlikely(!PageUptodate(page))) - err = -EIO; - continue; - } - - /* - * only if non-head page can be selected - * for inplace decompression - */ - pagenr = z_erofs_onlinepage_index(page); - - DBG_BUGON(pagenr >= nr_pages); - if (unlikely(pages[pagenr])) { - DBG_BUGON(1); - SetPageError(pages[pagenr]); - z_erofs_onlinepage_endio(pages[pagenr]); - err = -EFSCORRUPTED; - } - pages[pagenr] = page; - - overlapped = true; - } - - /* PG_error needs checking for inplaced and staging pages */ - if (unlikely(PageError(page))) { - DBG_BUGON(PageUptodate(page)); - err = -EIO; - } - } - - if (unlikely(err)) - goto out; - - llen = pcl->length >> Z_EROFS_PCLUSTER_LENGTH_BIT; - if (nr_pages << PAGE_SHIFT >= cl->pageofs + llen) { - outputsize = llen; - partial = !(pcl->length & Z_EROFS_PCLUSTER_FULL_LENGTH); - } else { - outputsize = (nr_pages << PAGE_SHIFT) - cl->pageofs; - partial = true; - } - - err = z_erofs_decompress(&(struct z_erofs_decompress_req) { - .sb = sb, - .in = compressed_pages, - .out = pages, - .pageofs_out = cl->pageofs, - .inputsize = PAGE_SIZE, - .outputsize = outputsize, - .alg = pcl->algorithmformat, - .inplace_io = overlapped, - .partial_decoding = partial - }, pagepool); - -out: - /* must handle all compressed pages before endding pages */ - for (i = 0; i < clusterpages; ++i) { - page = compressed_pages[i]; - - if (erofs_page_is_managed(sbi, page)) - continue; - - /* recycle all individual staging pages */ - (void)z_erofs_put_stagingpage(pagepool, page); - - WRITE_ONCE(compressed_pages[i], NULL); - } - - for (i = 0; i < nr_pages; ++i) { - page = pages[i]; - if (!page) - continue; - - DBG_BUGON(!page->mapping); - - /* recycle all individual staging pages */ - if (z_erofs_put_stagingpage(pagepool, page)) - continue; - - if (unlikely(err < 0)) - SetPageError(page); - - z_erofs_onlinepage_endio(page); - } - - if (pages == z_pagemap_global) - mutex_unlock(&z_pagemap_global_lock); - else if (unlikely(pages != pages_onstack)) - kvfree(pages); - - cl->nr_pages = 0; - cl->vcnt = 0; - - /* all cl locks MUST be taken before the following line */ - WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_NIL); - - /* all cl locks SHOULD be released right now */ - mutex_unlock(&cl->lock); - - z_erofs_collection_put(cl); - return err; -} - -static void z_erofs_vle_unzip_all(struct super_block *sb, - struct z_erofs_unzip_io *io, - struct list_head *pagepool) -{ - z_erofs_next_pcluster_t owned = io->head; - - while (owned != Z_EROFS_PCLUSTER_TAIL_CLOSED) { - struct z_erofs_pcluster *pcl; - - /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ - DBG_BUGON(owned == Z_EROFS_PCLUSTER_TAIL); - - /* no possible that 'owned' equals NULL */ - DBG_BUGON(owned == Z_EROFS_PCLUSTER_NIL); - - pcl = container_of(owned, struct z_erofs_pcluster, next); - owned = READ_ONCE(pcl->next); - - z_erofs_decompress_pcluster(sb, pcl, pagepool); - } -} - -static void z_erofs_vle_unzip_wq(struct work_struct *work) -{ - struct z_erofs_unzip_io_sb *iosb = - container_of(work, struct z_erofs_unzip_io_sb, io.u.work); - LIST_HEAD(pagepool); - - DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); - z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); - - put_pages_list(&pagepool); - kvfree(iosb); -} - -static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, - unsigned int nr, - struct list_head *pagepool, - struct address_space *mc, - gfp_t gfp) -{ - /* determined at compile time to avoid too many #ifdefs */ - const bool nocache = __builtin_constant_p(mc) ? !mc : false; - const pgoff_t index = pcl->obj.index; - bool tocache = false; - - struct address_space *mapping; - struct page *oldpage, *page; - - compressed_page_t t; - int justfound; - -repeat: - page = READ_ONCE(pcl->compressed_pages[nr]); - oldpage = page; - - if (!page) - goto out_allocpage; - - /* - * the cached page has not been allocated and - * an placeholder is out there, prepare it now. - */ - if (!nocache && page == PAGE_UNALLOCATED) { - tocache = true; - goto out_allocpage; - } - - /* process the target tagged pointer */ - t = tagptr_init(compressed_page_t, page); - justfound = tagptr_unfold_tags(t); - page = tagptr_unfold_ptr(t); - - mapping = READ_ONCE(page->mapping); - - /* - * if managed cache is disabled, it's no way to - * get such a cached-like page. - */ - if (nocache) { - /* if managed cache is disabled, it is impossible `justfound' */ - DBG_BUGON(justfound); - - /* and it should be locked, not uptodate, and not truncated */ - DBG_BUGON(!PageLocked(page)); - DBG_BUGON(PageUptodate(page)); - DBG_BUGON(!mapping); - goto out; - } - - /* - * unmanaged (file) pages are all locked solidly, - * therefore it is impossible for `mapping' to be NULL. - */ - if (mapping && mapping != mc) - /* ought to be unmanaged pages */ - goto out; - - lock_page(page); - - /* only true if page reclaim goes wrong, should never happen */ - DBG_BUGON(justfound && PagePrivate(page)); - - /* the page is still in manage cache */ - if (page->mapping == mc) { - WRITE_ONCE(pcl->compressed_pages[nr], page); - - ClearPageError(page); - if (!PagePrivate(page)) { - /* - * impossible to be !PagePrivate(page) for - * the current restriction as well if - * the page is already in compressed_pages[]. - */ - DBG_BUGON(!justfound); - - justfound = 0; - set_page_private(page, (unsigned long)pcl); - SetPagePrivate(page); - } - - /* no need to submit io if it is already up-to-date */ - if (PageUptodate(page)) { - unlock_page(page); - page = NULL; - } - goto out; - } - - /* - * the managed page has been truncated, it's unsafe to - * reuse this one, let's allocate a new cache-managed page. - */ - DBG_BUGON(page->mapping); - DBG_BUGON(!justfound); - - tocache = true; - unlock_page(page); - put_page(page); -out_allocpage: - page = __stagingpage_alloc(pagepool, gfp); - if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { - list_add(&page->lru, pagepool); - cpu_relax(); - goto repeat; - } - if (nocache || !tocache) - goto out; - if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { - page->mapping = Z_EROFS_MAPPING_STAGING; - goto out; - } - - set_page_private(page, (unsigned long)pcl); - SetPagePrivate(page); -out: /* the only exit (for tracing and debugging) */ - return page; -} - -static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, - struct z_erofs_unzip_io *io, - bool foreground) -{ - struct z_erofs_unzip_io_sb *iosb; - - if (foreground) { - /* waitqueue available for foreground io */ - DBG_BUGON(!io); - - init_waitqueue_head(&io->u.wait); - atomic_set(&io->pending_bios, 0); - goto out; - } - - iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); - DBG_BUGON(!iosb); - - /* initialize fields in the allocated descriptor */ - io = &iosb->io; - iosb->sb = sb; - INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); -out: - io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; - return io; -} - -/* define decompression jobqueue types */ -enum { - JQ_BYPASS, - JQ_SUBMIT, - NR_JOBQUEUES, -}; - -static void *jobqueueset_init(struct super_block *sb, - z_erofs_next_pcluster_t qtail[], - struct z_erofs_unzip_io *q[], - struct z_erofs_unzip_io *fgq, - bool forcefg) -{ - /* - * if managed cache is enabled, bypass jobqueue is needed, - * no need to read from device for all pclusters in this queue. - */ - q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); - qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; - - q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); - qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; - - return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); -} - -static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, - z_erofs_next_pcluster_t qtail[], - z_erofs_next_pcluster_t owned_head) -{ - z_erofs_next_pcluster_t *const submit_qtail = qtail[JQ_SUBMIT]; - z_erofs_next_pcluster_t *const bypass_qtail = qtail[JQ_BYPASS]; - - DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); - if (owned_head == Z_EROFS_PCLUSTER_TAIL) - owned_head = Z_EROFS_PCLUSTER_TAIL_CLOSED; - - WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_TAIL_CLOSED); - - WRITE_ONCE(*submit_qtail, owned_head); - WRITE_ONCE(*bypass_qtail, &pcl->next); - - qtail[JQ_BYPASS] = &pcl->next; -} - -static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], - unsigned int nr_bios, - bool force_fg) -{ - /* - * although background is preferred, no one is pending for submission. - * don't issue workqueue for decompression but drop it directly instead. - */ - if (force_fg || nr_bios) - return false; - - kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); - return true; -} - -static bool z_erofs_vle_submit_all(struct super_block *sb, - z_erofs_next_pcluster_t owned_head, - struct list_head *pagepool, - struct z_erofs_unzip_io *fgq, - bool force_fg) -{ - struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); - z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; - struct z_erofs_unzip_io *q[NR_JOBQUEUES]; - struct bio *bio; - void *bi_private; - /* since bio will be NULL, no need to initialize last_index */ - pgoff_t uninitialized_var(last_index); - bool force_submit = false; - unsigned int nr_bios; - - if (unlikely(owned_head == Z_EROFS_PCLUSTER_TAIL)) - return false; - - force_submit = false; - bio = NULL; - nr_bios = 0; - bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); - - /* by default, all need io submission */ - q[JQ_SUBMIT]->head = owned_head; - - do { - struct z_erofs_pcluster *pcl; - unsigned int clusterpages; - pgoff_t first_index; - struct page *page; - unsigned int i = 0, bypass = 0; - int err; - - /* no possible 'owned_head' equals the following */ - DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); - DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_NIL); - - pcl = container_of(owned_head, struct z_erofs_pcluster, next); - - clusterpages = BIT(pcl->clusterbits); - - /* close the main owned chain at first */ - owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, - Z_EROFS_PCLUSTER_TAIL_CLOSED); - - first_index = pcl->obj.index; - force_submit |= (first_index != last_index + 1); - -repeat: - page = pickup_page_for_submission(pcl, i, pagepool, - MNGD_MAPPING(sbi), - GFP_NOFS); - if (!page) { - force_submit = true; - ++bypass; - goto skippage; - } - - if (bio && force_submit) { -submit_bio_retry: - __submit_bio(bio, REQ_OP_READ, 0); - bio = NULL; - } - - if (!bio) { - bio = erofs_grab_bio(sb, first_index + i, - BIO_MAX_PAGES, bi_private, - z_erofs_vle_read_endio, true); - ++nr_bios; - } - - err = bio_add_page(bio, page, PAGE_SIZE, 0); - if (err < PAGE_SIZE) - goto submit_bio_retry; - - force_submit = false; - last_index = first_index + i; -skippage: - if (++i < clusterpages) - goto repeat; - - if (bypass < clusterpages) - qtail[JQ_SUBMIT] = &pcl->next; - else - move_to_bypass_jobqueue(pcl, qtail, owned_head); - } while (owned_head != Z_EROFS_PCLUSTER_TAIL); - - if (bio) - __submit_bio(bio, REQ_OP_READ, 0); - - if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) - return true; - - z_erofs_vle_unzip_kickoff(bi_private, nr_bios); - return true; -} - -static void z_erofs_submit_and_unzip(struct super_block *sb, - struct z_erofs_collector *clt, - struct list_head *pagepool, - bool force_fg) -{ - struct z_erofs_unzip_io io[NR_JOBQUEUES]; - - if (!z_erofs_vle_submit_all(sb, clt->owned_head, - pagepool, io, force_fg)) - return; - - /* decompress no I/O pclusters immediately */ - z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); - - if (!force_fg) - return; - - /* wait until all bios are completed */ - wait_event(io[JQ_SUBMIT].u.wait, - !atomic_read(&io[JQ_SUBMIT].pending_bios)); - - /* let's synchronous decompression */ - z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); -} - -static int z_erofs_vle_normalaccess_readpage(struct file *file, - struct page *page) -{ - struct inode *const inode = page->mapping->host; - struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); - int err; - LIST_HEAD(pagepool); - - trace_erofs_readpage(page, false); - - f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; - - err = z_erofs_do_read_page(&f, page, &pagepool); - (void)z_erofs_collector_end(&f.clt); - - /* if some compressed cluster ready, need submit them anyway */ - z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); - - if (err) - errln("%s, failed to read, err [%d]", __func__, err); - - if (f.map.mpage) - put_page(f.map.mpage); - - /* clean up the remaining free pages */ - put_pages_list(&pagepool); - return err; -} - -static bool should_decompress_synchronously(struct erofs_sb_info *sbi, - unsigned int nr) -{ - return nr <= sbi->max_sync_decompress_pages; -} - -static int z_erofs_vle_normalaccess_readpages(struct file *filp, - struct address_space *mapping, - struct list_head *pages, - unsigned int nr_pages) -{ - struct inode *const inode = mapping->host; - struct erofs_sb_info *const sbi = EROFS_I_SB(inode); - - bool sync = should_decompress_synchronously(sbi, nr_pages); - struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); - gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); - struct page *head = NULL; - LIST_HEAD(pagepool); - - trace_erofs_readpages(mapping->host, lru_to_page(pages), - nr_pages, false); - - f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT; - - for (; nr_pages; --nr_pages) { - struct page *page = lru_to_page(pages); - - prefetchw(&page->flags); - list_del(&page->lru); - - /* - * A pure asynchronous readahead is indicated if - * a PG_readahead marked page is hitted at first. - * Let's also do asynchronous decompression for this case. - */ - sync &= !(PageReadahead(page) && !head); - - if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { - list_add(&page->lru, &pagepool); - continue; - } - - set_page_private(page, (unsigned long)head); - head = page; - } - - while (head) { - struct page *page = head; - int err; - - /* traversal in reverse order */ - head = (void *)page_private(page); - - err = z_erofs_do_read_page(&f, page, &pagepool); - if (err) { - struct erofs_vnode *vi = EROFS_V(inode); - - errln("%s, readahead error at page %lu of nid %llu", - __func__, page->index, vi->nid); - } - put_page(page); - } - - (void)z_erofs_collector_end(&f.clt); - - z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); - - if (f.map.mpage) - put_page(f.map.mpage); - - /* clean up the remaining free pages */ - put_pages_list(&pagepool); - return 0; -} - -const struct address_space_operations z_erofs_vle_normalaccess_aops = { - .readpage = z_erofs_vle_normalaccess_readpage, - .readpages = z_erofs_vle_normalaccess_readpages, -}; - diff --git a/drivers/staging/erofs/zdata.h b/drivers/staging/erofs/zdata.h deleted file mode 100644 index e11fe1959ca2..000000000000 --- a/drivers/staging/erofs/zdata.h +++ /dev/null @@ -1,195 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/zdata.h - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_FS_ZDATA_H -#define __EROFS_FS_ZDATA_H - -#include "internal.h" -#include "zpvec.h" - -#define Z_EROFS_NR_INLINE_PAGEVECS 3 - -/* - * Structure fields follow one of the following exclusion rules. - * - * I: Modifiable by initialization/destruction paths and read-only - * for everyone else; - * - * L: Field should be protected by pageset lock; - * - * A: Field should be accessed / updated in atomic for parallelized code. - */ -struct z_erofs_collection { - struct mutex lock; - - /* I: page offset of start position of decompression */ - unsigned short pageofs; - - /* L: maximum relative page index in pagevec[] */ - unsigned short nr_pages; - - /* L: total number of pages in pagevec[] */ - unsigned int vcnt; - - union { - /* L: inline a certain number of pagevecs for bootstrap */ - erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; - - /* I: can be used to free the pcluster by RCU. */ - struct rcu_head rcu; - }; -}; - -#define Z_EROFS_PCLUSTER_FULL_LENGTH 0x00000001 -#define Z_EROFS_PCLUSTER_LENGTH_BIT 1 - -/* - * let's leave a type here in case of introducing - * another tagged pointer later. - */ -typedef void *z_erofs_next_pcluster_t; - -struct z_erofs_pcluster { - struct erofs_workgroup obj; - struct z_erofs_collection primary_collection; - - /* A: point to next chained pcluster or TAILs */ - z_erofs_next_pcluster_t next; - - /* A: compressed pages (including multi-usage pages) */ - struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; - - /* A: lower limit of decompressed length and if full length or not */ - unsigned int length; - - /* I: compression algorithm format */ - unsigned char algorithmformat; - /* I: bit shift of physical cluster size */ - unsigned char clusterbits; -}; - -#define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) - -/* let's avoid the valid 32-bit kernel addresses */ - -/* the chained workgroup has't submitted io (still open) */ -#define Z_EROFS_PCLUSTER_TAIL ((void *)0x5F0ECAFE) -/* the chained workgroup has already submitted io */ -#define Z_EROFS_PCLUSTER_TAIL_CLOSED ((void *)0x5F0EDEAD) - -#define Z_EROFS_PCLUSTER_NIL (NULL) - -#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) - -struct z_erofs_unzip_io { - atomic_t pending_bios; - z_erofs_next_pcluster_t head; - - union { - wait_queue_head_t wait; - struct work_struct work; - } u; -}; - -struct z_erofs_unzip_io_sb { - struct z_erofs_unzip_io io; - struct super_block *sb; -}; - -#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) -static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, - struct page *page) -{ - return page->mapping == MNGD_MAPPING(sbi); -} - -#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 -#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) -#define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) - -/* - * waiters (aka. ongoing_packs): # to unlock the page - * sub-index: 0 - for partial page, >= 1 full page sub-index - */ -typedef atomic_t z_erofs_onlinepage_t; - -/* type punning */ -union z_erofs_onlinepage_converter { - z_erofs_onlinepage_t *o; - unsigned long *v; -}; - -static inline unsigned int z_erofs_onlinepage_index(struct page *page) -{ - union z_erofs_onlinepage_converter u; - - DBG_BUGON(!PagePrivate(page)); - u.v = &page_private(page); - - return atomic_read(u.o) >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; -} - -static inline void z_erofs_onlinepage_init(struct page *page) -{ - union { - z_erofs_onlinepage_t o; - unsigned long v; - /* keep from being unlocked in advance */ - } u = { .o = ATOMIC_INIT(1) }; - - set_page_private(page, u.v); - smp_wmb(); - SetPagePrivate(page); -} - -static inline void z_erofs_onlinepage_fixup(struct page *page, - uintptr_t index, bool down) -{ - unsigned long *p, o, v, id; -repeat: - p = &page_private(page); - o = READ_ONCE(*p); - - id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; - if (id) { - if (!index) - return; - - DBG_BUGON(id != index); - } - - v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | - ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); - if (cmpxchg(p, o, v) != o) - goto repeat; -} - -static inline void z_erofs_onlinepage_endio(struct page *page) -{ - union z_erofs_onlinepage_converter u; - unsigned int v; - - DBG_BUGON(!PagePrivate(page)); - u.v = &page_private(page); - - v = atomic_dec_return(u.o); - if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) { - ClearPagePrivate(page); - if (!PageError(page)) - SetPageUptodate(page); - unlock_page(page); - } - debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); -} - -#define Z_EROFS_VMAP_ONSTACK_PAGES \ - min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) -#define Z_EROFS_VMAP_GLOBAL_PAGES 2048 - -#endif - diff --git a/drivers/staging/erofs/zmap.c b/drivers/staging/erofs/zmap.c deleted file mode 100644 index 774dacbc5b32..000000000000 --- a/drivers/staging/erofs/zmap.c +++ /dev/null @@ -1,468 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * linux/drivers/staging/erofs/zmap.c - * - * Copyright (C) 2018-2019 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#include "internal.h" -#include -#include - -int z_erofs_fill_inode(struct inode *inode) -{ - struct erofs_vnode *const vi = EROFS_V(inode); - - if (vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { - vi->z_advise = 0; - vi->z_algorithmtype[0] = 0; - vi->z_algorithmtype[1] = 0; - vi->z_logical_clusterbits = LOG_BLOCK_SIZE; - vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; - vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; - set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); - } - - inode->i_mapping->a_ops = &z_erofs_vle_normalaccess_aops; - return 0; -} - -static int fill_inode_lazy(struct inode *inode) -{ - struct erofs_vnode *const vi = EROFS_V(inode); - struct super_block *const sb = inode->i_sb; - int err; - erofs_off_t pos; - struct page *page; - void *kaddr; - struct z_erofs_map_header *h; - - if (test_bit(EROFS_V_Z_INITED_BIT, &vi->flags)) - return 0; - - if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_Z_BIT, TASK_KILLABLE)) - return -ERESTARTSYS; - - err = 0; - if (test_bit(EROFS_V_Z_INITED_BIT, &vi->flags)) - goto out_unlock; - - DBG_BUGON(vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY); - - pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + - vi->xattr_isize, 8); - page = erofs_get_meta_page(sb, erofs_blknr(pos), false); - if (IS_ERR(page)) { - err = PTR_ERR(page); - goto out_unlock; - } - - kaddr = kmap_atomic(page); - - h = kaddr + erofs_blkoff(pos); - vi->z_advise = le16_to_cpu(h->h_advise); - vi->z_algorithmtype[0] = h->h_algorithmtype & 15; - vi->z_algorithmtype[1] = h->h_algorithmtype >> 4; - - if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) { - errln("unknown compression format %u for nid %llu, please upgrade kernel", - vi->z_algorithmtype[0], vi->nid); - err = -EOPNOTSUPP; - goto unmap_done; - } - - vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7); - vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits + - ((h->h_clusterbits >> 3) & 3); - - if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) { - errln("unsupported physical clusterbits %u for nid %llu, please upgrade kernel", - vi->z_physical_clusterbits[0], vi->nid); - err = -EOPNOTSUPP; - goto unmap_done; - } - - vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + - ((h->h_clusterbits >> 5) & 7); - set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); -unmap_done: - kunmap_atomic(kaddr); - unlock_page(page); - put_page(page); -out_unlock: - clear_and_wake_up_bit(EROFS_V_BL_Z_BIT, &vi->flags); - return err; -} - -struct z_erofs_maprecorder { - struct inode *inode; - struct erofs_map_blocks *map; - void *kaddr; - - unsigned long lcn; - /* compression extent information gathered */ - u8 type; - u16 clusterofs; - u16 delta[2]; - erofs_blk_t pblk; -}; - -static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, - erofs_blk_t eblk) -{ - struct super_block *const sb = m->inode->i_sb; - struct erofs_map_blocks *const map = m->map; - struct page *mpage = map->mpage; - - if (mpage) { - if (mpage->index == eblk) { - if (!m->kaddr) - m->kaddr = kmap_atomic(mpage); - return 0; - } - - if (m->kaddr) { - kunmap_atomic(m->kaddr); - m->kaddr = NULL; - } - put_page(mpage); - } - - mpage = erofs_get_meta_page(sb, eblk, false); - if (IS_ERR(mpage)) { - map->mpage = NULL; - return PTR_ERR(mpage); - } - m->kaddr = kmap_atomic(mpage); - unlock_page(mpage); - map->mpage = mpage; - return 0; -} - -static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned long lcn) -{ - struct inode *const inode = m->inode; - struct erofs_vnode *const vi = EROFS_V(inode); - const erofs_off_t ibase = iloc(EROFS_I_SB(inode), vi->nid); - const erofs_off_t pos = - Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize + - vi->xattr_isize) + - lcn * sizeof(struct z_erofs_vle_decompressed_index); - struct z_erofs_vle_decompressed_index *di; - unsigned int advise, type; - int err; - - err = z_erofs_reload_indexes(m, erofs_blknr(pos)); - if (err) - return err; - - m->lcn = lcn; - di = m->kaddr + erofs_blkoff(pos); - - advise = le16_to_cpu(di->di_advise); - type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) & - ((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1); - switch (type) { - case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: - m->clusterofs = 1 << vi->z_logical_clusterbits; - m->delta[0] = le16_to_cpu(di->di_u.delta[0]); - m->delta[1] = le16_to_cpu(di->di_u.delta[1]); - break; - case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: - case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: - m->clusterofs = le16_to_cpu(di->di_clusterofs); - m->pblk = le32_to_cpu(di->di_u.blkaddr); - break; - default: - DBG_BUGON(1); - return -EOPNOTSUPP; - } - m->type = type; - return 0; -} - -static unsigned int decode_compactedbits(unsigned int lobits, - unsigned int lomask, - u8 *in, unsigned int pos, u8 *type) -{ - const unsigned int v = get_unaligned_le32(in + pos / 8) >> (pos & 7); - const unsigned int lo = v & lomask; - - *type = (v >> lobits) & 3; - return lo; -} - -static int unpack_compacted_index(struct z_erofs_maprecorder *m, - unsigned int amortizedshift, - unsigned int eofs) -{ - struct erofs_vnode *const vi = EROFS_V(m->inode); - const unsigned int lclusterbits = vi->z_logical_clusterbits; - const unsigned int lomask = (1 << lclusterbits) - 1; - unsigned int vcnt, base, lo, encodebits, nblk; - int i; - u8 *in, type; - - if (1 << amortizedshift == 4) - vcnt = 2; - else if (1 << amortizedshift == 2 && lclusterbits == 12) - vcnt = 16; - else - return -EOPNOTSUPP; - - encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt; - base = round_down(eofs, vcnt << amortizedshift); - in = m->kaddr + base; - - i = (eofs - base) >> amortizedshift; - - lo = decode_compactedbits(lclusterbits, lomask, - in, encodebits * i, &type); - m->type = type; - if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { - m->clusterofs = 1 << lclusterbits; - if (i + 1 != vcnt) { - m->delta[0] = lo; - return 0; - } - /* - * since the last lcluster in the pack is special, - * of which lo saves delta[1] rather than delta[0]. - * Hence, get delta[0] by the previous lcluster indirectly. - */ - lo = decode_compactedbits(lclusterbits, lomask, - in, encodebits * (i - 1), &type); - if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) - lo = 0; - m->delta[0] = lo + 1; - return 0; - } - m->clusterofs = lo; - m->delta[0] = 0; - /* figout out blkaddr (pblk) for HEAD lclusters */ - nblk = 1; - while (i > 0) { - --i; - lo = decode_compactedbits(lclusterbits, lomask, - in, encodebits * i, &type); - if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) - i -= lo; - - if (i >= 0) - ++nblk; - } - in += (vcnt << amortizedshift) - sizeof(__le32); - m->pblk = le32_to_cpu(*(__le32 *)in) + nblk; - return 0; -} - -static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned long lcn) -{ - struct inode *const inode = m->inode; - struct erofs_vnode *const vi = EROFS_V(inode); - const unsigned int lclusterbits = vi->z_logical_clusterbits; - const erofs_off_t ebase = ALIGN(iloc(EROFS_I_SB(inode), vi->nid) + - vi->inode_isize + vi->xattr_isize, 8) + - sizeof(struct z_erofs_map_header); - const unsigned int totalidx = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); - unsigned int compacted_4b_initial, compacted_2b; - unsigned int amortizedshift; - erofs_off_t pos; - int err; - - if (lclusterbits != 12) - return -EOPNOTSUPP; - - if (lcn >= totalidx) - return -EINVAL; - - m->lcn = lcn; - /* used to align to 32-byte (compacted_2b) alignment */ - compacted_4b_initial = (32 - ebase % 32) / 4; - if (compacted_4b_initial == 32 / 4) - compacted_4b_initial = 0; - - if (vi->z_advise & Z_EROFS_ADVISE_COMPACTED_2B) - compacted_2b = rounddown(totalidx - compacted_4b_initial, 16); - else - compacted_2b = 0; - - pos = ebase; - if (lcn < compacted_4b_initial) { - amortizedshift = 2; - goto out; - } - pos += compacted_4b_initial * 4; - lcn -= compacted_4b_initial; - - if (lcn < compacted_2b) { - amortizedshift = 1; - goto out; - } - pos += compacted_2b * 2; - lcn -= compacted_2b; - amortizedshift = 2; -out: - pos += lcn * (1 << amortizedshift); - err = z_erofs_reload_indexes(m, erofs_blknr(pos)); - if (err) - return err; - return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos)); -} - -static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, - unsigned int lcn) -{ - const unsigned int datamode = EROFS_V(m->inode)->datamode; - - if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) - return vle_legacy_load_cluster_from_disk(m, lcn); - - if (datamode == EROFS_INODE_FLAT_COMPRESSION) - return compacted_load_cluster_from_disk(m, lcn); - - return -EINVAL; -} - -static int vle_extent_lookback(struct z_erofs_maprecorder *m, - unsigned int lookback_distance) -{ - struct erofs_vnode *const vi = EROFS_V(m->inode); - struct erofs_map_blocks *const map = m->map; - const unsigned int lclusterbits = vi->z_logical_clusterbits; - unsigned long lcn = m->lcn; - int err; - - if (lcn < lookback_distance) { - errln("bogus lookback distance @ nid %llu", vi->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; - } - - /* load extent head logical cluster if needed */ - lcn -= lookback_distance; - err = vle_load_cluster_from_disk(m, lcn); - if (err) - return err; - - switch (m->type) { - case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: - if (unlikely(!m->delta[0])) { - errln("invalid lookback distance 0 at nid %llu", - vi->nid); - DBG_BUGON(1); - return -EFSCORRUPTED; - } - return vle_extent_lookback(m, m->delta[0]); - case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: - map->m_flags &= ~EROFS_MAP_ZIPPED; - /* fallthrough */ - case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: - map->m_la = (lcn << lclusterbits) | m->clusterofs; - break; - default: - errln("unknown type %u at lcn %lu of nid %llu", - m->type, lcn, vi->nid); - DBG_BUGON(1); - return -EOPNOTSUPP; - } - return 0; -} - -int z_erofs_map_blocks_iter(struct inode *inode, - struct erofs_map_blocks *map, - int flags) -{ - struct erofs_vnode *const vi = EROFS_V(inode); - struct z_erofs_maprecorder m = { - .inode = inode, - .map = map, - }; - int err = 0; - unsigned int lclusterbits, endoff; - unsigned long long ofs, end; - - trace_z_erofs_map_blocks_iter_enter(inode, map, flags); - - /* when trying to read beyond EOF, leave it unmapped */ - if (unlikely(map->m_la >= inode->i_size)) { - map->m_llen = map->m_la + 1 - inode->i_size; - map->m_la = inode->i_size; - map->m_flags = 0; - goto out; - } - - err = fill_inode_lazy(inode); - if (err) - goto out; - - lclusterbits = vi->z_logical_clusterbits; - ofs = map->m_la; - m.lcn = ofs >> lclusterbits; - endoff = ofs & ((1 << lclusterbits) - 1); - - err = vle_load_cluster_from_disk(&m, m.lcn); - if (err) - goto unmap_out; - - map->m_flags = EROFS_MAP_ZIPPED; /* by default, compressed */ - end = (m.lcn + 1ULL) << lclusterbits; - - switch (m.type) { - case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: - if (endoff >= m.clusterofs) - map->m_flags &= ~EROFS_MAP_ZIPPED; - /* fallthrough */ - case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: - if (endoff >= m.clusterofs) { - map->m_la = (m.lcn << lclusterbits) | m.clusterofs; - break; - } - /* m.lcn should be >= 1 if endoff < m.clusterofs */ - if (unlikely(!m.lcn)) { - errln("invalid logical cluster 0 at nid %llu", - vi->nid); - err = -EFSCORRUPTED; - goto unmap_out; - } - end = (m.lcn << lclusterbits) | m.clusterofs; - map->m_flags |= EROFS_MAP_FULL_MAPPED; - m.delta[0] = 1; - /* fallthrough */ - case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: - /* get the correspoinding first chunk */ - err = vle_extent_lookback(&m, m.delta[0]); - if (unlikely(err)) - goto unmap_out; - break; - default: - errln("unknown type %u at offset %llu of nid %llu", - m.type, ofs, vi->nid); - err = -EOPNOTSUPP; - goto unmap_out; - } - - map->m_llen = end - map->m_la; - map->m_plen = 1 << lclusterbits; - map->m_pa = blknr_to_addr(m.pblk); - map->m_flags |= EROFS_MAP_MAPPED; - -unmap_out: - if (m.kaddr) - kunmap_atomic(m.kaddr); - -out: - debugln("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o", - __func__, map->m_la, map->m_pa, - map->m_llen, map->m_plen, map->m_flags); - - trace_z_erofs_map_blocks_iter_exit(inode, map, flags, err); - - /* aggressively BUG_ON iff CONFIG_EROFS_FS_DEBUG is on */ - DBG_BUGON(err < 0 && err != -ENOMEM); - return err; -} - diff --git a/drivers/staging/erofs/zpvec.h b/drivers/staging/erofs/zpvec.h deleted file mode 100644 index 9798f5627786..000000000000 --- a/drivers/staging/erofs/zpvec.h +++ /dev/null @@ -1,159 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/drivers/staging/erofs/zpvec.h - * - * Copyright (C) 2018 HUAWEI, Inc. - * http://www.huawei.com/ - * Created by Gao Xiang - */ -#ifndef __EROFS_FS_ZPVEC_H -#define __EROFS_FS_ZPVEC_H - -#include "tagptr.h" - -/* page type in pagevec for decompress subsystem */ -enum z_erofs_page_type { - /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ - Z_EROFS_PAGE_TYPE_EXCLUSIVE, - - Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED, - - Z_EROFS_VLE_PAGE_TYPE_HEAD, - Z_EROFS_VLE_PAGE_TYPE_MAX -}; - -extern void __compiletime_error("Z_EROFS_PAGE_TYPE_EXCLUSIVE != 0") - __bad_page_type_exclusive(void); - -/* pagevec tagged pointer */ -typedef tagptr2_t erofs_vtptr_t; - -/* pagevec collector */ -struct z_erofs_pagevec_ctor { - struct page *curr, *next; - erofs_vtptr_t *pages; - - unsigned int nr, index; -}; - -static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, - bool atomic) -{ - if (!ctor->curr) - return; - - if (atomic) - kunmap_atomic(ctor->pages); - else - kunmap(ctor->curr); -} - -static inline struct page * -z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, - unsigned int nr) -{ - unsigned int index; - - /* keep away from occupied pages */ - if (ctor->next) - return ctor->next; - - for (index = 0; index < nr; ++index) { - const erofs_vtptr_t t = ctor->pages[index]; - const unsigned int tags = tagptr_unfold_tags(t); - - if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) - return tagptr_unfold_ptr(t); - } - DBG_BUGON(nr >= ctor->nr); - return NULL; -} - -static inline void -z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, - bool atomic) -{ - struct page *next = z_erofs_pagevec_ctor_next_page(ctor, ctor->nr); - - z_erofs_pagevec_ctor_exit(ctor, atomic); - - ctor->curr = next; - ctor->next = NULL; - ctor->pages = atomic ? - kmap_atomic(ctor->curr) : kmap(ctor->curr); - - ctor->nr = PAGE_SIZE / sizeof(struct page *); - ctor->index = 0; -} - -static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, - unsigned int nr, - erofs_vtptr_t *pages, - unsigned int i) -{ - ctor->nr = nr; - ctor->curr = ctor->next = NULL; - ctor->pages = pages; - - if (i >= nr) { - i -= nr; - z_erofs_pagevec_ctor_pagedown(ctor, false); - while (i > ctor->nr) { - i -= ctor->nr; - z_erofs_pagevec_ctor_pagedown(ctor, false); - } - } - ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); - ctor->index = i; -} - -static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, - struct page *page, - enum z_erofs_page_type type, - bool *occupied) -{ - *occupied = false; - if (unlikely(!ctor->next && type)) - if (ctor->index + 1 == ctor->nr) - return false; - - if (unlikely(ctor->index >= ctor->nr)) - z_erofs_pagevec_ctor_pagedown(ctor, false); - - /* exclusive page type must be 0 */ - if (Z_EROFS_PAGE_TYPE_EXCLUSIVE != (uintptr_t)NULL) - __bad_page_type_exclusive(); - - /* should remind that collector->next never equal to 1, 2 */ - if (type == (uintptr_t)ctor->next) { - ctor->next = page; - *occupied = true; - } - ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); - return true; -} - -static inline struct page * -z_erofs_pagevec_dequeue(struct z_erofs_pagevec_ctor *ctor, - enum z_erofs_page_type *type) -{ - erofs_vtptr_t t; - - if (unlikely(ctor->index >= ctor->nr)) { - DBG_BUGON(!ctor->next); - z_erofs_pagevec_ctor_pagedown(ctor, true); - } - - t = ctor->pages[ctor->index]; - - *type = tagptr_unfold_tags(t); - - /* should remind that collector->next never equal to 1, 2 */ - if (*type == (uintptr_t)ctor->next) - ctor->next = tagptr_unfold_ptr(t); - - ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, NULL, 0); - return tagptr_unfold_ptr(t); -} -#endif - diff --git a/fs/Kconfig b/fs/Kconfig index bfb1c6095c7a..669d46550e6d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -261,6 +261,7 @@ source "fs/romfs/Kconfig" source "fs/pstore/Kconfig" source "fs/sysv/Kconfig" source "fs/ufs/Kconfig" +source "fs/erofs/Kconfig" endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile index d60089fd689b..b2e4973a0bea 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -130,3 +130,4 @@ obj-$(CONFIG_F2FS_FS) += f2fs/ obj-$(CONFIG_CEPH_FS) += ceph/ obj-$(CONFIG_PSTORE) += pstore/ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ +obj-$(CONFIG_EROFS_FS) += erofs/ diff --git a/fs/erofs/Kconfig b/fs/erofs/Kconfig new file mode 100644 index 000000000000..16316d1adca3 --- /dev/null +++ b/fs/erofs/Kconfig @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config EROFS_FS + tristate "EROFS filesystem support" + depends on BLOCK + help + EROFS (Enhanced Read-Only File System) is a lightweight + read-only file system with modern designs (eg. page-sized + blocks, inline xattrs/data, etc.) for scenarios which need + high-performance read-only requirements, e.g. Android OS + for mobile phones and LIVECDs. + + It also provides fixed-sized output compression support, + which improves storage density, keeps relatively higher + compression ratios, which is more useful to achieve high + performance for embedded devices with limited memory. + + If unsure, say N. + +config EROFS_FS_DEBUG + bool "EROFS debugging feature" + depends on EROFS_FS + help + Print debugging messages and enable more BUG_ONs which check + filesystem consistency and find potential issues aggressively, + which can be used for Android eng build, for example. + + For daily use, say N. + +config EROFS_FAULT_INJECTION + bool "EROFS fault injection facility" + depends on EROFS_FS + help + Test EROFS to inject faults such as ENOMEM, EIO, and so on. + If unsure, say N. + +config EROFS_FS_XATTR + bool "EROFS extended attributes" + depends on EROFS_FS + default y + help + Extended attributes are name:value pairs associated with inodes by + the kernel or by users (see the attr(5) manual page, or visit + for details). + + If unsure, say N. + +config EROFS_FS_POSIX_ACL + bool "EROFS Access Control Lists" + depends on EROFS_FS_XATTR + select FS_POSIX_ACL + default y + help + Posix Access Control Lists (ACLs) support permissions for users and + groups beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the POSIX ACLs for + Linux website . + + If you don't know what Access Control Lists are, say N. + +config EROFS_FS_SECURITY + bool "EROFS Security Labels" + depends on EROFS_FS_XATTR + default y + help + Security labels provide an access control facility to support Linux + Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO + Linux. This option enables an extended attribute handler for file + security labels in the erofs filesystem, so that it requires enabling + the extended attribute support in advance. + + If you are not using a security module, say N. + +config EROFS_FS_ZIP + bool "EROFS Data Compression Support" + depends on EROFS_FS + select LZ4_DECOMPRESS + default y + help + Enable fixed-sized output compression for EROFS. + + If you don't want to enable compression feature, say N. + +config EROFS_FS_CLUSTER_PAGE_LIMIT + int "EROFS Cluster Pages Hard Limit" + depends on EROFS_FS_ZIP + range 1 256 + default "1" + help + Indicates maximum # of pages of a compressed + physical cluster. + + For example, if files in a image were compressed + into 8k-unit, hard limit should not be configured + less than 2. Otherwise, the image will be refused + to mount on this kernel. + diff --git a/fs/erofs/Makefile b/fs/erofs/Makefile new file mode 100644 index 000000000000..46f2aa4ba46c --- /dev/null +++ b/fs/erofs/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only + +EROFS_VERSION = "1.0" + +ccflags-y += -DEROFS_VERSION=\"$(EROFS_VERSION)\" + +obj-$(CONFIG_EROFS_FS) += erofs.o +erofs-objs := super.o inode.o data.o namei.o dir.o utils.o +erofs-$(CONFIG_EROFS_FS_XATTR) += xattr.o +erofs-$(CONFIG_EROFS_FS_ZIP) += decompressor.o zmap.o zdata.o + diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h new file mode 100644 index 000000000000..07d279fd5d67 --- /dev/null +++ b/fs/erofs/compress.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2019 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_FS_COMPRESS_H +#define __EROFS_FS_COMPRESS_H + +#include "internal.h" + +enum { + Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX, + Z_EROFS_COMPRESSION_RUNTIME_MAX +}; + +struct z_erofs_decompress_req { + struct super_block *sb; + struct page **in, **out; + + unsigned short pageofs_out; + unsigned int inputsize, outputsize; + + /* indicate the algorithm will be used for decompression */ + unsigned int alg; + bool inplace_io, partial_decoding; +}; + +/* + * - 0x5A110C8D ('sallocated', Z_EROFS_MAPPING_STAGING) - + * used to mark temporary allocated pages from other + * file/cached pages and NULL mapping pages. + */ +#define Z_EROFS_MAPPING_STAGING ((void *)0x5A110C8D) + +/* check if a page is marked as staging */ +static inline bool z_erofs_page_is_staging(struct page *page) +{ + return page->mapping == Z_EROFS_MAPPING_STAGING; +} + +static inline bool z_erofs_put_stagingpage(struct list_head *pagepool, + struct page *page) +{ + if (!z_erofs_page_is_staging(page)) + return false; + + /* staging pages should not be used by others at the same time */ + if (page_ref_count(page) > 1) + put_page(page); + else + list_add(&page->lru, pagepool); + return true; +} + +int z_erofs_decompress(struct z_erofs_decompress_req *rq, + struct list_head *pagepool); + +#endif + diff --git a/fs/erofs/data.c b/fs/erofs/data.c new file mode 100644 index 000000000000..fda16ec8863e --- /dev/null +++ b/fs/erofs/data.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "internal.h" +#include + +#include + +static inline void read_endio(struct bio *bio) +{ + struct super_block *const sb = bio->bi_private; + struct bio_vec *bvec; + blk_status_t err = bio->bi_status; + struct bvec_iter_all iter_all; + + if (time_to_inject(EROFS_SB(sb), FAULT_READ_IO)) { + erofs_show_injection_info(FAULT_READ_IO); + err = BLK_STS_IOERR; + } + + bio_for_each_segment_all(bvec, bio, iter_all) { + struct page *page = bvec->bv_page; + + /* page is already locked */ + DBG_BUGON(PageUptodate(page)); + + if (unlikely(err)) + SetPageError(page); + else + SetPageUptodate(page); + + unlock_page(page); + /* page could be reclaimed now */ + } + bio_put(bio); +} + +/* prio -- true is used for dir */ +struct page *__erofs_get_meta_page(struct super_block *sb, + erofs_blk_t blkaddr, bool prio, bool nofail) +{ + struct inode *const bd_inode = sb->s_bdev->bd_inode; + struct address_space *const mapping = bd_inode->i_mapping; + /* prefer retrying in the allocator to blindly looping below */ + const gfp_t gfp = mapping_gfp_constraint(mapping, ~__GFP_FS) | + (nofail ? __GFP_NOFAIL : 0); + unsigned int io_retries = nofail ? EROFS_IO_MAX_RETRIES_NOFAIL : 0; + struct page *page; + int err; + +repeat: + page = find_or_create_page(mapping, blkaddr, gfp); + if (unlikely(!page)) { + DBG_BUGON(nofail); + return ERR_PTR(-ENOMEM); + } + DBG_BUGON(!PageLocked(page)); + + if (!PageUptodate(page)) { + struct bio *bio; + + bio = erofs_grab_bio(sb, blkaddr, 1, sb, read_endio, nofail); + if (IS_ERR(bio)) { + DBG_BUGON(nofail); + err = PTR_ERR(bio); + goto err_out; + } + + err = bio_add_page(bio, page, PAGE_SIZE, 0); + if (unlikely(err != PAGE_SIZE)) { + err = -EFAULT; + goto err_out; + } + + __submit_bio(bio, REQ_OP_READ, + REQ_META | (prio ? REQ_PRIO : 0)); + + lock_page(page); + + /* this page has been truncated by others */ + if (unlikely(page->mapping != mapping)) { +unlock_repeat: + unlock_page(page); + put_page(page); + goto repeat; + } + + /* more likely a read error */ + if (unlikely(!PageUptodate(page))) { + if (io_retries) { + --io_retries; + goto unlock_repeat; + } + err = -EIO; + goto err_out; + } + } + return page; + +err_out: + unlock_page(page); + put_page(page); + return ERR_PTR(err); +} + +static int erofs_map_blocks_flatmode(struct inode *inode, + struct erofs_map_blocks *map, + int flags) +{ + int err = 0; + erofs_blk_t nblocks, lastblk; + u64 offset = map->m_la; + struct erofs_vnode *vi = EROFS_V(inode); + + trace_erofs_map_blocks_flatmode_enter(inode, map, flags); + + nblocks = DIV_ROUND_UP(inode->i_size, PAGE_SIZE); + lastblk = nblocks - is_inode_flat_inline(inode); + + if (unlikely(offset >= inode->i_size)) { + /* leave out-of-bound access unmapped */ + map->m_flags = 0; + map->m_plen = 0; + goto out; + } + + /* there is no hole in flatmode */ + map->m_flags = EROFS_MAP_MAPPED; + + if (offset < blknr_to_addr(lastblk)) { + map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la; + map->m_plen = blknr_to_addr(lastblk) - offset; + } else if (is_inode_flat_inline(inode)) { + /* 2 - inode inline B: inode, [xattrs], inline last blk... */ + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); + + map->m_pa = iloc(sbi, vi->nid) + vi->inode_isize + + vi->xattr_isize + erofs_blkoff(map->m_la); + map->m_plen = inode->i_size - offset; + + /* inline data should be located in one meta block */ + if (erofs_blkoff(map->m_pa) + map->m_plen > PAGE_SIZE) { + errln("inline data cross block boundary @ nid %llu", + vi->nid); + DBG_BUGON(1); + err = -EFSCORRUPTED; + goto err_out; + } + + map->m_flags |= EROFS_MAP_META; + } else { + errln("internal error @ nid: %llu (size %llu), m_la 0x%llx", + vi->nid, inode->i_size, map->m_la); + DBG_BUGON(1); + err = -EIO; + goto err_out; + } + +out: + map->m_llen = map->m_plen; + +err_out: + trace_erofs_map_blocks_flatmode_exit(inode, map, flags, 0); + return err; +} + +int erofs_map_blocks(struct inode *inode, + struct erofs_map_blocks *map, int flags) +{ + if (unlikely(is_inode_layout_compression(inode))) { + int err = z_erofs_map_blocks_iter(inode, map, flags); + + if (map->mpage) { + put_page(map->mpage); + map->mpage = NULL; + } + return err; + } + return erofs_map_blocks_flatmode(inode, map, flags); +} + +static inline struct bio *erofs_read_raw_page(struct bio *bio, + struct address_space *mapping, + struct page *page, + erofs_off_t *last_block, + unsigned int nblocks, + bool ra) +{ + struct inode *const inode = mapping->host; + struct super_block *const sb = inode->i_sb; + erofs_off_t current_block = (erofs_off_t)page->index; + int err; + + DBG_BUGON(!nblocks); + + if (PageUptodate(page)) { + err = 0; + goto has_updated; + } + + /* note that for readpage case, bio also equals to NULL */ + if (bio && + /* not continuous */ + *last_block + 1 != current_block) { +submit_bio_retry: + __submit_bio(bio, REQ_OP_READ, 0); + bio = NULL; + } + + if (!bio) { + struct erofs_map_blocks map = { + .m_la = blknr_to_addr(current_block), + }; + erofs_blk_t blknr; + unsigned int blkoff; + + err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); + if (unlikely(err)) + goto err_out; + + /* zero out the holed page */ + if (unlikely(!(map.m_flags & EROFS_MAP_MAPPED))) { + zero_user_segment(page, 0, PAGE_SIZE); + SetPageUptodate(page); + + /* imply err = 0, see erofs_map_blocks */ + goto has_updated; + } + + /* for RAW access mode, m_plen must be equal to m_llen */ + DBG_BUGON(map.m_plen != map.m_llen); + + blknr = erofs_blknr(map.m_pa); + blkoff = erofs_blkoff(map.m_pa); + + /* deal with inline page */ + if (map.m_flags & EROFS_MAP_META) { + void *vsrc, *vto; + struct page *ipage; + + DBG_BUGON(map.m_plen > PAGE_SIZE); + + ipage = erofs_get_meta_page(inode->i_sb, blknr, 0); + + if (IS_ERR(ipage)) { + err = PTR_ERR(ipage); + goto err_out; + } + + vsrc = kmap_atomic(ipage); + vto = kmap_atomic(page); + memcpy(vto, vsrc + blkoff, map.m_plen); + memset(vto + map.m_plen, 0, PAGE_SIZE - map.m_plen); + kunmap_atomic(vto); + kunmap_atomic(vsrc); + flush_dcache_page(page); + + SetPageUptodate(page); + /* TODO: could we unlock the page earlier? */ + unlock_page(ipage); + put_page(ipage); + + /* imply err = 0, see erofs_map_blocks */ + goto has_updated; + } + + /* pa must be block-aligned for raw reading */ + DBG_BUGON(erofs_blkoff(map.m_pa)); + + /* max # of continuous pages */ + if (nblocks > DIV_ROUND_UP(map.m_plen, PAGE_SIZE)) + nblocks = DIV_ROUND_UP(map.m_plen, PAGE_SIZE); + if (nblocks > BIO_MAX_PAGES) + nblocks = BIO_MAX_PAGES; + + bio = erofs_grab_bio(sb, blknr, nblocks, sb, + read_endio, false); + if (IS_ERR(bio)) { + err = PTR_ERR(bio); + bio = NULL; + goto err_out; + } + } + + err = bio_add_page(bio, page, PAGE_SIZE, 0); + /* out of the extent or bio is full */ + if (err < PAGE_SIZE) + goto submit_bio_retry; + + *last_block = current_block; + + /* shift in advance in case of it followed by too many gaps */ + if (bio->bi_iter.bi_size >= bio->bi_max_vecs * PAGE_SIZE) { + /* err should reassign to 0 after submitting */ + err = 0; + goto submit_bio_out; + } + + return bio; + +err_out: + /* for sync reading, set page error immediately */ + if (!ra) { + SetPageError(page); + ClearPageUptodate(page); + } +has_updated: + unlock_page(page); + + /* if updated manually, continuous pages has a gap */ + if (bio) +submit_bio_out: + __submit_bio(bio, REQ_OP_READ, 0); + + return unlikely(err) ? ERR_PTR(err) : NULL; +} + +/* + * since we dont have write or truncate flows, so no inode + * locking needs to be held at the moment. + */ +static int erofs_raw_access_readpage(struct file *file, struct page *page) +{ + erofs_off_t last_block; + struct bio *bio; + + trace_erofs_readpage(page, true); + + bio = erofs_read_raw_page(NULL, page->mapping, + page, &last_block, 1, false); + + if (IS_ERR(bio)) + return PTR_ERR(bio); + + DBG_BUGON(bio); /* since we have only one bio -- must be NULL */ + return 0; +} + +static int erofs_raw_access_readpages(struct file *filp, + struct address_space *mapping, + struct list_head *pages, + unsigned int nr_pages) +{ + erofs_off_t last_block; + struct bio *bio = NULL; + gfp_t gfp = readahead_gfp_mask(mapping); + struct page *page = list_last_entry(pages, struct page, lru); + + trace_erofs_readpages(mapping->host, page, nr_pages, true); + + for (; nr_pages; --nr_pages) { + page = list_entry(pages->prev, struct page, lru); + + prefetchw(&page->flags); + list_del(&page->lru); + + if (!add_to_page_cache_lru(page, mapping, page->index, gfp)) { + bio = erofs_read_raw_page(bio, mapping, page, + &last_block, nr_pages, true); + + /* all the page errors are ignored when readahead */ + if (IS_ERR(bio)) { + pr_err("%s, readahead error at page %lu of nid %llu\n", + __func__, page->index, + EROFS_V(mapping->host)->nid); + + bio = NULL; + } + } + + /* pages could still be locked */ + put_page(page); + } + DBG_BUGON(!list_empty(pages)); + + /* the rare case (end in gaps) */ + if (unlikely(bio)) + __submit_bio(bio, REQ_OP_READ, 0); + return 0; +} + +static int erofs_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int create) +{ + struct erofs_map_blocks map = { + .m_la = iblock << 9, + }; + int err; + + err = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW); + if (err) + return err; + + if (map.m_flags & EROFS_MAP_MAPPED) + bh->b_blocknr = erofs_blknr(map.m_pa); + + return err; +} + +static sector_t erofs_bmap(struct address_space *mapping, sector_t block) +{ + struct inode *inode = mapping->host; + + if (is_inode_flat_inline(inode)) { + erofs_blk_t blks = i_size_read(inode) >> LOG_BLOCK_SIZE; + + if (block >> LOG_SECTORS_PER_BLOCK >= blks) + return 0; + } + + return generic_block_bmap(mapping, block, erofs_get_block); +} + +/* for uncompressed (aligned) files and raw access for other files */ +const struct address_space_operations erofs_raw_access_aops = { + .readpage = erofs_raw_access_readpage, + .readpages = erofs_raw_access_readpages, + .bmap = erofs_bmap, +}; + diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c new file mode 100644 index 000000000000..5f4b7f302863 --- /dev/null +++ b/fs/erofs/decompressor.c @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2019 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "compress.h" +#include +#include + +#ifndef LZ4_DISTANCE_MAX /* history window size */ +#define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */ +#endif + +#define LZ4_MAX_DISTANCE_PAGES (DIV_ROUND_UP(LZ4_DISTANCE_MAX, PAGE_SIZE) + 1) +#ifndef LZ4_DECOMPRESS_INPLACE_MARGIN +#define LZ4_DECOMPRESS_INPLACE_MARGIN(srcsize) (((srcsize) >> 8) + 32) +#endif + +struct z_erofs_decompressor { + /* + * if destpages have sparsed pages, fill them with bounce pages. + * it also check whether destpages indicate continuous physical memory. + */ + int (*prepare_destpages)(struct z_erofs_decompress_req *rq, + struct list_head *pagepool); + int (*decompress)(struct z_erofs_decompress_req *rq, u8 *out); + char *name; +}; + +static bool use_vmap; +module_param(use_vmap, bool, 0444); +MODULE_PARM_DESC(use_vmap, "Use vmap() instead of vm_map_ram() (default 0)"); + +static int lz4_prepare_destpages(struct z_erofs_decompress_req *rq, + struct list_head *pagepool) +{ + const unsigned int nr = + PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; + struct page *availables[LZ4_MAX_DISTANCE_PAGES] = { NULL }; + unsigned long bounced[DIV_ROUND_UP(LZ4_MAX_DISTANCE_PAGES, + BITS_PER_LONG)] = { 0 }; + void *kaddr = NULL; + unsigned int i, j, top; + + top = 0; + for (i = j = 0; i < nr; ++i, ++j) { + struct page *const page = rq->out[i]; + struct page *victim; + + if (j >= LZ4_MAX_DISTANCE_PAGES) + j = 0; + + /* 'valid' bounced can only be tested after a complete round */ + if (test_bit(j, bounced)) { + DBG_BUGON(i < LZ4_MAX_DISTANCE_PAGES); + DBG_BUGON(top >= LZ4_MAX_DISTANCE_PAGES); + availables[top++] = rq->out[i - LZ4_MAX_DISTANCE_PAGES]; + } + + if (page) { + __clear_bit(j, bounced); + if (kaddr) { + if (kaddr + PAGE_SIZE == page_address(page)) + kaddr += PAGE_SIZE; + else + kaddr = NULL; + } else if (!i) { + kaddr = page_address(page); + } + continue; + } + kaddr = NULL; + __set_bit(j, bounced); + + if (top) { + victim = availables[--top]; + get_page(victim); + } else { + victim = erofs_allocpage(pagepool, GFP_KERNEL, false); + if (unlikely(!victim)) + return -ENOMEM; + victim->mapping = Z_EROFS_MAPPING_STAGING; + } + rq->out[i] = victim; + } + return kaddr ? 1 : 0; +} + +static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq, + u8 *src, unsigned int pageofs_in) +{ + /* + * if in-place decompression is ongoing, those decompressed + * pages should be copied in order to avoid being overlapped. + */ + struct page **in = rq->in; + u8 *const tmp = erofs_get_pcpubuf(0); + u8 *tmpp = tmp; + unsigned int inlen = rq->inputsize - pageofs_in; + unsigned int count = min_t(uint, inlen, PAGE_SIZE - pageofs_in); + + while (tmpp < tmp + inlen) { + if (!src) + src = kmap_atomic(*in); + memcpy(tmpp, src + pageofs_in, count); + kunmap_atomic(src); + src = NULL; + tmpp += count; + pageofs_in = 0; + count = PAGE_SIZE; + ++in; + } + return tmp; +} + +static int lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) +{ + unsigned int inputmargin, inlen; + u8 *src; + bool copied, support_0padding; + int ret; + + if (rq->inputsize > PAGE_SIZE) + return -EOPNOTSUPP; + + src = kmap_atomic(*rq->in); + inputmargin = 0; + support_0padding = false; + + /* decompression inplace is only safe when 0padding is enabled */ + if (EROFS_SB(rq->sb)->requirements & EROFS_REQUIREMENT_LZ4_0PADDING) { + support_0padding = true; + + while (!src[inputmargin & ~PAGE_MASK]) + if (!(++inputmargin & ~PAGE_MASK)) + break; + + if (inputmargin >= rq->inputsize) { + kunmap_atomic(src); + return -EIO; + } + } + + copied = false; + inlen = rq->inputsize - inputmargin; + if (rq->inplace_io) { + const uint oend = (rq->pageofs_out + + rq->outputsize) & ~PAGE_MASK; + const uint nr = PAGE_ALIGN(rq->pageofs_out + + rq->outputsize) >> PAGE_SHIFT; + + if (rq->partial_decoding || !support_0padding || + rq->out[nr - 1] != rq->in[0] || + rq->inputsize - oend < + LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) { + src = generic_copy_inplace_data(rq, src, inputmargin); + inputmargin = 0; + copied = true; + } + } + + ret = LZ4_decompress_safe_partial(src + inputmargin, out, + inlen, rq->outputsize, + rq->outputsize); + if (ret < 0) { + errln("%s, failed to decompress, in[%p, %u, %u] out[%p, %u]", + __func__, src + inputmargin, inlen, inputmargin, + out, rq->outputsize); + WARN_ON(1); + print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, + 16, 1, src + inputmargin, inlen, true); + print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, + 16, 1, out, rq->outputsize, true); + ret = -EIO; + } + + if (copied) + erofs_put_pcpubuf(src); + else + kunmap_atomic(src); + return ret; +} + +static struct z_erofs_decompressor decompressors[] = { + [Z_EROFS_COMPRESSION_SHIFTED] = { + .name = "shifted" + }, + [Z_EROFS_COMPRESSION_LZ4] = { + .prepare_destpages = lz4_prepare_destpages, + .decompress = lz4_decompress, + .name = "lz4" + }, +}; + +static void copy_from_pcpubuf(struct page **out, const char *dst, + unsigned short pageofs_out, + unsigned int outputsize) +{ + const char *end = dst + outputsize; + const unsigned int righthalf = PAGE_SIZE - pageofs_out; + const char *cur = dst - pageofs_out; + + while (cur < end) { + struct page *const page = *out++; + + if (page) { + char *buf = kmap_atomic(page); + + if (cur >= dst) { + memcpy(buf, cur, min_t(uint, PAGE_SIZE, + end - cur)); + } else { + memcpy(buf + pageofs_out, cur + pageofs_out, + min_t(uint, righthalf, end - cur)); + } + kunmap_atomic(buf); + } + cur += PAGE_SIZE; + } +} + +static void *erofs_vmap(struct page **pages, unsigned int count) +{ + int i = 0; + + if (use_vmap) + return vmap(pages, count, VM_MAP, PAGE_KERNEL); + + while (1) { + void *addr = vm_map_ram(pages, count, -1, PAGE_KERNEL); + + /* retry two more times (totally 3 times) */ + if (addr || ++i >= 3) + return addr; + vm_unmap_aliases(); + } + return NULL; +} + +static void erofs_vunmap(const void *mem, unsigned int count) +{ + if (!use_vmap) + vm_unmap_ram(mem, count); + else + vunmap(mem); +} + +static int decompress_generic(struct z_erofs_decompress_req *rq, + struct list_head *pagepool) +{ + const unsigned int nrpages_out = + PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; + const struct z_erofs_decompressor *alg = decompressors + rq->alg; + unsigned int dst_maptype; + void *dst; + int ret; + + if (nrpages_out == 1 && !rq->inplace_io) { + DBG_BUGON(!*rq->out); + dst = kmap_atomic(*rq->out); + dst_maptype = 0; + goto dstmap_out; + } + + /* + * For the case of small output size (especially much less + * than PAGE_SIZE), memcpy the decompressed data rather than + * compressed data is preferred. + */ + if (rq->outputsize <= PAGE_SIZE * 7 / 8) { + dst = erofs_get_pcpubuf(0); + if (IS_ERR(dst)) + return PTR_ERR(dst); + + rq->inplace_io = false; + ret = alg->decompress(rq, dst); + if (!ret) + copy_from_pcpubuf(rq->out, dst, rq->pageofs_out, + rq->outputsize); + + erofs_put_pcpubuf(dst); + return ret; + } + + ret = alg->prepare_destpages(rq, pagepool); + if (ret < 0) { + return ret; + } else if (ret) { + dst = page_address(*rq->out); + dst_maptype = 1; + goto dstmap_out; + } + + dst = erofs_vmap(rq->out, nrpages_out); + if (!dst) + return -ENOMEM; + dst_maptype = 2; + +dstmap_out: + ret = alg->decompress(rq, dst + rq->pageofs_out); + + if (!dst_maptype) + kunmap_atomic(dst); + else if (dst_maptype == 2) + erofs_vunmap(dst, nrpages_out); + return ret; +} + +static int shifted_decompress(const struct z_erofs_decompress_req *rq, + struct list_head *pagepool) +{ + const unsigned int nrpages_out = + PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT; + const unsigned int righthalf = PAGE_SIZE - rq->pageofs_out; + unsigned char *src, *dst; + + if (nrpages_out > 2) { + DBG_BUGON(1); + return -EIO; + } + + if (rq->out[0] == *rq->in) { + DBG_BUGON(nrpages_out != 1); + return 0; + } + + src = kmap_atomic(*rq->in); + if (!rq->out[0]) { + dst = NULL; + } else { + dst = kmap_atomic(rq->out[0]); + memcpy(dst + rq->pageofs_out, src, righthalf); + } + + if (rq->out[1] == *rq->in) { + memmove(src, src + righthalf, rq->pageofs_out); + } else if (nrpages_out == 2) { + if (dst) + kunmap_atomic(dst); + DBG_BUGON(!rq->out[1]); + dst = kmap_atomic(rq->out[1]); + memcpy(dst, src + righthalf, rq->pageofs_out); + } + if (dst) + kunmap_atomic(dst); + kunmap_atomic(src); + return 0; +} + +int z_erofs_decompress(struct z_erofs_decompress_req *rq, + struct list_head *pagepool) +{ + if (rq->alg == Z_EROFS_COMPRESSION_SHIFTED) + return shifted_decompress(rq, pagepool); + return decompress_generic(rq, pagepool); +} + diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c new file mode 100644 index 000000000000..1976e60e5174 --- /dev/null +++ b/fs/erofs/dir.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "internal.h" + +static void debug_one_dentry(unsigned char d_type, const char *de_name, + unsigned int de_namelen) +{ +#ifdef CONFIG_EROFS_FS_DEBUG + /* since the on-disk name could not have the trailing '\0' */ + unsigned char dbg_namebuf[EROFS_NAME_LEN + 1]; + + memcpy(dbg_namebuf, de_name, de_namelen); + dbg_namebuf[de_namelen] = '\0'; + + debugln("found dirent %s de_len %u d_type %d", dbg_namebuf, + de_namelen, d_type); +#endif +} + +static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx, + void *dentry_blk, unsigned int *ofs, + unsigned int nameoff, unsigned int maxsize) +{ + struct erofs_dirent *de = dentry_blk + *ofs; + const struct erofs_dirent *end = dentry_blk + nameoff; + + while (de < end) { + const char *de_name; + unsigned int de_namelen; + unsigned char d_type; + + d_type = fs_ftype_to_dtype(de->file_type); + + nameoff = le16_to_cpu(de->nameoff); + de_name = (char *)dentry_blk + nameoff; + + /* the last dirent in the block? */ + if (de + 1 >= end) + de_namelen = strnlen(de_name, maxsize - nameoff); + else + de_namelen = le16_to_cpu(de[1].nameoff) - nameoff; + + /* a corrupted entry is found */ + if (unlikely(nameoff + de_namelen > maxsize || + de_namelen > EROFS_NAME_LEN)) { + errln("bogus dirent @ nid %llu", EROFS_V(dir)->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } + + debug_one_dentry(d_type, de_name, de_namelen); + if (!dir_emit(ctx, de_name, de_namelen, + le64_to_cpu(de->nid), d_type)) + /* stopped by some reason */ + return 1; + ++de; + *ofs += sizeof(struct erofs_dirent); + } + *ofs = maxsize; + return 0; +} + +static int erofs_readdir(struct file *f, struct dir_context *ctx) +{ + struct inode *dir = file_inode(f); + struct address_space *mapping = dir->i_mapping; + const size_t dirsize = i_size_read(dir); + unsigned int i = ctx->pos / EROFS_BLKSIZ; + unsigned int ofs = ctx->pos % EROFS_BLKSIZ; + int err = 0; + bool initial = true; + + while (ctx->pos < dirsize) { + struct page *dentry_page; + struct erofs_dirent *de; + unsigned int nameoff, maxsize; + + dentry_page = read_mapping_page(mapping, i, NULL); + if (dentry_page == ERR_PTR(-ENOMEM)) { + err = -ENOMEM; + break; + } else if (IS_ERR(dentry_page)) { + errln("fail to readdir of logical block %u of nid %llu", + i, EROFS_V(dir)->nid); + err = -EFSCORRUPTED; + break; + } + + de = (struct erofs_dirent *)kmap(dentry_page); + + nameoff = le16_to_cpu(de->nameoff); + + if (unlikely(nameoff < sizeof(struct erofs_dirent) || + nameoff >= PAGE_SIZE)) { + errln("%s, invalid de[0].nameoff %u @ nid %llu", + __func__, nameoff, EROFS_V(dir)->nid); + err = -EFSCORRUPTED; + goto skip_this; + } + + maxsize = min_t(unsigned int, + dirsize - ctx->pos + ofs, PAGE_SIZE); + + /* search dirents at the arbitrary position */ + if (unlikely(initial)) { + initial = false; + + ofs = roundup(ofs, sizeof(struct erofs_dirent)); + if (unlikely(ofs >= nameoff)) + goto skip_this; + } + + err = erofs_fill_dentries(dir, ctx, de, &ofs, + nameoff, maxsize); +skip_this: + kunmap(dentry_page); + + put_page(dentry_page); + + ctx->pos = blknr_to_addr(i) + ofs; + + if (unlikely(err)) + break; + ++i; + ofs = 0; + } + return err < 0 ? err : 0; +} + +const struct file_operations erofs_dir_fops = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate_shared = erofs_readdir, +}; + diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h new file mode 100644 index 000000000000..afa7d45ca958 --- /dev/null +++ b/fs/erofs/erofs_fs.h @@ -0,0 +1,307 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_FS_H +#define __EROFS_FS_H + +/* Enhanced(Extended) ROM File System */ +#define EROFS_SUPER_OFFSET 1024 + +/* + * Any bits that aren't in EROFS_ALL_REQUIREMENTS should be + * incompatible with this kernel version. + */ +#define EROFS_REQUIREMENT_LZ4_0PADDING 0x00000001 +#define EROFS_ALL_REQUIREMENTS EROFS_REQUIREMENT_LZ4_0PADDING + +struct erofs_super_block { +/* 0 */__le32 magic; /* in the little endian */ +/* 4 */__le32 checksum; /* crc32c(super_block) */ +/* 8 */__le32 features; /* (aka. feature_compat) */ +/* 12 */__u8 blkszbits; /* support block_size == PAGE_SIZE only */ +/* 13 */__u8 reserved; + +/* 14 */__le16 root_nid; +/* 16 */__le64 inos; /* total valid ino # (== f_files - f_favail) */ + +/* 24 */__le64 build_time; /* inode v1 time derivation */ +/* 32 */__le32 build_time_nsec; +/* 36 */__le32 blocks; /* used for statfs */ +/* 40 */__le32 meta_blkaddr; +/* 44 */__le32 xattr_blkaddr; +/* 48 */__u8 uuid[16]; /* 128-bit uuid for volume */ +/* 64 */__u8 volume_name[16]; /* volume name */ +/* 80 */__le32 requirements; /* (aka. feature_incompat) */ + +/* 84 */__u8 reserved2[44]; +} __packed; /* 128 bytes */ + +/* + * erofs inode data mapping: + * 0 - inode plain without inline data A: + * inode, [xattrs], ... | ... | no-holed data + * 1 - inode VLE compression B (legacy): + * inode, [xattrs], extents ... | ... + * 2 - inode plain with inline data C: + * inode, [xattrs], last_inline_data, ... | ... | no-holed data + * 3 - inode compression D: + * inode, [xattrs], map_header, extents ... | ... + * 4~7 - reserved + */ +enum { + EROFS_INODE_FLAT_PLAIN, + EROFS_INODE_FLAT_COMPRESSION_LEGACY, + EROFS_INODE_FLAT_INLINE, + EROFS_INODE_FLAT_COMPRESSION, + EROFS_INODE_LAYOUT_MAX +}; + +static inline bool erofs_inode_is_data_compressed(unsigned int datamode) +{ + if (datamode == EROFS_INODE_FLAT_COMPRESSION) + return true; + return datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY; +} + +/* bit definitions of inode i_advise */ +#define EROFS_I_VERSION_BITS 1 +#define EROFS_I_DATA_MAPPING_BITS 3 + +#define EROFS_I_VERSION_BIT 0 +#define EROFS_I_DATA_MAPPING_BIT 1 + +struct erofs_inode_v1 { +/* 0 */__le16 i_advise; + +/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ +/* 2 */__le16 i_xattr_icount; +/* 4 */__le16 i_mode; +/* 6 */__le16 i_nlink; +/* 8 */__le32 i_size; +/* 12 */__le32 i_reserved; +/* 16 */union { + /* file total compressed blocks for data mapping 1 */ + __le32 compressed_blocks; + __le32 raw_blkaddr; + + /* for device files, used to indicate old/new device # */ + __le32 rdev; + } i_u __packed; +/* 20 */__le32 i_ino; /* only used for 32-bit stat compatibility */ +/* 24 */__le16 i_uid; +/* 26 */__le16 i_gid; +/* 28 */__le32 i_reserved2; +} __packed; + +/* 32 bytes on-disk inode */ +#define EROFS_INODE_LAYOUT_V1 0 +/* 64 bytes on-disk inode */ +#define EROFS_INODE_LAYOUT_V2 1 + +struct erofs_inode_v2 { +/* 0 */__le16 i_advise; + +/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ +/* 2 */__le16 i_xattr_icount; +/* 4 */__le16 i_mode; +/* 6 */__le16 i_reserved; +/* 8 */__le64 i_size; +/* 16 */union { + /* file total compressed blocks for data mapping 1 */ + __le32 compressed_blocks; + __le32 raw_blkaddr; + + /* for device files, used to indicate old/new device # */ + __le32 rdev; + } i_u __packed; + + /* only used for 32-bit stat compatibility */ +/* 20 */__le32 i_ino; + +/* 24 */__le32 i_uid; +/* 28 */__le32 i_gid; +/* 32 */__le64 i_ctime; +/* 40 */__le32 i_ctime_nsec; +/* 44 */__le32 i_nlink; +/* 48 */__u8 i_reserved2[16]; +} __packed; /* 64 bytes */ + +#define EROFS_MAX_SHARED_XATTRS (128) +/* h_shared_count between 129 ... 255 are special # */ +#define EROFS_SHARED_XATTR_EXTENT (255) + +/* + * inline xattrs (n == i_xattr_icount): + * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes + * 12 bytes / \ + * / \ + * /-----------------------\ + * | erofs_xattr_entries+ | + * +-----------------------+ + * inline xattrs must starts in erofs_xattr_ibody_header, + * for read-only fs, no need to introduce h_refcount + */ +struct erofs_xattr_ibody_header { + __le32 h_reserved; + __u8 h_shared_count; + __u8 h_reserved2[7]; + __le32 h_shared_xattrs[0]; /* shared xattr id array */ +} __packed; + +/* Name indexes */ +#define EROFS_XATTR_INDEX_USER 1 +#define EROFS_XATTR_INDEX_POSIX_ACL_ACCESS 2 +#define EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 +#define EROFS_XATTR_INDEX_TRUSTED 4 +#define EROFS_XATTR_INDEX_LUSTRE 5 +#define EROFS_XATTR_INDEX_SECURITY 6 + +/* xattr entry (for both inline & shared xattrs) */ +struct erofs_xattr_entry { + __u8 e_name_len; /* length of name */ + __u8 e_name_index; /* attribute name index */ + __le16 e_value_size; /* size of attribute value */ + /* followed by e_name and e_value */ + char e_name[0]; /* attribute name */ +} __packed; + +#define ondisk_xattr_ibody_size(count) ({\ + u32 __count = le16_to_cpu(count); \ + ((__count) == 0) ? 0 : \ + sizeof(struct erofs_xattr_ibody_header) + \ + sizeof(__u32) * ((__count) - 1); }) + +#define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry)) +#define EROFS_XATTR_ENTRY_SIZE(entry) EROFS_XATTR_ALIGN( \ + sizeof(struct erofs_xattr_entry) + \ + (entry)->e_name_len + le16_to_cpu((entry)->e_value_size)) + +/* available compression algorithm types */ +enum { + Z_EROFS_COMPRESSION_LZ4, + Z_EROFS_COMPRESSION_MAX +}; + +/* + * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) + * e.g. for 4k logical cluster size, 4B if compacted 2B is off; + * (4B) + 2B + (4B) if compacted 2B is on. + */ +#define Z_EROFS_ADVISE_COMPACTED_2B_BIT 0 + +#define Z_EROFS_ADVISE_COMPACTED_2B (1 << Z_EROFS_ADVISE_COMPACTED_2B_BIT) + +struct z_erofs_map_header { + __le32 h_reserved1; + __le16 h_advise; + /* + * bit 0-3 : algorithm type of head 1 (logical cluster type 01); + * bit 4-7 : algorithm type of head 2 (logical cluster type 11). + */ + __u8 h_algorithmtype; + /* + * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; + * bit 3-4 : (physical - logical) cluster bits of head 1: + * For example, if logical clustersize = 4096, 1 for 8192. + * bit 5-7 : (physical - logical) cluster bits of head 2. + */ + __u8 h_clusterbits; +}; + +#define Z_EROFS_VLE_LEGACY_HEADER_PADDING 8 + +/* + * Z_EROFS Variable-sized Logical Extent cluster type: + * 0 - literal (uncompressed) cluster + * 1 - compressed cluster (for the head logical cluster) + * 2 - compressed cluster (for the other logical clusters) + * + * In detail, + * 0 - literal (uncompressed) cluster, + * di_advise = 0 + * di_clusterofs = the literal data offset of the cluster + * di_blkaddr = the blkaddr of the literal cluster + * + * 1 - compressed cluster (for the head logical cluster) + * di_advise = 1 + * di_clusterofs = the decompressed data offset of the cluster + * di_blkaddr = the blkaddr of the compressed cluster + * + * 2 - compressed cluster (for the other logical clusters) + * di_advise = 2 + * di_clusterofs = + * the decompressed data offset in its own head cluster + * di_u.delta[0] = distance to its corresponding head cluster + * di_u.delta[1] = distance to its corresponding tail cluster + * (di_advise could be 0, 1 or 2) + */ +enum { + Z_EROFS_VLE_CLUSTER_TYPE_PLAIN, + Z_EROFS_VLE_CLUSTER_TYPE_HEAD, + Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD, + Z_EROFS_VLE_CLUSTER_TYPE_RESERVED, + Z_EROFS_VLE_CLUSTER_TYPE_MAX +}; + +#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2 +#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0 + +struct z_erofs_vle_decompressed_index { + __le16 di_advise; + /* where to decompress in the head cluster */ + __le16 di_clusterofs; + + union { + /* for the head cluster */ + __le32 blkaddr; + /* + * for the rest clusters + * eg. for 4k page-sized cluster, maximum 4K*64k = 256M) + * [0] - pointing to the head cluster + * [1] - pointing to the tail cluster + */ + __le16 delta[2]; + } di_u __packed; /* 8 bytes */ +} __packed; + +#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \ + (round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \ + sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING) + +/* dirent sorts in alphabet order, thus we can do binary search */ +struct erofs_dirent { + __le64 nid; /* 0, node number */ + __le16 nameoff; /* 8, start offset of file name */ + __u8 file_type; /* 10, file type */ + __u8 reserved; /* 11, reserved */ +} __packed; + +/* + * EROFS file types should match generic FT_* types and + * it seems no need to add BUILD_BUG_ONs since potential + * unmatchness will break other fses as well... + */ + +#define EROFS_NAME_LEN 255 + +/* check the EROFS on-disk layout strictly at compile time */ +static inline void erofs_check_ondisk_layout_definitions(void) +{ + BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); + BUILD_BUG_ON(sizeof(struct erofs_inode_v1) != 32); + BUILD_BUG_ON(sizeof(struct erofs_inode_v2) != 64); + BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); + BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); + BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); + BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8); + BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); + + BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) < + Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1); +} + +#endif + diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c new file mode 100644 index 000000000000..80f4fe919ee7 --- /dev/null +++ b/fs/erofs/inode.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "xattr.h" + +#include + +/* no locking */ +static int read_inode(struct inode *inode, void *data) +{ + struct erofs_vnode *vi = EROFS_V(inode); + struct erofs_inode_v1 *v1 = data; + const unsigned int advise = le16_to_cpu(v1->i_advise); + erofs_blk_t nblks = 0; + + vi->datamode = __inode_data_mapping(advise); + + if (unlikely(vi->datamode >= EROFS_INODE_LAYOUT_MAX)) { + errln("unsupported data mapping %u of nid %llu", + vi->datamode, vi->nid); + DBG_BUGON(1); + return -EOPNOTSUPP; + } + + if (__inode_version(advise) == EROFS_INODE_LAYOUT_V2) { + struct erofs_inode_v2 *v2 = data; + + vi->inode_isize = sizeof(struct erofs_inode_v2); + vi->xattr_isize = ondisk_xattr_ibody_size(v2->i_xattr_icount); + + inode->i_mode = le16_to_cpu(v2->i_mode); + if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode)) + vi->raw_blkaddr = le32_to_cpu(v2->i_u.raw_blkaddr); + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + inode->i_rdev = + new_decode_dev(le32_to_cpu(v2->i_u.rdev)); + else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) + inode->i_rdev = 0; + else + goto bogusimode; + + i_uid_write(inode, le32_to_cpu(v2->i_uid)); + i_gid_write(inode, le32_to_cpu(v2->i_gid)); + set_nlink(inode, le32_to_cpu(v2->i_nlink)); + + /* ns timestamp */ + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = + le64_to_cpu(v2->i_ctime); + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = + le32_to_cpu(v2->i_ctime_nsec); + + inode->i_size = le64_to_cpu(v2->i_size); + + /* total blocks for compressed files */ + if (is_inode_layout_compression(inode)) + nblks = le32_to_cpu(v2->i_u.compressed_blocks); + } else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) { + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); + + vi->inode_isize = sizeof(struct erofs_inode_v1); + vi->xattr_isize = ondisk_xattr_ibody_size(v1->i_xattr_icount); + + inode->i_mode = le16_to_cpu(v1->i_mode); + if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode)) + vi->raw_blkaddr = le32_to_cpu(v1->i_u.raw_blkaddr); + else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + inode->i_rdev = + new_decode_dev(le32_to_cpu(v1->i_u.rdev)); + else if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) + inode->i_rdev = 0; + else + goto bogusimode; + + i_uid_write(inode, le16_to_cpu(v1->i_uid)); + i_gid_write(inode, le16_to_cpu(v1->i_gid)); + set_nlink(inode, le16_to_cpu(v1->i_nlink)); + + /* use build time to derive all file time */ + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = + sbi->build_time; + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = + sbi->build_time_nsec; + + inode->i_size = le32_to_cpu(v1->i_size); + if (is_inode_layout_compression(inode)) + nblks = le32_to_cpu(v1->i_u.compressed_blocks); + } else { + errln("unsupported on-disk inode version %u of nid %llu", + __inode_version(advise), vi->nid); + DBG_BUGON(1); + return -EOPNOTSUPP; + } + + if (!nblks) + /* measure inode.i_blocks as generic filesystems */ + inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9; + else + inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK; + return 0; + +bogusimode: + errln("bogus i_mode (%o) @ nid %llu", inode->i_mode, vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; +} + +/* + * try_lock can be required since locking order is: + * file data(fs_inode) + * meta(bd_inode) + * but the majority of the callers is "iget", + * in that case we are pretty sure no deadlock since + * no data operations exist. However I tend to + * try_lock since it takes no much overhead and + * will success immediately. + */ +static int fill_inline_data(struct inode *inode, void *data, + unsigned int m_pofs) +{ + struct erofs_vnode *vi = EROFS_V(inode); + struct erofs_sb_info *sbi = EROFS_I_SB(inode); + + /* should be inode inline C */ + if (!is_inode_flat_inline(inode)) + return 0; + + /* fast symlink (following ext4) */ + if (S_ISLNK(inode->i_mode) && inode->i_size < PAGE_SIZE) { + char *lnk = erofs_kmalloc(sbi, inode->i_size + 1, GFP_KERNEL); + + if (unlikely(!lnk)) + return -ENOMEM; + + m_pofs += vi->inode_isize + vi->xattr_isize; + + /* inline symlink data shouldn't across page boundary as well */ + if (unlikely(m_pofs + inode->i_size > PAGE_SIZE)) { + kfree(lnk); + errln("inline data cross block boundary @ nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } + + /* get in-page inline data */ + memcpy(lnk, data + m_pofs, inode->i_size); + lnk[inode->i_size] = '\0'; + + inode->i_link = lnk; + set_inode_fast_symlink(inode); + } + return 0; +} + +static int fill_inode(struct inode *inode, int isdir) +{ + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb); + struct erofs_vnode *vi = EROFS_V(inode); + struct page *page; + void *data; + int err; + erofs_blk_t blkaddr; + unsigned int ofs; + erofs_off_t inode_loc; + + trace_erofs_fill_inode(inode, isdir); + inode_loc = iloc(sbi, vi->nid); + blkaddr = erofs_blknr(inode_loc); + ofs = erofs_blkoff(inode_loc); + + debugln("%s, reading inode nid %llu at %u of blkaddr %u", + __func__, vi->nid, ofs, blkaddr); + + page = erofs_get_meta_page(inode->i_sb, blkaddr, isdir); + + if (IS_ERR(page)) { + errln("failed to get inode (nid: %llu) page, err %ld", + vi->nid, PTR_ERR(page)); + return PTR_ERR(page); + } + + DBG_BUGON(!PageUptodate(page)); + data = page_address(page); + + err = read_inode(inode, data + ofs); + if (!err) { + /* setup the new inode */ + if (S_ISREG(inode->i_mode)) { + inode->i_op = &erofs_generic_iops; + inode->i_fop = &generic_ro_fops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &erofs_dir_iops; + inode->i_fop = &erofs_dir_fops; + } else if (S_ISLNK(inode->i_mode)) { + /* by default, page_get_link is used for symlink */ + inode->i_op = &erofs_symlink_iops; + inode_nohighmem(inode); + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + inode->i_op = &erofs_generic_iops; + init_special_inode(inode, inode->i_mode, inode->i_rdev); + goto out_unlock; + } else { + err = -EFSCORRUPTED; + goto out_unlock; + } + + if (is_inode_layout_compression(inode)) { + err = z_erofs_fill_inode(inode); + goto out_unlock; + } + + inode->i_mapping->a_ops = &erofs_raw_access_aops; + + /* fill last page if inline data is available */ + err = fill_inline_data(inode, data, ofs); + } + +out_unlock: + unlock_page(page); + put_page(page); + return err; +} + +/* + * erofs nid is 64bits, but i_ino is 'unsigned long', therefore + * we should do more for 32-bit platform to find the right inode. + */ +#if BITS_PER_LONG == 32 +static int erofs_ilookup_test_actor(struct inode *inode, void *opaque) +{ + const erofs_nid_t nid = *(erofs_nid_t *)opaque; + + return EROFS_V(inode)->nid == nid; +} + +static int erofs_iget_set_actor(struct inode *inode, void *opaque) +{ + const erofs_nid_t nid = *(erofs_nid_t *)opaque; + + inode->i_ino = erofs_inode_hash(nid); + return 0; +} +#endif + +static inline struct inode *erofs_iget_locked(struct super_block *sb, + erofs_nid_t nid) +{ + const unsigned long hashval = erofs_inode_hash(nid); + +#if BITS_PER_LONG >= 64 + /* it is safe to use iget_locked for >= 64-bit platform */ + return iget_locked(sb, hashval); +#else + return iget5_locked(sb, hashval, erofs_ilookup_test_actor, + erofs_iget_set_actor, &nid); +#endif +} + +struct inode *erofs_iget(struct super_block *sb, + erofs_nid_t nid, + bool isdir) +{ + struct inode *inode = erofs_iget_locked(sb, nid); + + if (unlikely(!inode)) + return ERR_PTR(-ENOMEM); + + if (inode->i_state & I_NEW) { + int err; + struct erofs_vnode *vi = EROFS_V(inode); + + vi->nid = nid; + + err = fill_inode(inode, isdir); + if (likely(!err)) + unlock_new_inode(inode); + else { + iget_failed(inode); + inode = ERR_PTR(err); + } + } + return inode; +} + +int erofs_getattr(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int query_flags) +{ + struct inode *const inode = d_inode(path->dentry); + + if (is_inode_layout_compression(inode)) + stat->attributes |= STATX_ATTR_COMPRESSED; + + stat->attributes |= STATX_ATTR_IMMUTABLE; + stat->attributes_mask |= (STATX_ATTR_COMPRESSED | + STATX_ATTR_IMMUTABLE); + + generic_fillattr(inode, stat); + return 0; +} + +const struct inode_operations erofs_generic_iops = { + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + +const struct inode_operations erofs_symlink_iops = { + .get_link = page_get_link, + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + +const struct inode_operations erofs_fast_symlink_iops = { + .get_link = simple_get_link, + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h new file mode 100644 index 000000000000..620b73fcc416 --- /dev/null +++ b/fs/erofs/internal.h @@ -0,0 +1,553 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_INTERNAL_H +#define __EROFS_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "erofs_fs.h" + +/* redefine pr_fmt "erofs: " */ +#undef pr_fmt +#define pr_fmt(fmt) "erofs: " fmt + +#define errln(x, ...) pr_err(x "\n", ##__VA_ARGS__) +#define infoln(x, ...) pr_info(x "\n", ##__VA_ARGS__) +#ifdef CONFIG_EROFS_FS_DEBUG +#define debugln(x, ...) pr_debug(x "\n", ##__VA_ARGS__) +#define DBG_BUGON BUG_ON +#else +#define debugln(x, ...) ((void)0) +#define DBG_BUGON(x) ((void)(x)) +#endif /* !CONFIG_EROFS_FS_DEBUG */ + +enum { + FAULT_KMALLOC, + FAULT_READ_IO, + FAULT_MAX, +}; + +#ifdef CONFIG_EROFS_FAULT_INJECTION +extern const char *erofs_fault_name[FAULT_MAX]; +#define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type))) + +struct erofs_fault_info { + atomic_t inject_ops; + unsigned int inject_rate; + unsigned int inject_type; +}; +#endif /* CONFIG_EROFS_FAULT_INJECTION */ + +/* EROFS_SUPER_MAGIC_V1 to represent the whole file system */ +#define EROFS_SUPER_MAGIC EROFS_SUPER_MAGIC_V1 + +typedef u64 erofs_nid_t; +typedef u64 erofs_off_t; +/* data type for filesystem-wide blocks number */ +typedef u32 erofs_blk_t; + +struct erofs_sb_info { +#ifdef CONFIG_EROFS_FS_ZIP + /* list for all registered superblocks, mainly for shrinker */ + struct list_head list; + struct mutex umount_mutex; + + /* the dedicated workstation for compression */ + struct radix_tree_root workstn_tree; + + /* threshold for decompression synchronously */ + unsigned int max_sync_decompress_pages; + + unsigned int shrinker_run_no; + + /* current strategy of how to use managed cache */ + unsigned char cache_strategy; + + /* pseudo inode to manage cached pages */ + struct inode *managed_cache; +#endif /* CONFIG_EROFS_FS_ZIP */ + u32 blocks; + u32 meta_blkaddr; +#ifdef CONFIG_EROFS_FS_XATTR + u32 xattr_blkaddr; +#endif + + /* inode slot unit size in bit shift */ + unsigned char islotbits; + + u32 build_time_nsec; + u64 build_time; + + /* what we really care is nid, rather than ino.. */ + erofs_nid_t root_nid; + /* used for statfs, f_files - f_favail */ + u64 inos; + + u8 uuid[16]; /* 128-bit uuid for volume */ + u8 volume_name[16]; /* volume name */ + u32 requirements; + + unsigned int mount_opt; + +#ifdef CONFIG_EROFS_FAULT_INJECTION + struct erofs_fault_info fault_info; /* For fault injection */ +#endif +}; + +#ifdef CONFIG_EROFS_FAULT_INJECTION +#define erofs_show_injection_info(type) \ + infoln("inject %s in %s of %pS", erofs_fault_name[type], \ + __func__, __builtin_return_address(0)) + +static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) +{ + struct erofs_fault_info *ffi = &sbi->fault_info; + + if (!ffi->inject_rate) + return false; + + if (!IS_FAULT_SET(ffi, type)) + return false; + + atomic_inc(&ffi->inject_ops); + if (atomic_read(&ffi->inject_ops) >= ffi->inject_rate) { + atomic_set(&ffi->inject_ops, 0); + return true; + } + return false; +} +#else +static inline bool time_to_inject(struct erofs_sb_info *sbi, int type) +{ + return false; +} + +static inline void erofs_show_injection_info(int type) +{ +} +#endif /* !CONFIG_EROFS_FAULT_INJECTION */ + +static inline void *erofs_kmalloc(struct erofs_sb_info *sbi, + size_t size, gfp_t flags) +{ + if (time_to_inject(sbi, FAULT_KMALLOC)) { + erofs_show_injection_info(FAULT_KMALLOC); + return NULL; + } + return kmalloc(size, flags); +} + +#define EROFS_SB(sb) ((struct erofs_sb_info *)(sb)->s_fs_info) +#define EROFS_I_SB(inode) ((struct erofs_sb_info *)(inode)->i_sb->s_fs_info) + +/* Mount flags set via mount options or defaults */ +#define EROFS_MOUNT_XATTR_USER 0x00000010 +#define EROFS_MOUNT_POSIX_ACL 0x00000020 +#define EROFS_MOUNT_FAULT_INJECTION 0x00000040 + +#define clear_opt(sbi, option) ((sbi)->mount_opt &= ~EROFS_MOUNT_##option) +#define set_opt(sbi, option) ((sbi)->mount_opt |= EROFS_MOUNT_##option) +#define test_opt(sbi, option) ((sbi)->mount_opt & EROFS_MOUNT_##option) + +#ifdef CONFIG_EROFS_FS_ZIP +enum { + EROFS_ZIP_CACHE_DISABLED, + EROFS_ZIP_CACHE_READAHEAD, + EROFS_ZIP_CACHE_READAROUND +}; + +#define EROFS_LOCKED_MAGIC (INT_MIN | 0xE0F510CCL) + +/* basic unit of the workstation of a super_block */ +struct erofs_workgroup { + /* the workgroup index in the workstation */ + pgoff_t index; + + /* overall workgroup reference count */ + atomic_t refcount; +}; + +#if defined(CONFIG_SMP) +static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, + int val) +{ + preempt_disable(); + if (val != atomic_cmpxchg(&grp->refcount, val, EROFS_LOCKED_MAGIC)) { + preempt_enable(); + return false; + } + return true; +} + +static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp, + int orig_val) +{ + /* + * other observers should notice all modifications + * in the freezing period. + */ + smp_mb(); + atomic_set(&grp->refcount, orig_val); + preempt_enable(); +} + +static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) +{ + return atomic_cond_read_relaxed(&grp->refcount, + VAL != EROFS_LOCKED_MAGIC); +} +#else +static inline bool erofs_workgroup_try_to_freeze(struct erofs_workgroup *grp, + int val) +{ + preempt_disable(); + /* no need to spin on UP platforms, let's just disable preemption. */ + if (val != atomic_read(&grp->refcount)) { + preempt_enable(); + return false; + } + return true; +} + +static inline void erofs_workgroup_unfreeze(struct erofs_workgroup *grp, + int orig_val) +{ + preempt_enable(); +} + +static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp) +{ + int v = atomic_read(&grp->refcount); + + /* workgroup is never freezed on uniprocessor systems */ + DBG_BUGON(v == EROFS_LOCKED_MAGIC); + return v; +} +#endif /* !CONFIG_SMP */ + +/* hard limit of pages per compressed cluster */ +#define Z_EROFS_CLUSTER_MAX_PAGES (CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT) +#define EROFS_PCPUBUF_NR_PAGES Z_EROFS_CLUSTER_MAX_PAGES +#else +#define EROFS_PCPUBUF_NR_PAGES 0 +#endif /* !CONFIG_EROFS_FS_ZIP */ + +/* we strictly follow PAGE_SIZE and no buffer head yet */ +#define LOG_BLOCK_SIZE PAGE_SHIFT + +#undef LOG_SECTORS_PER_BLOCK +#define LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) + +#undef SECTORS_PER_BLOCK +#define SECTORS_PER_BLOCK (1 << SECTORS_PER_BLOCK) + +#define EROFS_BLKSIZ (1 << LOG_BLOCK_SIZE) + +#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ) +#error erofs cannot be used in this platform +#endif + +#define EROFS_IO_MAX_RETRIES_NOFAIL 5 + +#define ROOT_NID(sb) ((sb)->root_nid) + +#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ) +#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ) +#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ) + +static inline erofs_off_t iloc(struct erofs_sb_info *sbi, erofs_nid_t nid) +{ + return blknr_to_addr(sbi->meta_blkaddr) + (nid << sbi->islotbits); +} + +/* atomic flag definitions */ +#define EROFS_V_EA_INITED_BIT 0 +#define EROFS_V_Z_INITED_BIT 1 + +/* bitlock definitions (arranged in reverse order) */ +#define EROFS_V_BL_XATTR_BIT (BITS_PER_LONG - 1) +#define EROFS_V_BL_Z_BIT (BITS_PER_LONG - 2) + +struct erofs_vnode { + erofs_nid_t nid; + + /* atomic flags (including bitlocks) */ + unsigned long flags; + + unsigned char datamode; + unsigned char inode_isize; + unsigned short xattr_isize; + + unsigned int xattr_shared_count; + unsigned int *xattr_shared_xattrs; + + union { + erofs_blk_t raw_blkaddr; +#ifdef CONFIG_EROFS_FS_ZIP + struct { + unsigned short z_advise; + unsigned char z_algorithmtype[2]; + unsigned char z_logical_clusterbits; + unsigned char z_physical_clusterbits[2]; + }; +#endif /* CONFIG_EROFS_FS_ZIP */ + }; + /* the corresponding vfs inode */ + struct inode vfs_inode; +}; + +#define EROFS_V(ptr) \ + container_of(ptr, struct erofs_vnode, vfs_inode) + +#define __inode_advise(x, bit, bits) \ + (((x) >> (bit)) & ((1 << (bits)) - 1)) + +#define __inode_version(advise) \ + __inode_advise(advise, EROFS_I_VERSION_BIT, \ + EROFS_I_VERSION_BITS) + +#define __inode_data_mapping(advise) \ + __inode_advise(advise, EROFS_I_DATA_MAPPING_BIT,\ + EROFS_I_DATA_MAPPING_BITS) + +static inline unsigned long inode_datablocks(struct inode *inode) +{ + /* since i_size cannot be changed */ + return DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); +} + +static inline bool is_inode_layout_compression(struct inode *inode) +{ + return erofs_inode_is_data_compressed(EROFS_V(inode)->datamode); +} + +static inline bool is_inode_flat_inline(struct inode *inode) +{ + return EROFS_V(inode)->datamode == EROFS_INODE_FLAT_INLINE; +} + +extern const struct super_operations erofs_sops; + +extern const struct address_space_operations erofs_raw_access_aops; +#ifdef CONFIG_EROFS_FS_ZIP +extern const struct address_space_operations z_erofs_vle_normalaccess_aops; +#endif + +/* + * Logical to physical block mapping, used by erofs_map_blocks() + * + * Different with other file systems, it is used for 2 access modes: + * + * 1) RAW access mode: + * + * Users pass a valid (m_lblk, m_lofs -- usually 0) pair, + * and get the valid m_pblk, m_pofs and the longest m_len(in bytes). + * + * Note that m_lblk in the RAW access mode refers to the number of + * the compressed ondisk block rather than the uncompressed + * in-memory block for the compressed file. + * + * m_pofs equals to m_lofs except for the inline data page. + * + * 2) Normal access mode: + * + * If the inode is not compressed, it has no difference with + * the RAW access mode. However, if the inode is compressed, + * users should pass a valid (m_lblk, m_lofs) pair, and get + * the needed m_pblk, m_pofs, m_len to get the compressed data + * and the updated m_lblk, m_lofs which indicates the start + * of the corresponding uncompressed data in the file. + */ +enum { + BH_Zipped = BH_PrivateStart, + BH_FullMapped, +}; + +/* Has a disk mapping */ +#define EROFS_MAP_MAPPED (1 << BH_Mapped) +/* Located in metadata (could be copied from bd_inode) */ +#define EROFS_MAP_META (1 << BH_Meta) +/* The extent has been compressed */ +#define EROFS_MAP_ZIPPED (1 << BH_Zipped) +/* The length of extent is full */ +#define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped) + +struct erofs_map_blocks { + erofs_off_t m_pa, m_la; + u64 m_plen, m_llen; + + unsigned int m_flags; + + struct page *mpage; +}; + +/* Flags used by erofs_map_blocks() */ +#define EROFS_GET_BLOCKS_RAW 0x0001 + +/* zmap.c */ +#ifdef CONFIG_EROFS_FS_ZIP +int z_erofs_fill_inode(struct inode *inode); +int z_erofs_map_blocks_iter(struct inode *inode, + struct erofs_map_blocks *map, + int flags); +#else +static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; } +static inline int z_erofs_map_blocks_iter(struct inode *inode, + struct erofs_map_blocks *map, + int flags) +{ + return -EOPNOTSUPP; +} +#endif /* !CONFIG_EROFS_FS_ZIP */ + +/* data.c */ +static inline struct bio *erofs_grab_bio(struct super_block *sb, + erofs_blk_t blkaddr, + unsigned int nr_pages, + void *bi_private, bio_end_io_t endio, + bool nofail) +{ + const gfp_t gfp = GFP_NOIO; + struct bio *bio; + + do { + if (nr_pages == 1) { + bio = bio_alloc(gfp | (nofail ? __GFP_NOFAIL : 0), 1); + if (unlikely(!bio)) { + DBG_BUGON(nofail); + return ERR_PTR(-ENOMEM); + } + break; + } + bio = bio_alloc(gfp, nr_pages); + nr_pages /= 2; + } while (unlikely(!bio)); + + bio->bi_end_io = endio; + bio_set_dev(bio, sb->s_bdev); + bio->bi_iter.bi_sector = (sector_t)blkaddr << LOG_SECTORS_PER_BLOCK; + bio->bi_private = bi_private; + return bio; +} + +static inline void __submit_bio(struct bio *bio, unsigned int op, + unsigned int op_flags) +{ + bio_set_op_attrs(bio, op, op_flags); + submit_bio(bio); +} + +struct page *__erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr, + bool prio, bool nofail); + +static inline struct page *erofs_get_meta_page(struct super_block *sb, + erofs_blk_t blkaddr, bool prio) +{ + return __erofs_get_meta_page(sb, blkaddr, prio, false); +} + +int erofs_map_blocks(struct inode *, struct erofs_map_blocks *, int); + +static inline struct page *erofs_get_inline_page(struct inode *inode, + erofs_blk_t blkaddr) +{ + return erofs_get_meta_page(inode->i_sb, blkaddr, + S_ISDIR(inode->i_mode)); +} + +/* inode.c */ +static inline unsigned long erofs_inode_hash(erofs_nid_t nid) +{ +#if BITS_PER_LONG == 32 + return (nid >> 32) ^ (nid & 0xffffffff); +#else + return nid; +#endif +} + +extern const struct inode_operations erofs_generic_iops; +extern const struct inode_operations erofs_symlink_iops; +extern const struct inode_operations erofs_fast_symlink_iops; + +static inline void set_inode_fast_symlink(struct inode *inode) +{ + inode->i_op = &erofs_fast_symlink_iops; +} + +static inline bool is_inode_fast_symlink(struct inode *inode) +{ + return inode->i_op == &erofs_fast_symlink_iops; +} + +struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid, bool dir); +int erofs_getattr(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int query_flags); + +/* namei.c */ +extern const struct inode_operations erofs_dir_iops; + +int erofs_namei(struct inode *dir, struct qstr *name, + erofs_nid_t *nid, unsigned int *d_type); + +/* dir.c */ +extern const struct file_operations erofs_dir_fops; + +/* utils.c / zdata.c */ +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail); + +#if (EROFS_PCPUBUF_NR_PAGES > 0) +void *erofs_get_pcpubuf(unsigned int pagenr); +#define erofs_put_pcpubuf(buf) do { \ + (void)&(buf); \ + preempt_enable(); \ +} while (0) +#else +static inline void *erofs_get_pcpubuf(unsigned int pagenr) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +#define erofs_put_pcpubuf(buf) do {} while (0) +#endif + +#ifdef CONFIG_EROFS_FS_ZIP +int erofs_workgroup_put(struct erofs_workgroup *grp); +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag); +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, bool tag); +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp); +void erofs_shrinker_register(struct super_block *sb); +void erofs_shrinker_unregister(struct super_block *sb); +int __init erofs_init_shrinker(void); +void erofs_exit_shrinker(void); +int __init z_erofs_init_zip_subsystem(void); +void z_erofs_exit_zip_subsystem(void); +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *egrp); +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page); +#else +static inline void erofs_shrinker_register(struct super_block *sb) {} +static inline void erofs_shrinker_unregister(struct super_block *sb) {} +static inline int erofs_init_shrinker(void) { return 0; } +static inline void erofs_exit_shrinker(void) {} +static inline int z_erofs_init_zip_subsystem(void) { return 0; } +static inline void z_erofs_exit_zip_subsystem(void) {} +#endif /* !CONFIG_EROFS_FS_ZIP */ + +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ + +#endif /* __EROFS_INTERNAL_H */ + diff --git a/fs/erofs/namei.c b/fs/erofs/namei.c new file mode 100644 index 000000000000..8832b5d95d91 --- /dev/null +++ b/fs/erofs/namei.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "xattr.h" + +#include + +struct erofs_qstr { + const unsigned char *name; + const unsigned char *end; +}; + +/* based on the end of qn is accurate and it must have the trailing '\0' */ +static inline int dirnamecmp(const struct erofs_qstr *qn, + const struct erofs_qstr *qd, + unsigned int *matched) +{ + unsigned int i = *matched; + + /* + * on-disk error, let's only BUG_ON in the debugging mode. + * otherwise, it will return 1 to just skip the invalid name + * and go on (in consideration of the lookup performance). + */ + DBG_BUGON(qd->name > qd->end); + + /* qd could not have trailing '\0' */ + /* However it is absolutely safe if < qd->end */ + while (qd->name + i < qd->end && qd->name[i] != '\0') { + if (qn->name[i] != qd->name[i]) { + *matched = i; + return qn->name[i] > qd->name[i] ? 1 : -1; + } + ++i; + } + *matched = i; + /* See comments in __d_alloc on the terminating NUL character */ + return qn->name[i] == '\0' ? 0 : 1; +} + +#define nameoff_from_disk(off, sz) (le16_to_cpu(off) & ((sz) - 1)) + +static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name, + u8 *data, + unsigned int dirblksize, + const int ndirents) +{ + int head, back; + unsigned int startprfx, endprfx; + struct erofs_dirent *const de = (struct erofs_dirent *)data; + + /* since the 1st dirent has been evaluated previously */ + head = 1; + back = ndirents - 1; + startprfx = endprfx = 0; + + while (head <= back) { + const int mid = head + (back - head) / 2; + const int nameoff = nameoff_from_disk(de[mid].nameoff, + dirblksize); + unsigned int matched = min(startprfx, endprfx); + struct erofs_qstr dname = { + .name = data + nameoff, + .end = unlikely(mid >= ndirents - 1) ? + data + dirblksize : + data + nameoff_from_disk(de[mid + 1].nameoff, + dirblksize) + }; + + /* string comparison without already matched prefix */ + int ret = dirnamecmp(name, &dname, &matched); + + if (unlikely(!ret)) { + return de + mid; + } else if (ret > 0) { + head = mid + 1; + startprfx = matched; + } else { + back = mid - 1; + endprfx = matched; + } + } + + return ERR_PTR(-ENOENT); +} + +static struct page *find_target_block_classic(struct inode *dir, + struct erofs_qstr *name, + int *_ndirents) +{ + unsigned int startprfx, endprfx; + int head, back; + struct address_space *const mapping = dir->i_mapping; + struct page *candidate = ERR_PTR(-ENOENT); + + startprfx = endprfx = 0; + head = 0; + back = inode_datablocks(dir) - 1; + + while (head <= back) { + const int mid = head + (back - head) / 2; + struct page *page = read_mapping_page(mapping, mid, NULL); + + if (!IS_ERR(page)) { + struct erofs_dirent *de = kmap_atomic(page); + const int nameoff = nameoff_from_disk(de->nameoff, + EROFS_BLKSIZ); + const int ndirents = nameoff / sizeof(*de); + int diff; + unsigned int matched; + struct erofs_qstr dname; + + if (unlikely(!ndirents)) { + kunmap_atomic(de); + put_page(page); + errln("corrupted dir block %d @ nid %llu", + mid, EROFS_V(dir)->nid); + DBG_BUGON(1); + page = ERR_PTR(-EFSCORRUPTED); + goto out; + } + + matched = min(startprfx, endprfx); + + dname.name = (u8 *)de + nameoff; + if (ndirents == 1) + dname.end = (u8 *)de + EROFS_BLKSIZ; + else + dname.end = (u8 *)de + + nameoff_from_disk(de[1].nameoff, + EROFS_BLKSIZ); + + /* string comparison without already matched prefix */ + diff = dirnamecmp(name, &dname, &matched); + kunmap_atomic(de); + + if (unlikely(!diff)) { + *_ndirents = 0; + goto out; + } else if (diff > 0) { + head = mid + 1; + startprfx = matched; + + if (!IS_ERR(candidate)) + put_page(candidate); + candidate = page; + *_ndirents = ndirents; + } else { + put_page(page); + + back = mid - 1; + endprfx = matched; + } + continue; + } +out: /* free if the candidate is valid */ + if (!IS_ERR(candidate)) + put_page(candidate); + return page; + } + return candidate; +} + +int erofs_namei(struct inode *dir, + struct qstr *name, + erofs_nid_t *nid, unsigned int *d_type) +{ + int ndirents; + struct page *page; + void *data; + struct erofs_dirent *de; + struct erofs_qstr qn; + + if (unlikely(!dir->i_size)) + return -ENOENT; + + qn.name = name->name; + qn.end = name->name + name->len; + + ndirents = 0; + page = find_target_block_classic(dir, &qn, &ndirents); + + if (IS_ERR(page)) + return PTR_ERR(page); + + data = kmap_atomic(page); + /* the target page has been mapped */ + if (ndirents) + de = find_target_dirent(&qn, data, EROFS_BLKSIZ, ndirents); + else + de = (struct erofs_dirent *)data; + + if (!IS_ERR(de)) { + *nid = le64_to_cpu(de->nid); + *d_type = de->file_type; + } + + kunmap_atomic(data); + put_page(page); + + return PTR_ERR_OR_ZERO(de); +} + +/* NOTE: i_mutex is already held by vfs */ +static struct dentry *erofs_lookup(struct inode *dir, + struct dentry *dentry, + unsigned int flags) +{ + int err; + erofs_nid_t nid; + unsigned int d_type; + struct inode *inode; + + DBG_BUGON(!d_really_is_negative(dentry)); + /* dentry must be unhashed in lookup, no need to worry about */ + DBG_BUGON(!d_unhashed(dentry)); + + trace_erofs_lookup(dir, dentry, flags); + + /* file name exceeds fs limit */ + if (unlikely(dentry->d_name.len > EROFS_NAME_LEN)) + return ERR_PTR(-ENAMETOOLONG); + + /* false uninitialized warnings on gcc 4.8.x */ + err = erofs_namei(dir, &dentry->d_name, &nid, &d_type); + + if (err == -ENOENT) { + /* negative dentry */ + inode = NULL; + } else if (unlikely(err)) { + inode = ERR_PTR(err); + } else { + debugln("%s, %s (nid %llu) found, d_type %u", __func__, + dentry->d_name.name, nid, d_type); + inode = erofs_iget(dir->i_sb, nid, d_type == FT_DIR); + } + return d_splice_alias(inode, dentry); +} + +const struct inode_operations erofs_dir_iops = { + .lookup = erofs_lookup, + .getattr = erofs_getattr, +#ifdef CONFIG_EROFS_FS_XATTR + .listxattr = erofs_listxattr, +#endif + .get_acl = erofs_get_acl, +}; + diff --git a/fs/erofs/super.c b/fs/erofs/super.c new file mode 100644 index 000000000000..6d3a9bcb8daa --- /dev/null +++ b/fs/erofs/super.c @@ -0,0 +1,669 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include +#include +#include +#include +#include +#include "xattr.h" + +#define CREATE_TRACE_POINTS +#include + +static struct kmem_cache *erofs_inode_cachep __read_mostly; + +static void init_once(void *ptr) +{ + struct erofs_vnode *vi = ptr; + + inode_init_once(&vi->vfs_inode); +} + +static int __init erofs_init_inode_cache(void) +{ + erofs_inode_cachep = kmem_cache_create("erofs_inode", + sizeof(struct erofs_vnode), 0, + SLAB_RECLAIM_ACCOUNT, + init_once); + + return erofs_inode_cachep ? 0 : -ENOMEM; +} + +static void erofs_exit_inode_cache(void) +{ + kmem_cache_destroy(erofs_inode_cachep); +} + +static struct inode *alloc_inode(struct super_block *sb) +{ + struct erofs_vnode *vi = + kmem_cache_alloc(erofs_inode_cachep, GFP_KERNEL); + + if (!vi) + return NULL; + + /* zero out everything except vfs_inode */ + memset(vi, 0, offsetof(struct erofs_vnode, vfs_inode)); + return &vi->vfs_inode; +} + +static void free_inode(struct inode *inode) +{ + struct erofs_vnode *vi = EROFS_V(inode); + + /* be careful RCU symlink path (see ext4_inode_info->i_data)! */ + if (is_inode_fast_symlink(inode)) + kfree(inode->i_link); + + kfree(vi->xattr_shared_xattrs); + + kmem_cache_free(erofs_inode_cachep, vi); +} + +static bool check_layout_compatibility(struct super_block *sb, + struct erofs_super_block *layout) +{ + const unsigned int requirements = le32_to_cpu(layout->requirements); + + EROFS_SB(sb)->requirements = requirements; + + /* check if current kernel meets all mandatory requirements */ + if (requirements & (~EROFS_ALL_REQUIREMENTS)) { + errln("unidentified requirements %x, please upgrade kernel version", + requirements & ~EROFS_ALL_REQUIREMENTS); + return false; + } + return true; +} + +static int superblock_read(struct super_block *sb) +{ + struct erofs_sb_info *sbi; + struct buffer_head *bh; + struct erofs_super_block *layout; + unsigned int blkszbits; + int ret; + + bh = sb_bread(sb, 0); + + if (!bh) { + errln("cannot read erofs superblock"); + return -EIO; + } + + sbi = EROFS_SB(sb); + layout = (struct erofs_super_block *)((u8 *)bh->b_data + + EROFS_SUPER_OFFSET); + + ret = -EINVAL; + if (le32_to_cpu(layout->magic) != EROFS_SUPER_MAGIC_V1) { + errln("cannot find valid erofs superblock"); + goto out; + } + + blkszbits = layout->blkszbits; + /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ + if (unlikely(blkszbits != LOG_BLOCK_SIZE)) { + errln("blksize %u isn't supported on this platform", + 1 << blkszbits); + goto out; + } + + if (!check_layout_compatibility(sb, layout)) + goto out; + + sbi->blocks = le32_to_cpu(layout->blocks); + sbi->meta_blkaddr = le32_to_cpu(layout->meta_blkaddr); +#ifdef CONFIG_EROFS_FS_XATTR + sbi->xattr_blkaddr = le32_to_cpu(layout->xattr_blkaddr); +#endif + sbi->islotbits = ffs(sizeof(struct erofs_inode_v1)) - 1; + sbi->root_nid = le16_to_cpu(layout->root_nid); + sbi->inos = le64_to_cpu(layout->inos); + + sbi->build_time = le64_to_cpu(layout->build_time); + sbi->build_time_nsec = le32_to_cpu(layout->build_time_nsec); + + memcpy(&sb->s_uuid, layout->uuid, sizeof(layout->uuid)); + + ret = strscpy(sbi->volume_name, layout->volume_name, + sizeof(layout->volume_name)); + if (ret < 0) { /* -E2BIG */ + errln("bad volume name without NIL terminator"); + ret = -EFSCORRUPTED; + goto out; + } + ret = 0; +out: + brelse(bh); + return ret; +} + +#ifdef CONFIG_EROFS_FAULT_INJECTION +const char *erofs_fault_name[FAULT_MAX] = { + [FAULT_KMALLOC] = "kmalloc", + [FAULT_READ_IO] = "read IO error", +}; + +static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, + unsigned int rate) +{ + struct erofs_fault_info *ffi = &sbi->fault_info; + + if (rate) { + atomic_set(&ffi->inject_ops, 0); + ffi->inject_rate = rate; + ffi->inject_type = (1 << FAULT_MAX) - 1; + } else { + memset(ffi, 0, sizeof(struct erofs_fault_info)); + } + + set_opt(sbi, FAULT_INJECTION); +} + +static int erofs_build_fault_attr(struct erofs_sb_info *sbi, + substring_t *args) +{ + int rate = 0; + + if (args->from && match_int(args, &rate)) + return -EINVAL; + + __erofs_build_fault_attr(sbi, rate); + return 0; +} + +static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) +{ + return sbi->fault_info.inject_rate; +} +#else +static void __erofs_build_fault_attr(struct erofs_sb_info *sbi, + unsigned int rate) +{ +} + +static int erofs_build_fault_attr(struct erofs_sb_info *sbi, + substring_t *args) +{ + infoln("fault_injection options not supported"); + return 0; +} + +static unsigned int erofs_get_fault_rate(struct erofs_sb_info *sbi) +{ + return 0; +} +#endif + +#ifdef CONFIG_EROFS_FS_ZIP +static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, + substring_t *args) +{ + const char *cs = match_strdup(args); + int err = 0; + + if (!cs) { + errln("Not enough memory to store cache strategy"); + return -ENOMEM; + } + + if (!strcmp(cs, "disabled")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_DISABLED; + } else if (!strcmp(cs, "readahead")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAHEAD; + } else if (!strcmp(cs, "readaround")) { + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + } else { + errln("Unrecognized cache strategy \"%s\"", cs); + err = -EINVAL; + } + kfree(cs); + return err; +} +#else +static int erofs_build_cache_strategy(struct erofs_sb_info *sbi, + substring_t *args) +{ + infoln("EROFS compression is disabled, so cache strategy is ignored"); + return 0; +} +#endif + +/* set up default EROFS parameters */ +static void default_options(struct erofs_sb_info *sbi) +{ +#ifdef CONFIG_EROFS_FS_ZIP + sbi->cache_strategy = EROFS_ZIP_CACHE_READAROUND; + sbi->max_sync_decompress_pages = 3; +#endif +#ifdef CONFIG_EROFS_FS_XATTR + set_opt(sbi, XATTR_USER); +#endif +#ifdef CONFIG_EROFS_FS_POSIX_ACL + set_opt(sbi, POSIX_ACL); +#endif +} + +enum { + Opt_user_xattr, + Opt_nouser_xattr, + Opt_acl, + Opt_noacl, + Opt_fault_injection, + Opt_cache_strategy, + Opt_err +}; + +static match_table_t erofs_tokens = { + {Opt_user_xattr, "user_xattr"}, + {Opt_nouser_xattr, "nouser_xattr"}, + {Opt_acl, "acl"}, + {Opt_noacl, "noacl"}, + {Opt_fault_injection, "fault_injection=%u"}, + {Opt_cache_strategy, "cache_strategy=%s"}, + {Opt_err, NULL} +}; + +static int parse_options(struct super_block *sb, char *options) +{ + substring_t args[MAX_OPT_ARGS]; + char *p; + int err; + + if (!options) + return 0; + + while ((p = strsep(&options, ","))) { + int token; + + if (!*p) + continue; + + args[0].to = args[0].from = NULL; + token = match_token(p, erofs_tokens, args); + + switch (token) { +#ifdef CONFIG_EROFS_FS_XATTR + case Opt_user_xattr: + set_opt(EROFS_SB(sb), XATTR_USER); + break; + case Opt_nouser_xattr: + clear_opt(EROFS_SB(sb), XATTR_USER); + break; +#else + case Opt_user_xattr: + infoln("user_xattr options not supported"); + break; + case Opt_nouser_xattr: + infoln("nouser_xattr options not supported"); + break; +#endif +#ifdef CONFIG_EROFS_FS_POSIX_ACL + case Opt_acl: + set_opt(EROFS_SB(sb), POSIX_ACL); + break; + case Opt_noacl: + clear_opt(EROFS_SB(sb), POSIX_ACL); + break; +#else + case Opt_acl: + infoln("acl options not supported"); + break; + case Opt_noacl: + infoln("noacl options not supported"); + break; +#endif + case Opt_fault_injection: + err = erofs_build_fault_attr(EROFS_SB(sb), args); + if (err) + return err; + break; + case Opt_cache_strategy: + err = erofs_build_cache_strategy(EROFS_SB(sb), args); + if (err) + return err; + break; + default: + errln("Unrecognized mount option \"%s\" or missing value", p); + return -EINVAL; + } + } + return 0; +} + +#ifdef CONFIG_EROFS_FS_ZIP +static const struct address_space_operations managed_cache_aops; + +static int managed_cache_releasepage(struct page *page, gfp_t gfp_mask) +{ + int ret = 1; /* 0 - busy */ + struct address_space *const mapping = page->mapping; + + DBG_BUGON(!PageLocked(page)); + DBG_BUGON(mapping->a_ops != &managed_cache_aops); + + if (PagePrivate(page)) + ret = erofs_try_to_free_cached_page(mapping, page); + + return ret; +} + +static void managed_cache_invalidatepage(struct page *page, + unsigned int offset, + unsigned int length) +{ + const unsigned int stop = length + offset; + + DBG_BUGON(!PageLocked(page)); + + /* Check for potential overflow in debug mode */ + DBG_BUGON(stop > PAGE_SIZE || stop < length); + + if (offset == 0 && stop == PAGE_SIZE) + while (!managed_cache_releasepage(page, GFP_NOFS)) + cond_resched(); +} + +static const struct address_space_operations managed_cache_aops = { + .releasepage = managed_cache_releasepage, + .invalidatepage = managed_cache_invalidatepage, +}; + +static int erofs_init_managed_cache(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + struct inode *const inode = new_inode(sb); + + if (unlikely(!inode)) + return -ENOMEM; + + set_nlink(inode, 1); + inode->i_size = OFFSET_MAX; + + inode->i_mapping->a_ops = &managed_cache_aops; + mapping_set_gfp_mask(inode->i_mapping, + GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE); + sbi->managed_cache = inode; + return 0; +} +#else +static int erofs_init_managed_cache(struct super_block *sb) { return 0; } +#endif + +static int erofs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *inode; + struct erofs_sb_info *sbi; + int err; + + infoln("fill_super, device -> %s", sb->s_id); + infoln("options -> %s", (char *)data); + + sb->s_magic = EROFS_SUPER_MAGIC; + + if (unlikely(!sb_set_blocksize(sb, EROFS_BLKSIZ))) { + errln("failed to set erofs blksize"); + return -EINVAL; + } + + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); + if (unlikely(!sbi)) + return -ENOMEM; + + sb->s_fs_info = sbi; + err = superblock_read(sb); + if (err) + return err; + + sb->s_flags |= SB_RDONLY | SB_NOATIME; + sb->s_maxbytes = MAX_LFS_FILESIZE; + sb->s_time_gran = 1; + + sb->s_op = &erofs_sops; + +#ifdef CONFIG_EROFS_FS_XATTR + sb->s_xattr = erofs_xattr_handlers; +#endif + /* set erofs default mount options */ + default_options(sbi); + + err = parse_options(sb, data); + if (unlikely(err)) + return err; + + if (!silent) + infoln("root inode @ nid %llu", ROOT_NID(sbi)); + + if (test_opt(sbi, POSIX_ACL)) + sb->s_flags |= SB_POSIXACL; + else + sb->s_flags &= ~SB_POSIXACL; + +#ifdef CONFIG_EROFS_FS_ZIP + INIT_RADIX_TREE(&sbi->workstn_tree, GFP_ATOMIC); +#endif + + /* get the root inode */ + inode = erofs_iget(sb, ROOT_NID(sbi), true); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + if (unlikely(!S_ISDIR(inode->i_mode))) { + errln("rootino(nid %llu) is not a directory(i_mode %o)", + ROOT_NID(sbi), inode->i_mode); + iput(inode); + return -EINVAL; + } + + sb->s_root = d_make_root(inode); + if (unlikely(!sb->s_root)) + return -ENOMEM; + + erofs_shrinker_register(sb); + /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */ + err = erofs_init_managed_cache(sb); + if (unlikely(err)) + return err; + + if (!silent) + infoln("mounted on %s with opts: %s.", sb->s_id, (char *)data); + return 0; +} + +static struct dentry *erofs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, erofs_fill_super); +} + +/* + * could be triggered after deactivate_locked_super() + * is called, thus including umount and failed to initialize. + */ +static void erofs_kill_sb(struct super_block *sb) +{ + struct erofs_sb_info *sbi; + + WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); + infoln("unmounting for %s", sb->s_id); + + kill_block_super(sb); + + sbi = EROFS_SB(sb); + if (!sbi) + return; + kfree(sbi); + sb->s_fs_info = NULL; +} + +/* called when ->s_root is non-NULL */ +static void erofs_put_super(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + DBG_BUGON(!sbi); + + erofs_shrinker_unregister(sb); +#ifdef CONFIG_EROFS_FS_ZIP + iput(sbi->managed_cache); + sbi->managed_cache = NULL; +#endif +} + +static struct file_system_type erofs_fs_type = { + .owner = THIS_MODULE, + .name = "erofs", + .mount = erofs_mount, + .kill_sb = erofs_kill_sb, + .fs_flags = FS_REQUIRES_DEV, +}; +MODULE_ALIAS_FS("erofs"); + +static int __init erofs_module_init(void) +{ + int err; + + erofs_check_ondisk_layout_definitions(); + infoln("initializing erofs " EROFS_VERSION); + + err = erofs_init_inode_cache(); + if (err) + goto icache_err; + + err = erofs_init_shrinker(); + if (err) + goto shrinker_err; + + err = z_erofs_init_zip_subsystem(); + if (err) + goto zip_err; + + err = register_filesystem(&erofs_fs_type); + if (err) + goto fs_err; + + infoln("successfully to initialize erofs"); + return 0; + +fs_err: + z_erofs_exit_zip_subsystem(); +zip_err: + erofs_exit_shrinker(); +shrinker_err: + erofs_exit_inode_cache(); +icache_err: + return err; +} + +static void __exit erofs_module_exit(void) +{ + unregister_filesystem(&erofs_fs_type); + z_erofs_exit_zip_subsystem(); + erofs_exit_shrinker(); + erofs_exit_inode_cache(); + infoln("successfully finalize erofs"); +} + +/* get filesystem statistics */ +static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + struct erofs_sb_info *sbi = EROFS_SB(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + + buf->f_type = sb->s_magic; + buf->f_bsize = EROFS_BLKSIZ; + buf->f_blocks = sbi->blocks; + buf->f_bfree = buf->f_bavail = 0; + + buf->f_files = ULLONG_MAX; + buf->f_ffree = ULLONG_MAX - sbi->inos; + + buf->f_namelen = EROFS_NAME_LEN; + + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + return 0; +} + +static int erofs_show_options(struct seq_file *seq, struct dentry *root) +{ + struct erofs_sb_info *sbi __maybe_unused = EROFS_SB(root->d_sb); + +#ifdef CONFIG_EROFS_FS_XATTR + if (test_opt(sbi, XATTR_USER)) + seq_puts(seq, ",user_xattr"); + else + seq_puts(seq, ",nouser_xattr"); +#endif +#ifdef CONFIG_EROFS_FS_POSIX_ACL + if (test_opt(sbi, POSIX_ACL)) + seq_puts(seq, ",acl"); + else + seq_puts(seq, ",noacl"); +#endif + if (test_opt(sbi, FAULT_INJECTION)) + seq_printf(seq, ",fault_injection=%u", + erofs_get_fault_rate(sbi)); +#ifdef CONFIG_EROFS_FS_ZIP + if (sbi->cache_strategy == EROFS_ZIP_CACHE_DISABLED) { + seq_puts(seq, ",cache_strategy=disabled"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAHEAD) { + seq_puts(seq, ",cache_strategy=readahead"); + } else if (sbi->cache_strategy == EROFS_ZIP_CACHE_READAROUND) { + seq_puts(seq, ",cache_strategy=readaround"); + } else { + seq_puts(seq, ",cache_strategy=(unknown)"); + DBG_BUGON(1); + } +#endif + return 0; +} + +static int erofs_remount(struct super_block *sb, int *flags, char *data) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + unsigned int org_mnt_opt = sbi->mount_opt; + unsigned int org_inject_rate = erofs_get_fault_rate(sbi); + int err; + + DBG_BUGON(!sb_rdonly(sb)); + err = parse_options(sb, data); + if (err) + goto out; + + if (test_opt(sbi, POSIX_ACL)) + sb->s_flags |= SB_POSIXACL; + else + sb->s_flags &= ~SB_POSIXACL; + + *flags |= SB_RDONLY; + return 0; +out: + __erofs_build_fault_attr(sbi, org_inject_rate); + sbi->mount_opt = org_mnt_opt; + + return err; +} + +const struct super_operations erofs_sops = { + .put_super = erofs_put_super, + .alloc_inode = alloc_inode, + .free_inode = free_inode, + .statfs = erofs_statfs, + .show_options = erofs_show_options, + .remount_fs = erofs_remount, +}; + +module_init(erofs_module_init); +module_exit(erofs_module_exit); + +MODULE_DESCRIPTION("Enhanced ROM File System"); +MODULE_AUTHOR("Gao Xiang, Chao Yu, Miao Xie, CONSUMER BG, HUAWEI Inc."); +MODULE_LICENSE("GPL"); + diff --git a/fs/erofs/tagptr.h b/fs/erofs/tagptr.h new file mode 100644 index 000000000000..a72897c86744 --- /dev/null +++ b/fs/erofs/tagptr.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * A tagged pointer implementation + * + * Copyright (C) 2018 Gao Xiang + */ +#ifndef __EROFS_FS_TAGPTR_H +#define __EROFS_FS_TAGPTR_H + +#include +#include + +/* + * the name of tagged pointer types are tagptr{1, 2, 3...}_t + * avoid directly using the internal structs __tagptr{1, 2, 3...} + */ +#define __MAKE_TAGPTR(n) \ +typedef struct __tagptr##n { \ + uintptr_t v; \ +} tagptr##n##_t; + +__MAKE_TAGPTR(1) +__MAKE_TAGPTR(2) +__MAKE_TAGPTR(3) +__MAKE_TAGPTR(4) + +#undef __MAKE_TAGPTR + +extern void __compiletime_error("bad tagptr tags") + __bad_tagptr_tags(void); + +extern void __compiletime_error("bad tagptr type") + __bad_tagptr_type(void); + +/* fix the broken usage of "#define tagptr2_t tagptr3_t" by users */ +#define __tagptr_mask_1(ptr, n) \ + __builtin_types_compatible_p(typeof(ptr), struct __tagptr##n) ? \ + (1UL << (n)) - 1 : + +#define __tagptr_mask(ptr) (\ + __tagptr_mask_1(ptr, 1) ( \ + __tagptr_mask_1(ptr, 2) ( \ + __tagptr_mask_1(ptr, 3) ( \ + __tagptr_mask_1(ptr, 4) ( \ + __bad_tagptr_type(), 0))))) + +/* generate a tagged pointer from a raw value */ +#define tagptr_init(type, val) \ + ((typeof(type)){ .v = (uintptr_t)(val) }) + +/* + * directly cast a tagged pointer to the native pointer type, which + * could be used for backward compatibility of existing code. + */ +#define tagptr_cast_ptr(tptr) ((void *)(tptr).v) + +/* encode tagged pointers */ +#define tagptr_fold(type, ptr, _tags) ({ \ + const typeof(_tags) tags = (_tags); \ + if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(type))) \ + __bad_tagptr_tags(); \ +tagptr_init(type, (uintptr_t)(ptr) | tags); }) + +/* decode tagged pointers */ +#define tagptr_unfold_ptr(tptr) \ + ((void *)((tptr).v & ~__tagptr_mask(tptr))) + +#define tagptr_unfold_tags(tptr) \ + ((tptr).v & __tagptr_mask(tptr)) + +/* operations for the tagger pointer */ +#define tagptr_eq(_tptr1, _tptr2) ({ \ + typeof(_tptr1) tptr1 = (_tptr1); \ + typeof(_tptr2) tptr2 = (_tptr2); \ + (void)(&tptr1 == &tptr2); \ +(tptr1).v == (tptr2).v; }) + +/* lock-free CAS operation */ +#define tagptr_cmpxchg(_ptptr, _o, _n) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + typeof(_o) o = (_o); \ + typeof(_n) n = (_n); \ + (void)(&o == &n); \ + (void)(&o == ptptr); \ +tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) + +/* wrap WRITE_ONCE if atomic update is needed */ +#define tagptr_replace_tags(_ptptr, tags) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + *ptptr = tagptr_fold(*ptptr, tagptr_unfold_ptr(*ptptr), tags); \ +*ptptr; }) + +#define tagptr_set_tags(_ptptr, _tags) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + const typeof(_tags) tags = (_tags); \ + if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ + __bad_tagptr_tags(); \ + ptptr->v |= tags; \ +*ptptr; }) + +#define tagptr_clear_tags(_ptptr, _tags) ({ \ + typeof(_ptptr) ptptr = (_ptptr); \ + const typeof(_tags) tags = (_tags); \ + if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ + __bad_tagptr_tags(); \ + ptptr->v &= ~tags; \ +*ptptr; }) + +#endif /* __EROFS_FS_TAGPTR_H */ + diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c new file mode 100644 index 000000000000..1dd041aa0f5a --- /dev/null +++ b/fs/erofs/utils.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "internal.h" +#include + +struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp, bool nofail) +{ + struct page *page; + + if (!list_empty(pool)) { + page = lru_to_page(pool); + DBG_BUGON(page_ref_count(page) != 1); + list_del(&page->lru); + } else { + page = alloc_pages(gfp | (nofail ? __GFP_NOFAIL : 0), 0); + } + return page; +} + +#if (EROFS_PCPUBUF_NR_PAGES > 0) +static struct { + u8 data[PAGE_SIZE * EROFS_PCPUBUF_NR_PAGES]; +} ____cacheline_aligned_in_smp erofs_pcpubuf[NR_CPUS]; + +void *erofs_get_pcpubuf(unsigned int pagenr) +{ + preempt_disable(); + return &erofs_pcpubuf[smp_processor_id()].data[pagenr * PAGE_SIZE]; +} +#endif + +#ifdef CONFIG_EROFS_FS_ZIP +/* global shrink count (for all mounted EROFS instances) */ +static atomic_long_t erofs_global_shrink_cnt; + +#define __erofs_workgroup_get(grp) atomic_inc(&(grp)->refcount) +#define __erofs_workgroup_put(grp) atomic_dec(&(grp)->refcount) + +static int erofs_workgroup_get(struct erofs_workgroup *grp) +{ + int o; + +repeat: + o = erofs_wait_on_workgroup_freezed(grp); + if (unlikely(o <= 0)) + return -1; + + if (unlikely(atomic_cmpxchg(&grp->refcount, o, o + 1) != o)) + goto repeat; + + /* decrease refcount paired by erofs_workgroup_put */ + if (unlikely(o == 1)) + atomic_long_dec(&erofs_global_shrink_cnt); + return 0; +} + +struct erofs_workgroup *erofs_find_workgroup(struct super_block *sb, + pgoff_t index, bool *tag) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + struct erofs_workgroup *grp; + +repeat: + rcu_read_lock(); + grp = radix_tree_lookup(&sbi->workstn_tree, index); + if (grp) { + *tag = xa_pointer_tag(grp); + grp = xa_untag_pointer(grp); + + if (erofs_workgroup_get(grp)) { + /* prefer to relax rcu read side */ + rcu_read_unlock(); + goto repeat; + } + + DBG_BUGON(index != grp->index); + } + rcu_read_unlock(); + return grp; +} + +int erofs_register_workgroup(struct super_block *sb, + struct erofs_workgroup *grp, + bool tag) +{ + struct erofs_sb_info *sbi; + int err; + + /* grp shouldn't be broken or used before */ + if (unlikely(atomic_read(&grp->refcount) != 1)) { + DBG_BUGON(1); + return -EINVAL; + } + + err = radix_tree_preload(GFP_NOFS); + if (err) + return err; + + sbi = EROFS_SB(sb); + xa_lock(&sbi->workstn_tree); + + grp = xa_tag_pointer(grp, tag); + + /* + * Bump up reference count before making this workgroup + * visible to other users in order to avoid potential UAF + * without serialized by workstn_lock. + */ + __erofs_workgroup_get(grp); + + err = radix_tree_insert(&sbi->workstn_tree, grp->index, grp); + if (unlikely(err)) + /* + * it's safe to decrease since the workgroup isn't visible + * and refcount >= 2 (cannot be freezed). + */ + __erofs_workgroup_put(grp); + + xa_unlock(&sbi->workstn_tree); + radix_tree_preload_end(); + return err; +} + +static void __erofs_workgroup_free(struct erofs_workgroup *grp) +{ + atomic_long_dec(&erofs_global_shrink_cnt); + erofs_workgroup_free_rcu(grp); +} + +int erofs_workgroup_put(struct erofs_workgroup *grp) +{ + int count = atomic_dec_return(&grp->refcount); + + if (count == 1) + atomic_long_inc(&erofs_global_shrink_cnt); + else if (!count) + __erofs_workgroup_free(grp); + return count; +} + +static void erofs_workgroup_unfreeze_final(struct erofs_workgroup *grp) +{ + erofs_workgroup_unfreeze(grp, 0); + __erofs_workgroup_free(grp); +} + +static bool erofs_try_to_release_workgroup(struct erofs_sb_info *sbi, + struct erofs_workgroup *grp, + bool cleanup) +{ + /* + * If managed cache is on, refcount of workgroups + * themselves could be < 0 (freezed). In other words, + * there is no guarantee that all refcounts > 0. + */ + if (!erofs_workgroup_try_to_freeze(grp, 1)) + return false; + + /* + * Note that all cached pages should be unattached + * before deleted from the radix tree. Otherwise some + * cached pages could be still attached to the orphan + * old workgroup when the new one is available in the tree. + */ + if (erofs_try_to_free_all_cached_pages(sbi, grp)) { + erofs_workgroup_unfreeze(grp, 1); + return false; + } + + /* + * It's impossible to fail after the workgroup is freezed, + * however in order to avoid some race conditions, add a + * DBG_BUGON to observe this in advance. + */ + DBG_BUGON(xa_untag_pointer(radix_tree_delete(&sbi->workstn_tree, + grp->index)) != grp); + + /* + * If managed cache is on, last refcount should indicate + * the related workstation. + */ + erofs_workgroup_unfreeze_final(grp); + return true; +} + +static unsigned long erofs_shrink_workstation(struct erofs_sb_info *sbi, + unsigned long nr_shrink, + bool cleanup) +{ + pgoff_t first_index = 0; + void *batch[PAGEVEC_SIZE]; + unsigned int freed = 0; + + int i, found; +repeat: + xa_lock(&sbi->workstn_tree); + + found = radix_tree_gang_lookup(&sbi->workstn_tree, + batch, first_index, PAGEVEC_SIZE); + + for (i = 0; i < found; ++i) { + struct erofs_workgroup *grp = xa_untag_pointer(batch[i]); + + first_index = grp->index + 1; + + /* try to shrink each valid workgroup */ + if (!erofs_try_to_release_workgroup(sbi, grp, cleanup)) + continue; + + ++freed; + if (unlikely(!--nr_shrink)) + break; + } + xa_unlock(&sbi->workstn_tree); + + if (i && nr_shrink) + goto repeat; + return freed; +} + +/* protected by 'erofs_sb_list_lock' */ +static unsigned int shrinker_run_no; + +/* protects the mounted 'erofs_sb_list' */ +static DEFINE_SPINLOCK(erofs_sb_list_lock); +static LIST_HEAD(erofs_sb_list); + +void erofs_shrinker_register(struct super_block *sb) +{ + struct erofs_sb_info *sbi = EROFS_SB(sb); + + mutex_init(&sbi->umount_mutex); + + spin_lock(&erofs_sb_list_lock); + list_add(&sbi->list, &erofs_sb_list); + spin_unlock(&erofs_sb_list_lock); +} + +void erofs_shrinker_unregister(struct super_block *sb) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + mutex_lock(&sbi->umount_mutex); + erofs_shrink_workstation(sbi, ~0UL, true); + + spin_lock(&erofs_sb_list_lock); + list_del(&sbi->list); + spin_unlock(&erofs_sb_list_lock); + mutex_unlock(&sbi->umount_mutex); +} + +static unsigned long erofs_shrink_count(struct shrinker *shrink, + struct shrink_control *sc) +{ + return atomic_long_read(&erofs_global_shrink_cnt); +} + +static unsigned long erofs_shrink_scan(struct shrinker *shrink, + struct shrink_control *sc) +{ + struct erofs_sb_info *sbi; + struct list_head *p; + + unsigned long nr = sc->nr_to_scan; + unsigned int run_no; + unsigned long freed = 0; + + spin_lock(&erofs_sb_list_lock); + do { + run_no = ++shrinker_run_no; + } while (run_no == 0); + + /* Iterate over all mounted superblocks and try to shrink them */ + p = erofs_sb_list.next; + while (p != &erofs_sb_list) { + sbi = list_entry(p, struct erofs_sb_info, list); + + /* + * We move the ones we do to the end of the list, so we stop + * when we see one we have already done. + */ + if (sbi->shrinker_run_no == run_no) + break; + + if (!mutex_trylock(&sbi->umount_mutex)) { + p = p->next; + continue; + } + + spin_unlock(&erofs_sb_list_lock); + sbi->shrinker_run_no = run_no; + + freed += erofs_shrink_workstation(sbi, nr, false); + + spin_lock(&erofs_sb_list_lock); + /* Get the next list element before we move this one */ + p = p->next; + + /* + * Move this one to the end of the list to provide some + * fairness. + */ + list_move_tail(&sbi->list, &erofs_sb_list); + mutex_unlock(&sbi->umount_mutex); + + if (freed >= nr) + break; + } + spin_unlock(&erofs_sb_list_lock); + return freed; +} + +static struct shrinker erofs_shrinker_info = { + .scan_objects = erofs_shrink_scan, + .count_objects = erofs_shrink_count, + .seeks = DEFAULT_SEEKS, +}; + +int __init erofs_init_shrinker(void) +{ + return register_shrinker(&erofs_shrinker_info); +} + +void erofs_exit_shrinker(void) +{ + unregister_shrinker(&erofs_shrinker_info); +} +#endif /* !CONFIG_EROFS_FS_ZIP */ + diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c new file mode 100644 index 000000000000..a8286998a079 --- /dev/null +++ b/fs/erofs/xattr.c @@ -0,0 +1,703 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include +#include "xattr.h" + +struct xattr_iter { + struct super_block *sb; + struct page *page; + void *kaddr; + + erofs_blk_t blkaddr; + unsigned int ofs; +}; + +static inline void xattr_iter_end(struct xattr_iter *it, bool atomic) +{ + /* the only user of kunmap() is 'init_inode_xattrs' */ + if (unlikely(!atomic)) + kunmap(it->page); + else + kunmap_atomic(it->kaddr); + + unlock_page(it->page); + put_page(it->page); +} + +static inline void xattr_iter_end_final(struct xattr_iter *it) +{ + if (!it->page) + return; + + xattr_iter_end(it, true); +} + +static int init_inode_xattrs(struct inode *inode) +{ + struct erofs_vnode *const vi = EROFS_V(inode); + struct xattr_iter it; + unsigned int i; + struct erofs_xattr_ibody_header *ih; + struct super_block *sb; + struct erofs_sb_info *sbi; + bool atomic_map; + int ret = 0; + + /* the most case is that xattrs of this inode are initialized. */ + if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags)) + return 0; + + if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_XATTR_BIT, TASK_KILLABLE)) + return -ERESTARTSYS; + + /* someone has initialized xattrs for us? */ + if (test_bit(EROFS_V_EA_INITED_BIT, &vi->flags)) + goto out_unlock; + + /* + * bypass all xattr operations if ->xattr_isize is not greater than + * sizeof(struct erofs_xattr_ibody_header), in detail: + * 1) it is not enough to contain erofs_xattr_ibody_header then + * ->xattr_isize should be 0 (it means no xattr); + * 2) it is just to contain erofs_xattr_ibody_header, which is on-disk + * undefined right now (maybe use later with some new sb feature). + */ + if (vi->xattr_isize == sizeof(struct erofs_xattr_ibody_header)) { + errln("xattr_isize %d of nid %llu is not supported yet", + vi->xattr_isize, vi->nid); + ret = -EOPNOTSUPP; + goto out_unlock; + } else if (vi->xattr_isize < sizeof(struct erofs_xattr_ibody_header)) { + if (unlikely(vi->xattr_isize)) { + errln("bogus xattr ibody @ nid %llu", vi->nid); + DBG_BUGON(1); + ret = -EFSCORRUPTED; + goto out_unlock; /* xattr ondisk layout error */ + } + ret = -ENOATTR; + goto out_unlock; + } + + sb = inode->i_sb; + sbi = EROFS_SB(sb); + it.blkaddr = erofs_blknr(iloc(sbi, vi->nid) + vi->inode_isize); + it.ofs = erofs_blkoff(iloc(sbi, vi->nid) + vi->inode_isize); + + it.page = erofs_get_inline_page(inode, it.blkaddr); + if (IS_ERR(it.page)) { + ret = PTR_ERR(it.page); + goto out_unlock; + } + + /* read in shared xattr array (non-atomic, see kmalloc below) */ + it.kaddr = kmap(it.page); + atomic_map = false; + + ih = (struct erofs_xattr_ibody_header *)(it.kaddr + it.ofs); + + vi->xattr_shared_count = ih->h_shared_count; + vi->xattr_shared_xattrs = kmalloc_array(vi->xattr_shared_count, + sizeof(uint), GFP_KERNEL); + if (!vi->xattr_shared_xattrs) { + xattr_iter_end(&it, atomic_map); + ret = -ENOMEM; + goto out_unlock; + } + + /* let's skip ibody header */ + it.ofs += sizeof(struct erofs_xattr_ibody_header); + + for (i = 0; i < vi->xattr_shared_count; ++i) { + if (unlikely(it.ofs >= EROFS_BLKSIZ)) { + /* cannot be unaligned */ + DBG_BUGON(it.ofs != EROFS_BLKSIZ); + xattr_iter_end(&it, atomic_map); + + it.page = erofs_get_meta_page(sb, ++it.blkaddr, + S_ISDIR(inode->i_mode)); + if (IS_ERR(it.page)) { + kfree(vi->xattr_shared_xattrs); + vi->xattr_shared_xattrs = NULL; + ret = PTR_ERR(it.page); + goto out_unlock; + } + + it.kaddr = kmap_atomic(it.page); + atomic_map = true; + it.ofs = 0; + } + vi->xattr_shared_xattrs[i] = + le32_to_cpu(*(__le32 *)(it.kaddr + it.ofs)); + it.ofs += sizeof(__le32); + } + xattr_iter_end(&it, atomic_map); + + set_bit(EROFS_V_EA_INITED_BIT, &vi->flags); + +out_unlock: + clear_and_wake_up_bit(EROFS_V_BL_XATTR_BIT, &vi->flags); + return ret; +} + +/* + * the general idea for these return values is + * if 0 is returned, go on processing the current xattr; + * 1 (> 0) is returned, skip this round to process the next xattr; + * -err (< 0) is returned, an error (maybe ENOXATTR) occurred + * and need to be handled + */ +struct xattr_iter_handlers { + int (*entry)(struct xattr_iter *_it, struct erofs_xattr_entry *entry); + int (*name)(struct xattr_iter *_it, unsigned int processed, char *buf, + unsigned int len); + int (*alloc_buffer)(struct xattr_iter *_it, unsigned int value_sz); + void (*value)(struct xattr_iter *_it, unsigned int processed, char *buf, + unsigned int len); +}; + +static inline int xattr_iter_fixup(struct xattr_iter *it) +{ + if (it->ofs < EROFS_BLKSIZ) + return 0; + + xattr_iter_end(it, true); + + it->blkaddr += erofs_blknr(it->ofs); + + it->page = erofs_get_meta_page(it->sb, it->blkaddr, false); + if (IS_ERR(it->page)) { + int err = PTR_ERR(it->page); + + it->page = NULL; + return err; + } + + it->kaddr = kmap_atomic(it->page); + it->ofs = erofs_blkoff(it->ofs); + return 0; +} + +static int inline_xattr_iter_begin(struct xattr_iter *it, + struct inode *inode) +{ + struct erofs_vnode *const vi = EROFS_V(inode); + struct erofs_sb_info *const sbi = EROFS_SB(inode->i_sb); + unsigned int xattr_header_sz, inline_xattr_ofs; + + xattr_header_sz = inlinexattr_header_size(inode); + if (unlikely(xattr_header_sz >= vi->xattr_isize)) { + DBG_BUGON(xattr_header_sz > vi->xattr_isize); + return -ENOATTR; + } + + inline_xattr_ofs = vi->inode_isize + xattr_header_sz; + + it->blkaddr = erofs_blknr(iloc(sbi, vi->nid) + inline_xattr_ofs); + it->ofs = erofs_blkoff(iloc(sbi, vi->nid) + inline_xattr_ofs); + + it->page = erofs_get_inline_page(inode, it->blkaddr); + if (IS_ERR(it->page)) + return PTR_ERR(it->page); + + it->kaddr = kmap_atomic(it->page); + return vi->xattr_isize - xattr_header_sz; +} + +/* + * Regardless of success or failure, `xattr_foreach' will end up with + * `ofs' pointing to the next xattr item rather than an arbitrary position. + */ +static int xattr_foreach(struct xattr_iter *it, + const struct xattr_iter_handlers *op, + unsigned int *tlimit) +{ + struct erofs_xattr_entry entry; + unsigned int value_sz, processed, slice; + int err; + + /* 0. fixup blkaddr, ofs, ipage */ + err = xattr_iter_fixup(it); + if (err) + return err; + + /* + * 1. read xattr entry to the memory, + * since we do EROFS_XATTR_ALIGN + * therefore entry should be in the page + */ + entry = *(struct erofs_xattr_entry *)(it->kaddr + it->ofs); + if (tlimit) { + unsigned int entry_sz = EROFS_XATTR_ENTRY_SIZE(&entry); + + /* xattr on-disk corruption: xattr entry beyond xattr_isize */ + if (unlikely(*tlimit < entry_sz)) { + DBG_BUGON(1); + return -EFSCORRUPTED; + } + *tlimit -= entry_sz; + } + + it->ofs += sizeof(struct erofs_xattr_entry); + value_sz = le16_to_cpu(entry.e_value_size); + + /* handle entry */ + err = op->entry(it, &entry); + if (err) { + it->ofs += entry.e_name_len + value_sz; + goto out; + } + + /* 2. handle xattr name (ofs will finally be at the end of name) */ + processed = 0; + + while (processed < entry.e_name_len) { + if (it->ofs >= EROFS_BLKSIZ) { + DBG_BUGON(it->ofs > EROFS_BLKSIZ); + + err = xattr_iter_fixup(it); + if (err) + goto out; + it->ofs = 0; + } + + slice = min_t(unsigned int, PAGE_SIZE - it->ofs, + entry.e_name_len - processed); + + /* handle name */ + err = op->name(it, processed, it->kaddr + it->ofs, slice); + if (err) { + it->ofs += entry.e_name_len - processed + value_sz; + goto out; + } + + it->ofs += slice; + processed += slice; + } + + /* 3. handle xattr value */ + processed = 0; + + if (op->alloc_buffer) { + err = op->alloc_buffer(it, value_sz); + if (err) { + it->ofs += value_sz; + goto out; + } + } + + while (processed < value_sz) { + if (it->ofs >= EROFS_BLKSIZ) { + DBG_BUGON(it->ofs > EROFS_BLKSIZ); + + err = xattr_iter_fixup(it); + if (err) + goto out; + it->ofs = 0; + } + + slice = min_t(unsigned int, PAGE_SIZE - it->ofs, + value_sz - processed); + op->value(it, processed, it->kaddr + it->ofs, slice); + it->ofs += slice; + processed += slice; + } + +out: + /* xattrs should be 4-byte aligned (on-disk constraint) */ + it->ofs = EROFS_XATTR_ALIGN(it->ofs); + return err < 0 ? err : 0; +} + +struct getxattr_iter { + struct xattr_iter it; + + char *buffer; + int buffer_size, index; + struct qstr name; +}; + +static int xattr_entrymatch(struct xattr_iter *_it, + struct erofs_xattr_entry *entry) +{ + struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); + + return (it->index != entry->e_name_index || + it->name.len != entry->e_name_len) ? -ENOATTR : 0; +} + +static int xattr_namematch(struct xattr_iter *_it, + unsigned int processed, char *buf, unsigned int len) +{ + struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); + + return memcmp(buf, it->name.name + processed, len) ? -ENOATTR : 0; +} + +static int xattr_checkbuffer(struct xattr_iter *_it, + unsigned int value_sz) +{ + struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); + int err = it->buffer_size < value_sz ? -ERANGE : 0; + + it->buffer_size = value_sz; + return !it->buffer ? 1 : err; +} + +static void xattr_copyvalue(struct xattr_iter *_it, + unsigned int processed, + char *buf, unsigned int len) +{ + struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it); + + memcpy(it->buffer + processed, buf, len); +} + +static const struct xattr_iter_handlers find_xattr_handlers = { + .entry = xattr_entrymatch, + .name = xattr_namematch, + .alloc_buffer = xattr_checkbuffer, + .value = xattr_copyvalue +}; + +static int inline_getxattr(struct inode *inode, struct getxattr_iter *it) +{ + int ret; + unsigned int remaining; + + ret = inline_xattr_iter_begin(&it->it, inode); + if (ret < 0) + return ret; + + remaining = ret; + while (remaining) { + ret = xattr_foreach(&it->it, &find_xattr_handlers, &remaining); + if (ret != -ENOATTR) + break; + } + xattr_iter_end_final(&it->it); + + return ret ? ret : it->buffer_size; +} + +static int shared_getxattr(struct inode *inode, struct getxattr_iter *it) +{ + struct erofs_vnode *const vi = EROFS_V(inode); + struct super_block *const sb = inode->i_sb; + struct erofs_sb_info *const sbi = EROFS_SB(sb); + unsigned int i; + int ret = -ENOATTR; + + for (i = 0; i < vi->xattr_shared_count; ++i) { + erofs_blk_t blkaddr = + xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]); + + it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]); + + if (!i || blkaddr != it->it.blkaddr) { + if (i) + xattr_iter_end(&it->it, true); + + it->it.page = erofs_get_meta_page(sb, blkaddr, false); + if (IS_ERR(it->it.page)) + return PTR_ERR(it->it.page); + + it->it.kaddr = kmap_atomic(it->it.page); + it->it.blkaddr = blkaddr; + } + + ret = xattr_foreach(&it->it, &find_xattr_handlers, NULL); + if (ret != -ENOATTR) + break; + } + if (vi->xattr_shared_count) + xattr_iter_end_final(&it->it); + + return ret ? ret : it->buffer_size; +} + +static bool erofs_xattr_user_list(struct dentry *dentry) +{ + return test_opt(EROFS_SB(dentry->d_sb), XATTR_USER); +} + +static bool erofs_xattr_trusted_list(struct dentry *dentry) +{ + return capable(CAP_SYS_ADMIN); +} + +int erofs_getxattr(struct inode *inode, int index, + const char *name, + void *buffer, size_t buffer_size) +{ + int ret; + struct getxattr_iter it; + + if (unlikely(!name)) + return -EINVAL; + + ret = init_inode_xattrs(inode); + if (ret) + return ret; + + it.index = index; + + it.name.len = strlen(name); + if (it.name.len > EROFS_NAME_LEN) + return -ERANGE; + it.name.name = name; + + it.buffer = buffer; + it.buffer_size = buffer_size; + + it.it.sb = inode->i_sb; + ret = inline_getxattr(inode, &it); + if (ret == -ENOATTR) + ret = shared_getxattr(inode, &it); + return ret; +} + +static int erofs_xattr_generic_get(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + struct erofs_sb_info *const sbi = EROFS_I_SB(inode); + + switch (handler->flags) { + case EROFS_XATTR_INDEX_USER: + if (!test_opt(sbi, XATTR_USER)) + return -EOPNOTSUPP; + break; + case EROFS_XATTR_INDEX_TRUSTED: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + break; + case EROFS_XATTR_INDEX_SECURITY: + break; + default: + return -EINVAL; + } + + return erofs_getxattr(inode, handler->flags, name, buffer, size); +} + +const struct xattr_handler erofs_xattr_user_handler = { + .prefix = XATTR_USER_PREFIX, + .flags = EROFS_XATTR_INDEX_USER, + .list = erofs_xattr_user_list, + .get = erofs_xattr_generic_get, +}; + +const struct xattr_handler erofs_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .flags = EROFS_XATTR_INDEX_TRUSTED, + .list = erofs_xattr_trusted_list, + .get = erofs_xattr_generic_get, +}; + +#ifdef CONFIG_EROFS_FS_SECURITY +const struct xattr_handler __maybe_unused erofs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .flags = EROFS_XATTR_INDEX_SECURITY, + .get = erofs_xattr_generic_get, +}; +#endif + +const struct xattr_handler *erofs_xattr_handlers[] = { + &erofs_xattr_user_handler, +#ifdef CONFIG_EROFS_FS_POSIX_ACL + &posix_acl_access_xattr_handler, + &posix_acl_default_xattr_handler, +#endif + &erofs_xattr_trusted_handler, +#ifdef CONFIG_EROFS_FS_SECURITY + &erofs_xattr_security_handler, +#endif + NULL, +}; + +struct listxattr_iter { + struct xattr_iter it; + + struct dentry *dentry; + char *buffer; + int buffer_size, buffer_ofs; +}; + +static int xattr_entrylist(struct xattr_iter *_it, + struct erofs_xattr_entry *entry) +{ + struct listxattr_iter *it = + container_of(_it, struct listxattr_iter, it); + unsigned int prefix_len; + const char *prefix; + + const struct xattr_handler *h = + erofs_xattr_handler(entry->e_name_index); + + if (!h || (h->list && !h->list(it->dentry))) + return 1; + + prefix = xattr_prefix(h); + prefix_len = strlen(prefix); + + if (!it->buffer) { + it->buffer_ofs += prefix_len + entry->e_name_len + 1; + return 1; + } + + if (it->buffer_ofs + prefix_len + + entry->e_name_len + 1 > it->buffer_size) + return -ERANGE; + + memcpy(it->buffer + it->buffer_ofs, prefix, prefix_len); + it->buffer_ofs += prefix_len; + return 0; +} + +static int xattr_namelist(struct xattr_iter *_it, + unsigned int processed, char *buf, unsigned int len) +{ + struct listxattr_iter *it = + container_of(_it, struct listxattr_iter, it); + + memcpy(it->buffer + it->buffer_ofs, buf, len); + it->buffer_ofs += len; + return 0; +} + +static int xattr_skipvalue(struct xattr_iter *_it, + unsigned int value_sz) +{ + struct listxattr_iter *it = + container_of(_it, struct listxattr_iter, it); + + it->buffer[it->buffer_ofs++] = '\0'; + return 1; +} + +static const struct xattr_iter_handlers list_xattr_handlers = { + .entry = xattr_entrylist, + .name = xattr_namelist, + .alloc_buffer = xattr_skipvalue, + .value = NULL +}; + +static int inline_listxattr(struct listxattr_iter *it) +{ + int ret; + unsigned int remaining; + + ret = inline_xattr_iter_begin(&it->it, d_inode(it->dentry)); + if (ret < 0) + return ret; + + remaining = ret; + while (remaining) { + ret = xattr_foreach(&it->it, &list_xattr_handlers, &remaining); + if (ret) + break; + } + xattr_iter_end_final(&it->it); + return ret ? ret : it->buffer_ofs; +} + +static int shared_listxattr(struct listxattr_iter *it) +{ + struct inode *const inode = d_inode(it->dentry); + struct erofs_vnode *const vi = EROFS_V(inode); + struct super_block *const sb = inode->i_sb; + struct erofs_sb_info *const sbi = EROFS_SB(sb); + unsigned int i; + int ret = 0; + + for (i = 0; i < vi->xattr_shared_count; ++i) { + erofs_blk_t blkaddr = + xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]); + + it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]); + if (!i || blkaddr != it->it.blkaddr) { + if (i) + xattr_iter_end(&it->it, true); + + it->it.page = erofs_get_meta_page(sb, blkaddr, false); + if (IS_ERR(it->it.page)) + return PTR_ERR(it->it.page); + + it->it.kaddr = kmap_atomic(it->it.page); + it->it.blkaddr = blkaddr; + } + + ret = xattr_foreach(&it->it, &list_xattr_handlers, NULL); + if (ret) + break; + } + if (vi->xattr_shared_count) + xattr_iter_end_final(&it->it); + + return ret ? ret : it->buffer_ofs; +} + +ssize_t erofs_listxattr(struct dentry *dentry, + char *buffer, size_t buffer_size) +{ + int ret; + struct listxattr_iter it; + + ret = init_inode_xattrs(d_inode(dentry)); + if (ret) + return ret; + + it.dentry = dentry; + it.buffer = buffer; + it.buffer_size = buffer_size; + it.buffer_ofs = 0; + + it.it.sb = dentry->d_sb; + + ret = inline_listxattr(&it); + if (ret < 0 && ret != -ENOATTR) + return ret; + return shared_listxattr(&it); +} + +#ifdef CONFIG_EROFS_FS_POSIX_ACL +struct posix_acl *erofs_get_acl(struct inode *inode, int type) +{ + struct posix_acl *acl; + int prefix, rc; + char *value = NULL; + + switch (type) { + case ACL_TYPE_ACCESS: + prefix = EROFS_XATTR_INDEX_POSIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + prefix = EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT; + break; + default: + return ERR_PTR(-EINVAL); + } + + rc = erofs_getxattr(inode, prefix, "", NULL, 0); + if (rc > 0) { + value = kmalloc(rc, GFP_KERNEL); + if (!value) + return ERR_PTR(-ENOMEM); + rc = erofs_getxattr(inode, prefix, "", value, rc); + } + + if (rc == -ENOATTR) + acl = NULL; + else if (rc < 0) + acl = ERR_PTR(rc); + else + acl = posix_acl_from_xattr(&init_user_ns, value, rc); + kfree(value); + return acl; +} +#endif + diff --git a/fs/erofs/xattr.h b/fs/erofs/xattr.h new file mode 100644 index 000000000000..c5ca47d814dd --- /dev/null +++ b/fs/erofs/xattr.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2017-2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_XATTR_H +#define __EROFS_XATTR_H + +#include "internal.h" +#include +#include + +/* Attribute not found */ +#define ENOATTR ENODATA + +static inline unsigned int inlinexattr_header_size(struct inode *inode) +{ + return sizeof(struct erofs_xattr_ibody_header) + + sizeof(u32) * EROFS_V(inode)->xattr_shared_count; +} + +static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi, + unsigned int xattr_id) +{ +#ifdef CONFIG_EROFS_FS_XATTR + return sbi->xattr_blkaddr + + xattr_id * sizeof(__u32) / EROFS_BLKSIZ; +#else + return 0; +#endif +} + +static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi, + unsigned int xattr_id) +{ + return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ; +} + +#ifdef CONFIG_EROFS_FS_XATTR +extern const struct xattr_handler erofs_xattr_user_handler; +extern const struct xattr_handler erofs_xattr_trusted_handler; +#ifdef CONFIG_EROFS_FS_SECURITY +extern const struct xattr_handler erofs_xattr_security_handler; +#endif + +static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx) +{ +static const struct xattr_handler *xattr_handler_map[] = { + [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler, +#ifdef CONFIG_EROFS_FS_POSIX_ACL + [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler, + [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = + &posix_acl_default_xattr_handler, +#endif + [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler, +#ifdef CONFIG_EROFS_FS_SECURITY + [EROFS_XATTR_INDEX_SECURITY] = &erofs_xattr_security_handler, +#endif +}; + + return idx && idx < ARRAY_SIZE(xattr_handler_map) ? + xattr_handler_map[idx] : NULL; +} + +extern const struct xattr_handler *erofs_xattr_handlers[]; + +int erofs_getxattr(struct inode *, int, const char *, void *, size_t); +ssize_t erofs_listxattr(struct dentry *, char *, size_t); +#else +static inline int erofs_getxattr(struct inode *inode, int index, + const char *name, void *buffer, + size_t buffer_size) +{ + return -EOPNOTSUPP; +} + +static inline ssize_t erofs_listxattr(struct dentry *dentry, + char *buffer, size_t buffer_size) +{ + return -EOPNOTSUPP; +} +#endif /* !CONFIG_EROFS_FS_XATTR */ + +#ifdef CONFIG_EROFS_FS_POSIX_ACL +struct posix_acl *erofs_get_acl(struct inode *inode, int type); +#else +#define erofs_get_acl (NULL) +#endif + +#endif + diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c new file mode 100644 index 000000000000..b32ad585237c --- /dev/null +++ b/fs/erofs/zdata.c @@ -0,0 +1,1432 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "zdata.h" +#include "compress.h" +#include + +#include + +/* + * a compressed_pages[] placeholder in order to avoid + * being filled with file pages for in-place decompression. + */ +#define PAGE_UNALLOCATED ((void *)0x5F0E4B1D) + +/* how to allocate cached pages for a pcluster */ +enum z_erofs_cache_alloctype { + DONTALLOC, /* don't allocate any cached pages */ + DELAYEDALLOC, /* delayed allocation (at the time of submitting io) */ +}; + +/* + * tagged pointer with 1-bit tag for all compressed pages + * tag 0 - the page is just found with an extra page reference + */ +typedef tagptr1_t compressed_page_t; + +#define tag_compressed_page_justfound(page) \ + tagptr_fold(compressed_page_t, page, 1) + +static struct workqueue_struct *z_erofs_workqueue __read_mostly; +static struct kmem_cache *pcluster_cachep __read_mostly; + +void z_erofs_exit_zip_subsystem(void) +{ + destroy_workqueue(z_erofs_workqueue); + kmem_cache_destroy(pcluster_cachep); +} + +static inline int init_unzip_workqueue(void) +{ + const unsigned int onlinecpus = num_possible_cpus(); + const unsigned int flags = WQ_UNBOUND | WQ_HIGHPRI | WQ_CPU_INTENSIVE; + + /* + * no need to spawn too many threads, limiting threads could minimum + * scheduling overhead, perhaps per-CPU threads should be better? + */ + z_erofs_workqueue = alloc_workqueue("erofs_unzipd", flags, + onlinecpus + onlinecpus / 4); + return z_erofs_workqueue ? 0 : -ENOMEM; +} + +static void init_once(void *ptr) +{ + struct z_erofs_pcluster *pcl = ptr; + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); + unsigned int i; + + mutex_init(&cl->lock); + cl->nr_pages = 0; + cl->vcnt = 0; + for (i = 0; i < Z_EROFS_CLUSTER_MAX_PAGES; ++i) + pcl->compressed_pages[i] = NULL; +} + +static void init_always(struct z_erofs_pcluster *pcl) +{ + struct z_erofs_collection *cl = z_erofs_primarycollection(pcl); + + atomic_set(&pcl->obj.refcount, 1); + + DBG_BUGON(cl->nr_pages); + DBG_BUGON(cl->vcnt); +} + +int __init z_erofs_init_zip_subsystem(void) +{ + pcluster_cachep = kmem_cache_create("erofs_compress", + Z_EROFS_WORKGROUP_SIZE, 0, + SLAB_RECLAIM_ACCOUNT, init_once); + if (pcluster_cachep) { + if (!init_unzip_workqueue()) + return 0; + + kmem_cache_destroy(pcluster_cachep); + } + return -ENOMEM; +} + +enum z_erofs_collectmode { + COLLECT_SECONDARY, + COLLECT_PRIMARY, + /* + * The current collection was the tail of an exist chain, in addition + * that the previous processed chained collections are all decided to + * be hooked up to it. + * A new chain will be created for the remaining collections which are + * not processed yet, therefore different from COLLECT_PRIMARY_FOLLOWED, + * the next collection cannot reuse the whole page safely in + * the following scenario: + * ________________________________________________________________ + * | tail (partial) page | head (partial) page | + * | (belongs to the next cl) | (belongs to the current cl) | + * |_______PRIMARY_FOLLOWED_______|________PRIMARY_HOOKED___________| + */ + COLLECT_PRIMARY_HOOKED, + COLLECT_PRIMARY_FOLLOWED_NOINPLACE, + /* + * The current collection has been linked with the owned chain, and + * could also be linked with the remaining collections, which means + * if the processing page is the tail page of the collection, thus + * the current collection can safely use the whole page (since + * the previous collection is under control) for in-place I/O, as + * illustrated below: + * ________________________________________________________________ + * | tail (partial) page | head (partial) page | + * | (of the current cl) | (of the previous collection) | + * | PRIMARY_FOLLOWED or | | + * |_____PRIMARY_HOOKED___|____________PRIMARY_FOLLOWED____________| + * + * [ (*) the above page can be used as inplace I/O. ] + */ + COLLECT_PRIMARY_FOLLOWED, +}; + +struct z_erofs_collector { + struct z_erofs_pagevec_ctor vector; + + struct z_erofs_pcluster *pcl, *tailpcl; + struct z_erofs_collection *cl; + struct page **compressedpages; + z_erofs_next_pcluster_t owned_head; + + enum z_erofs_collectmode mode; +}; + +struct z_erofs_decompress_frontend { + struct inode *const inode; + + struct z_erofs_collector clt; + struct erofs_map_blocks map; + + /* used for applying cache strategy on the fly */ + bool backmost; + erofs_off_t headoffset; +}; + +#define COLLECTOR_INIT() { \ + .owned_head = Z_EROFS_PCLUSTER_TAIL, \ + .mode = COLLECT_PRIMARY_FOLLOWED } + +#define DECOMPRESS_FRONTEND_INIT(__i) { \ + .inode = __i, .clt = COLLECTOR_INIT(), \ + .backmost = true, } + +static struct page *z_pagemap_global[Z_EROFS_VMAP_GLOBAL_PAGES]; +static DEFINE_MUTEX(z_pagemap_global_lock); + +static void preload_compressed_pages(struct z_erofs_collector *clt, + struct address_space *mc, + enum z_erofs_cache_alloctype type, + struct list_head *pagepool) +{ + const struct z_erofs_pcluster *pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct page **pages = clt->compressedpages; + pgoff_t index = pcl->obj.index + (pages - pcl->compressed_pages); + bool standalone = true; + + if (clt->mode < COLLECT_PRIMARY_FOLLOWED) + return; + + for (; pages < pcl->compressed_pages + clusterpages; ++pages) { + struct page *page; + compressed_page_t t; + + /* the compressed page was loaded before */ + if (READ_ONCE(*pages)) + continue; + + page = find_get_page(mc, index); + + if (page) { + t = tag_compressed_page_justfound(page); + } else if (type == DELAYEDALLOC) { + t = tagptr_init(compressed_page_t, PAGE_UNALLOCATED); + } else { /* DONTALLOC */ + if (standalone) + clt->compressedpages = pages; + standalone = false; + continue; + } + + if (!cmpxchg_relaxed(pages, NULL, tagptr_cast_ptr(t))) + continue; + + if (page) + put_page(page); + } + + if (standalone) /* downgrade to PRIMARY_FOLLOWED_NOINPLACE */ + clt->mode = COLLECT_PRIMARY_FOLLOWED_NOINPLACE; +} + +/* called by erofs_shrinker to get rid of all compressed_pages */ +int erofs_try_to_free_all_cached_pages(struct erofs_sb_info *sbi, + struct erofs_workgroup *grp) +{ + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + struct address_space *const mapping = MNGD_MAPPING(sbi); + const unsigned int clusterpages = BIT(pcl->clusterbits); + int i; + + /* + * refcount of workgroup is now freezed as 1, + * therefore no need to worry about available decompression users. + */ + for (i = 0; i < clusterpages; ++i) { + struct page *page = pcl->compressed_pages[i]; + + if (!page) + continue; + + /* block other users from reclaiming or migrating the page */ + if (!trylock_page(page)) + return -EBUSY; + + if (unlikely(page->mapping != mapping)) + continue; + + /* barrier is implied in the following 'unlock_page' */ + WRITE_ONCE(pcl->compressed_pages[i], NULL); + set_page_private(page, 0); + ClearPagePrivate(page); + + unlock_page(page); + put_page(page); + } + return 0; +} + +int erofs_try_to_free_cached_page(struct address_space *mapping, + struct page *page) +{ + struct z_erofs_pcluster *const pcl = (void *)page_private(page); + const unsigned int clusterpages = BIT(pcl->clusterbits); + int ret = 0; /* 0 - busy */ + + if (erofs_workgroup_try_to_freeze(&pcl->obj, 1)) { + unsigned int i; + + for (i = 0; i < clusterpages; ++i) { + if (pcl->compressed_pages[i] == page) { + WRITE_ONCE(pcl->compressed_pages[i], NULL); + ret = 1; + break; + } + } + erofs_workgroup_unfreeze(&pcl->obj, 1); + + if (ret) { + ClearPagePrivate(page); + put_page(page); + } + } + return ret; +} + +/* page_type must be Z_EROFS_PAGE_TYPE_EXCLUSIVE */ +static inline bool try_inplace_io(struct z_erofs_collector *clt, + struct page *page) +{ + struct z_erofs_pcluster *const pcl = clt->pcl; + const unsigned int clusterpages = BIT(pcl->clusterbits); + + while (clt->compressedpages < pcl->compressed_pages + clusterpages) { + if (!cmpxchg(clt->compressedpages++, NULL, page)) + return true; + } + return false; +} + +/* callers must be with collection lock held */ +static int z_erofs_attach_page(struct z_erofs_collector *clt, + struct page *page, + enum z_erofs_page_type type) +{ + int ret; + bool occupied; + + /* give priority for inplaceio */ + if (clt->mode >= COLLECT_PRIMARY && + type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && + try_inplace_io(clt, page)) + return 0; + + ret = z_erofs_pagevec_enqueue(&clt->vector, + page, type, &occupied); + clt->cl->vcnt += (unsigned int)ret; + + return ret ? 0 : -EAGAIN; +} + +static enum z_erofs_collectmode +try_to_claim_pcluster(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t *owned_head) +{ + /* let's claim these following types of pclusters */ +retry: + if (pcl->next == Z_EROFS_PCLUSTER_NIL) { + /* type 1, nil pcluster */ + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_NIL, + *owned_head) != Z_EROFS_PCLUSTER_NIL) + goto retry; + + *owned_head = &pcl->next; + /* lucky, I am the followee :) */ + return COLLECT_PRIMARY_FOLLOWED; + } else if (pcl->next == Z_EROFS_PCLUSTER_TAIL) { + /* + * type 2, link to the end of a existing open chain, + * be careful that its submission itself is governed + * by the original owned chain. + */ + if (cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + *owned_head) != Z_EROFS_PCLUSTER_TAIL) + goto retry; + *owned_head = Z_EROFS_PCLUSTER_TAIL; + return COLLECT_PRIMARY_HOOKED; + } + return COLLECT_PRIMARY; /* :( better luck next time */ +} + +static struct z_erofs_collection *cllookup(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct erofs_workgroup *grp; + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + unsigned int length; + bool tag; + + grp = erofs_find_workgroup(inode->i_sb, map->m_pa >> PAGE_SHIFT, &tag); + if (!grp) + return NULL; + + pcl = container_of(grp, struct z_erofs_pcluster, obj); + if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } + + cl = z_erofs_primarycollection(pcl); + if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } + + length = READ_ONCE(pcl->length); + if (length & Z_EROFS_PCLUSTER_FULL_LENGTH) { + if ((map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) > length) { + DBG_BUGON(1); + erofs_workgroup_put(grp); + return ERR_PTR(-EFSCORRUPTED); + } + } else { + unsigned int llen = map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT; + + if (map->m_flags & EROFS_MAP_FULL_MAPPED) + llen |= Z_EROFS_PCLUSTER_FULL_LENGTH; + + while (llen > length && + length != cmpxchg_relaxed(&pcl->length, length, llen)) { + cpu_relax(); + length = READ_ONCE(pcl->length); + } + } + mutex_lock(&cl->lock); + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; + clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); + /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = NULL; + clt->pcl = pcl; + clt->cl = cl; + return cl; +} + +static struct z_erofs_collection *clregister(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct z_erofs_pcluster *pcl; + struct z_erofs_collection *cl; + int err; + + /* no available workgroup, let's allocate one */ + pcl = kmem_cache_alloc(pcluster_cachep, GFP_NOFS); + if (unlikely(!pcl)) + return ERR_PTR(-ENOMEM); + + init_always(pcl); + pcl->obj.index = map->m_pa >> PAGE_SHIFT; + + pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) | + (map->m_flags & EROFS_MAP_FULL_MAPPED ? + Z_EROFS_PCLUSTER_FULL_LENGTH : 0); + + if (map->m_flags & EROFS_MAP_ZIPPED) + pcl->algorithmformat = Z_EROFS_COMPRESSION_LZ4; + else + pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; + + pcl->clusterbits = EROFS_V(inode)->z_physical_clusterbits[0]; + pcl->clusterbits -= PAGE_SHIFT; + + /* new pclusters should be claimed as type 1, primary and followed */ + pcl->next = clt->owned_head; + clt->mode = COLLECT_PRIMARY_FOLLOWED; + + cl = z_erofs_primarycollection(pcl); + cl->pageofs = map->m_la & ~PAGE_MASK; + + /* + * lock all primary followed works before visible to others + * and mutex_trylock *never* fails for a new pcluster. + */ + mutex_trylock(&cl->lock); + + err = erofs_register_workgroup(inode->i_sb, &pcl->obj, 0); + if (err) { + mutex_unlock(&cl->lock); + kmem_cache_free(pcluster_cachep, pcl); + return ERR_PTR(-EAGAIN); + } + /* used to check tail merging loop due to corrupted images */ + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) + clt->tailpcl = pcl; + clt->owned_head = &pcl->next; + clt->pcl = pcl; + clt->cl = cl; + return cl; +} + +static int z_erofs_collector_begin(struct z_erofs_collector *clt, + struct inode *inode, + struct erofs_map_blocks *map) +{ + struct z_erofs_collection *cl; + + DBG_BUGON(clt->cl); + + /* must be Z_EROFS_PCLUSTER_TAIL or pointed to previous collection */ + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_NIL); + DBG_BUGON(clt->owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + + if (!PAGE_ALIGNED(map->m_pa)) { + DBG_BUGON(1); + return -EINVAL; + } + +repeat: + cl = cllookup(clt, inode, map); + if (!cl) { + cl = clregister(clt, inode, map); + + if (unlikely(cl == ERR_PTR(-EAGAIN))) + goto repeat; + } + + if (IS_ERR(cl)) + return PTR_ERR(cl); + + z_erofs_pagevec_ctor_init(&clt->vector, Z_EROFS_NR_INLINE_PAGEVECS, + cl->pagevec, cl->vcnt); + + clt->compressedpages = clt->pcl->compressed_pages; + if (clt->mode <= COLLECT_PRIMARY) /* cannot do in-place I/O */ + clt->compressedpages += Z_EROFS_CLUSTER_MAX_PAGES; + return 0; +} + +/* + * keep in mind that no referenced pclusters will be freed + * only after a RCU grace period. + */ +static void z_erofs_rcu_callback(struct rcu_head *head) +{ + struct z_erofs_collection *const cl = + container_of(head, struct z_erofs_collection, rcu); + + kmem_cache_free(pcluster_cachep, + container_of(cl, struct z_erofs_pcluster, + primary_collection)); +} + +void erofs_workgroup_free_rcu(struct erofs_workgroup *grp) +{ + struct z_erofs_pcluster *const pcl = + container_of(grp, struct z_erofs_pcluster, obj); + struct z_erofs_collection *const cl = z_erofs_primarycollection(pcl); + + call_rcu(&cl->rcu, z_erofs_rcu_callback); +} + +static void z_erofs_collection_put(struct z_erofs_collection *cl) +{ + struct z_erofs_pcluster *const pcl = + container_of(cl, struct z_erofs_pcluster, primary_collection); + + erofs_workgroup_put(&pcl->obj); +} + +static bool z_erofs_collector_end(struct z_erofs_collector *clt) +{ + struct z_erofs_collection *cl = clt->cl; + + if (!cl) + return false; + + z_erofs_pagevec_ctor_exit(&clt->vector, false); + mutex_unlock(&cl->lock); + + /* + * if all pending pages are added, don't hold its reference + * any longer if the pcluster isn't hosted by ourselves. + */ + if (clt->mode < COLLECT_PRIMARY_FOLLOWED_NOINPLACE) + z_erofs_collection_put(cl); + + clt->cl = NULL; + return true; +} + +static inline struct page *__stagingpage_alloc(struct list_head *pagepool, + gfp_t gfp) +{ + struct page *page = erofs_allocpage(pagepool, gfp, true); + + page->mapping = Z_EROFS_MAPPING_STAGING; + return page; +} + +static bool should_alloc_managed_pages(struct z_erofs_decompress_frontend *fe, + unsigned int cachestrategy, + erofs_off_t la) +{ + if (cachestrategy <= EROFS_ZIP_CACHE_DISABLED) + return false; + + if (fe->backmost) + return true; + + return cachestrategy >= EROFS_ZIP_CACHE_READAROUND && + la < fe->headoffset; +} + +static int z_erofs_do_read_page(struct z_erofs_decompress_frontend *fe, + struct page *page, + struct list_head *pagepool) +{ + struct inode *const inode = fe->inode; + struct erofs_sb_info *const sbi __maybe_unused = EROFS_I_SB(inode); + struct erofs_map_blocks *const map = &fe->map; + struct z_erofs_collector *const clt = &fe->clt; + const loff_t offset = page_offset(page); + bool tight = (clt->mode >= COLLECT_PRIMARY_HOOKED); + + enum z_erofs_cache_alloctype cache_strategy; + enum z_erofs_page_type page_type; + unsigned int cur, end, spiltted, index; + int err = 0; + + /* register locked file pages as online pages in pack */ + z_erofs_onlinepage_init(page); + + spiltted = 0; + end = PAGE_SIZE; +repeat: + cur = end - 1; + + /* lucky, within the range of the current map_blocks */ + if (offset + cur >= map->m_la && + offset + cur < map->m_la + map->m_llen) { + /* didn't get a valid collection previously (very rare) */ + if (!clt->cl) + goto restart_now; + goto hitted; + } + + /* go ahead the next map_blocks */ + debugln("%s: [out-of-range] pos %llu", __func__, offset + cur); + + if (z_erofs_collector_end(clt)) + fe->backmost = false; + + map->m_la = offset + cur; + map->m_llen = 0; + err = z_erofs_map_blocks_iter(inode, map, 0); + if (unlikely(err)) + goto err_out; + +restart_now: + if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) + goto hitted; + + err = z_erofs_collector_begin(clt, inode, map); + if (unlikely(err)) + goto err_out; + + /* preload all compressed pages (maybe downgrade role if necessary) */ + if (should_alloc_managed_pages(fe, sbi->cache_strategy, map->m_la)) + cache_strategy = DELAYEDALLOC; + else + cache_strategy = DONTALLOC; + + preload_compressed_pages(clt, MNGD_MAPPING(sbi), + cache_strategy, pagepool); + + tight &= (clt->mode >= COLLECT_PRIMARY_HOOKED); +hitted: + cur = end - min_t(unsigned int, offset + end - map->m_la, end); + if (unlikely(!(map->m_flags & EROFS_MAP_MAPPED))) { + zero_user_segment(page, cur, end); + goto next_part; + } + + /* let's derive page type */ + page_type = cur ? Z_EROFS_VLE_PAGE_TYPE_HEAD : + (!spiltted ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : + (tight ? Z_EROFS_PAGE_TYPE_EXCLUSIVE : + Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED)); + + if (cur) + tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); + +retry: + err = z_erofs_attach_page(clt, page, page_type); + /* should allocate an additional staging page for pagevec */ + if (err == -EAGAIN) { + struct page *const newpage = + __stagingpage_alloc(pagepool, GFP_NOFS); + + err = z_erofs_attach_page(clt, newpage, + Z_EROFS_PAGE_TYPE_EXCLUSIVE); + if (likely(!err)) + goto retry; + } + + if (unlikely(err)) + goto err_out; + + index = page->index - (map->m_la >> PAGE_SHIFT); + + z_erofs_onlinepage_fixup(page, index, true); + + /* bump up the number of spiltted parts of a page */ + ++spiltted; + /* also update nr_pages */ + clt->cl->nr_pages = max_t(pgoff_t, clt->cl->nr_pages, index + 1); +next_part: + /* can be used for verification */ + map->m_llen = offset + cur - map->m_la; + + end = cur; + if (end > 0) + goto repeat; + +out: + z_erofs_onlinepage_endio(page); + + debugln("%s, finish page: %pK spiltted: %u map->m_llen %llu", + __func__, page, spiltted, map->m_llen); + return err; + + /* if some error occurred while processing this page */ +err_out: + SetPageError(page); + goto out; +} + +static void z_erofs_vle_unzip_kickoff(void *ptr, int bios) +{ + tagptr1_t t = tagptr_init(tagptr1_t, ptr); + struct z_erofs_unzip_io *io = tagptr_unfold_ptr(t); + bool background = tagptr_unfold_tags(t); + + if (!background) { + unsigned long flags; + + spin_lock_irqsave(&io->u.wait.lock, flags); + if (!atomic_add_return(bios, &io->pending_bios)) + wake_up_locked(&io->u.wait); + spin_unlock_irqrestore(&io->u.wait.lock, flags); + return; + } + + if (!atomic_add_return(bios, &io->pending_bios)) + queue_work(z_erofs_workqueue, &io->u.work); +} + +static inline void z_erofs_vle_read_endio(struct bio *bio) +{ + struct erofs_sb_info *sbi = NULL; + blk_status_t err = bio->bi_status; + struct bio_vec *bvec; + struct bvec_iter_all iter_all; + + bio_for_each_segment_all(bvec, bio, iter_all) { + struct page *page = bvec->bv_page; + bool cachemngd = false; + + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!page->mapping); + + if (unlikely(!sbi && !z_erofs_page_is_staging(page))) { + sbi = EROFS_SB(page->mapping->host->i_sb); + + if (time_to_inject(sbi, FAULT_READ_IO)) { + erofs_show_injection_info(FAULT_READ_IO); + err = BLK_STS_IOERR; + } + } + + /* sbi should already be gotten if the page is managed */ + if (sbi) + cachemngd = erofs_page_is_managed(sbi, page); + + if (unlikely(err)) + SetPageError(page); + else if (cachemngd) + SetPageUptodate(page); + + if (cachemngd) + unlock_page(page); + } + + z_erofs_vle_unzip_kickoff(bio->bi_private, -1); + bio_put(bio); +} + +static int z_erofs_decompress_pcluster(struct super_block *sb, + struct z_erofs_pcluster *pcl, + struct list_head *pagepool) +{ + struct erofs_sb_info *const sbi = EROFS_SB(sb); + const unsigned int clusterpages = BIT(pcl->clusterbits); + struct z_erofs_pagevec_ctor ctor; + unsigned int i, outputsize, llen, nr_pages; + struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES]; + struct page **pages, **compressed_pages, *page; + + enum z_erofs_page_type page_type; + bool overlapped, partial; + struct z_erofs_collection *cl; + int err; + + might_sleep(); + cl = z_erofs_primarycollection(pcl); + DBG_BUGON(!READ_ONCE(cl->nr_pages)); + + mutex_lock(&cl->lock); + nr_pages = cl->nr_pages; + + if (likely(nr_pages <= Z_EROFS_VMAP_ONSTACK_PAGES)) { + pages = pages_onstack; + } else if (nr_pages <= Z_EROFS_VMAP_GLOBAL_PAGES && + mutex_trylock(&z_pagemap_global_lock)) { + pages = z_pagemap_global; + } else { + gfp_t gfp_flags = GFP_KERNEL; + + if (nr_pages > Z_EROFS_VMAP_GLOBAL_PAGES) + gfp_flags |= __GFP_NOFAIL; + + pages = kvmalloc_array(nr_pages, sizeof(struct page *), + gfp_flags); + + /* fallback to global pagemap for the lowmem scenario */ + if (unlikely(!pages)) { + mutex_lock(&z_pagemap_global_lock); + pages = z_pagemap_global; + } + } + + for (i = 0; i < nr_pages; ++i) + pages[i] = NULL; + + err = 0; + z_erofs_pagevec_ctor_init(&ctor, Z_EROFS_NR_INLINE_PAGEVECS, + cl->pagevec, 0); + + for (i = 0; i < cl->vcnt; ++i) { + unsigned int pagenr; + + page = z_erofs_pagevec_dequeue(&ctor, &page_type); + + /* all pages in pagevec ought to be valid */ + DBG_BUGON(!page); + DBG_BUGON(!page->mapping); + + if (z_erofs_put_stagingpage(pagepool, page)) + continue; + + if (page_type == Z_EROFS_VLE_PAGE_TYPE_HEAD) + pagenr = 0; + else + pagenr = z_erofs_onlinepage_index(page); + + DBG_BUGON(pagenr >= nr_pages); + + /* + * currently EROFS doesn't support multiref(dedup), + * so here erroring out one multiref page. + */ + if (unlikely(pages[pagenr])) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } + pages[pagenr] = page; + } + z_erofs_pagevec_ctor_exit(&ctor, true); + + overlapped = false; + compressed_pages = pcl->compressed_pages; + + for (i = 0; i < clusterpages; ++i) { + unsigned int pagenr; + + page = compressed_pages[i]; + + /* all compressed pages ought to be valid */ + DBG_BUGON(!page); + DBG_BUGON(!page->mapping); + + if (!z_erofs_page_is_staging(page)) { + if (erofs_page_is_managed(sbi, page)) { + if (unlikely(!PageUptodate(page))) + err = -EIO; + continue; + } + + /* + * only if non-head page can be selected + * for inplace decompression + */ + pagenr = z_erofs_onlinepage_index(page); + + DBG_BUGON(pagenr >= nr_pages); + if (unlikely(pages[pagenr])) { + DBG_BUGON(1); + SetPageError(pages[pagenr]); + z_erofs_onlinepage_endio(pages[pagenr]); + err = -EFSCORRUPTED; + } + pages[pagenr] = page; + + overlapped = true; + } + + /* PG_error needs checking for inplaced and staging pages */ + if (unlikely(PageError(page))) { + DBG_BUGON(PageUptodate(page)); + err = -EIO; + } + } + + if (unlikely(err)) + goto out; + + llen = pcl->length >> Z_EROFS_PCLUSTER_LENGTH_BIT; + if (nr_pages << PAGE_SHIFT >= cl->pageofs + llen) { + outputsize = llen; + partial = !(pcl->length & Z_EROFS_PCLUSTER_FULL_LENGTH); + } else { + outputsize = (nr_pages << PAGE_SHIFT) - cl->pageofs; + partial = true; + } + + err = z_erofs_decompress(&(struct z_erofs_decompress_req) { + .sb = sb, + .in = compressed_pages, + .out = pages, + .pageofs_out = cl->pageofs, + .inputsize = PAGE_SIZE, + .outputsize = outputsize, + .alg = pcl->algorithmformat, + .inplace_io = overlapped, + .partial_decoding = partial + }, pagepool); + +out: + /* must handle all compressed pages before endding pages */ + for (i = 0; i < clusterpages; ++i) { + page = compressed_pages[i]; + + if (erofs_page_is_managed(sbi, page)) + continue; + + /* recycle all individual staging pages */ + (void)z_erofs_put_stagingpage(pagepool, page); + + WRITE_ONCE(compressed_pages[i], NULL); + } + + for (i = 0; i < nr_pages; ++i) { + page = pages[i]; + if (!page) + continue; + + DBG_BUGON(!page->mapping); + + /* recycle all individual staging pages */ + if (z_erofs_put_stagingpage(pagepool, page)) + continue; + + if (unlikely(err < 0)) + SetPageError(page); + + z_erofs_onlinepage_endio(page); + } + + if (pages == z_pagemap_global) + mutex_unlock(&z_pagemap_global_lock); + else if (unlikely(pages != pages_onstack)) + kvfree(pages); + + cl->nr_pages = 0; + cl->vcnt = 0; + + /* all cl locks MUST be taken before the following line */ + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_NIL); + + /* all cl locks SHOULD be released right now */ + mutex_unlock(&cl->lock); + + z_erofs_collection_put(cl); + return err; +} + +static void z_erofs_vle_unzip_all(struct super_block *sb, + struct z_erofs_unzip_io *io, + struct list_head *pagepool) +{ + z_erofs_next_pcluster_t owned = io->head; + + while (owned != Z_EROFS_PCLUSTER_TAIL_CLOSED) { + struct z_erofs_pcluster *pcl; + + /* no possible that 'owned' equals Z_EROFS_WORK_TPTR_TAIL */ + DBG_BUGON(owned == Z_EROFS_PCLUSTER_TAIL); + + /* no possible that 'owned' equals NULL */ + DBG_BUGON(owned == Z_EROFS_PCLUSTER_NIL); + + pcl = container_of(owned, struct z_erofs_pcluster, next); + owned = READ_ONCE(pcl->next); + + z_erofs_decompress_pcluster(sb, pcl, pagepool); + } +} + +static void z_erofs_vle_unzip_wq(struct work_struct *work) +{ + struct z_erofs_unzip_io_sb *iosb = + container_of(work, struct z_erofs_unzip_io_sb, io.u.work); + LIST_HEAD(pagepool); + + DBG_BUGON(iosb->io.head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + z_erofs_vle_unzip_all(iosb->sb, &iosb->io, &pagepool); + + put_pages_list(&pagepool); + kvfree(iosb); +} + +static struct page *pickup_page_for_submission(struct z_erofs_pcluster *pcl, + unsigned int nr, + struct list_head *pagepool, + struct address_space *mc, + gfp_t gfp) +{ + /* determined at compile time to avoid too many #ifdefs */ + const bool nocache = __builtin_constant_p(mc) ? !mc : false; + const pgoff_t index = pcl->obj.index; + bool tocache = false; + + struct address_space *mapping; + struct page *oldpage, *page; + + compressed_page_t t; + int justfound; + +repeat: + page = READ_ONCE(pcl->compressed_pages[nr]); + oldpage = page; + + if (!page) + goto out_allocpage; + + /* + * the cached page has not been allocated and + * an placeholder is out there, prepare it now. + */ + if (!nocache && page == PAGE_UNALLOCATED) { + tocache = true; + goto out_allocpage; + } + + /* process the target tagged pointer */ + t = tagptr_init(compressed_page_t, page); + justfound = tagptr_unfold_tags(t); + page = tagptr_unfold_ptr(t); + + mapping = READ_ONCE(page->mapping); + + /* + * if managed cache is disabled, it's no way to + * get such a cached-like page. + */ + if (nocache) { + /* if managed cache is disabled, it is impossible `justfound' */ + DBG_BUGON(justfound); + + /* and it should be locked, not uptodate, and not truncated */ + DBG_BUGON(!PageLocked(page)); + DBG_BUGON(PageUptodate(page)); + DBG_BUGON(!mapping); + goto out; + } + + /* + * unmanaged (file) pages are all locked solidly, + * therefore it is impossible for `mapping' to be NULL. + */ + if (mapping && mapping != mc) + /* ought to be unmanaged pages */ + goto out; + + lock_page(page); + + /* only true if page reclaim goes wrong, should never happen */ + DBG_BUGON(justfound && PagePrivate(page)); + + /* the page is still in manage cache */ + if (page->mapping == mc) { + WRITE_ONCE(pcl->compressed_pages[nr], page); + + ClearPageError(page); + if (!PagePrivate(page)) { + /* + * impossible to be !PagePrivate(page) for + * the current restriction as well if + * the page is already in compressed_pages[]. + */ + DBG_BUGON(!justfound); + + justfound = 0; + set_page_private(page, (unsigned long)pcl); + SetPagePrivate(page); + } + + /* no need to submit io if it is already up-to-date */ + if (PageUptodate(page)) { + unlock_page(page); + page = NULL; + } + goto out; + } + + /* + * the managed page has been truncated, it's unsafe to + * reuse this one, let's allocate a new cache-managed page. + */ + DBG_BUGON(page->mapping); + DBG_BUGON(!justfound); + + tocache = true; + unlock_page(page); + put_page(page); +out_allocpage: + page = __stagingpage_alloc(pagepool, gfp); + if (oldpage != cmpxchg(&pcl->compressed_pages[nr], oldpage, page)) { + list_add(&page->lru, pagepool); + cpu_relax(); + goto repeat; + } + if (nocache || !tocache) + goto out; + if (add_to_page_cache_lru(page, mc, index + nr, gfp)) { + page->mapping = Z_EROFS_MAPPING_STAGING; + goto out; + } + + set_page_private(page, (unsigned long)pcl); + SetPagePrivate(page); +out: /* the only exit (for tracing and debugging) */ + return page; +} + +static struct z_erofs_unzip_io *jobqueue_init(struct super_block *sb, + struct z_erofs_unzip_io *io, + bool foreground) +{ + struct z_erofs_unzip_io_sb *iosb; + + if (foreground) { + /* waitqueue available for foreground io */ + DBG_BUGON(!io); + + init_waitqueue_head(&io->u.wait); + atomic_set(&io->pending_bios, 0); + goto out; + } + + iosb = kvzalloc(sizeof(*iosb), GFP_KERNEL | __GFP_NOFAIL); + DBG_BUGON(!iosb); + + /* initialize fields in the allocated descriptor */ + io = &iosb->io; + iosb->sb = sb; + INIT_WORK(&io->u.work, z_erofs_vle_unzip_wq); +out: + io->head = Z_EROFS_PCLUSTER_TAIL_CLOSED; + return io; +} + +/* define decompression jobqueue types */ +enum { + JQ_BYPASS, + JQ_SUBMIT, + NR_JOBQUEUES, +}; + +static void *jobqueueset_init(struct super_block *sb, + z_erofs_next_pcluster_t qtail[], + struct z_erofs_unzip_io *q[], + struct z_erofs_unzip_io *fgq, + bool forcefg) +{ + /* + * if managed cache is enabled, bypass jobqueue is needed, + * no need to read from device for all pclusters in this queue. + */ + q[JQ_BYPASS] = jobqueue_init(sb, fgq + JQ_BYPASS, true); + qtail[JQ_BYPASS] = &q[JQ_BYPASS]->head; + + q[JQ_SUBMIT] = jobqueue_init(sb, fgq + JQ_SUBMIT, forcefg); + qtail[JQ_SUBMIT] = &q[JQ_SUBMIT]->head; + + return tagptr_cast_ptr(tagptr_fold(tagptr1_t, q[JQ_SUBMIT], !forcefg)); +} + +static void move_to_bypass_jobqueue(struct z_erofs_pcluster *pcl, + z_erofs_next_pcluster_t qtail[], + z_erofs_next_pcluster_t owned_head) +{ + z_erofs_next_pcluster_t *const submit_qtail = qtail[JQ_SUBMIT]; + z_erofs_next_pcluster_t *const bypass_qtail = qtail[JQ_BYPASS]; + + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + if (owned_head == Z_EROFS_PCLUSTER_TAIL) + owned_head = Z_EROFS_PCLUSTER_TAIL_CLOSED; + + WRITE_ONCE(pcl->next, Z_EROFS_PCLUSTER_TAIL_CLOSED); + + WRITE_ONCE(*submit_qtail, owned_head); + WRITE_ONCE(*bypass_qtail, &pcl->next); + + qtail[JQ_BYPASS] = &pcl->next; +} + +static bool postsubmit_is_all_bypassed(struct z_erofs_unzip_io *q[], + unsigned int nr_bios, + bool force_fg) +{ + /* + * although background is preferred, no one is pending for submission. + * don't issue workqueue for decompression but drop it directly instead. + */ + if (force_fg || nr_bios) + return false; + + kvfree(container_of(q[JQ_SUBMIT], struct z_erofs_unzip_io_sb, io)); + return true; +} + +static bool z_erofs_vle_submit_all(struct super_block *sb, + z_erofs_next_pcluster_t owned_head, + struct list_head *pagepool, + struct z_erofs_unzip_io *fgq, + bool force_fg) +{ + struct erofs_sb_info *const sbi __maybe_unused = EROFS_SB(sb); + z_erofs_next_pcluster_t qtail[NR_JOBQUEUES]; + struct z_erofs_unzip_io *q[NR_JOBQUEUES]; + struct bio *bio; + void *bi_private; + /* since bio will be NULL, no need to initialize last_index */ + pgoff_t uninitialized_var(last_index); + bool force_submit = false; + unsigned int nr_bios; + + if (unlikely(owned_head == Z_EROFS_PCLUSTER_TAIL)) + return false; + + force_submit = false; + bio = NULL; + nr_bios = 0; + bi_private = jobqueueset_init(sb, qtail, q, fgq, force_fg); + + /* by default, all need io submission */ + q[JQ_SUBMIT]->head = owned_head; + + do { + struct z_erofs_pcluster *pcl; + unsigned int clusterpages; + pgoff_t first_index; + struct page *page; + unsigned int i = 0, bypass = 0; + int err; + + /* no possible 'owned_head' equals the following */ + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_TAIL_CLOSED); + DBG_BUGON(owned_head == Z_EROFS_PCLUSTER_NIL); + + pcl = container_of(owned_head, struct z_erofs_pcluster, next); + + clusterpages = BIT(pcl->clusterbits); + + /* close the main owned chain at first */ + owned_head = cmpxchg(&pcl->next, Z_EROFS_PCLUSTER_TAIL, + Z_EROFS_PCLUSTER_TAIL_CLOSED); + + first_index = pcl->obj.index; + force_submit |= (first_index != last_index + 1); + +repeat: + page = pickup_page_for_submission(pcl, i, pagepool, + MNGD_MAPPING(sbi), + GFP_NOFS); + if (!page) { + force_submit = true; + ++bypass; + goto skippage; + } + + if (bio && force_submit) { +submit_bio_retry: + __submit_bio(bio, REQ_OP_READ, 0); + bio = NULL; + } + + if (!bio) { + bio = erofs_grab_bio(sb, first_index + i, + BIO_MAX_PAGES, bi_private, + z_erofs_vle_read_endio, true); + ++nr_bios; + } + + err = bio_add_page(bio, page, PAGE_SIZE, 0); + if (err < PAGE_SIZE) + goto submit_bio_retry; + + force_submit = false; + last_index = first_index + i; +skippage: + if (++i < clusterpages) + goto repeat; + + if (bypass < clusterpages) + qtail[JQ_SUBMIT] = &pcl->next; + else + move_to_bypass_jobqueue(pcl, qtail, owned_head); + } while (owned_head != Z_EROFS_PCLUSTER_TAIL); + + if (bio) + __submit_bio(bio, REQ_OP_READ, 0); + + if (postsubmit_is_all_bypassed(q, nr_bios, force_fg)) + return true; + + z_erofs_vle_unzip_kickoff(bi_private, nr_bios); + return true; +} + +static void z_erofs_submit_and_unzip(struct super_block *sb, + struct z_erofs_collector *clt, + struct list_head *pagepool, + bool force_fg) +{ + struct z_erofs_unzip_io io[NR_JOBQUEUES]; + + if (!z_erofs_vle_submit_all(sb, clt->owned_head, + pagepool, io, force_fg)) + return; + + /* decompress no I/O pclusters immediately */ + z_erofs_vle_unzip_all(sb, &io[JQ_BYPASS], pagepool); + + if (!force_fg) + return; + + /* wait until all bios are completed */ + wait_event(io[JQ_SUBMIT].u.wait, + !atomic_read(&io[JQ_SUBMIT].pending_bios)); + + /* let's synchronous decompression */ + z_erofs_vle_unzip_all(sb, &io[JQ_SUBMIT], pagepool); +} + +static int z_erofs_vle_normalaccess_readpage(struct file *file, + struct page *page) +{ + struct inode *const inode = page->mapping->host; + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); + int err; + LIST_HEAD(pagepool); + + trace_erofs_readpage(page, false); + + f.headoffset = (erofs_off_t)page->index << PAGE_SHIFT; + + err = z_erofs_do_read_page(&f, page, &pagepool); + (void)z_erofs_collector_end(&f.clt); + + /* if some compressed cluster ready, need submit them anyway */ + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, true); + + if (err) + errln("%s, failed to read, err [%d]", __func__, err); + + if (f.map.mpage) + put_page(f.map.mpage); + + /* clean up the remaining free pages */ + put_pages_list(&pagepool); + return err; +} + +static bool should_decompress_synchronously(struct erofs_sb_info *sbi, + unsigned int nr) +{ + return nr <= sbi->max_sync_decompress_pages; +} + +static int z_erofs_vle_normalaccess_readpages(struct file *filp, + struct address_space *mapping, + struct list_head *pages, + unsigned int nr_pages) +{ + struct inode *const inode = mapping->host; + struct erofs_sb_info *const sbi = EROFS_I_SB(inode); + + bool sync = should_decompress_synchronously(sbi, nr_pages); + struct z_erofs_decompress_frontend f = DECOMPRESS_FRONTEND_INIT(inode); + gfp_t gfp = mapping_gfp_constraint(mapping, GFP_KERNEL); + struct page *head = NULL; + LIST_HEAD(pagepool); + + trace_erofs_readpages(mapping->host, lru_to_page(pages), + nr_pages, false); + + f.headoffset = (erofs_off_t)lru_to_page(pages)->index << PAGE_SHIFT; + + for (; nr_pages; --nr_pages) { + struct page *page = lru_to_page(pages); + + prefetchw(&page->flags); + list_del(&page->lru); + + /* + * A pure asynchronous readahead is indicated if + * a PG_readahead marked page is hitted at first. + * Let's also do asynchronous decompression for this case. + */ + sync &= !(PageReadahead(page) && !head); + + if (add_to_page_cache_lru(page, mapping, page->index, gfp)) { + list_add(&page->lru, &pagepool); + continue; + } + + set_page_private(page, (unsigned long)head); + head = page; + } + + while (head) { + struct page *page = head; + int err; + + /* traversal in reverse order */ + head = (void *)page_private(page); + + err = z_erofs_do_read_page(&f, page, &pagepool); + if (err) { + struct erofs_vnode *vi = EROFS_V(inode); + + errln("%s, readahead error at page %lu of nid %llu", + __func__, page->index, vi->nid); + } + put_page(page); + } + + (void)z_erofs_collector_end(&f.clt); + + z_erofs_submit_and_unzip(inode->i_sb, &f.clt, &pagepool, sync); + + if (f.map.mpage) + put_page(f.map.mpage); + + /* clean up the remaining free pages */ + put_pages_list(&pagepool); + return 0; +} + +const struct address_space_operations z_erofs_vle_normalaccess_aops = { + .readpage = z_erofs_vle_normalaccess_readpage, + .readpages = z_erofs_vle_normalaccess_readpages, +}; + diff --git a/fs/erofs/zdata.h b/fs/erofs/zdata.h new file mode 100644 index 000000000000..4fc547bc01f9 --- /dev/null +++ b/fs/erofs/zdata.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_FS_ZDATA_H +#define __EROFS_FS_ZDATA_H + +#include "internal.h" +#include "zpvec.h" + +#define Z_EROFS_NR_INLINE_PAGEVECS 3 + +/* + * Structure fields follow one of the following exclusion rules. + * + * I: Modifiable by initialization/destruction paths and read-only + * for everyone else; + * + * L: Field should be protected by pageset lock; + * + * A: Field should be accessed / updated in atomic for parallelized code. + */ +struct z_erofs_collection { + struct mutex lock; + + /* I: page offset of start position of decompression */ + unsigned short pageofs; + + /* L: maximum relative page index in pagevec[] */ + unsigned short nr_pages; + + /* L: total number of pages in pagevec[] */ + unsigned int vcnt; + + union { + /* L: inline a certain number of pagevecs for bootstrap */ + erofs_vtptr_t pagevec[Z_EROFS_NR_INLINE_PAGEVECS]; + + /* I: can be used to free the pcluster by RCU. */ + struct rcu_head rcu; + }; +}; + +#define Z_EROFS_PCLUSTER_FULL_LENGTH 0x00000001 +#define Z_EROFS_PCLUSTER_LENGTH_BIT 1 + +/* + * let's leave a type here in case of introducing + * another tagged pointer later. + */ +typedef void *z_erofs_next_pcluster_t; + +struct z_erofs_pcluster { + struct erofs_workgroup obj; + struct z_erofs_collection primary_collection; + + /* A: point to next chained pcluster or TAILs */ + z_erofs_next_pcluster_t next; + + /* A: compressed pages (including multi-usage pages) */ + struct page *compressed_pages[Z_EROFS_CLUSTER_MAX_PAGES]; + + /* A: lower limit of decompressed length and if full length or not */ + unsigned int length; + + /* I: compression algorithm format */ + unsigned char algorithmformat; + /* I: bit shift of physical cluster size */ + unsigned char clusterbits; +}; + +#define z_erofs_primarycollection(pcluster) (&(pcluster)->primary_collection) + +/* let's avoid the valid 32-bit kernel addresses */ + +/* the chained workgroup has't submitted io (still open) */ +#define Z_EROFS_PCLUSTER_TAIL ((void *)0x5F0ECAFE) +/* the chained workgroup has already submitted io */ +#define Z_EROFS_PCLUSTER_TAIL_CLOSED ((void *)0x5F0EDEAD) + +#define Z_EROFS_PCLUSTER_NIL (NULL) + +#define Z_EROFS_WORKGROUP_SIZE sizeof(struct z_erofs_pcluster) + +struct z_erofs_unzip_io { + atomic_t pending_bios; + z_erofs_next_pcluster_t head; + + union { + wait_queue_head_t wait; + struct work_struct work; + } u; +}; + +struct z_erofs_unzip_io_sb { + struct z_erofs_unzip_io io; + struct super_block *sb; +}; + +#define MNGD_MAPPING(sbi) ((sbi)->managed_cache->i_mapping) +static inline bool erofs_page_is_managed(const struct erofs_sb_info *sbi, + struct page *page) +{ + return page->mapping == MNGD_MAPPING(sbi); +} + +#define Z_EROFS_ONLINEPAGE_COUNT_BITS 2 +#define Z_EROFS_ONLINEPAGE_COUNT_MASK ((1 << Z_EROFS_ONLINEPAGE_COUNT_BITS) - 1) +#define Z_EROFS_ONLINEPAGE_INDEX_SHIFT (Z_EROFS_ONLINEPAGE_COUNT_BITS) + +/* + * waiters (aka. ongoing_packs): # to unlock the page + * sub-index: 0 - for partial page, >= 1 full page sub-index + */ +typedef atomic_t z_erofs_onlinepage_t; + +/* type punning */ +union z_erofs_onlinepage_converter { + z_erofs_onlinepage_t *o; + unsigned long *v; +}; + +static inline unsigned int z_erofs_onlinepage_index(struct page *page) +{ + union z_erofs_onlinepage_converter u; + + DBG_BUGON(!PagePrivate(page)); + u.v = &page_private(page); + + return atomic_read(u.o) >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; +} + +static inline void z_erofs_onlinepage_init(struct page *page) +{ + union { + z_erofs_onlinepage_t o; + unsigned long v; + /* keep from being unlocked in advance */ + } u = { .o = ATOMIC_INIT(1) }; + + set_page_private(page, u.v); + smp_wmb(); + SetPagePrivate(page); +} + +static inline void z_erofs_onlinepage_fixup(struct page *page, + uintptr_t index, bool down) +{ + unsigned long *p, o, v, id; +repeat: + p = &page_private(page); + o = READ_ONCE(*p); + + id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT; + if (id) { + if (!index) + return; + + DBG_BUGON(id != index); + } + + v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) | + ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down); + if (cmpxchg(p, o, v) != o) + goto repeat; +} + +static inline void z_erofs_onlinepage_endio(struct page *page) +{ + union z_erofs_onlinepage_converter u; + unsigned int v; + + DBG_BUGON(!PagePrivate(page)); + u.v = &page_private(page); + + v = atomic_dec_return(u.o); + if (!(v & Z_EROFS_ONLINEPAGE_COUNT_MASK)) { + ClearPagePrivate(page); + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); + } + debugln("%s, page %p value %x", __func__, page, atomic_read(u.o)); +} + +#define Z_EROFS_VMAP_ONSTACK_PAGES \ + min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U) +#define Z_EROFS_VMAP_GLOBAL_PAGES 2048 + +#endif + diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c new file mode 100644 index 000000000000..4dc9cec01297 --- /dev/null +++ b/fs/erofs/zmap.c @@ -0,0 +1,466 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2018-2019 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#include "internal.h" +#include +#include + +int z_erofs_fill_inode(struct inode *inode) +{ + struct erofs_vnode *const vi = EROFS_V(inode); + + if (vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) { + vi->z_advise = 0; + vi->z_algorithmtype[0] = 0; + vi->z_algorithmtype[1] = 0; + vi->z_logical_clusterbits = LOG_BLOCK_SIZE; + vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits; + vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits; + set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); + } + + inode->i_mapping->a_ops = &z_erofs_vle_normalaccess_aops; + return 0; +} + +static int fill_inode_lazy(struct inode *inode) +{ + struct erofs_vnode *const vi = EROFS_V(inode); + struct super_block *const sb = inode->i_sb; + int err; + erofs_off_t pos; + struct page *page; + void *kaddr; + struct z_erofs_map_header *h; + + if (test_bit(EROFS_V_Z_INITED_BIT, &vi->flags)) + return 0; + + if (wait_on_bit_lock(&vi->flags, EROFS_V_BL_Z_BIT, TASK_KILLABLE)) + return -ERESTARTSYS; + + err = 0; + if (test_bit(EROFS_V_Z_INITED_BIT, &vi->flags)) + goto out_unlock; + + DBG_BUGON(vi->datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY); + + pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize + + vi->xattr_isize, 8); + page = erofs_get_meta_page(sb, erofs_blknr(pos), false); + if (IS_ERR(page)) { + err = PTR_ERR(page); + goto out_unlock; + } + + kaddr = kmap_atomic(page); + + h = kaddr + erofs_blkoff(pos); + vi->z_advise = le16_to_cpu(h->h_advise); + vi->z_algorithmtype[0] = h->h_algorithmtype & 15; + vi->z_algorithmtype[1] = h->h_algorithmtype >> 4; + + if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX) { + errln("unknown compression format %u for nid %llu, please upgrade kernel", + vi->z_algorithmtype[0], vi->nid); + err = -EOPNOTSUPP; + goto unmap_done; + } + + vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7); + vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits + + ((h->h_clusterbits >> 3) & 3); + + if (vi->z_physical_clusterbits[0] != LOG_BLOCK_SIZE) { + errln("unsupported physical clusterbits %u for nid %llu, please upgrade kernel", + vi->z_physical_clusterbits[0], vi->nid); + err = -EOPNOTSUPP; + goto unmap_done; + } + + vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits + + ((h->h_clusterbits >> 5) & 7); + set_bit(EROFS_V_Z_INITED_BIT, &vi->flags); +unmap_done: + kunmap_atomic(kaddr); + unlock_page(page); + put_page(page); +out_unlock: + clear_and_wake_up_bit(EROFS_V_BL_Z_BIT, &vi->flags); + return err; +} + +struct z_erofs_maprecorder { + struct inode *inode; + struct erofs_map_blocks *map; + void *kaddr; + + unsigned long lcn; + /* compression extent information gathered */ + u8 type; + u16 clusterofs; + u16 delta[2]; + erofs_blk_t pblk; +}; + +static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m, + erofs_blk_t eblk) +{ + struct super_block *const sb = m->inode->i_sb; + struct erofs_map_blocks *const map = m->map; + struct page *mpage = map->mpage; + + if (mpage) { + if (mpage->index == eblk) { + if (!m->kaddr) + m->kaddr = kmap_atomic(mpage); + return 0; + } + + if (m->kaddr) { + kunmap_atomic(m->kaddr); + m->kaddr = NULL; + } + put_page(mpage); + } + + mpage = erofs_get_meta_page(sb, eblk, false); + if (IS_ERR(mpage)) { + map->mpage = NULL; + return PTR_ERR(mpage); + } + m->kaddr = kmap_atomic(mpage); + unlock_page(mpage); + map->mpage = mpage; + return 0; +} + +static int vle_legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned long lcn) +{ + struct inode *const inode = m->inode; + struct erofs_vnode *const vi = EROFS_V(inode); + const erofs_off_t ibase = iloc(EROFS_I_SB(inode), vi->nid); + const erofs_off_t pos = + Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize + + vi->xattr_isize) + + lcn * sizeof(struct z_erofs_vle_decompressed_index); + struct z_erofs_vle_decompressed_index *di; + unsigned int advise, type; + int err; + + err = z_erofs_reload_indexes(m, erofs_blknr(pos)); + if (err) + return err; + + m->lcn = lcn; + di = m->kaddr + erofs_blkoff(pos); + + advise = le16_to_cpu(di->di_advise); + type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) & + ((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1); + switch (type) { + case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + m->clusterofs = 1 << vi->z_logical_clusterbits; + m->delta[0] = le16_to_cpu(di->di_u.delta[0]); + m->delta[1] = le16_to_cpu(di->di_u.delta[1]); + break; + case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: + case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: + m->clusterofs = le16_to_cpu(di->di_clusterofs); + m->pblk = le32_to_cpu(di->di_u.blkaddr); + break; + default: + DBG_BUGON(1); + return -EOPNOTSUPP; + } + m->type = type; + return 0; +} + +static unsigned int decode_compactedbits(unsigned int lobits, + unsigned int lomask, + u8 *in, unsigned int pos, u8 *type) +{ + const unsigned int v = get_unaligned_le32(in + pos / 8) >> (pos & 7); + const unsigned int lo = v & lomask; + + *type = (v >> lobits) & 3; + return lo; +} + +static int unpack_compacted_index(struct z_erofs_maprecorder *m, + unsigned int amortizedshift, + unsigned int eofs) +{ + struct erofs_vnode *const vi = EROFS_V(m->inode); + const unsigned int lclusterbits = vi->z_logical_clusterbits; + const unsigned int lomask = (1 << lclusterbits) - 1; + unsigned int vcnt, base, lo, encodebits, nblk; + int i; + u8 *in, type; + + if (1 << amortizedshift == 4) + vcnt = 2; + else if (1 << amortizedshift == 2 && lclusterbits == 12) + vcnt = 16; + else + return -EOPNOTSUPP; + + encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt; + base = round_down(eofs, vcnt << amortizedshift); + in = m->kaddr + base; + + i = (eofs - base) >> amortizedshift; + + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + m->type = type; + if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) { + m->clusterofs = 1 << lclusterbits; + if (i + 1 != vcnt) { + m->delta[0] = lo; + return 0; + } + /* + * since the last lcluster in the pack is special, + * of which lo saves delta[1] rather than delta[0]. + * Hence, get delta[0] by the previous lcluster indirectly. + */ + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * (i - 1), &type); + if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) + lo = 0; + m->delta[0] = lo + 1; + return 0; + } + m->clusterofs = lo; + m->delta[0] = 0; + /* figout out blkaddr (pblk) for HEAD lclusters */ + nblk = 1; + while (i > 0) { + --i; + lo = decode_compactedbits(lclusterbits, lomask, + in, encodebits * i, &type); + if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) + i -= lo; + + if (i >= 0) + ++nblk; + } + in += (vcnt << amortizedshift) - sizeof(__le32); + m->pblk = le32_to_cpu(*(__le32 *)in) + nblk; + return 0; +} + +static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned long lcn) +{ + struct inode *const inode = m->inode; + struct erofs_vnode *const vi = EROFS_V(inode); + const unsigned int lclusterbits = vi->z_logical_clusterbits; + const erofs_off_t ebase = ALIGN(iloc(EROFS_I_SB(inode), vi->nid) + + vi->inode_isize + vi->xattr_isize, 8) + + sizeof(struct z_erofs_map_header); + const unsigned int totalidx = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ); + unsigned int compacted_4b_initial, compacted_2b; + unsigned int amortizedshift; + erofs_off_t pos; + int err; + + if (lclusterbits != 12) + return -EOPNOTSUPP; + + if (lcn >= totalidx) + return -EINVAL; + + m->lcn = lcn; + /* used to align to 32-byte (compacted_2b) alignment */ + compacted_4b_initial = (32 - ebase % 32) / 4; + if (compacted_4b_initial == 32 / 4) + compacted_4b_initial = 0; + + if (vi->z_advise & Z_EROFS_ADVISE_COMPACTED_2B) + compacted_2b = rounddown(totalidx - compacted_4b_initial, 16); + else + compacted_2b = 0; + + pos = ebase; + if (lcn < compacted_4b_initial) { + amortizedshift = 2; + goto out; + } + pos += compacted_4b_initial * 4; + lcn -= compacted_4b_initial; + + if (lcn < compacted_2b) { + amortizedshift = 1; + goto out; + } + pos += compacted_2b * 2; + lcn -= compacted_2b; + amortizedshift = 2; +out: + pos += lcn * (1 << amortizedshift); + err = z_erofs_reload_indexes(m, erofs_blknr(pos)); + if (err) + return err; + return unpack_compacted_index(m, amortizedshift, erofs_blkoff(pos)); +} + +static int vle_load_cluster_from_disk(struct z_erofs_maprecorder *m, + unsigned int lcn) +{ + const unsigned int datamode = EROFS_V(m->inode)->datamode; + + if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY) + return vle_legacy_load_cluster_from_disk(m, lcn); + + if (datamode == EROFS_INODE_FLAT_COMPRESSION) + return compacted_load_cluster_from_disk(m, lcn); + + return -EINVAL; +} + +static int vle_extent_lookback(struct z_erofs_maprecorder *m, + unsigned int lookback_distance) +{ + struct erofs_vnode *const vi = EROFS_V(m->inode); + struct erofs_map_blocks *const map = m->map; + const unsigned int lclusterbits = vi->z_logical_clusterbits; + unsigned long lcn = m->lcn; + int err; + + if (lcn < lookback_distance) { + errln("bogus lookback distance @ nid %llu", vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } + + /* load extent head logical cluster if needed */ + lcn -= lookback_distance; + err = vle_load_cluster_from_disk(m, lcn); + if (err) + return err; + + switch (m->type) { + case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + if (unlikely(!m->delta[0])) { + errln("invalid lookback distance 0 at nid %llu", + vi->nid); + DBG_BUGON(1); + return -EFSCORRUPTED; + } + return vle_extent_lookback(m, m->delta[0]); + case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: + map->m_flags &= ~EROFS_MAP_ZIPPED; + /* fallthrough */ + case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: + map->m_la = (lcn << lclusterbits) | m->clusterofs; + break; + default: + errln("unknown type %u at lcn %lu of nid %llu", + m->type, lcn, vi->nid); + DBG_BUGON(1); + return -EOPNOTSUPP; + } + return 0; +} + +int z_erofs_map_blocks_iter(struct inode *inode, + struct erofs_map_blocks *map, + int flags) +{ + struct erofs_vnode *const vi = EROFS_V(inode); + struct z_erofs_maprecorder m = { + .inode = inode, + .map = map, + }; + int err = 0; + unsigned int lclusterbits, endoff; + unsigned long long ofs, end; + + trace_z_erofs_map_blocks_iter_enter(inode, map, flags); + + /* when trying to read beyond EOF, leave it unmapped */ + if (unlikely(map->m_la >= inode->i_size)) { + map->m_llen = map->m_la + 1 - inode->i_size; + map->m_la = inode->i_size; + map->m_flags = 0; + goto out; + } + + err = fill_inode_lazy(inode); + if (err) + goto out; + + lclusterbits = vi->z_logical_clusterbits; + ofs = map->m_la; + m.lcn = ofs >> lclusterbits; + endoff = ofs & ((1 << lclusterbits) - 1); + + err = vle_load_cluster_from_disk(&m, m.lcn); + if (err) + goto unmap_out; + + map->m_flags = EROFS_MAP_ZIPPED; /* by default, compressed */ + end = (m.lcn + 1ULL) << lclusterbits; + + switch (m.type) { + case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: + if (endoff >= m.clusterofs) + map->m_flags &= ~EROFS_MAP_ZIPPED; + /* fallthrough */ + case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: + if (endoff >= m.clusterofs) { + map->m_la = (m.lcn << lclusterbits) | m.clusterofs; + break; + } + /* m.lcn should be >= 1 if endoff < m.clusterofs */ + if (unlikely(!m.lcn)) { + errln("invalid logical cluster 0 at nid %llu", + vi->nid); + err = -EFSCORRUPTED; + goto unmap_out; + } + end = (m.lcn << lclusterbits) | m.clusterofs; + map->m_flags |= EROFS_MAP_FULL_MAPPED; + m.delta[0] = 1; + /* fallthrough */ + case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: + /* get the correspoinding first chunk */ + err = vle_extent_lookback(&m, m.delta[0]); + if (unlikely(err)) + goto unmap_out; + break; + default: + errln("unknown type %u at offset %llu of nid %llu", + m.type, ofs, vi->nid); + err = -EOPNOTSUPP; + goto unmap_out; + } + + map->m_llen = end - map->m_la; + map->m_plen = 1 << lclusterbits; + map->m_pa = blknr_to_addr(m.pblk); + map->m_flags |= EROFS_MAP_MAPPED; + +unmap_out: + if (m.kaddr) + kunmap_atomic(m.kaddr); + +out: + debugln("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o", + __func__, map->m_la, map->m_pa, + map->m_llen, map->m_plen, map->m_flags); + + trace_z_erofs_map_blocks_iter_exit(inode, map, flags, err); + + /* aggressively BUG_ON iff CONFIG_EROFS_FS_DEBUG is on */ + DBG_BUGON(err < 0 && err != -ENOMEM); + return err; +} + diff --git a/fs/erofs/zpvec.h b/fs/erofs/zpvec.h new file mode 100644 index 000000000000..bd3cee16491c --- /dev/null +++ b/fs/erofs/zpvec.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2018 HUAWEI, Inc. + * http://www.huawei.com/ + * Created by Gao Xiang + */ +#ifndef __EROFS_FS_ZPVEC_H +#define __EROFS_FS_ZPVEC_H + +#include "tagptr.h" + +/* page type in pagevec for decompress subsystem */ +enum z_erofs_page_type { + /* including Z_EROFS_VLE_PAGE_TAIL_EXCLUSIVE */ + Z_EROFS_PAGE_TYPE_EXCLUSIVE, + + Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED, + + Z_EROFS_VLE_PAGE_TYPE_HEAD, + Z_EROFS_VLE_PAGE_TYPE_MAX +}; + +extern void __compiletime_error("Z_EROFS_PAGE_TYPE_EXCLUSIVE != 0") + __bad_page_type_exclusive(void); + +/* pagevec tagged pointer */ +typedef tagptr2_t erofs_vtptr_t; + +/* pagevec collector */ +struct z_erofs_pagevec_ctor { + struct page *curr, *next; + erofs_vtptr_t *pages; + + unsigned int nr, index; +}; + +static inline void z_erofs_pagevec_ctor_exit(struct z_erofs_pagevec_ctor *ctor, + bool atomic) +{ + if (!ctor->curr) + return; + + if (atomic) + kunmap_atomic(ctor->pages); + else + kunmap(ctor->curr); +} + +static inline struct page * +z_erofs_pagevec_ctor_next_page(struct z_erofs_pagevec_ctor *ctor, + unsigned int nr) +{ + unsigned int index; + + /* keep away from occupied pages */ + if (ctor->next) + return ctor->next; + + for (index = 0; index < nr; ++index) { + const erofs_vtptr_t t = ctor->pages[index]; + const unsigned int tags = tagptr_unfold_tags(t); + + if (tags == Z_EROFS_PAGE_TYPE_EXCLUSIVE) + return tagptr_unfold_ptr(t); + } + DBG_BUGON(nr >= ctor->nr); + return NULL; +} + +static inline void +z_erofs_pagevec_ctor_pagedown(struct z_erofs_pagevec_ctor *ctor, + bool atomic) +{ + struct page *next = z_erofs_pagevec_ctor_next_page(ctor, ctor->nr); + + z_erofs_pagevec_ctor_exit(ctor, atomic); + + ctor->curr = next; + ctor->next = NULL; + ctor->pages = atomic ? + kmap_atomic(ctor->curr) : kmap(ctor->curr); + + ctor->nr = PAGE_SIZE / sizeof(struct page *); + ctor->index = 0; +} + +static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor, + unsigned int nr, + erofs_vtptr_t *pages, + unsigned int i) +{ + ctor->nr = nr; + ctor->curr = ctor->next = NULL; + ctor->pages = pages; + + if (i >= nr) { + i -= nr; + z_erofs_pagevec_ctor_pagedown(ctor, false); + while (i > ctor->nr) { + i -= ctor->nr; + z_erofs_pagevec_ctor_pagedown(ctor, false); + } + } + ctor->next = z_erofs_pagevec_ctor_next_page(ctor, i); + ctor->index = i; +} + +static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, + struct page *page, + enum z_erofs_page_type type, + bool *occupied) +{ + *occupied = false; + if (unlikely(!ctor->next && type)) + if (ctor->index + 1 == ctor->nr) + return false; + + if (unlikely(ctor->index >= ctor->nr)) + z_erofs_pagevec_ctor_pagedown(ctor, false); + + /* exclusive page type must be 0 */ + if (Z_EROFS_PAGE_TYPE_EXCLUSIVE != (uintptr_t)NULL) + __bad_page_type_exclusive(); + + /* should remind that collector->next never equal to 1, 2 */ + if (type == (uintptr_t)ctor->next) { + ctor->next = page; + *occupied = true; + } + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); + return true; +} + +static inline struct page * +z_erofs_pagevec_dequeue(struct z_erofs_pagevec_ctor *ctor, + enum z_erofs_page_type *type) +{ + erofs_vtptr_t t; + + if (unlikely(ctor->index >= ctor->nr)) { + DBG_BUGON(!ctor->next); + z_erofs_pagevec_ctor_pagedown(ctor, true); + } + + t = ctor->pages[ctor->index]; + + *type = tagptr_unfold_tags(t); + + /* should remind that collector->next never equal to 1, 2 */ + if (*type == (uintptr_t)ctor->next) + ctor->next = tagptr_unfold_ptr(t); + + ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, NULL, 0); + return tagptr_unfold_ptr(t); +} +#endif + diff --git a/include/trace/events/erofs.h b/include/trace/events/erofs.h new file mode 100644 index 000000000000..bfb2da9c4eee --- /dev/null +++ b/include/trace/events/erofs.h @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM erofs + +#if !defined(_TRACE_EROFS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_EROFS_H + +#include + +#define show_dev(dev) MAJOR(dev), MINOR(dev) +#define show_dev_nid(entry) show_dev(entry->dev), entry->nid + +#define show_file_type(type) \ + __print_symbolic(type, \ + { 0, "FILE" }, \ + { 1, "DIR" }) + +#define show_map_flags(flags) __print_flags(flags, "|", \ + { EROFS_GET_BLOCKS_RAW, "RAW" }) + +#define show_mflags(flags) __print_flags(flags, "", \ + { EROFS_MAP_MAPPED, "M" }, \ + { EROFS_MAP_META, "I" }, \ + { EROFS_MAP_ZIPPED, "Z" }) + +TRACE_EVENT(erofs_lookup, + + TP_PROTO(struct inode *dir, struct dentry *dentry, unsigned int flags), + + TP_ARGS(dir, dentry, flags), + + TP_STRUCT__entry( + __field(dev_t, dev ) + __field(erofs_nid_t, nid ) + __field(const char *, name ) + __field(unsigned int, flags ) + ), + + TP_fast_assign( + __entry->dev = dir->i_sb->s_dev; + __entry->nid = EROFS_V(dir)->nid; + __entry->name = dentry->d_name.name; + __entry->flags = flags; + ), + + TP_printk("dev = (%d,%d), pnid = %llu, name:%s, flags:%x", + show_dev_nid(__entry), + __entry->name, + __entry->flags) +); + +TRACE_EVENT(erofs_fill_inode, + TP_PROTO(struct inode *inode, int isdir), + TP_ARGS(inode, isdir), + + TP_STRUCT__entry( + __field(dev_t, dev ) + __field(erofs_nid_t, nid ) + __field(erofs_blk_t, blkaddr ) + __field(unsigned int, ofs ) + __field(int, isdir ) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->nid = EROFS_V(inode)->nid; + __entry->blkaddr = erofs_blknr(iloc(EROFS_I_SB(inode), __entry->nid)); + __entry->ofs = erofs_blkoff(iloc(EROFS_I_SB(inode), __entry->nid)); + __entry->isdir = isdir; + ), + + TP_printk("dev = (%d,%d), nid = %llu, blkaddr %u ofs %u, isdir %d", + show_dev_nid(__entry), + __entry->blkaddr, __entry->ofs, + __entry->isdir) +); + +TRACE_EVENT(erofs_readpage, + + TP_PROTO(struct page *page, bool raw), + + TP_ARGS(page, raw), + + TP_STRUCT__entry( + __field(dev_t, dev ) + __field(erofs_nid_t, nid ) + __field(int, dir ) + __field(pgoff_t, index ) + __field(int, uptodate) + __field(bool, raw ) + ), + + TP_fast_assign( + __entry->dev = page->mapping->host->i_sb->s_dev; + __entry->nid = EROFS_V(page->mapping->host)->nid; + __entry->dir = S_ISDIR(page->mapping->host->i_mode); + __entry->index = page->index; + __entry->uptodate = PageUptodate(page); + __entry->raw = raw; + ), + + TP_printk("dev = (%d,%d), nid = %llu, %s, index = %lu, uptodate = %d " + "raw = %d", + show_dev_nid(__entry), + show_file_type(__entry->dir), + (unsigned long)__entry->index, + __entry->uptodate, + __entry->raw) +); + +TRACE_EVENT(erofs_readpages, + + TP_PROTO(struct inode *inode, struct page *page, unsigned int nrpage, + bool raw), + + TP_ARGS(inode, page, nrpage, raw), + + TP_STRUCT__entry( + __field(dev_t, dev ) + __field(erofs_nid_t, nid ) + __field(pgoff_t, start ) + __field(unsigned int, nrpage ) + __field(bool, raw ) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->nid = EROFS_V(inode)->nid; + __entry->start = page->index; + __entry->nrpage = nrpage; + __entry->raw = raw; + ), + + TP_printk("dev = (%d,%d), nid = %llu, start = %lu nrpage = %u raw = %d", + show_dev_nid(__entry), + (unsigned long)__entry->start, + __entry->nrpage, + __entry->raw) +); + +DECLARE_EVENT_CLASS(erofs__map_blocks_enter, + TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, + unsigned int flags), + + TP_ARGS(inode, map, flags), + + TP_STRUCT__entry( + __field( dev_t, dev ) + __field( erofs_nid_t, nid ) + __field( erofs_off_t, la ) + __field( u64, llen ) + __field( unsigned int, flags ) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->nid = EROFS_V(inode)->nid; + __entry->la = map->m_la; + __entry->llen = map->m_llen; + __entry->flags = flags; + ), + + TP_printk("dev = (%d,%d), nid = %llu, la %llu llen %llu flags %s", + show_dev_nid(__entry), + __entry->la, __entry->llen, + __entry->flags ? show_map_flags(__entry->flags) : "NULL") +); + +DEFINE_EVENT(erofs__map_blocks_enter, erofs_map_blocks_flatmode_enter, + TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, + unsigned flags), + + TP_ARGS(inode, map, flags) +); + +DEFINE_EVENT(erofs__map_blocks_enter, z_erofs_map_blocks_iter_enter, + TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, + unsigned int flags), + + TP_ARGS(inode, map, flags) +); + +DECLARE_EVENT_CLASS(erofs__map_blocks_exit, + TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, + unsigned int flags, int ret), + + TP_ARGS(inode, map, flags, ret), + + TP_STRUCT__entry( + __field( dev_t, dev ) + __field( erofs_nid_t, nid ) + __field( unsigned int, flags ) + __field( erofs_off_t, la ) + __field( erofs_off_t, pa ) + __field( u64, llen ) + __field( u64, plen ) + __field( unsigned int, mflags ) + __field( int, ret ) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->nid = EROFS_V(inode)->nid; + __entry->flags = flags; + __entry->la = map->m_la; + __entry->pa = map->m_pa; + __entry->llen = map->m_llen; + __entry->plen = map->m_plen; + __entry->mflags = map->m_flags; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), nid = %llu, flags %s " + "la %llu pa %llu llen %llu plen %llu mflags %s ret %d", + show_dev_nid(__entry), + __entry->flags ? show_map_flags(__entry->flags) : "NULL", + __entry->la, __entry->pa, __entry->llen, __entry->plen, + show_mflags(__entry->mflags), __entry->ret) +); + +DEFINE_EVENT(erofs__map_blocks_exit, erofs_map_blocks_flatmode_exit, + TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, + unsigned flags, int ret), + + TP_ARGS(inode, map, flags, ret) +); + +DEFINE_EVENT(erofs__map_blocks_exit, z_erofs_map_blocks_iter_exit, + TP_PROTO(struct inode *inode, struct erofs_map_blocks *map, + unsigned int flags, int ret), + + TP_ARGS(inode, map, flags, ret) +); + +TRACE_EVENT(erofs_destroy_inode, + TP_PROTO(struct inode *inode), + + TP_ARGS(inode), + + TP_STRUCT__entry( + __field( dev_t, dev ) + __field( erofs_nid_t, nid ) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->nid = EROFS_V(inode)->nid; + ), + + TP_printk("dev = (%d,%d), nid = %llu", show_dev_nid(__entry)) +); + +#endif /* _TRACE_EROFS_H */ + + /* This part must be outside protection */ +#include diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index 1274c692e59c..903cc2d2750b 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -19,6 +19,7 @@ #define SQUASHFS_MAGIC 0x73717368 #define ECRYPTFS_SUPER_MAGIC 0xf15f #define EFS_SUPER_MAGIC 0x414A53 +#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 #define EXT2_SUPER_MAGIC 0xEF53 #define EXT3_SUPER_MAGIC 0xEF53 #define XENFS_SUPER_MAGIC 0xabba1974 -- cgit v1.2.3-59-g8ed1b From de9defd21539d37816dc869b098ae8eed12857ad Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Wed, 21 Aug 2019 22:31:10 +0530 Subject: staging: rtl8723bs: os_dep: Remove unused declarations Remove unused Macro declarations Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/1566406901-6700-1-git-send-email-hariprasad.kelam@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 2 -- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 3 --- drivers/staging/rtl8723bs/os_dep/wifi_regd.c | 5 ----- 3 files changed, 10 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 57876463b9b2..f819abb756dc 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -19,8 +19,6 @@ #define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 /* ms */ #define RTW_MAX_NUM_PMKIDS 4 -#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */ - static const u32 rtw_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 90c2997256b7..0e565c0ed6bc 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -21,13 +21,10 @@ #define RATE_COUNT 4 /* combo scan */ -#define WEXT_CSCAN_AMOUNT 9 -#define WEXT_CSCAN_BUF_LEN 360 #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" #define WEXT_CSCAN_HEADER_SIZE 12 #define WEXT_CSCAN_SSID_SECTION 'S' #define WEXT_CSCAN_CHANNEL_SECTION 'C' -#define WEXT_CSCAN_NPROBE_SECTION 'N' #define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' #define WEXT_CSCAN_PASV_DWELL_SECTION 'P' #define WEXT_CSCAN_HOME_DWELL_SECTION 'H' diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c index aa2f62acc994..578b9f734231 100644 --- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c +++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c @@ -33,11 +33,6 @@ REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20, \ NL80211_RRF_PASSIVE_SCAN) -/* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */ -#define RTW_2GHZ_CH14 \ - REG_RULE(2484 - 10, 2484 + 10, 40, 0, 20, \ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) - static const struct ieee80211_regdomain rtw_regdom_rd = { .n_reg_rules = 3, .alpha2 = "99", -- cgit v1.2.3-59-g8ed1b From eac53016919f2d2a8df607c69dc2b1d47273a61e Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Wed, 21 Aug 2019 23:32:01 +0530 Subject: staging: rtl8723bs: hal: Drop condition with no effect As the "else if" and "else" branch body are identical the condition has no effect. So drop the else if condition. Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190821180153.GA10678@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/hal_btcoex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/hal_btcoex.c b/drivers/staging/rtl8723bs/hal/hal_btcoex.c index 19486f0e0ead..6e4a1fcb8790 100644 --- a/drivers/staging/rtl8723bs/hal/hal_btcoex.c +++ b/drivers/staging/rtl8723bs/hal/hal_btcoex.c @@ -482,10 +482,8 @@ static u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf) *pU4Tmp = BTC_WIFI_BW_LEGACY; else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20) *pU4Tmp = BTC_WIFI_BW_HT20; - else if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) - *pU4Tmp = BTC_WIFI_BW_HT40; else - *pU4Tmp = BTC_WIFI_BW_HT40; /* todo */ + *pU4Tmp = BTC_WIFI_BW_HT40; break; case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION: -- cgit v1.2.3-59-g8ed1b From 5ab706bd0bcaea0296426ecca333f69bad60d24e Mon Sep 17 00:00:00 2001 From: Saurav Girepunje Date: Wed, 21 Aug 2019 23:46:34 +0530 Subject: staging: rtl8723bs: os_dep: Drop condition with no effect As the "else if" and "else" branch body are identical the condition has no effect. So drop the "else if" condition. Signed-off-by: Saurav Girepunje Link: https://lore.kernel.org/r/20190821181631.GA11082@saurav Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 0e565c0ed6bc..d1b199e3e5bd 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -212,8 +212,6 @@ static char *translate_scan(struct adapter *padapter, } else if (ht_cap) { if (mcs_rate&0x8000) { /* MCS15 */ max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130); - } else if (mcs_rate&0x0080) { /* MCS7 */ - max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); } else { /* default MCS7 */ /* DBG_871X("wx_get_scan, mcs_rate_bitmap = 0x%x\n", mcs_rate); */ max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65); -- cgit v1.2.3-59-g8ed1b From 5e718a12e1a125045b451678faf6ceffc7591e3b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 22 Aug 2019 09:46:09 +0100 Subject: staging: rtl8192u: remove redundant assignment to pointer crypt The pointer crypt is being set with a value that is never read, the assignment is redundant and hence can be removed. Thanks to Dan Carpenter for sanity checking that this was indeed redundant. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190822084609.8971-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index e0da0900a4f7..33a6af7aad22 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -743,7 +743,6 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - crypt = ieee->crypt[ieee->tx_keyidx]; if (encrypt) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); -- cgit v1.2.3-59-g8ed1b From 76fe9cfb09e7bf261b814a155f5953fa4d2df89a Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Thu, 22 Aug 2019 20:25:45 +0530 Subject: staging: rtl8192u: Remove unnecessary blank lines This patch fixes the file r8180_93cx6.c to avoid the checkpatch.pl warning: CHECK: Please don't use multiple blank lines Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190822145545.19894-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8180_93cx6.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c index de83daa0c9ed..6ebf121eac0c 100644 --- a/drivers/staging/rtl8192u/r8180_93cx6.c +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -39,7 +39,6 @@ static void eprom_cs(struct net_device *dev, short bit) udelay(EPROM_DELAY); } - static void eprom_ck_cycle(struct net_device *dev) { u8 cmdreg; @@ -58,7 +57,6 @@ static void eprom_ck_cycle(struct net_device *dev) udelay(EPROM_DELAY); } - static void eprom_w(struct net_device *dev, short bit) { u8 cmdreg; @@ -76,7 +74,6 @@ static void eprom_w(struct net_device *dev, short bit) udelay(EPROM_DELAY); } - static short eprom_r(struct net_device *dev) { u8 bit; @@ -94,7 +91,6 @@ static short eprom_r(struct net_device *dev) return 0; } - static void eprom_send_bits_string(struct net_device *dev, short b[], int len) { int i; @@ -105,7 +101,6 @@ static void eprom_send_bits_string(struct net_device *dev, short b[], int len) } } - int eprom_read(struct net_device *dev, u32 addr) { struct r8192_priv *priv = ieee80211_priv(dev); -- cgit v1.2.3-59-g8ed1b From 684c215dd06eccc515dfd786347ac556c00f895a Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Fri, 23 Aug 2019 09:24:10 -0700 Subject: staging: rtl8192u: remove code under TO_DO_LIST Several blocks of code are guarded by #ifdef TO_DO_LIST. If this is defined, compilation fails. No machinery exists to define this, and no documenation on the in-progress feature exists. Since this code is dead, let's delete it. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190823162410.10038-1-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 2 - drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c | 21 ----- .../staging/rtl8192u/ieee80211/rtl819x_HTProc.c | 4 - .../staging/rtl8192u/ieee80211/rtl819x_TSProc.c | 4 - drivers/staging/rtl8192u/r8192U_core.c | 101 +-------------------- drivers/staging/rtl8192u/r819xU_phy.c | 59 ------------ 6 files changed, 4 insertions(+), 187 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index daebbbd8f4dd..9576b647f6b1 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -1649,10 +1649,8 @@ struct ieee80211_device { struct list_head Rx_TS_Pending_List; struct list_head Rx_TS_Unused_List; struct rx_ts_record RxTsRecord[TOTAL_TS_NUM]; -//#ifdef TO_DO_LIST struct rx_reorder_entry RxReorderEntry[128]; struct list_head RxReorder_Unused_List; -//#endif // Qos related. Added by Annie, 2005-11-01. // PSTA_QOS pStaQos; u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index e76bdedc8409..140e3cb66a2e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -302,13 +302,6 @@ static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, if (is_multicast_ether_addr(hdr->addr1)) return; //check packet and mode later -#ifdef TO_DO_LIST - if (pTcb->PacketLength >= 4096) - return; - // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation. - if (!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) - return; -#endif if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) { return; } @@ -509,20 +502,6 @@ NO_PROTECTION: static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, struct cb_desc *tcb_desc) { -#ifdef TO_DO_LIST - if (!IsDataFrame(pFrame)) { - pTcb->bTxDisableRateFallBack = true; - pTcb->bTxUseDriverAssingedRate = true; - pTcb->RATRIndex = 7; - return; - } - - if (pMgntInfo->ForcedDataRate != 0) { - pTcb->bTxDisableRateFallBack = true; - pTcb->bTxUseDriverAssingedRate = true; - return; - } -#endif if (ieee->bTxDisableRateFallBack) tcb_desc->bTxDisableRateFallBack = true; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c index c73a8058cf87..dba3f2db9f48 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c @@ -93,10 +93,6 @@ void HTUpdateDefaultSetting(struct ieee80211_device *ieee) ieee->bTxDisableRateFallBack = 0; ieee->bTxUseDriverAssingedRate = 0; -#ifdef TO_DO_LIST - // 8190 only. Assign duration operation mode to firmware - pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur; -#endif /* * 8190 only, Realtek proprietary aggregation mode * Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index f4e5aa07421f..5cee1031a27c 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -180,14 +180,12 @@ void TSInitialize(struct ieee80211_device *ieee) } // Initialize unused Rx Reorder List. INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); -//#ifdef TO_DO_LIST for (count = 0; count < REORDER_ENTRY_NUM; count++) { list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List); if (count == (REORDER_ENTRY_NUM - 1)) break; pRxReorderEntry = &ieee->RxReorderEntry[count + 1]; } -//#endif } static void AdmitTS(struct ieee80211_device *ieee, @@ -417,7 +415,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info * TsInitDelBA(ieee, pTs, TxRxSelect); if (TxRxSelect == RX_DIR) { -//#ifdef TO_DO_LIST struct rx_reorder_entry *pRxReorderEntry; struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs; if (timer_pending(&pRxTS->rx_pkt_pending_timer)) @@ -445,7 +442,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, struct ts_common_info * spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); } -//#endif } else { struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs; del_timer_sync(&pTxTS->ts_add_ba_timer); diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index 569d02240bf5..2821411878ce 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2076,14 +2076,6 @@ static void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode) wireless_mode = WIRELESS_MODE_B; } } -#ifdef TO_DO_LIST - /* TODO: this function doesn't work well at this time, - * we should wait for FPGA - */ - ActUpdateChannelAccessSetting( - pAdapter, pHalData->CurrentWirelessMode, - &pAdapter->MgntInfo.Info8185.ChannelAccessSetting); -#endif priv->ieee80211->mode = wireless_mode; if (wireless_mode == WIRELESS_MODE_N_24G || @@ -2159,12 +2151,6 @@ static int rtl8192_init_priv_variable(struct net_device *dev) priv->ieee80211->InitialGainHandler = InitialGain819xUsb; priv->card_type = USB; -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) { - pHalData->ShortRetryLimit = 7; - pHalData->LongRetryLimit = 7; - } -#endif priv->ShortRetryLimit = 0x30; priv->LongRetryLimit = 0x30; priv->EarlyRxThreshold = 7; @@ -2180,34 +2166,6 @@ static int rtl8192_init_priv_variable(struct net_device *dev) * TRUE: SW provides them */ (false ? TCR_SAT : 0); -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) - pHalData->ReceiveConfig = - pHalData->CSMethod | - /* accept management/data */ - RCR_AMF | RCR_ADF | - /* accept control frame for SW - * AP needs PS-poll - */ - RCR_ACF | - /* accept BC/MC/UC */ - RCR_AB | RCR_AM | RCR_APM | - /* accept ICV/CRC error - * packet - */ - RCR_AICV | RCR_ACRC32 | - /* Max DMA Burst Size per Tx - * DMA Burst, 7: unlimited. - */ - ((u32)7 << RCR_MXDMA_OFFSET) | - /* Rx FIFO Threshold, - * 7: No Rx threshold. - */ - (pHalData->EarlyRxThreshold << RCR_FIFO_OFFSET) | - (pHalData->EarlyRxThreshold == 7 ? RCR_OnlyErlPkt : 0); - else - -#endif priv->ReceiveConfig = /* accept management/data */ RCR_AMF | RCR_ADF | @@ -2665,19 +2623,10 @@ static void rtl8192_hwconfig(struct net_device *dev) regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_AUTO: -#ifdef TO_DO_LIST - if (Adapter->bInHctTest) { - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - } else -#endif - { - regBwOpMode = BW_OPMODE_20MHZ; - regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - } + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; break; case WIRELESS_MODE_N_24G: /* It support CCK rate by default. CCK rate will be filtered @@ -2848,48 +2797,6 @@ static bool rtl8192_adapter_start(struct net_device *dev) } RT_TRACE(COMP_INIT, "%s():after firmware download\n", __func__); -#ifdef TO_DO_LIST - if (Adapter->ResetProgress == RESET_TYPE_NORESET) { - if (pMgntInfo->RegRfOff) { /* User disable RF via registry. */ - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n")); - MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW); - /* Those actions will be discard in MgntActSet_RF_State - * because of the same state - */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) - PHY_SetRFReg(Adapter, - (enum rf90_radio_path_e)eRFPath, - 0x4, 0xC00, 0x0); - } else if (pMgntInfo->RfOffReason > RF_CHANGE_BY_PS) { - /* H/W or S/W RF OFF before sleep. */ - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): Turn off RF for RfOffReason(%d) ----------\n", - pMgntInfo->RfOffReason)); - MgntActSet_RF_State(Adapter, - eRfOff, - pMgntInfo->RfOffReason); - } else { - pHalData->eRFPowerState = eRfOn; - pMgntInfo->RfOffReason = 0; - RT_TRACE((COMP_INIT | COMP_RF), DBG_LOUD, - ("InitializeAdapter819xUsb(): RF is on ----------\n")); - } - } else { - if (pHalData->eRFPowerState == eRfOff) { - MgntActSet_RF_State(Adapter, - eRfOff, - pMgntInfo->RfOffReason); - /* Those actions will be discard in MgntActSet_RF_State - * because of the same state - */ - for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) - PHY_SetRFReg(Adapter, - (enum rf90_radio_path_e)eRFPath, - 0x4, 0xC00, 0x0); - } - } -#endif /* config RF. */ if (priv->ResetProgress == RESET_TYPE_NORESET) { rtl8192_phy_RFConfig(dev); diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index 5f04afe53d69..c04d8eca0cfb 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -516,16 +516,6 @@ static void rtl8192_phyConfigBB(struct net_device *dev, { u32 i; -#ifdef TO_DO_LIST - u32 *rtl8192PhyRegArrayTable = NULL, *rtl8192AgcTabArrayTable = NULL; - - if (Adapter->bInHctTest) { - PHY_REGArrayLen = PHY_REGArrayLengthDTM; - AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM; - Rtl8190PHY_REGArray_Table = Rtl819XPHY_REGArrayDTM; - Rtl8190AGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM; - } -#endif if (ConfigType == BASEBAND_CONFIG_PHY_REG) { for (i = 0; i < PHY_REG_1T2RArrayLength; i += 2) { rtl8192_setBBreg(dev, Rtl8192UsbPHY_REG_1T2RArray[i], @@ -1059,10 +1049,6 @@ static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel) switch (priv->rf_chip) { case RF_8225: -#ifdef TO_DO_LIST - PHY_SetRF8225CckTxPower(Adapter, powerlevel); - PHY_SetRF8225OfdmTxPower(Adapter, powerlevelOFDM24G); -#endif break; case RF_8256: @@ -1160,48 +1146,6 @@ bool rtl8192_SetRFPowerState(struct net_device *dev, RT_TRACE(COMP_ERR, "Not support rf_chip(%x)\n", priv->rf_chip); break; } -#ifdef TO_DO_LIST - if (bResult) { - /* Update current RF state variable. */ - pHalData->eRFPowerState = eRFPowerState; - switch (pHalData->RFChipID) { - case RF_8256: - switch (pHalData->eRFPowerState) { - case eRfOff: - /* If Rf off reason is from IPS, - * LED should blink with no link - */ - if (pMgntInfo->RfOffReason == RF_CHANGE_BY_IPS) - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); - else - /* Turn off LED if RF is not ON. */ - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF); - break; - - case eRfOn: - /* Turn on RF we are still linked, which might - * happen when we quickly turn off and on HW RF. - */ - if (pMgntInfo->bMediaConnect) - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK); - else - /* Turn off LED if RF is not ON. */ - Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK); - break; - - default: - break; - } - break; - - default: - RT_TRACE(COMP_RF, DBG_LOUD, "%s(): Unknown RF type\n", - __func__); - break; - } - - } -#endif priv->SetRFPowerStateInProgress = false; return bResult; @@ -1628,9 +1572,6 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev) /* <3> Set RF related register */ switch (priv->rf_chip) { case RF_8225: -#ifdef TO_DO_LIST - PHY_SetRF8225Bandwidth(Adapter, pHalData->CurrentChannelBW); -#endif break; case RF_8256: -- cgit v1.2.3-59-g8ed1b From cadcc6b20d971510f00ea19f3da6d3b992658f0b Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Fri, 23 Aug 2019 01:05:35 +0530 Subject: staging: rtl8192u: Add space around binary operators This patch fixes the file r8180_93cx6.c to avoid the checkpatch.pl warnings: CHECK: spaces preferred around that '<<' (ctx:VxV) CHECK: spaces preferred around that '-' (ctx:VxV) Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190822193535.14357-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8180_93cx6.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c index 6ebf121eac0c..2527cea60e3e 100644 --- a/drivers/staging/rtl8192u/r8180_93cx6.c +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -114,7 +114,7 @@ int eprom_read(struct net_device *dev, u32 addr) ret = 0; /* enable EPROM programming */ write_nic_byte_E(dev, EPROM_CMD, - (EPROM_CMD_PROGRAM< Date: Mon, 26 Aug 2019 01:58:49 +0800 Subject: staging: most-core: Fix checkpatch warnings Hi, This patch solves the following checkpatch.pl's messages in drivers/staging/most/core.c. WARNING: line over 80 characters + return snprintf(buf, PAGE_SIZE, "%s", ch_data_type[i].name); CHECK: Please use a blank line after function/struct/union/enum declarations +} +/** Signed-off-by: Peikan Tsai Link: https://lore.kernel.org/r/20190825175849.GA74586@MarkdeMacBook-Pro.local Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index b9841adb7181..8e9a0b67c6ed 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -303,7 +303,8 @@ static ssize_t set_datatype_show(struct device *dev, for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) - return snprintf(buf, PAGE_SIZE, "%s", ch_data_type[i].name); + return snprintf(buf, PAGE_SIZE, "%s", + ch_data_type[i].name); } return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -721,6 +722,7 @@ int most_add_link(char *mdev, char *mdev_ch, char *comp_name, char *link_name, return link_channel_to_component(c, comp, link_name, comp_param); } + /** * remove_link_store - store function for remove_link attribute * @drv: device driver -- cgit v1.2.3-59-g8ed1b From 8e480989dff378bc0b2418e3ccf47294fa77f5bf Mon Sep 17 00:00:00 2001 From: "Taihsiang Ho (tai271828)" Date: Mon, 26 Aug 2019 13:20:18 +0800 Subject: staging: rtl8712: wifi: checkpatch style fix Remove multiple blank lines. Signed-off-by: Taihsiang Ho (tai271828) Link: https://lore.kernel.org/r/20190826052018.18649-1-tai271828@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/wifi.h | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 1a5b966a167e..be731f1a2209 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -300,7 +300,6 @@ static inline unsigned char *get_da(unsigned char *pframe) return da; } - static inline unsigned char *get_sa(unsigned char *pframe) { unsigned char *sa; @@ -346,8 +345,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) return sa; } - - /*----------------------------------------------------------------------------- * Below is for the security related definition *----------------------------------------------------------------------------- @@ -392,7 +389,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define _RESERVED47_ 47 - /* --------------------------------------------------------------------------- * Below is the fixed elements... * --------------------------------------------------------------------------- @@ -436,7 +432,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define _WMM_IE_Length_ 7 /* for WMM STA */ #define _WMM_Para_Element_Length_ 24 - /*----------------------------------------------------------------------------- * Below is the definition for 802.11n *------------------------------------------------------------------------------ @@ -456,7 +451,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define GetOrderBit(pbuf) (((*(__le16 *)(pbuf)) & \ le16_to_cpu(_ORDER_)) != 0) - /** * struct ieee80211_bar - HT Block Ack Request * @@ -476,7 +470,6 @@ struct ieee80211_bar { #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - /* * struct ieee80211_ht_cap - HT capabilities * @@ -552,7 +545,6 @@ struct ieee80211_ht_addt_info { */ #define IEEE80211_MIN_AMPDU_BUF 0x8 - /* Spatial Multiplexing Power Save Modes */ #define WLAN_HT_CAP_SM_PS_STATIC 0 #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 -- cgit v1.2.3-59-g8ed1b From 8c10170fe141c989b204a840921a612bfc7ca72d Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Mon, 26 Aug 2019 23:39:09 +0530 Subject: staging: rtl8192u: Add or remove spaces to fix style issues This patch fixes the file r8190_rtl8256.c to avoid the following checkpatch.pl warnings: CHECK: spaces preferred around that '<<' (ctx:VxV) CHECK: spaces preferred around that '-' (ctx:VxV) CHECK: No space is necessary after a cast Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190826180909.27775-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8190_rtl8256.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 0bedf88525cd..7c7f8247b27a 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -42,9 +42,9 @@ void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Band switch (Bandwidth) { case HT_CHANNEL_WIDTH_20: - if (priv->card_8192_version == VERSION_819XU_A - || priv->card_8192_version - == VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ + if (priv->card_8192_version == VERSION_819XU_A || + priv->card_8192_version == + VERSION_819XU_B) { /* 8256 D-cut, E-cut, xiong: consider it later! */ rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0b, bMask12Bits, 0x100); /* phy para:1ba */ @@ -137,12 +137,12 @@ static void phy_rf8256_config_para_file(struct net_device *dev) break; case RF90_PATH_B: case RF90_PATH_D: - u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16); + u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16); break; } /*----Set RF_ENV enable----*/ - rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); + rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); /*----Set RF_ENV output high----*/ rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); @@ -151,7 +151,7 @@ static void phy_rf8256_config_para_file(struct net_device *dev) rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258 */ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ??? */ - rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e) eRFPath, 0x0, bMask12Bits, 0xbf); + rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path_e)eRFPath, 0x0, bMask12Bits, 0xbf); /* Check RF block (for FPGA platform only)---- * TODO: this function should be removed on ASIC , Emily 2007.2.2 @@ -207,7 +207,7 @@ static void phy_rf8256_config_para_file(struct net_device *dev) break; case RF90_PATH_B: case RF90_PATH_D: - rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue); + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue); break; } @@ -255,16 +255,16 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) u8 byte0, byte1, byte2, byte3; powerBase0 = powerlevel + priv->TxPowerDiff; /* OFDM rates */ - powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0; + powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | (powerBase0 << 8) | powerBase0; powerBase1 = powerlevel; /* MCS rates */ - powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1; + powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; for (index = 0; index < 6; index++) { - writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2)?powerBase0:powerBase1); + writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index < 2) ? powerBase0 : powerBase1); byte0 = (u8)(writeVal & 0x7f); - byte1 = (u8)((writeVal & 0x7f00)>>8); - byte2 = (u8)((writeVal & 0x7f0000)>>16); - byte3 = (u8)((writeVal & 0x7f000000)>>24); + byte1 = (u8)((writeVal & 0x7f00) >> 8); + byte2 = (u8)((writeVal & 0x7f0000) >> 16); + byte3 = (u8)((writeVal & 0x7f000000) >> 24); if (byte0 > 0x24) /* Max power index = 0x24 */ @@ -278,7 +278,7 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) /* for tx power track */ if (index == 3) { - writeVal_tmp = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; + writeVal_tmp = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; priv->Pwr_Track = writeVal_tmp; } @@ -288,7 +288,7 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) */ writeVal = 0x03030303; } else { - writeVal = (byte3<<24) | (byte2<<16) | (byte1<<8) | byte0; + writeVal = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0; } rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); } -- cgit v1.2.3-59-g8ed1b From 48d911f29e9f4e51eda87e0dc3c944be79771a0d Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Mon, 26 Aug 2019 23:52:27 +0530 Subject: staging: rtl8192u: Add or remove blank lines as required This patch fixes the file r8190_rtl8256.c to avoid the following checkpatch.pl warnings: CHECK: Blank lines aren't necessary before a close brace '}' CHECK: Please use a blank line after function/struct/union/enum declarations CHECK: Please don't use multiple blank line Signed-off-by: Sumera Priyadarsini Link: https://lore.kernel.org/r/20190826182227.30738-1-sylphrenadin@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8190_rtl8256.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 7c7f8247b27a..b169460b9f26 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -79,10 +79,10 @@ void phy_set_rf8256_bandwidth(struct net_device *dev, enum ht_channel_width Band default: RT_TRACE(COMP_ERR, "phy_set_rf8256_bandwidth(): unknown Bandwidth: %#X\n", Bandwidth); break; - } } } + /*-------------------------------------------------------------------------- * Overview: Interface to config 8256 * Input: struct net_device* dev @@ -101,6 +101,7 @@ void phy_rf8256_config(struct net_device *dev) /* Config BB and RF */ phy_rf8256_config_para_file(dev); } + /*-------------------------------------------------------------------------- * Overview: Interface to config 8256 * Input: struct net_device* dev @@ -215,7 +216,6 @@ static void phy_rf8256_config_para_file(struct net_device *dev) RT_TRACE(COMP_ERR, "phy_rf8256_config_para_file():Radio[%d] Fail!!", eRFPath); goto phy_RF8256_Config_ParaFile_Fail; } - } RT_TRACE(COMP_PHY, "PHY Initialization Success\n"); @@ -225,11 +225,11 @@ phy_RF8256_Config_ParaFile_Fail: RT_TRACE(COMP_ERR, "PHY Initialization failed\n"); } - void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel) { u32 TxAGC = 0; struct r8192_priv *priv = ieee80211_priv(dev); + TxAGC = powerlevel; if (priv->bDynamicTxLowPower) { @@ -244,7 +244,6 @@ void phy_set_rf8256_cck_tx_power(struct net_device *dev, u8 powerlevel) rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); } - void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -293,5 +292,4 @@ void phy_set_rf8256_ofdm_tx_power(struct net_device *dev, u8 powerlevel) rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); } return; - } -- cgit v1.2.3-59-g8ed1b From baeeb02ccd704e3a6cdff95a78a41916e6a85b21 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:21 +0200 Subject: staging: greybus: fix up SPDX comment in .h files When these files originally got an SPDX tag, I used // instead of /* */ for the .h files. Fix this up to use // properly. Cc: Johan Hovold Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-2-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/firmware.h | 2 +- drivers/staging/greybus/gb-camera.h | 2 +- drivers/staging/greybus/gbphy.h | 2 +- drivers/staging/greybus/greybus.h | 2 +- drivers/staging/greybus/greybus_authentication.h | 2 +- drivers/staging/greybus/greybus_firmware.h | 2 +- drivers/staging/greybus/greybus_manifest.h | 2 +- drivers/staging/greybus/greybus_protocols.h | 2 +- drivers/staging/greybus/greybus_trace.h | 2 +- drivers/staging/greybus/hd.h | 2 +- drivers/staging/greybus/interface.h | 2 +- drivers/staging/greybus/manifest.h | 2 +- drivers/staging/greybus/module.h | 2 +- drivers/staging/greybus/operation.h | 2 +- drivers/staging/greybus/spilib.h | 2 +- drivers/staging/greybus/svc.h | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index 946221307ef6..72dfabfa4704 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Firmware Management Header * diff --git a/drivers/staging/greybus/gb-camera.h b/drivers/staging/greybus/gb-camera.h index ee293e461fc3..5fc469101fc1 100644 --- a/drivers/staging/greybus/gb-camera.h +++ b/drivers/staging/greybus/gb-camera.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Camera protocol driver. * diff --git a/drivers/staging/greybus/gbphy.h b/drivers/staging/greybus/gbphy.h index 99463489d7d6..087928a586fb 100644 --- a/drivers/staging/greybus/gbphy.h +++ b/drivers/staging/greybus/gbphy.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Bridged-Phy Bus driver * diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index d03ddb7c9df0..f0488ffff93e 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus driver and device API * diff --git a/drivers/staging/greybus/greybus_authentication.h b/drivers/staging/greybus/greybus_authentication.h index 03ea9615b217..d654760cf175 100644 --- a/drivers/staging/greybus/greybus_authentication.h +++ b/drivers/staging/greybus/greybus_authentication.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Greybus Component Authentication User Header * diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index b58281a63ba4..13ef3aa5279e 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Greybus Firmware Management User Header * diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h index 2cec5cf7a846..db68f7e7d5a7 100644 --- a/drivers/staging/greybus/greybus_manifest.h +++ b/drivers/staging/greybus/greybus_manifest.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus manifest definition * diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index ddc73f10eb22..7d649a7fc4c9 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h index 7b5e2c6b1f6b..1bc9f1275c65 100644 --- a/drivers/staging/greybus/greybus_trace.h +++ b/drivers/staging/greybus/greybus_trace.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus driver and device API * diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index 6cf024a20a58..348b76fabc9a 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Host Device * diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 1c00c5bb3ec9..8fb1eacda302 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Interface Block code * diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h index f3c95a255631..88aa7e44cad5 100644 --- a/drivers/staging/greybus/manifest.h +++ b/drivers/staging/greybus/manifest.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus manifest parsing * diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h index b1ebcc6636db..2a27e520ee94 100644 --- a/drivers/staging/greybus/module.h +++ b/drivers/staging/greybus/module.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus Module code * diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h index 40b7b02fff88..17ba3daf111b 100644 --- a/drivers/staging/greybus/operation.h +++ b/drivers/staging/greybus/operation.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus operations * diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h index 043d4d32c3ee..9d416839e3be 100644 --- a/drivers/staging/greybus/spilib.h +++ b/drivers/staging/greybus/spilib.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus SPI library header * diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index ad01783bac9c..e7452057cfe4 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /* * Greybus SVC code * -- cgit v1.2.3-59-g8ed1b From 137bfbd006b2aad72fa90b6fbe096f3a1db5b32a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:22 +0200 Subject: staging: greybus: remove license "boilerplate" When the greybus drivers were converted to SPDX identifiers for the license text, some license boilerplate was not removed. Clean this up by removing this unneeded text now. Cc: Johan Hovold Cc: Vaibhav Agarwal Cc: "Bryan O'Donoghue" Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Mark Greer Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-3-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- .../greybus/Documentation/firmware/authenticate.c | 46 ---------------------- .../greybus/Documentation/firmware/firmware.c | 46 ---------------------- drivers/staging/greybus/arpc.h | 46 ---------------------- drivers/staging/greybus/audio_apbridgea.h | 26 +----------- drivers/staging/greybus/greybus_authentication.h | 46 ---------------------- drivers/staging/greybus/greybus_firmware.h | 46 ---------------------- drivers/staging/greybus/greybus_protocols.h | 46 ---------------------- drivers/staging/greybus/tools/loopback_test.c | 2 - 8 files changed, 1 insertion(+), 303 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/Documentation/firmware/authenticate.c b/drivers/staging/greybus/Documentation/firmware/authenticate.c index 806e75b7f405..3d2c6f88a138 100644 --- a/drivers/staging/greybus/Documentation/firmware/authenticate.c +++ b/drivers/staging/greybus/Documentation/firmware/authenticate.c @@ -2,54 +2,8 @@ /* * Sample code to test CAP protocol * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2016 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include diff --git a/drivers/staging/greybus/Documentation/firmware/firmware.c b/drivers/staging/greybus/Documentation/firmware/firmware.c index 31d9c23e2eeb..765d69faa9cc 100644 --- a/drivers/staging/greybus/Documentation/firmware/firmware.c +++ b/drivers/staging/greybus/Documentation/firmware/firmware.c @@ -2,54 +2,8 @@ /* * Sample code to test firmware-management protocol * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2016 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h index 3dab6375909c..c8b83c5cfa79 100644 --- a/drivers/staging/greybus/arpc.h +++ b/drivers/staging/greybus/arpc.h @@ -1,53 +1,7 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2016 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __ARPC_H diff --git a/drivers/staging/greybus/audio_apbridgea.h b/drivers/staging/greybus/audio_apbridgea.h index 330fc7a397eb..3f1f4dd2c61a 100644 --- a/drivers/staging/greybus/audio_apbridgea.h +++ b/drivers/staging/greybus/audio_apbridgea.h @@ -1,30 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -/** +/* * Copyright (c) 2015-2016 Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This is a special protocol for configuring communication over the diff --git a/drivers/staging/greybus/greybus_authentication.h b/drivers/staging/greybus/greybus_authentication.h index d654760cf175..7edc7295b7ab 100644 --- a/drivers/staging/greybus/greybus_authentication.h +++ b/drivers/staging/greybus/greybus_authentication.h @@ -2,54 +2,8 @@ /* * Greybus Component Authentication User Header * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2016 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __GREYBUS_AUTHENTICATION_USER_H diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 13ef3aa5279e..f68fd5e25321 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -2,54 +2,8 @@ /* * Greybus Firmware Management User Header * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2016 Google Inc. All rights reserved. * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __GREYBUS_FIRMWARE_USER_H diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 7d649a7fc4c9..5f34d1effb59 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -1,53 +1,7 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License 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 version 2 for more details. - * - * BSD LICENSE - * - * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. - * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. or Linaro Ltd. nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR - * LINARO LTD. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __GREYBUS_PROTOCOLS_H diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index cebc1d90a180..ba6f905f26fa 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -4,8 +4,6 @@ * * Copyright 2015 Google Inc. * Copyright 2015 Linaro Ltd. - * - * Provided under the three clause BSD license found in the LICENSE file. */ #include #include -- cgit v1.2.3-59-g8ed1b From a11ac9ef4b1604ce5d068932ab85b0906d1109c0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:23 +0200 Subject: staging: greybus: hd: Fix up some alignment checkpatch issues Some function prototypes do not match the expected alignment formatting so fix that up so that checkpatch is happy. Cc: Johan Hovold Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-4-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/hd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 969f86697673..e2b9ab5f6ec2 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -31,7 +31,7 @@ int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, EXPORT_SYMBOL_GPL(gb_hd_output); static ssize_t bus_id_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, char *buf) { struct gb_host_device *hd = to_gb_host_device(dev); @@ -70,7 +70,7 @@ EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved); /* Locking: Caller guarantees serialisation */ int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, - unsigned long flags) + unsigned long flags) { struct ida *id_map = &hd->cport_id_map; int ida_start, ida_end; @@ -122,9 +122,9 @@ struct device_type greybus_hd_type = { }; struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports) + struct device *parent, + size_t buffer_size_max, + size_t num_cports) { struct gb_host_device *hd; int ret; -- cgit v1.2.3-59-g8ed1b From ee989b020404023a27bfe34003748dc199835f23 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:24 +0200 Subject: staging: greybus: manifest: Fix up some alignment checkpatch issues Some function prototypes do not match the expected alignment formatting so fix that up so that checkpatch is happy. Cc: Johan Hovold Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-5-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/manifest.c | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 08db49264f2b..4ebbba52b07c 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -104,15 +104,15 @@ static int identify_descriptor(struct gb_interface *intf, size_t expected_size; if (size < sizeof(*desc_header)) { - dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", - size, sizeof(*desc_header)); + dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", size, + sizeof(*desc_header)); return -EINVAL; /* Must at least have header */ } desc_size = le16_to_cpu(desc_header->size); if (desc_size > size) { dev_err(&intf->dev, "descriptor too big (%zu > %zu)\n", - desc_size, size); + desc_size, size); return -EINVAL; } @@ -139,22 +139,22 @@ static int identify_descriptor(struct gb_interface *intf, case GREYBUS_TYPE_INVALID: default: dev_err(&intf->dev, "invalid descriptor type (%u)\n", - desc_header->type); + desc_header->type); return -EINVAL; } if (desc_size < expected_size) { dev_err(&intf->dev, "%s descriptor too small (%zu < %zu)\n", - get_descriptor_type_string(desc_header->type), - desc_size, expected_size); + get_descriptor_type_string(desc_header->type), + desc_size, expected_size); return -EINVAL; } /* Descriptor bigger than what we expect */ if (desc_size > expected_size) { dev_warn(&intf->dev, "%s descriptor size mismatch (want %zu got %zu)\n", - get_descriptor_type_string(desc_header->type), - expected_size, desc_size); + get_descriptor_type_string(desc_header->type), + expected_size, desc_size); } descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); @@ -208,7 +208,7 @@ static char *gb_string_get(struct gb_interface *intf, u8 string_id) /* Allocate an extra byte so we can guarantee it's NUL-terminated */ string = kmemdup(&desc_string->string, desc_string->length + 1, - GFP_KERNEL); + GFP_KERNEL); if (!string) return ERR_PTR(-ENOMEM); string[desc_string->length] = '\0'; @@ -264,8 +264,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) desc_cport = tmp->data; if (cport_id == le16_to_cpu(desc_cport->id)) { dev_err(&bundle->dev, - "duplicate CPort %u found\n", - cport_id); + "duplicate CPort %u found\n", cport_id); goto exit; } } @@ -277,7 +276,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) return 0; bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), - GFP_KERNEL); + GFP_KERNEL); if (!bundle->cport_desc) goto exit; @@ -287,7 +286,7 @@ static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) list_for_each_entry_safe(desc, next, &list, links) { desc_cport = desc->data; memcpy(&bundle->cport_desc[i++], desc_cport, - sizeof(*desc_cport)); + sizeof(*desc_cport)); /* Release the cport descriptor */ release_manifest_descriptor(desc); @@ -333,9 +332,9 @@ static u32 gb_manifest_parse_bundles(struct gb_interface *intf) /* Ignore any legacy control bundles */ if (bundle_id == GB_CONTROL_BUNDLE_ID) { dev_dbg(&intf->dev, "%s - ignoring control bundle\n", - __func__); + __func__); release_cport_descriptors(&intf->manifest_descs, - bundle_id); + bundle_id); continue; } @@ -468,7 +467,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) /* we have to have at _least_ the manifest header */ if (size < sizeof(*header)) { dev_err(&intf->dev, "short manifest (%zu < %zu)\n", - size, sizeof(*header)); + size, sizeof(*header)); return false; } @@ -478,15 +477,15 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) manifest_size = le16_to_cpu(header->size); if (manifest_size != size) { dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", - size, manifest_size); + size, manifest_size); return false; } /* Validate major/minor number */ if (header->version_major > GREYBUS_VERSION_MAJOR) { dev_err(&intf->dev, "manifest version too new (%u.%u > %u.%u)\n", - header->version_major, header->version_minor, - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); + header->version_major, header->version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); return false; } @@ -513,7 +512,7 @@ bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) } if (found != 1) { dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", - found); + found); result = false; goto out; } -- cgit v1.2.3-59-g8ed1b From 9238238589a3e5d289cfbf90f7ce65c6554e1614 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:25 +0200 Subject: staging: greybus: log: Fix up some alignment checkpatch issues Some function prototypes do not match the expected alignment formatting so fix that up so that checkpatch is happy. Cc: David Lin Cc: Johan Hovold Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/log.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c index 15a88574dbb0..4f1f161ff11c 100644 --- a/drivers/staging/greybus/log.c +++ b/drivers/staging/greybus/log.c @@ -31,14 +31,14 @@ static int gb_log_request_handler(struct gb_operation *op) /* Verify size of payload */ if (op->request->payload_size < sizeof(*receive)) { dev_err(dev, "log request too small (%zu < %zu)\n", - op->request->payload_size, sizeof(*receive)); + op->request->payload_size, sizeof(*receive)); return -EINVAL; } receive = op->request->payload; len = le16_to_cpu(receive->len); if (len != (op->request->payload_size - sizeof(*receive))) { dev_err(dev, "log request wrong size %d vs %zu\n", len, - (op->request->payload_size - sizeof(*receive))); + (op->request->payload_size - sizeof(*receive))); return -EINVAL; } if (len == 0) { @@ -83,7 +83,7 @@ static int gb_log_probe(struct gb_bundle *bundle, return -ENOMEM; connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id), - gb_log_request_handler); + gb_log_request_handler); if (IS_ERR(connection)) { retval = PTR_ERR(connection); goto error_free; -- cgit v1.2.3-59-g8ed1b From 9c31973907fb157ac91f61f479e8bf43bb43aded Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:26 +0200 Subject: staging: greybus: loopback: Fix up some alignment checkpatch issues Some function prototypes do not match the expected alignment formatting so fix that up so that checkpatch is happy. Cc: "Bryan O'Donoghue" Cc: Johan Hovold Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-7-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/loopback.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 48d85ebe404a..b0ab0eed5c18 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -882,7 +882,7 @@ static int gb_loopback_fn(void *data) gb->type = 0; gb->send_count = 0; sysfs_notify(&gb->dev->kobj, NULL, - "iteration_count"); + "iteration_count"); dev_dbg(&bundle->dev, "load test complete\n"); } else { dev_dbg(&bundle->dev, @@ -1054,7 +1054,7 @@ static int gb_loopback_probe(struct gb_bundle *bundle, /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), - GFP_KERNEL)) { + GFP_KERNEL)) { retval = -ENOMEM; goto out_conn; } -- cgit v1.2.3-59-g8ed1b From ec0ad868173da8a75121f9dc116a5d5478ff614d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:27 +0200 Subject: staging: greybus: move core include files to include/linux/greybus/ With the goal of moving the core of the greybus code out of staging, the include files need to be moved to include/linux/greybus.h and include/linux/greybus/ Cc: Vaibhav Hiremath Cc: Johan Hovold Cc: Vaibhav Agarwal Cc: Rui Miguel Silva Cc: David Lin Cc: "Bryan O'Donoghue" Cc: greybus-dev@lists.linaro.org Cc: devel@driverdev.osuosl.org Acked-by: Mark Greer Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-8-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/arche-platform.c | 2 +- drivers/staging/greybus/audio_apbridgea.c | 3 +- drivers/staging/greybus/audio_codec.h | 4 +- drivers/staging/greybus/audio_gb.c | 4 +- drivers/staging/greybus/authentication.c | 3 +- drivers/staging/greybus/bootrom.c | 2 +- drivers/staging/greybus/bundle.c | 2 +- drivers/staging/greybus/bundle.h | 89 -- drivers/staging/greybus/camera.c | 2 +- drivers/staging/greybus/connection.c | 2 +- drivers/staging/greybus/connection.h | 128 -- drivers/staging/greybus/control.c | 2 +- drivers/staging/greybus/control.h | 57 - drivers/staging/greybus/core.c | 2 +- drivers/staging/greybus/debugfs.c | 3 +- drivers/staging/greybus/es2.c | 3 +- drivers/staging/greybus/firmware.h | 2 +- drivers/staging/greybus/fw-core.c | 2 +- drivers/staging/greybus/fw-download.c | 2 +- drivers/staging/greybus/fw-management.c | 2 +- drivers/staging/greybus/gbphy.c | 2 +- drivers/staging/greybus/gpio.c | 2 +- drivers/staging/greybus/greybus.h | 152 -- drivers/staging/greybus/greybus_id.h | 27 - drivers/staging/greybus/greybus_manifest.h | 178 --- drivers/staging/greybus/greybus_protocols.h | 2176 --------------------------- drivers/staging/greybus/hd.c | 2 +- drivers/staging/greybus/hd.h | 82 - drivers/staging/greybus/hid.c | 3 +- drivers/staging/greybus/i2c.c | 2 +- drivers/staging/greybus/interface.c | 2 +- drivers/staging/greybus/interface.h | 82 - drivers/staging/greybus/light.c | 4 +- drivers/staging/greybus/log.c | 3 +- drivers/staging/greybus/loopback.c | 5 +- drivers/staging/greybus/manifest.c | 2 +- drivers/staging/greybus/manifest.h | 15 - drivers/staging/greybus/module.c | 2 +- drivers/staging/greybus/module.h | 33 - drivers/staging/greybus/operation.c | 2 +- drivers/staging/greybus/operation.h | 224 --- drivers/staging/greybus/power_supply.c | 3 +- drivers/staging/greybus/pwm.c | 2 +- drivers/staging/greybus/raw.c | 3 +- drivers/staging/greybus/sdio.c | 2 +- drivers/staging/greybus/spi.c | 2 +- drivers/staging/greybus/spilib.c | 2 +- drivers/staging/greybus/svc.c | 3 +- drivers/staging/greybus/svc.h | 101 -- drivers/staging/greybus/svc_watchdog.c | 2 +- drivers/staging/greybus/uart.c | 2 +- drivers/staging/greybus/usb.c | 2 +- drivers/staging/greybus/vibrator.c | 3 +- include/linux/greybus.h | 152 ++ include/linux/greybus/bundle.h | 89 ++ include/linux/greybus/connection.h | 128 ++ include/linux/greybus/control.h | 57 + include/linux/greybus/greybus_id.h | 27 + include/linux/greybus/greybus_manifest.h | 178 +++ include/linux/greybus/greybus_protocols.h | 2176 +++++++++++++++++++++++++++ include/linux/greybus/hd.h | 82 + include/linux/greybus/interface.h | 82 + include/linux/greybus/manifest.h | 15 + include/linux/greybus/module.h | 33 + include/linux/greybus/operation.h | 224 +++ include/linux/greybus/svc.h | 101 ++ 66 files changed, 3384 insertions(+), 3403 deletions(-) delete mode 100644 drivers/staging/greybus/bundle.h delete mode 100644 drivers/staging/greybus/connection.h delete mode 100644 drivers/staging/greybus/control.h delete mode 100644 drivers/staging/greybus/greybus.h delete mode 100644 drivers/staging/greybus/greybus_id.h delete mode 100644 drivers/staging/greybus/greybus_manifest.h delete mode 100644 drivers/staging/greybus/greybus_protocols.h delete mode 100644 drivers/staging/greybus/hd.h delete mode 100644 drivers/staging/greybus/interface.h delete mode 100644 drivers/staging/greybus/manifest.h delete mode 100644 drivers/staging/greybus/module.h delete mode 100644 drivers/staging/greybus/operation.h delete mode 100644 drivers/staging/greybus/svc.h create mode 100644 include/linux/greybus.h create mode 100644 include/linux/greybus/bundle.h create mode 100644 include/linux/greybus/connection.h create mode 100644 include/linux/greybus/control.h create mode 100644 include/linux/greybus/greybus_id.h create mode 100644 include/linux/greybus/greybus_manifest.h create mode 100644 include/linux/greybus/greybus_protocols.h create mode 100644 include/linux/greybus/hd.h create mode 100644 include/linux/greybus/interface.h create mode 100644 include/linux/greybus/manifest.h create mode 100644 include/linux/greybus/module.h create mode 100644 include/linux/greybus/operation.h create mode 100644 include/linux/greybus/svc.h (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index 6eb842040c22..eebf0deb39f5 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -19,8 +19,8 @@ #include #include #include +#include #include "arche_platform.h" -#include "greybus.h" #if IS_ENABLED(CONFIG_USB_HSIC_USB3613) #include diff --git a/drivers/staging/greybus/audio_apbridgea.c b/drivers/staging/greybus/audio_apbridgea.c index 7ebb1bde5cb7..26117e390deb 100644 --- a/drivers/staging/greybus/audio_apbridgea.c +++ b/drivers/staging/greybus/audio_apbridgea.c @@ -5,8 +5,7 @@ * Copyright 2015-2016 Google Inc. */ -#include "greybus.h" -#include "greybus_protocols.h" +#include #include "audio_apbridgea.h" #include "audio_codec.h" diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h index 9ba09ea9c2fc..cb5d271da1a5 100644 --- a/drivers/staging/greybus/audio_codec.h +++ b/drivers/staging/greybus/audio_codec.h @@ -8,12 +8,10 @@ #ifndef __LINUX_GBAUDIO_CODEC_H #define __LINUX_GBAUDIO_CODEC_H +#include #include #include -#include "greybus.h" -#include "greybus_protocols.h" - #define NAME_SIZE 32 #define MAX_DAIS 2 /* APB1, APB2 */ diff --git a/drivers/staging/greybus/audio_gb.c b/drivers/staging/greybus/audio_gb.c index 8894f1c87d48..9d8994fdb41a 100644 --- a/drivers/staging/greybus/audio_gb.c +++ b/drivers/staging/greybus/audio_gb.c @@ -5,9 +5,7 @@ * Copyright 2015-2016 Google Inc. */ -#include "greybus.h" -#include "greybus_protocols.h" -#include "operation.h" +#include #include "audio_codec.h" /* TODO: Split into separate calls */ diff --git a/drivers/staging/greybus/authentication.c b/drivers/staging/greybus/authentication.c index a5d7c53df987..297e69f011c7 100644 --- a/drivers/staging/greybus/authentication.c +++ b/drivers/staging/greybus/authentication.c @@ -6,8 +6,7 @@ * Copyright 2016 Linaro Ltd. */ -#include "greybus.h" - +#include #include #include #include diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c index 402e6360834f..a8efb86de140 100644 --- a/drivers/staging/greybus/bootrom.c +++ b/drivers/staging/greybus/bootrom.c @@ -10,8 +10,8 @@ #include #include #include +#include -#include "greybus.h" #include "firmware.h" /* Timeout, in jiffies, within which the next request must be received */ diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c index 3f702db9e098..84660729538b 100644 --- a/drivers/staging/greybus/bundle.c +++ b/drivers/staging/greybus/bundle.c @@ -6,7 +6,7 @@ * Copyright 2014-2015 Linaro Ltd. */ -#include "greybus.h" +#include #include "greybus_trace.h" static ssize_t bundle_class_show(struct device *dev, diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h deleted file mode 100644 index 8734d2055657..000000000000 --- a/drivers/staging/greybus/bundle.h +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus bundles - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#ifndef __BUNDLE_H -#define __BUNDLE_H - -#include - -#define BUNDLE_ID_NONE U8_MAX - -/* Greybus "public" definitions" */ -struct gb_bundle { - struct device dev; - struct gb_interface *intf; - - u8 id; - u8 class; - u8 class_major; - u8 class_minor; - - size_t num_cports; - struct greybus_descriptor_cport *cport_desc; - - struct list_head connections; - u8 *state; - - struct list_head links; /* interface->bundles */ -}; -#define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) - -/* Greybus "private" definitions" */ -struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, - u8 class); -int gb_bundle_add(struct gb_bundle *bundle); -void gb_bundle_destroy(struct gb_bundle *bundle); - -/* Bundle Runtime PM wrappers */ -#ifdef CONFIG_PM -static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) -{ - int retval; - - retval = pm_runtime_get_sync(&bundle->dev); - if (retval < 0) { - dev_err(&bundle->dev, - "pm_runtime_get_sync failed: %d\n", retval); - pm_runtime_put_noidle(&bundle->dev); - return retval; - } - - return 0; -} - -static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) -{ - int retval; - - pm_runtime_mark_last_busy(&bundle->dev); - retval = pm_runtime_put_autosuspend(&bundle->dev); - - return retval; -} - -static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) -{ - pm_runtime_get_noresume(&bundle->dev); -} - -static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) -{ - pm_runtime_put_noidle(&bundle->dev); -} - -#else -static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) -{ return 0; } -static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) -{ return 0; } - -static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {} -static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {} -#endif - -#endif /* __BUNDLE_H */ diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c index 615c8e7fd51e..b570e13394ac 100644 --- a/drivers/staging/greybus/camera.c +++ b/drivers/staging/greybus/camera.c @@ -14,9 +14,9 @@ #include #include #include +#include #include "gb-camera.h" -#include "greybus.h" #include "greybus_protocols.h" enum gb_camera_debugs_buffer_id { diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index eda964208cce..fc8f57f97ce6 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -7,8 +7,8 @@ */ #include +#include -#include "greybus.h" #include "greybus_trace.h" #define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT 1000 diff --git a/drivers/staging/greybus/connection.h b/drivers/staging/greybus/connection.h deleted file mode 100644 index 5ca3befc0636..000000000000 --- a/drivers/staging/greybus/connection.h +++ /dev/null @@ -1,128 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus connections - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#ifndef __CONNECTION_H -#define __CONNECTION_H - -#include -#include - -#define GB_CONNECTION_FLAG_CSD BIT(0) -#define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) -#define GB_CONNECTION_FLAG_OFFLOADED BIT(2) -#define GB_CONNECTION_FLAG_CDSI1 BIT(3) -#define GB_CONNECTION_FLAG_CONTROL BIT(4) -#define GB_CONNECTION_FLAG_HIGH_PRIO BIT(5) - -#define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL - -enum gb_connection_state { - GB_CONNECTION_STATE_DISABLED = 0, - GB_CONNECTION_STATE_ENABLED_TX = 1, - GB_CONNECTION_STATE_ENABLED = 2, - GB_CONNECTION_STATE_DISCONNECTING = 3, -}; - -struct gb_operation; - -typedef int (*gb_request_handler_t)(struct gb_operation *); - -struct gb_connection { - struct gb_host_device *hd; - struct gb_interface *intf; - struct gb_bundle *bundle; - struct kref kref; - u16 hd_cport_id; - u16 intf_cport_id; - - struct list_head hd_links; - struct list_head bundle_links; - - gb_request_handler_t handler; - unsigned long flags; - - struct mutex mutex; - spinlock_t lock; - enum gb_connection_state state; - struct list_head operations; - - char name[16]; - struct workqueue_struct *wq; - - atomic_t op_cycle; - - void *private; - - bool mode_switch; -}; - -struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, - u16 hd_cport_id, gb_request_handler_t handler); -struct gb_connection *gb_connection_create_control(struct gb_interface *intf); -struct gb_connection *gb_connection_create(struct gb_bundle *bundle, - u16 cport_id, gb_request_handler_t handler); -struct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle, - u16 cport_id, gb_request_handler_t handler, - unsigned long flags); -struct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle, - u16 cport_id, unsigned long flags); -void gb_connection_destroy(struct gb_connection *connection); - -static inline bool gb_connection_is_static(struct gb_connection *connection) -{ - return !connection->intf; -} - -int gb_connection_enable(struct gb_connection *connection); -int gb_connection_enable_tx(struct gb_connection *connection); -void gb_connection_disable_rx(struct gb_connection *connection); -void gb_connection_disable(struct gb_connection *connection); -void gb_connection_disable_forced(struct gb_connection *connection); - -void gb_connection_mode_switch_prepare(struct gb_connection *connection); -void gb_connection_mode_switch_complete(struct gb_connection *connection); - -void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, - u8 *data, size_t length); - -void gb_connection_latency_tag_enable(struct gb_connection *connection); -void gb_connection_latency_tag_disable(struct gb_connection *connection); - -static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) -{ - return !(connection->flags & GB_CONNECTION_FLAG_CSD); -} - -static inline bool -gb_connection_flow_control_disabled(struct gb_connection *connection) -{ - return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; -} - -static inline bool gb_connection_is_offloaded(struct gb_connection *connection) -{ - return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; -} - -static inline bool gb_connection_is_control(struct gb_connection *connection) -{ - return connection->flags & GB_CONNECTION_FLAG_CONTROL; -} - -static inline void *gb_connection_get_data(struct gb_connection *connection) -{ - return connection->private; -} - -static inline void gb_connection_set_data(struct gb_connection *connection, - void *data) -{ - connection->private = data; -} - -#endif /* __CONNECTION_H */ diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index a9e8b6036cac..359a25841973 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -9,7 +9,7 @@ #include #include #include -#include "greybus.h" +#include /* Highest control-protocol version supported */ #define GB_CONTROL_VERSION_MAJOR 0 diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h deleted file mode 100644 index 3a29ec05f631..000000000000 --- a/drivers/staging/greybus/control.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus CPort control protocol - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - */ - -#ifndef __CONTROL_H -#define __CONTROL_H - -struct gb_control { - struct device dev; - struct gb_interface *intf; - - struct gb_connection *connection; - - u8 protocol_major; - u8 protocol_minor; - - bool has_bundle_activate; - bool has_bundle_version; - - char *vendor_string; - char *product_string; -}; -#define to_gb_control(d) container_of(d, struct gb_control, dev) - -struct gb_control *gb_control_create(struct gb_interface *intf); -int gb_control_enable(struct gb_control *control); -void gb_control_disable(struct gb_control *control); -int gb_control_suspend(struct gb_control *control); -int gb_control_resume(struct gb_control *control); -int gb_control_add(struct gb_control *control); -void gb_control_del(struct gb_control *control); -struct gb_control *gb_control_get(struct gb_control *control); -void gb_control_put(struct gb_control *control); - -int gb_control_get_bundle_versions(struct gb_control *control); -int gb_control_connected_operation(struct gb_control *control, u16 cport_id); -int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); -int gb_control_disconnecting_operation(struct gb_control *control, - u16 cport_id); -int gb_control_mode_switch_operation(struct gb_control *control); -void gb_control_mode_switch_prepare(struct gb_control *control); -void gb_control_mode_switch_complete(struct gb_control *control); -int gb_control_get_manifest_size_operation(struct gb_interface *intf); -int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, - size_t size); -int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); -int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); -int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); -int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); -int gb_control_interface_suspend_prepare(struct gb_control *control); -int gb_control_interface_deactivate_prepare(struct gb_control *control); -int gb_control_interface_hibernate_abort(struct gb_control *control); -#endif /* __CONTROL_H */ diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index d6b0d49130c0..e546c6431877 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -9,7 +9,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define CREATE_TRACE_POINTS -#include "greybus.h" +#include #include "greybus_trace.h" #define GB_BUNDLE_AUTOSUSPEND_MS 3000 diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c index 56e20c30feb5..e102d7badb9d 100644 --- a/drivers/staging/greybus/debugfs.c +++ b/drivers/staging/greybus/debugfs.c @@ -7,8 +7,7 @@ */ #include - -#include "greybus.h" +#include static struct dentry *gb_debug_root; diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index be6af18cec31..366716f11b1a 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -11,12 +11,11 @@ #include #include #include +#include #include #include "arpc.h" -#include "greybus.h" #include "greybus_trace.h" -#include "connection.h" /* Default timeout for USB vendor requests. */ diff --git a/drivers/staging/greybus/firmware.h b/drivers/staging/greybus/firmware.h index 72dfabfa4704..5d2564462ffc 100644 --- a/drivers/staging/greybus/firmware.h +++ b/drivers/staging/greybus/firmware.h @@ -9,7 +9,7 @@ #ifndef __FIRMWARE_H #define __FIRMWARE_H -#include "greybus.h" +#include #define FW_NAME_PREFIX "gmp_" diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 388866d92f5b..57bebf24636b 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -8,8 +8,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include "firmware.h" -#include "greybus.h" #include "spilib.h" struct gb_fw_core { diff --git a/drivers/staging/greybus/fw-download.c b/drivers/staging/greybus/fw-download.c index d3b7cccbc10d..543692c567f9 100644 --- a/drivers/staging/greybus/fw-download.c +++ b/drivers/staging/greybus/fw-download.c @@ -10,8 +10,8 @@ #include #include #include +#include #include "firmware.h" -#include "greybus.h" /* Estimated minimum buffer size, actual size can be smaller than this */ #define MIN_FETCH_SIZE 512 diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 71aec14f8181..687c6405c65b 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -13,10 +13,10 @@ #include #include #include +#include #include "firmware.h" #include "greybus_firmware.h" -#include "greybus.h" #define FW_MGMT_TIMEOUT_MS 1000 diff --git a/drivers/staging/greybus/gbphy.c b/drivers/staging/greybus/gbphy.c index 6cb85c3d3572..9fc5c47be9bd 100644 --- a/drivers/staging/greybus/gbphy.c +++ b/drivers/staging/greybus/gbphy.c @@ -13,8 +13,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" #define GB_GBPHY_AUTOSUSPEND_MS 3000 diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c index 3151004d26fb..1ff34abd5692 100644 --- a/drivers/staging/greybus/gpio.c +++ b/drivers/staging/greybus/gpio.c @@ -13,8 +13,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" struct gb_gpio_line { diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h deleted file mode 100644 index f0488ffff93e..000000000000 --- a/drivers/staging/greybus/greybus.h +++ /dev/null @@ -1,152 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus driver and device API - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#ifndef __LINUX_GREYBUS_H -#define __LINUX_GREYBUS_H - -#ifdef __KERNEL__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "greybus_id.h" -#include "greybus_manifest.h" -#include "greybus_protocols.h" -#include "manifest.h" -#include "hd.h" -#include "svc.h" -#include "control.h" -#include "module.h" -#include "interface.h" -#include "bundle.h" -#include "connection.h" -#include "operation.h" - -/* Matches up with the Greybus Protocol specification document */ -#define GREYBUS_VERSION_MAJOR 0x00 -#define GREYBUS_VERSION_MINOR 0x01 - -#define GREYBUS_ID_MATCH_DEVICE \ - (GREYBUS_ID_MATCH_VENDOR | GREYBUS_ID_MATCH_PRODUCT) - -#define GREYBUS_DEVICE(v, p) \ - .match_flags = GREYBUS_ID_MATCH_DEVICE, \ - .vendor = (v), \ - .product = (p), - -#define GREYBUS_DEVICE_CLASS(c) \ - .match_flags = GREYBUS_ID_MATCH_CLASS, \ - .class = (c), - -/* Maximum number of CPorts */ -#define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ -#define CPORT_ID_BAD U16_MAX - -struct greybus_driver { - const char *name; - - int (*probe)(struct gb_bundle *bundle, - const struct greybus_bundle_id *id); - void (*disconnect)(struct gb_bundle *bundle); - - const struct greybus_bundle_id *id_table; - - struct device_driver driver; -}; -#define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) - -static inline void greybus_set_drvdata(struct gb_bundle *bundle, void *data) -{ - dev_set_drvdata(&bundle->dev, data); -} - -static inline void *greybus_get_drvdata(struct gb_bundle *bundle) -{ - return dev_get_drvdata(&bundle->dev); -} - -/* Don't call these directly, use the module_greybus_driver() macro instead */ -int greybus_register_driver(struct greybus_driver *driver, - struct module *module, const char *mod_name); -void greybus_deregister_driver(struct greybus_driver *driver); - -/* define to get proper THIS_MODULE and KBUILD_MODNAME values */ -#define greybus_register(driver) \ - greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) -#define greybus_deregister(driver) \ - greybus_deregister_driver(driver) - -/** - * module_greybus_driver() - Helper macro for registering a Greybus driver - * @__greybus_driver: greybus_driver structure - * - * Helper macro for Greybus drivers to set up proper module init / exit - * functions. Replaces module_init() and module_exit() and keeps people from - * printing pointless things to the kernel log when their driver is loaded. - */ -#define module_greybus_driver(__greybus_driver) \ - module_driver(__greybus_driver, greybus_register, greybus_deregister) - -int greybus_disabled(void); - -void gb_debugfs_init(void); -void gb_debugfs_cleanup(void); -struct dentry *gb_debugfs_get(void); - -extern struct bus_type greybus_bus_type; - -extern struct device_type greybus_hd_type; -extern struct device_type greybus_module_type; -extern struct device_type greybus_interface_type; -extern struct device_type greybus_control_type; -extern struct device_type greybus_bundle_type; -extern struct device_type greybus_svc_type; - -static inline int is_gb_host_device(const struct device *dev) -{ - return dev->type == &greybus_hd_type; -} - -static inline int is_gb_module(const struct device *dev) -{ - return dev->type == &greybus_module_type; -} - -static inline int is_gb_interface(const struct device *dev) -{ - return dev->type == &greybus_interface_type; -} - -static inline int is_gb_control(const struct device *dev) -{ - return dev->type == &greybus_control_type; -} - -static inline int is_gb_bundle(const struct device *dev) -{ - return dev->type == &greybus_bundle_type; -} - -static inline int is_gb_svc(const struct device *dev) -{ - return dev->type == &greybus_svc_type; -} - -static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) -{ - return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; -} - -#endif /* __KERNEL__ */ -#endif /* __LINUX_GREYBUS_H */ diff --git a/drivers/staging/greybus/greybus_id.h b/drivers/staging/greybus/greybus_id.h deleted file mode 100644 index f4c8440093e4..000000000000 --- a/drivers/staging/greybus/greybus_id.h +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* FIXME - * move this to include/linux/mod_devicetable.h when merging - */ - -#ifndef __LINUX_GREYBUS_ID_H -#define __LINUX_GREYBUS_ID_H - -#include -#include - - -struct greybus_bundle_id { - __u16 match_flags; - __u32 vendor; - __u32 product; - __u8 class; - - kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); -}; - -/* Used to match the greybus_bundle_id */ -#define GREYBUS_ID_MATCH_VENDOR BIT(0) -#define GREYBUS_ID_MATCH_PRODUCT BIT(1) -#define GREYBUS_ID_MATCH_CLASS BIT(2) - -#endif /* __LINUX_GREYBUS_ID_H */ diff --git a/drivers/staging/greybus/greybus_manifest.h b/drivers/staging/greybus/greybus_manifest.h deleted file mode 100644 index db68f7e7d5a7..000000000000 --- a/drivers/staging/greybus/greybus_manifest.h +++ /dev/null @@ -1,178 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus manifest definition - * - * See "Greybus Application Protocol" document (version 0.1) for - * details on these values and structures. - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - * - * Released under the GPLv2 and BSD licenses. - */ - -#ifndef __GREYBUS_MANIFEST_H -#define __GREYBUS_MANIFEST_H - -enum greybus_descriptor_type { - GREYBUS_TYPE_INVALID = 0x00, - GREYBUS_TYPE_INTERFACE = 0x01, - GREYBUS_TYPE_STRING = 0x02, - GREYBUS_TYPE_BUNDLE = 0x03, - GREYBUS_TYPE_CPORT = 0x04, -}; - -enum greybus_protocol { - GREYBUS_PROTOCOL_CONTROL = 0x00, - /* 0x01 is unused */ - GREYBUS_PROTOCOL_GPIO = 0x02, - GREYBUS_PROTOCOL_I2C = 0x03, - GREYBUS_PROTOCOL_UART = 0x04, - GREYBUS_PROTOCOL_HID = 0x05, - GREYBUS_PROTOCOL_USB = 0x06, - GREYBUS_PROTOCOL_SDIO = 0x07, - GREYBUS_PROTOCOL_POWER_SUPPLY = 0x08, - GREYBUS_PROTOCOL_PWM = 0x09, - /* 0x0a is unused */ - GREYBUS_PROTOCOL_SPI = 0x0b, - GREYBUS_PROTOCOL_DISPLAY = 0x0c, - GREYBUS_PROTOCOL_CAMERA_MGMT = 0x0d, - GREYBUS_PROTOCOL_SENSOR = 0x0e, - GREYBUS_PROTOCOL_LIGHTS = 0x0f, - GREYBUS_PROTOCOL_VIBRATOR = 0x10, - GREYBUS_PROTOCOL_LOOPBACK = 0x11, - GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, - GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, - GREYBUS_PROTOCOL_SVC = 0x14, - GREYBUS_PROTOCOL_BOOTROM = 0x15, - GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, - GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, - GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, - GREYBUS_PROTOCOL_AUTHENTICATION = 0x19, - GREYBUS_PROTOCOL_LOG = 0x1a, - /* ... */ - GREYBUS_PROTOCOL_RAW = 0xfe, - GREYBUS_PROTOCOL_VENDOR = 0xff, -}; - -enum greybus_class_type { - GREYBUS_CLASS_CONTROL = 0x00, - /* 0x01 is unused */ - /* 0x02 is unused */ - /* 0x03 is unused */ - /* 0x04 is unused */ - GREYBUS_CLASS_HID = 0x05, - /* 0x06 is unused */ - /* 0x07 is unused */ - GREYBUS_CLASS_POWER_SUPPLY = 0x08, - /* 0x09 is unused */ - GREYBUS_CLASS_BRIDGED_PHY = 0x0a, - /* 0x0b is unused */ - GREYBUS_CLASS_DISPLAY = 0x0c, - GREYBUS_CLASS_CAMERA = 0x0d, - GREYBUS_CLASS_SENSOR = 0x0e, - GREYBUS_CLASS_LIGHTS = 0x0f, - GREYBUS_CLASS_VIBRATOR = 0x10, - GREYBUS_CLASS_LOOPBACK = 0x11, - GREYBUS_CLASS_AUDIO = 0x12, - /* 0x13 is unused */ - /* 0x14 is unused */ - GREYBUS_CLASS_BOOTROM = 0x15, - GREYBUS_CLASS_FW_MANAGEMENT = 0x16, - GREYBUS_CLASS_LOG = 0x17, - /* ... */ - GREYBUS_CLASS_RAW = 0xfe, - GREYBUS_CLASS_VENDOR = 0xff, -}; - -enum { - GREYBUS_INTERFACE_FEATURE_TIMESYNC = BIT(0), -}; - -/* - * The string in a string descriptor is not NUL-terminated. The - * size of the descriptor will be rounded up to a multiple of 4 - * bytes, by padding the string with 0x00 bytes if necessary. - */ -struct greybus_descriptor_string { - __u8 length; - __u8 id; - __u8 string[0]; -} __packed; - -/* - * An interface descriptor describes information about an interface as a whole, - * *not* the functions within it. - */ -struct greybus_descriptor_interface { - __u8 vendor_stringid; - __u8 product_stringid; - __u8 features; - __u8 pad; -} __packed; - -/* - * An bundle descriptor defines an identification number and a class for - * each bundle. - * - * @id: Uniquely identifies a bundle within a interface, its sole purpose is to - * allow CPort descriptors to specify which bundle they are associated with. - * The first bundle will have id 0, second will have 1 and so on. - * - * The largest CPort id associated with an bundle (defined by a - * CPort descriptor in the manifest) is used to determine how to - * encode the device id and module number in UniPro packets - * that use the bundle. - * - * @class: It is used by kernel to know the functionality provided by the - * bundle and will be matched against drivers functinality while probing greybus - * driver. It should contain one of the values defined in - * 'enum greybus_class_type'. - * - */ -struct greybus_descriptor_bundle { - __u8 id; /* interface-relative id (0..) */ - __u8 class; - __u8 pad[2]; -} __packed; - -/* - * A CPort descriptor indicates the id of the bundle within the - * module it's associated with, along with the CPort id used to - * address the CPort. The protocol id defines the format of messages - * exchanged using the CPort. - */ -struct greybus_descriptor_cport { - __le16 id; - __u8 bundle; - __u8 protocol_id; /* enum greybus_protocol */ -} __packed; - -struct greybus_descriptor_header { - __le16 size; - __u8 type; /* enum greybus_descriptor_type */ - __u8 pad; -} __packed; - -struct greybus_descriptor { - struct greybus_descriptor_header header; - union { - struct greybus_descriptor_string string; - struct greybus_descriptor_interface interface; - struct greybus_descriptor_bundle bundle; - struct greybus_descriptor_cport cport; - }; -} __packed; - -struct greybus_manifest_header { - __le16 size; - __u8 version_major; - __u8 version_minor; -} __packed; - -struct greybus_manifest { - struct greybus_manifest_header header; - struct greybus_descriptor descriptors[0]; -} __packed; - -#endif /* __GREYBUS_MANIFEST_H */ diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h deleted file mode 100644 index 5f34d1effb59..000000000000 --- a/drivers/staging/greybus/greybus_protocols.h +++ /dev/null @@ -1,2176 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ -/* - * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. - * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. - */ - -#ifndef __GREYBUS_PROTOCOLS_H -#define __GREYBUS_PROTOCOLS_H - -/* Fixed IDs for control/svc protocols */ - -/* SVC switch-port device ids */ -#define GB_SVC_DEVICE_ID_SVC 0 -#define GB_SVC_DEVICE_ID_AP 1 -#define GB_SVC_DEVICE_ID_MIN 2 -#define GB_SVC_DEVICE_ID_MAX 31 - -#define GB_SVC_CPORT_ID 0 -#define GB_CONTROL_BUNDLE_ID 0 -#define GB_CONTROL_CPORT_ID 0 - - -/* - * All operation messages (both requests and responses) begin with - * a header that encodes the size of the message (header included). - * This header also contains a unique identifier, that associates a - * response message with its operation. The header contains an - * operation type field, whose interpretation is dependent on what - * type of protocol is used over the connection. The high bit - * (0x80) of the operation type field is used to indicate whether - * the message is a request (clear) or a response (set). - * - * Response messages include an additional result byte, which - * communicates the result of the corresponding request. A zero - * result value means the operation completed successfully. Any - * other value indicates an error; in this case, the payload of the - * response message (if any) is ignored. The result byte must be - * zero in the header for a request message. - * - * The wire format for all numeric fields in the header is little - * endian. Any operation-specific data begins immediately after the - * header. - */ -struct gb_operation_msg_hdr { - __le16 size; /* Size in bytes of header + payload */ - __le16 operation_id; /* Operation unique id */ - __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ - __u8 result; /* Result of request (in responses only) */ - __u8 pad[2]; /* must be zero (ignore when read) */ -} __packed; - - -/* Generic request types */ -#define GB_REQUEST_TYPE_CPORT_SHUTDOWN 0x00 -#define GB_REQUEST_TYPE_INVALID 0x7f - -struct gb_cport_shutdown_request { - __u8 phase; -} __packed; - - -/* Control Protocol */ - -/* Greybus control request types */ -#define GB_CONTROL_TYPE_VERSION 0x01 -#define GB_CONTROL_TYPE_PROBE_AP 0x02 -#define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 -#define GB_CONTROL_TYPE_GET_MANIFEST 0x04 -#define GB_CONTROL_TYPE_CONNECTED 0x05 -#define GB_CONTROL_TYPE_DISCONNECTED 0x06 -#define GB_CONTROL_TYPE_TIMESYNC_ENABLE 0x07 -#define GB_CONTROL_TYPE_TIMESYNC_DISABLE 0x08 -#define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 -/* Unused 0x0a */ -#define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b -#define GB_CONTROL_TYPE_DISCONNECTING 0x0c -#define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d -#define GB_CONTROL_TYPE_MODE_SWITCH 0x0e -#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f -#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 -#define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 -#define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 -#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 -#define GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE 0x14 -#define GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT 0x15 - -struct gb_control_version_request { - __u8 major; - __u8 minor; -} __packed; - -struct gb_control_version_response { - __u8 major; - __u8 minor; -} __packed; - -struct gb_control_bundle_version_request { - __u8 bundle_id; -} __packed; - -struct gb_control_bundle_version_response { - __u8 major; - __u8 minor; -} __packed; - -/* Control protocol manifest get size request has no payload*/ -struct gb_control_get_manifest_size_response { - __le16 size; -} __packed; - -/* Control protocol manifest get request has no payload */ -struct gb_control_get_manifest_response { - __u8 data[0]; -} __packed; - -/* Control protocol [dis]connected request */ -struct gb_control_connected_request { - __le16 cport_id; -} __packed; - -struct gb_control_disconnecting_request { - __le16 cport_id; -} __packed; -/* disconnecting response has no payload */ - -struct gb_control_disconnected_request { - __le16 cport_id; -} __packed; -/* Control protocol [dis]connected response has no payload */ - -/* - * All Bundle power management operations use the same request and response - * layout and status codes. - */ - -#define GB_CONTROL_BUNDLE_PM_OK 0x00 -#define GB_CONTROL_BUNDLE_PM_INVAL 0x01 -#define GB_CONTROL_BUNDLE_PM_BUSY 0x02 -#define GB_CONTROL_BUNDLE_PM_FAIL 0x03 -#define GB_CONTROL_BUNDLE_PM_NA 0x04 - -struct gb_control_bundle_pm_request { - __u8 bundle_id; -} __packed; - -struct gb_control_bundle_pm_response { - __u8 status; -} __packed; - -/* - * Interface Suspend Prepare and Deactivate Prepare operations use the same - * response layout and error codes. Define a single response structure and reuse - * it. Both operations have no payload. - */ - -#define GB_CONTROL_INTF_PM_OK 0x00 -#define GB_CONTROL_INTF_PM_BUSY 0x01 -#define GB_CONTROL_INTF_PM_NA 0x02 - -struct gb_control_intf_pm_response { - __u8 status; -} __packed; - -/* APBridge protocol */ - -/* request APB1 log */ -#define GB_APB_REQUEST_LOG 0x02 - -/* request to map a cport to bulk in and bulk out endpoints */ -#define GB_APB_REQUEST_EP_MAPPING 0x03 - -/* request to get the number of cports available */ -#define GB_APB_REQUEST_CPORT_COUNT 0x04 - -/* request to reset a cport state */ -#define GB_APB_REQUEST_RESET_CPORT 0x05 - -/* request to time the latency of messages on a given cport */ -#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 -#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 - -/* request to control the CSI transmitter */ -#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 - -/* request to control audio streaming */ -#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 - -/* TimeSync requests */ -#define GB_APB_REQUEST_TIMESYNC_ENABLE 0x0d -#define GB_APB_REQUEST_TIMESYNC_DISABLE 0x0e -#define GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE 0x0f -#define GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 - -/* requests to set Greybus CPort flags */ -#define GB_APB_REQUEST_CPORT_FLAGS 0x11 - -/* ARPC request */ -#define GB_APB_REQUEST_ARPC_RUN 0x12 - -struct gb_apb_request_cport_flags { - __le32 flags; -#define GB_APB_CPORT_FLAG_CONTROL 0x01 -#define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 -} __packed; - - -/* Firmware Download Protocol */ - -/* Request Types */ -#define GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE 0x01 -#define GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE 0x02 -#define GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE 0x03 - -#define GB_FIRMWARE_TAG_MAX_SIZE 10 - -/* firmware download find firmware request/response */ -struct gb_fw_download_find_firmware_request { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; -} __packed; - -struct gb_fw_download_find_firmware_response { - __u8 firmware_id; - __le32 size; -} __packed; - -/* firmware download fetch firmware request/response */ -struct gb_fw_download_fetch_firmware_request { - __u8 firmware_id; - __le32 offset; - __le32 size; -} __packed; - -struct gb_fw_download_fetch_firmware_response { - __u8 data[0]; -} __packed; - -/* firmware download release firmware request */ -struct gb_fw_download_release_firmware_request { - __u8 firmware_id; -} __packed; -/* firmware download release firmware response has no payload */ - - -/* Firmware Management Protocol */ - -/* Request Types */ -#define GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION 0x01 -#define GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW 0x02 -#define GB_FW_MGMT_TYPE_LOADED_FW 0x03 -#define GB_FW_MGMT_TYPE_BACKEND_FW_VERSION 0x04 -#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE 0x05 -#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED 0x06 - -#define GB_FW_LOAD_METHOD_UNIPRO 0x01 -#define GB_FW_LOAD_METHOD_INTERNAL 0x02 - -#define GB_FW_LOAD_STATUS_FAILED 0x00 -#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 -#define GB_FW_LOAD_STATUS_VALIDATED 0x02 -#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 - -#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 -#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 -#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 -#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 -#define GB_FW_BACKEND_FW_STATUS_INT 0x05 -#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 -#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 - -#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 -#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 -#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 -#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 -#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 - -/* firmware management interface firmware version request has no payload */ -struct gb_fw_mgmt_interface_fw_version_response { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; - __le16 major; - __le16 minor; -} __packed; - -/* firmware management load and validate firmware request/response */ -struct gb_fw_mgmt_load_and_validate_fw_request { - __u8 request_id; - __u8 load_method; - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; -} __packed; -/* firmware management load and validate firmware response has no payload*/ - -/* firmware management loaded firmware request */ -struct gb_fw_mgmt_loaded_fw_request { - __u8 request_id; - __u8 status; - __le16 major; - __le16 minor; -} __packed; -/* firmware management loaded firmware response has no payload */ - -/* firmware management backend firmware version request/response */ -struct gb_fw_mgmt_backend_fw_version_request { - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; -} __packed; - -struct gb_fw_mgmt_backend_fw_version_response { - __le16 major; - __le16 minor; - __u8 status; -} __packed; - -/* firmware management backend firmware update request */ -struct gb_fw_mgmt_backend_fw_update_request { - __u8 request_id; - __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; -} __packed; -/* firmware management backend firmware update response has no payload */ - -/* firmware management backend firmware updated request */ -struct gb_fw_mgmt_backend_fw_updated_request { - __u8 request_id; - __u8 status; -} __packed; -/* firmware management backend firmware updated response has no payload */ - - -/* Component Authentication Protocol (CAP) */ - -/* Request Types */ -#define GB_CAP_TYPE_GET_ENDPOINT_UID 0x01 -#define GB_CAP_TYPE_GET_IMS_CERTIFICATE 0x02 -#define GB_CAP_TYPE_AUTHENTICATE 0x03 - -/* CAP get endpoint uid request has no payload */ -struct gb_cap_get_endpoint_uid_response { - __u8 uid[8]; -} __packed; - -/* CAP get endpoint ims certificate request/response */ -struct gb_cap_get_ims_certificate_request { - __le32 certificate_class; - __le32 certificate_id; -} __packed; - -struct gb_cap_get_ims_certificate_response { - __u8 result_code; - __u8 certificate[0]; -} __packed; - -/* CAP authenticate request/response */ -struct gb_cap_authenticate_request { - __le32 auth_type; - __u8 uid[8]; - __u8 challenge[32]; -} __packed; - -struct gb_cap_authenticate_response { - __u8 result_code; - __u8 response[64]; - __u8 signature[0]; -} __packed; - - -/* Bootrom Protocol */ - -/* Version of the Greybus bootrom protocol we support */ -#define GB_BOOTROM_VERSION_MAJOR 0x00 -#define GB_BOOTROM_VERSION_MINOR 0x01 - -/* Greybus bootrom request types */ -#define GB_BOOTROM_TYPE_VERSION 0x01 -#define GB_BOOTROM_TYPE_FIRMWARE_SIZE 0x02 -#define GB_BOOTROM_TYPE_GET_FIRMWARE 0x03 -#define GB_BOOTROM_TYPE_READY_TO_BOOT 0x04 -#define GB_BOOTROM_TYPE_AP_READY 0x05 /* Request with no-payload */ -#define GB_BOOTROM_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ - -/* Greybus bootrom boot stages */ -#define GB_BOOTROM_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ -#define GB_BOOTROM_BOOT_STAGE_TWO 0x02 /* Bootrom package to be loaded by the boot ROM */ -#define GB_BOOTROM_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ - -/* Greybus bootrom ready to boot status */ -#define GB_BOOTROM_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ -#define GB_BOOTROM_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ -#define GB_BOOTROM_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ - -/* Max bootrom data fetch size in bytes */ -#define GB_BOOTROM_FETCH_MAX 2000 - -struct gb_bootrom_version_request { - __u8 major; - __u8 minor; -} __packed; - -struct gb_bootrom_version_response { - __u8 major; - __u8 minor; -} __packed; - -/* Bootrom protocol firmware size request/response */ -struct gb_bootrom_firmware_size_request { - __u8 stage; -} __packed; - -struct gb_bootrom_firmware_size_response { - __le32 size; -} __packed; - -/* Bootrom protocol get firmware request/response */ -struct gb_bootrom_get_firmware_request { - __le32 offset; - __le32 size; -} __packed; - -struct gb_bootrom_get_firmware_response { - __u8 data[0]; -} __packed; - -/* Bootrom protocol Ready to boot request */ -struct gb_bootrom_ready_to_boot_request { - __u8 status; -} __packed; -/* Bootrom protocol Ready to boot response has no payload */ - -/* Bootrom protocol get VID/PID request has no payload */ -struct gb_bootrom_get_vid_pid_response { - __le32 vendor_id; - __le32 product_id; -} __packed; - - -/* Power Supply */ - -/* Greybus power supply request types */ -#define GB_POWER_SUPPLY_TYPE_GET_SUPPLIES 0x02 -#define GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION 0x03 -#define GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS 0x04 -#define GB_POWER_SUPPLY_TYPE_GET_PROPERTY 0x05 -#define GB_POWER_SUPPLY_TYPE_SET_PROPERTY 0x06 -#define GB_POWER_SUPPLY_TYPE_EVENT 0x07 - -/* Greybus power supply battery technologies types */ -#define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_TECH_NiMH 0x0001 -#define GB_POWER_SUPPLY_TECH_LION 0x0002 -#define GB_POWER_SUPPLY_TECH_LIPO 0x0003 -#define GB_POWER_SUPPLY_TECH_LiFe 0x0004 -#define GB_POWER_SUPPLY_TECH_NiCd 0x0005 -#define GB_POWER_SUPPLY_TECH_LiMn 0x0006 - -/* Greybus power supply types */ -#define GB_POWER_SUPPLY_UNKNOWN_TYPE 0x0000 -#define GB_POWER_SUPPLY_BATTERY_TYPE 0x0001 -#define GB_POWER_SUPPLY_UPS_TYPE 0x0002 -#define GB_POWER_SUPPLY_MAINS_TYPE 0x0003 -#define GB_POWER_SUPPLY_USB_TYPE 0x0004 -#define GB_POWER_SUPPLY_USB_DCP_TYPE 0x0005 -#define GB_POWER_SUPPLY_USB_CDP_TYPE 0x0006 -#define GB_POWER_SUPPLY_USB_ACA_TYPE 0x0007 - -/* Greybus power supply health values */ -#define GB_POWER_SUPPLY_HEALTH_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_HEALTH_GOOD 0x0001 -#define GB_POWER_SUPPLY_HEALTH_OVERHEAT 0x0002 -#define GB_POWER_SUPPLY_HEALTH_DEAD 0x0003 -#define GB_POWER_SUPPLY_HEALTH_OVERVOLTAGE 0x0004 -#define GB_POWER_SUPPLY_HEALTH_UNSPEC_FAILURE 0x0005 -#define GB_POWER_SUPPLY_HEALTH_COLD 0x0006 -#define GB_POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE 0x0007 -#define GB_POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE 0x0008 - -/* Greybus power supply status values */ -#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 -#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 -#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 -#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 - -/* Greybus power supply capacity level values */ -#define GB_POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL 0x0001 -#define GB_POWER_SUPPLY_CAPACITY_LEVEL_LOW 0x0002 -#define GB_POWER_SUPPLY_CAPACITY_LEVEL_NORMAL 0x0003 -#define GB_POWER_SUPPLY_CAPACITY_LEVEL_HIGH 0x0004 -#define GB_POWER_SUPPLY_CAPACITY_LEVEL_FULL 0x0005 - -/* Greybus power supply scope values */ -#define GB_POWER_SUPPLY_SCOPE_UNKNOWN 0x0000 -#define GB_POWER_SUPPLY_SCOPE_SYSTEM 0x0001 -#define GB_POWER_SUPPLY_SCOPE_DEVICE 0x0002 - -struct gb_power_supply_get_supplies_response { - __u8 supplies_count; -} __packed; - -struct gb_power_supply_get_description_request { - __u8 psy_id; -} __packed; - -struct gb_power_supply_get_description_response { - __u8 manufacturer[32]; - __u8 model[32]; - __u8 serial_number[32]; - __le16 type; - __u8 properties_count; -} __packed; - -struct gb_power_supply_props_desc { - __u8 property; -#define GB_POWER_SUPPLY_PROP_STATUS 0x00 -#define GB_POWER_SUPPLY_PROP_CHARGE_TYPE 0x01 -#define GB_POWER_SUPPLY_PROP_HEALTH 0x02 -#define GB_POWER_SUPPLY_PROP_PRESENT 0x03 -#define GB_POWER_SUPPLY_PROP_ONLINE 0x04 -#define GB_POWER_SUPPLY_PROP_AUTHENTIC 0x05 -#define GB_POWER_SUPPLY_PROP_TECHNOLOGY 0x06 -#define GB_POWER_SUPPLY_PROP_CYCLE_COUNT 0x07 -#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX 0x08 -#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN 0x09 -#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN 0x0A -#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN 0x0B -#define GB_POWER_SUPPLY_PROP_VOLTAGE_NOW 0x0C -#define GB_POWER_SUPPLY_PROP_VOLTAGE_AVG 0x0D -#define GB_POWER_SUPPLY_PROP_VOLTAGE_OCV 0x0E -#define GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT 0x0F -#define GB_POWER_SUPPLY_PROP_CURRENT_MAX 0x10 -#define GB_POWER_SUPPLY_PROP_CURRENT_NOW 0x11 -#define GB_POWER_SUPPLY_PROP_CURRENT_AVG 0x12 -#define GB_POWER_SUPPLY_PROP_CURRENT_BOOT 0x13 -#define GB_POWER_SUPPLY_PROP_POWER_NOW 0x14 -#define GB_POWER_SUPPLY_PROP_POWER_AVG 0x15 -#define GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN 0x16 -#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN 0x17 -#define GB_POWER_SUPPLY_PROP_CHARGE_FULL 0x18 -#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY 0x19 -#define GB_POWER_SUPPLY_PROP_CHARGE_NOW 0x1A -#define GB_POWER_SUPPLY_PROP_CHARGE_AVG 0x1B -#define GB_POWER_SUPPLY_PROP_CHARGE_COUNTER 0x1C -#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT 0x1D -#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX 0x1E -#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE 0x1F -#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX 0x20 -#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT 0x21 -#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX 0x22 -#define GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT 0x23 -#define GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN 0x24 -#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN 0x25 -#define GB_POWER_SUPPLY_PROP_ENERGY_FULL 0x26 -#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY 0x27 -#define GB_POWER_SUPPLY_PROP_ENERGY_NOW 0x28 -#define GB_POWER_SUPPLY_PROP_ENERGY_AVG 0x29 -#define GB_POWER_SUPPLY_PROP_CAPACITY 0x2A -#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN 0x2B -#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX 0x2C -#define GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL 0x2D -#define GB_POWER_SUPPLY_PROP_TEMP 0x2E -#define GB_POWER_SUPPLY_PROP_TEMP_MAX 0x2F -#define GB_POWER_SUPPLY_PROP_TEMP_MIN 0x30 -#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN 0x31 -#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX 0x32 -#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT 0x33 -#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN 0x34 -#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX 0x35 -#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW 0x36 -#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG 0x37 -#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW 0x38 -#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG 0x39 -#define GB_POWER_SUPPLY_PROP_TYPE 0x3A -#define GB_POWER_SUPPLY_PROP_SCOPE 0x3B -#define GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT 0x3C -#define GB_POWER_SUPPLY_PROP_CALIBRATE 0x3D - __u8 is_writeable; -} __packed; - -struct gb_power_supply_get_property_descriptors_request { - __u8 psy_id; -} __packed; - -struct gb_power_supply_get_property_descriptors_response { - __u8 properties_count; - struct gb_power_supply_props_desc props[]; -} __packed; - -struct gb_power_supply_get_property_request { - __u8 psy_id; - __u8 property; -} __packed; - -struct gb_power_supply_get_property_response { - __le32 prop_val; -}; - -struct gb_power_supply_set_property_request { - __u8 psy_id; - __u8 property; - __le32 prop_val; -} __packed; - -struct gb_power_supply_event_request { - __u8 psy_id; - __u8 event; -#define GB_POWER_SUPPLY_UPDATE 0x01 -} __packed; - - -/* HID */ - -/* Greybus HID operation types */ -#define GB_HID_TYPE_GET_DESC 0x02 -#define GB_HID_TYPE_GET_REPORT_DESC 0x03 -#define GB_HID_TYPE_PWR_ON 0x04 -#define GB_HID_TYPE_PWR_OFF 0x05 -#define GB_HID_TYPE_GET_REPORT 0x06 -#define GB_HID_TYPE_SET_REPORT 0x07 -#define GB_HID_TYPE_IRQ_EVENT 0x08 - -/* Report type */ -#define GB_HID_INPUT_REPORT 0 -#define GB_HID_OUTPUT_REPORT 1 -#define GB_HID_FEATURE_REPORT 2 - -/* Different request/response structures */ -/* HID get descriptor response */ -struct gb_hid_desc_response { - __u8 bLength; - __le16 wReportDescLength; - __le16 bcdHID; - __le16 wProductID; - __le16 wVendorID; - __u8 bCountryCode; -} __packed; - -/* HID get report request/response */ -struct gb_hid_get_report_request { - __u8 report_type; - __u8 report_id; -} __packed; - -/* HID set report request */ -struct gb_hid_set_report_request { - __u8 report_type; - __u8 report_id; - __u8 report[0]; -} __packed; - -/* HID input report request, via interrupt pipe */ -struct gb_hid_input_report_request { - __u8 report[0]; -} __packed; - - -/* I2C */ - -/* Greybus i2c request types */ -#define GB_I2C_TYPE_FUNCTIONALITY 0x02 -#define GB_I2C_TYPE_TRANSFER 0x05 - -/* functionality request has no payload */ -struct gb_i2c_functionality_response { - __le32 functionality; -} __packed; - -/* - * Outgoing data immediately follows the op count and ops array. - * The data for each write (master -> slave) op in the array is sent - * in order, with no (e.g. pad) bytes separating them. - * - * Short reads cause the entire transfer request to fail So response - * payload consists only of bytes read, and the number of bytes is - * exactly what was specified in the corresponding op. Like - * outgoing data, the incoming data is in order and contiguous. - */ -struct gb_i2c_transfer_op { - __le16 addr; - __le16 flags; - __le16 size; -} __packed; - -struct gb_i2c_transfer_request { - __le16 op_count; - struct gb_i2c_transfer_op ops[0]; /* op_count of these */ -} __packed; -struct gb_i2c_transfer_response { - __u8 data[0]; /* inbound data */ -} __packed; - - -/* GPIO */ - -/* Greybus GPIO request types */ -#define GB_GPIO_TYPE_LINE_COUNT 0x02 -#define GB_GPIO_TYPE_ACTIVATE 0x03 -#define GB_GPIO_TYPE_DEACTIVATE 0x04 -#define GB_GPIO_TYPE_GET_DIRECTION 0x05 -#define GB_GPIO_TYPE_DIRECTION_IN 0x06 -#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 -#define GB_GPIO_TYPE_GET_VALUE 0x08 -#define GB_GPIO_TYPE_SET_VALUE 0x09 -#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a -#define GB_GPIO_TYPE_IRQ_TYPE 0x0b -#define GB_GPIO_TYPE_IRQ_MASK 0x0c -#define GB_GPIO_TYPE_IRQ_UNMASK 0x0d -#define GB_GPIO_TYPE_IRQ_EVENT 0x0e - -#define GB_GPIO_IRQ_TYPE_NONE 0x00 -#define GB_GPIO_IRQ_TYPE_EDGE_RISING 0x01 -#define GB_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 -#define GB_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 -#define GB_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 -#define GB_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 - -/* line count request has no payload */ -struct gb_gpio_line_count_response { - __u8 count; -} __packed; - -struct gb_gpio_activate_request { - __u8 which; -} __packed; -/* activate response has no payload */ - -struct gb_gpio_deactivate_request { - __u8 which; -} __packed; -/* deactivate response has no payload */ - -struct gb_gpio_get_direction_request { - __u8 which; -} __packed; -struct gb_gpio_get_direction_response { - __u8 direction; -} __packed; - -struct gb_gpio_direction_in_request { - __u8 which; -} __packed; -/* direction in response has no payload */ - -struct gb_gpio_direction_out_request { - __u8 which; - __u8 value; -} __packed; -/* direction out response has no payload */ - -struct gb_gpio_get_value_request { - __u8 which; -} __packed; -struct gb_gpio_get_value_response { - __u8 value; -} __packed; - -struct gb_gpio_set_value_request { - __u8 which; - __u8 value; -} __packed; -/* set value response has no payload */ - -struct gb_gpio_set_debounce_request { - __u8 which; - __le16 usec; -} __packed; -/* debounce response has no payload */ - -struct gb_gpio_irq_type_request { - __u8 which; - __u8 type; -} __packed; -/* irq type response has no payload */ - -struct gb_gpio_irq_mask_request { - __u8 which; -} __packed; -/* irq mask response has no payload */ - -struct gb_gpio_irq_unmask_request { - __u8 which; -} __packed; -/* irq unmask response has no payload */ - -/* irq event requests originate on another module and are handled on the AP */ -struct gb_gpio_irq_event_request { - __u8 which; -} __packed; -/* irq event has no response */ - - -/* PWM */ - -/* Greybus PWM operation types */ -#define GB_PWM_TYPE_PWM_COUNT 0x02 -#define GB_PWM_TYPE_ACTIVATE 0x03 -#define GB_PWM_TYPE_DEACTIVATE 0x04 -#define GB_PWM_TYPE_CONFIG 0x05 -#define GB_PWM_TYPE_POLARITY 0x06 -#define GB_PWM_TYPE_ENABLE 0x07 -#define GB_PWM_TYPE_DISABLE 0x08 - -/* pwm count request has no payload */ -struct gb_pwm_count_response { - __u8 count; -} __packed; - -struct gb_pwm_activate_request { - __u8 which; -} __packed; - -struct gb_pwm_deactivate_request { - __u8 which; -} __packed; - -struct gb_pwm_config_request { - __u8 which; - __le32 duty; - __le32 period; -} __packed; - -struct gb_pwm_polarity_request { - __u8 which; - __u8 polarity; -} __packed; - -struct gb_pwm_enable_request { - __u8 which; -} __packed; - -struct gb_pwm_disable_request { - __u8 which; -} __packed; - -/* SPI */ - -/* Should match up with modes in linux/spi/spi.h */ -#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ -#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ -#define GB_SPI_MODE_MODE_0 (0 | 0) /* (original MicroWire) */ -#define GB_SPI_MODE_MODE_1 (0 | GB_SPI_MODE_CPHA) -#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL | 0) -#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL | GB_SPI_MODE_CPHA) -#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ -#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ -#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ -#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ -#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ -#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ - -/* Should match up with flags in linux/spi/spi.h */ -#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ -#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ -#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ - -/* Greybus spi operation types */ -#define GB_SPI_TYPE_MASTER_CONFIG 0x02 -#define GB_SPI_TYPE_DEVICE_CONFIG 0x03 -#define GB_SPI_TYPE_TRANSFER 0x04 - -/* mode request has no payload */ -struct gb_spi_master_config_response { - __le32 bits_per_word_mask; - __le32 min_speed_hz; - __le32 max_speed_hz; - __le16 mode; - __le16 flags; - __u8 num_chipselect; -} __packed; - -struct gb_spi_device_config_request { - __u8 chip_select; -} __packed; - -struct gb_spi_device_config_response { - __le16 mode; - __u8 bits_per_word; - __le32 max_speed_hz; - __u8 device_type; -#define GB_SPI_SPI_DEV 0x00 -#define GB_SPI_SPI_NOR 0x01 -#define GB_SPI_SPI_MODALIAS 0x02 - __u8 name[32]; -} __packed; - -/** - * struct gb_spi_transfer - a read/write buffer pair - * @speed_hz: Select a speed other than the device default for this transfer. If - * 0 the default (from @spi_device) is used. - * @len: size of rx and tx buffers (in bytes) - * @delay_usecs: microseconds to delay after this transfer before (optionally) - * changing the chipselect status, then starting the next transfer or - * completing this spi_message. - * @cs_change: affects chipselect after this transfer completes - * @bits_per_word: select a bits_per_word other than the device default for this - * transfer. If 0 the default (from @spi_device) is used. - */ -struct gb_spi_transfer { - __le32 speed_hz; - __le32 len; - __le16 delay_usecs; - __u8 cs_change; - __u8 bits_per_word; - __u8 xfer_flags; -#define GB_SPI_XFER_READ 0x01 -#define GB_SPI_XFER_WRITE 0x02 -#define GB_SPI_XFER_INPROGRESS 0x04 -} __packed; - -struct gb_spi_transfer_request { - __u8 chip_select; /* of the spi device */ - __u8 mode; /* of the spi device */ - __le16 count; - struct gb_spi_transfer transfers[0]; /* count of these */ -} __packed; - -struct gb_spi_transfer_response { - __u8 data[0]; /* inbound data */ -} __packed; - -/* Version of the Greybus SVC protocol we support */ -#define GB_SVC_VERSION_MAJOR 0x00 -#define GB_SVC_VERSION_MINOR 0x01 - -/* Greybus SVC request types */ -#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 -#define GB_SVC_TYPE_SVC_HELLO 0x02 -#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 -#define GB_SVC_TYPE_INTF_RESET 0x06 -#define GB_SVC_TYPE_CONN_CREATE 0x07 -#define GB_SVC_TYPE_CONN_DESTROY 0x08 -#define GB_SVC_TYPE_DME_PEER_GET 0x09 -#define GB_SVC_TYPE_DME_PEER_SET 0x0a -#define GB_SVC_TYPE_ROUTE_CREATE 0x0b -#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c -#define GB_SVC_TYPE_TIMESYNC_ENABLE 0x0d -#define GB_SVC_TYPE_TIMESYNC_DISABLE 0x0e -#define GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE 0x0f -#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 -#define GB_SVC_TYPE_INTF_EJECT 0x11 -#define GB_SVC_TYPE_PING 0x13 -#define GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET 0x14 -#define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 -#define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 -#define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 -#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 -#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 -#define GB_SVC_TYPE_TIMESYNC_PING 0x1a -#define GB_SVC_TYPE_MODULE_INSERTED 0x1f -#define GB_SVC_TYPE_MODULE_REMOVED 0x20 -#define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 -#define GB_SVC_TYPE_INTF_VSYS_DISABLE 0x22 -#define GB_SVC_TYPE_INTF_REFCLK_ENABLE 0x23 -#define GB_SVC_TYPE_INTF_REFCLK_DISABLE 0x24 -#define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25 -#define GB_SVC_TYPE_INTF_UNIPRO_DISABLE 0x26 -#define GB_SVC_TYPE_INTF_ACTIVATE 0x27 -#define GB_SVC_TYPE_INTF_RESUME 0x28 -#define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 -#define GB_SVC_TYPE_INTF_OOPS 0x2a - -/* Greybus SVC protocol status values */ -#define GB_SVC_OP_SUCCESS 0x00 -#define GB_SVC_OP_UNKNOWN_ERROR 0x01 -#define GB_SVC_INTF_NOT_DETECTED 0x02 -#define GB_SVC_INTF_NO_UPRO_LINK 0x03 -#define GB_SVC_INTF_UPRO_NOT_DOWN 0x04 -#define GB_SVC_INTF_UPRO_NOT_HIBERNATED 0x05 -#define GB_SVC_INTF_NO_V_SYS 0x06 -#define GB_SVC_INTF_V_CHG 0x07 -#define GB_SVC_INTF_WAKE_BUSY 0x08 -#define GB_SVC_INTF_NO_REFCLK 0x09 -#define GB_SVC_INTF_RELEASING 0x0a -#define GB_SVC_INTF_NO_ORDER 0x0b -#define GB_SVC_INTF_MBOX_SET 0x0c -#define GB_SVC_INTF_BAD_MBOX 0x0d -#define GB_SVC_INTF_OP_TIMEOUT 0x0e -#define GB_SVC_PWRMON_OP_NOT_PRESENT 0x0f - -struct gb_svc_version_request { - __u8 major; - __u8 minor; -} __packed; - -struct gb_svc_version_response { - __u8 major; - __u8 minor; -} __packed; - -/* SVC protocol hello request */ -struct gb_svc_hello_request { - __le16 endo_id; - __u8 interface_id; -} __packed; -/* hello response has no payload */ - -struct gb_svc_intf_device_id_request { - __u8 intf_id; - __u8 device_id; -} __packed; -/* device id response has no payload */ - -struct gb_svc_intf_reset_request { - __u8 intf_id; -} __packed; -/* interface reset response has no payload */ - -struct gb_svc_intf_eject_request { - __u8 intf_id; -} __packed; -/* interface eject response has no payload */ - -struct gb_svc_conn_create_request { - __u8 intf1_id; - __le16 cport1_id; - __u8 intf2_id; - __le16 cport2_id; - __u8 tc; - __u8 flags; -} __packed; -/* connection create response has no payload */ - -struct gb_svc_conn_destroy_request { - __u8 intf1_id; - __le16 cport1_id; - __u8 intf2_id; - __le16 cport2_id; -} __packed; -/* connection destroy response has no payload */ - -struct gb_svc_dme_peer_get_request { - __u8 intf_id; - __le16 attr; - __le16 selector; -} __packed; - -struct gb_svc_dme_peer_get_response { - __le16 result_code; - __le32 attr_value; -} __packed; - -struct gb_svc_dme_peer_set_request { - __u8 intf_id; - __le16 attr; - __le16 selector; - __le32 value; -} __packed; - -struct gb_svc_dme_peer_set_response { - __le16 result_code; -} __packed; - -/* Greybus init-status values, currently retrieved using DME peer gets. */ -#define GB_INIT_SPI_BOOT_STARTED 0x02 -#define GB_INIT_TRUSTED_SPI_BOOT_FINISHED 0x03 -#define GB_INIT_UNTRUSTED_SPI_BOOT_FINISHED 0x04 -#define GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED 0x06 -#define GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 -#define GB_INIT_S2_LOADER_BOOT_STARTED 0x0D - -struct gb_svc_route_create_request { - __u8 intf1_id; - __u8 dev1_id; - __u8 intf2_id; - __u8 dev2_id; -} __packed; -/* route create response has no payload */ - -struct gb_svc_route_destroy_request { - __u8 intf1_id; - __u8 intf2_id; -} __packed; -/* route destroy response has no payload */ - -/* used for svc_intf_vsys_{enable,disable} */ -struct gb_svc_intf_vsys_request { - __u8 intf_id; -} __packed; - -struct gb_svc_intf_vsys_response { - __u8 result_code; -#define GB_SVC_INTF_VSYS_OK 0x00 - /* 0x01 is reserved */ -#define GB_SVC_INTF_VSYS_FAIL 0x02 -} __packed; - -/* used for svc_intf_refclk_{enable,disable} */ -struct gb_svc_intf_refclk_request { - __u8 intf_id; -} __packed; - -struct gb_svc_intf_refclk_response { - __u8 result_code; -#define GB_SVC_INTF_REFCLK_OK 0x00 - /* 0x01 is reserved */ -#define GB_SVC_INTF_REFCLK_FAIL 0x02 -} __packed; - -/* used for svc_intf_unipro_{enable,disable} */ -struct gb_svc_intf_unipro_request { - __u8 intf_id; -} __packed; - -struct gb_svc_intf_unipro_response { - __u8 result_code; -#define GB_SVC_INTF_UNIPRO_OK 0x00 - /* 0x01 is reserved */ -#define GB_SVC_INTF_UNIPRO_FAIL 0x02 -#define GB_SVC_INTF_UNIPRO_NOT_OFF 0x03 -} __packed; - -#define GB_SVC_UNIPRO_FAST_MODE 0x01 -#define GB_SVC_UNIPRO_SLOW_MODE 0x02 -#define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 -#define GB_SVC_UNIPRO_SLOW_AUTO_MODE 0x05 -#define GB_SVC_UNIPRO_MODE_UNCHANGED 0x07 -#define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 -#define GB_SVC_UNIPRO_OFF_MODE 0x12 - -#define GB_SVC_SMALL_AMPLITUDE 0x01 -#define GB_SVC_LARGE_AMPLITUDE 0x02 - -#define GB_SVC_NO_DE_EMPHASIS 0x00 -#define GB_SVC_SMALL_DE_EMPHASIS 0x01 -#define GB_SVC_LARGE_DE_EMPHASIS 0x02 - -#define GB_SVC_PWRM_RXTERMINATION 0x01 -#define GB_SVC_PWRM_TXTERMINATION 0x02 -#define GB_SVC_PWRM_LINE_RESET 0x04 -#define GB_SVC_PWRM_SCRAMBLING 0x20 - -#define GB_SVC_PWRM_QUIRK_HSSER 0x00000001 - -#define GB_SVC_UNIPRO_HS_SERIES_A 0x01 -#define GB_SVC_UNIPRO_HS_SERIES_B 0x02 - -#define GB_SVC_SETPWRM_PWR_OK 0x00 -#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 -#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 -#define GB_SVC_SETPWRM_PWR_BUSY 0x03 -#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 -#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 - -struct gb_svc_l2_timer_cfg { - __le16 tsb_fc0_protection_timeout; - __le16 tsb_tc0_replay_timeout; - __le16 tsb_afc0_req_timeout; - __le16 tsb_fc1_protection_timeout; - __le16 tsb_tc1_replay_timeout; - __le16 tsb_afc1_req_timeout; - __le16 reserved_for_tc2[3]; - __le16 reserved_for_tc3[3]; -} __packed; - -struct gb_svc_intf_set_pwrm_request { - __u8 intf_id; - __u8 hs_series; - __u8 tx_mode; - __u8 tx_gear; - __u8 tx_nlanes; - __u8 tx_amplitude; - __u8 tx_hs_equalizer; - __u8 rx_mode; - __u8 rx_gear; - __u8 rx_nlanes; - __u8 flags; - __le32 quirks; - struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; -} __packed; - -struct gb_svc_intf_set_pwrm_response { - __u8 result_code; -} __packed; - -struct gb_svc_key_event_request { - __le16 key_code; -#define GB_KEYCODE_ARA 0x00 - - __u8 key_event; -#define GB_SVC_KEY_RELEASED 0x00 -#define GB_SVC_KEY_PRESSED 0x01 -} __packed; - -#define GB_SVC_PWRMON_MAX_RAIL_COUNT 254 - -struct gb_svc_pwrmon_rail_count_get_response { - __u8 rail_count; -} __packed; - -#define GB_SVC_PWRMON_RAIL_NAME_BUFSIZE 32 - -struct gb_svc_pwrmon_rail_names_get_response { - __u8 status; - __u8 name[0][GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; -} __packed; - -#define GB_SVC_PWRMON_TYPE_CURR 0x01 -#define GB_SVC_PWRMON_TYPE_VOL 0x02 -#define GB_SVC_PWRMON_TYPE_PWR 0x03 - -#define GB_SVC_PWRMON_GET_SAMPLE_OK 0x00 -#define GB_SVC_PWRMON_GET_SAMPLE_INVAL 0x01 -#define GB_SVC_PWRMON_GET_SAMPLE_NOSUPP 0x02 -#define GB_SVC_PWRMON_GET_SAMPLE_HWERR 0x03 - -struct gb_svc_pwrmon_sample_get_request { - __u8 rail_id; - __u8 measurement_type; -} __packed; - -struct gb_svc_pwrmon_sample_get_response { - __u8 result; - __le32 measurement; -} __packed; - -struct gb_svc_pwrmon_intf_sample_get_request { - __u8 intf_id; - __u8 measurement_type; -} __packed; - -struct gb_svc_pwrmon_intf_sample_get_response { - __u8 result; - __le32 measurement; -} __packed; - -#define GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY 0x0001 - -struct gb_svc_module_inserted_request { - __u8 primary_intf_id; - __u8 intf_count; - __le16 flags; -} __packed; -/* module_inserted response has no payload */ - -struct gb_svc_module_removed_request { - __u8 primary_intf_id; -} __packed; -/* module_removed response has no payload */ - -struct gb_svc_intf_activate_request { - __u8 intf_id; -} __packed; - -#define GB_SVC_INTF_TYPE_UNKNOWN 0x00 -#define GB_SVC_INTF_TYPE_DUMMY 0x01 -#define GB_SVC_INTF_TYPE_UNIPRO 0x02 -#define GB_SVC_INTF_TYPE_GREYBUS 0x03 - -struct gb_svc_intf_activate_response { - __u8 status; - __u8 intf_type; -} __packed; - -struct gb_svc_intf_resume_request { - __u8 intf_id; -} __packed; - -struct gb_svc_intf_resume_response { - __u8 status; -} __packed; - -#define GB_SVC_INTF_MAILBOX_NONE 0x00 -#define GB_SVC_INTF_MAILBOX_AP 0x01 -#define GB_SVC_INTF_MAILBOX_GREYBUS 0x02 - -struct gb_svc_intf_mailbox_event_request { - __u8 intf_id; - __le16 result_code; - __le32 mailbox; -} __packed; -/* intf_mailbox_event response has no payload */ - -struct gb_svc_intf_oops_request { - __u8 intf_id; - __u8 reason; -} __packed; -/* intf_oops response has no payload */ - - -/* RAW */ - -/* Greybus raw request types */ -#define GB_RAW_TYPE_SEND 0x02 - -struct gb_raw_send_request { - __le32 len; - __u8 data[0]; -} __packed; - - -/* UART */ - -/* Greybus UART operation types */ -#define GB_UART_TYPE_SEND_DATA 0x02 -#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ -#define GB_UART_TYPE_SET_LINE_CODING 0x04 -#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 -#define GB_UART_TYPE_SEND_BREAK 0x06 -#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ -#define GB_UART_TYPE_RECEIVE_CREDITS 0x08 -#define GB_UART_TYPE_FLUSH_FIFOS 0x09 - -/* Represents data from AP -> Module */ -struct gb_uart_send_data_request { - __le16 size; - __u8 data[0]; -} __packed; - -/* recv-data-request flags */ -#define GB_UART_RECV_FLAG_FRAMING 0x01 /* Framing error */ -#define GB_UART_RECV_FLAG_PARITY 0x02 /* Parity error */ -#define GB_UART_RECV_FLAG_OVERRUN 0x04 /* Overrun error */ -#define GB_UART_RECV_FLAG_BREAK 0x08 /* Break */ - -/* Represents data from Module -> AP */ -struct gb_uart_recv_data_request { - __le16 size; - __u8 flags; - __u8 data[0]; -} __packed; - -struct gb_uart_receive_credits_request { - __le16 count; -} __packed; - -struct gb_uart_set_line_coding_request { - __le32 rate; - __u8 format; -#define GB_SERIAL_1_STOP_BITS 0 -#define GB_SERIAL_1_5_STOP_BITS 1 -#define GB_SERIAL_2_STOP_BITS 2 - - __u8 parity; -#define GB_SERIAL_NO_PARITY 0 -#define GB_SERIAL_ODD_PARITY 1 -#define GB_SERIAL_EVEN_PARITY 2 -#define GB_SERIAL_MARK_PARITY 3 -#define GB_SERIAL_SPACE_PARITY 4 - - __u8 data_bits; - - __u8 flow_control; -#define GB_SERIAL_AUTO_RTSCTS_EN 0x1 -} __packed; - -/* output control lines */ -#define GB_UART_CTRL_DTR 0x01 -#define GB_UART_CTRL_RTS 0x02 - -struct gb_uart_set_control_line_state_request { - __u8 control; -} __packed; - -struct gb_uart_set_break_request { - __u8 state; -} __packed; - -/* input control lines and line errors */ -#define GB_UART_CTRL_DCD 0x01 -#define GB_UART_CTRL_DSR 0x02 -#define GB_UART_CTRL_RI 0x04 - -struct gb_uart_serial_state_request { - __u8 control; -} __packed; - -struct gb_uart_serial_flush_request { - __u8 flags; -#define GB_SERIAL_FLAG_FLUSH_TRANSMITTER 0x01 -#define GB_SERIAL_FLAG_FLUSH_RECEIVER 0x02 -} __packed; - -/* Loopback */ - -/* Greybus loopback request types */ -#define GB_LOOPBACK_TYPE_PING 0x02 -#define GB_LOOPBACK_TYPE_TRANSFER 0x03 -#define GB_LOOPBACK_TYPE_SINK 0x04 - -/* - * Loopback request/response header format should be identical - * to simplify bandwidth and data movement analysis. - */ -struct gb_loopback_transfer_request { - __le32 len; - __le32 reserved0; - __le32 reserved1; - __u8 data[0]; -} __packed; - -struct gb_loopback_transfer_response { - __le32 len; - __le32 reserved0; - __le32 reserved1; - __u8 data[0]; -} __packed; - -/* SDIO */ -/* Greybus SDIO operation types */ -#define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 -#define GB_SDIO_TYPE_SET_IOS 0x03 -#define GB_SDIO_TYPE_COMMAND 0x04 -#define GB_SDIO_TYPE_TRANSFER 0x05 -#define GB_SDIO_TYPE_EVENT 0x06 - -/* get caps response: request has no payload */ -struct gb_sdio_get_caps_response { - __le32 caps; -#define GB_SDIO_CAP_NONREMOVABLE 0x00000001 -#define GB_SDIO_CAP_4_BIT_DATA 0x00000002 -#define GB_SDIO_CAP_8_BIT_DATA 0x00000004 -#define GB_SDIO_CAP_MMC_HS 0x00000008 -#define GB_SDIO_CAP_SD_HS 0x00000010 -#define GB_SDIO_CAP_ERASE 0x00000020 -#define GB_SDIO_CAP_1_2V_DDR 0x00000040 -#define GB_SDIO_CAP_1_8V_DDR 0x00000080 -#define GB_SDIO_CAP_POWER_OFF_CARD 0x00000100 -#define GB_SDIO_CAP_UHS_SDR12 0x00000200 -#define GB_SDIO_CAP_UHS_SDR25 0x00000400 -#define GB_SDIO_CAP_UHS_SDR50 0x00000800 -#define GB_SDIO_CAP_UHS_SDR104 0x00001000 -#define GB_SDIO_CAP_UHS_DDR50 0x00002000 -#define GB_SDIO_CAP_DRIVER_TYPE_A 0x00004000 -#define GB_SDIO_CAP_DRIVER_TYPE_C 0x00008000 -#define GB_SDIO_CAP_DRIVER_TYPE_D 0x00010000 -#define GB_SDIO_CAP_HS200_1_2V 0x00020000 -#define GB_SDIO_CAP_HS200_1_8V 0x00040000 -#define GB_SDIO_CAP_HS400_1_2V 0x00080000 -#define GB_SDIO_CAP_HS400_1_8V 0x00100000 - - /* see possible values below at vdd */ - __le32 ocr; - __le32 f_min; - __le32 f_max; - __le16 max_blk_count; - __le16 max_blk_size; -} __packed; - -/* set ios request: response has no payload */ -struct gb_sdio_set_ios_request { - __le32 clock; - __le32 vdd; -#define GB_SDIO_VDD_165_195 0x00000001 -#define GB_SDIO_VDD_20_21 0x00000002 -#define GB_SDIO_VDD_21_22 0x00000004 -#define GB_SDIO_VDD_22_23 0x00000008 -#define GB_SDIO_VDD_23_24 0x00000010 -#define GB_SDIO_VDD_24_25 0x00000020 -#define GB_SDIO_VDD_25_26 0x00000040 -#define GB_SDIO_VDD_26_27 0x00000080 -#define GB_SDIO_VDD_27_28 0x00000100 -#define GB_SDIO_VDD_28_29 0x00000200 -#define GB_SDIO_VDD_29_30 0x00000400 -#define GB_SDIO_VDD_30_31 0x00000800 -#define GB_SDIO_VDD_31_32 0x00001000 -#define GB_SDIO_VDD_32_33 0x00002000 -#define GB_SDIO_VDD_33_34 0x00004000 -#define GB_SDIO_VDD_34_35 0x00008000 -#define GB_SDIO_VDD_35_36 0x00010000 - - __u8 bus_mode; -#define GB_SDIO_BUSMODE_OPENDRAIN 0x00 -#define GB_SDIO_BUSMODE_PUSHPULL 0x01 - - __u8 power_mode; -#define GB_SDIO_POWER_OFF 0x00 -#define GB_SDIO_POWER_UP 0x01 -#define GB_SDIO_POWER_ON 0x02 -#define GB_SDIO_POWER_UNDEFINED 0x03 - - __u8 bus_width; -#define GB_SDIO_BUS_WIDTH_1 0x00 -#define GB_SDIO_BUS_WIDTH_4 0x02 -#define GB_SDIO_BUS_WIDTH_8 0x03 - - __u8 timing; -#define GB_SDIO_TIMING_LEGACY 0x00 -#define GB_SDIO_TIMING_MMC_HS 0x01 -#define GB_SDIO_TIMING_SD_HS 0x02 -#define GB_SDIO_TIMING_UHS_SDR12 0x03 -#define GB_SDIO_TIMING_UHS_SDR25 0x04 -#define GB_SDIO_TIMING_UHS_SDR50 0x05 -#define GB_SDIO_TIMING_UHS_SDR104 0x06 -#define GB_SDIO_TIMING_UHS_DDR50 0x07 -#define GB_SDIO_TIMING_MMC_DDR52 0x08 -#define GB_SDIO_TIMING_MMC_HS200 0x09 -#define GB_SDIO_TIMING_MMC_HS400 0x0A - - __u8 signal_voltage; -#define GB_SDIO_SIGNAL_VOLTAGE_330 0x00 -#define GB_SDIO_SIGNAL_VOLTAGE_180 0x01 -#define GB_SDIO_SIGNAL_VOLTAGE_120 0x02 - - __u8 drv_type; -#define GB_SDIO_SET_DRIVER_TYPE_B 0x00 -#define GB_SDIO_SET_DRIVER_TYPE_A 0x01 -#define GB_SDIO_SET_DRIVER_TYPE_C 0x02 -#define GB_SDIO_SET_DRIVER_TYPE_D 0x03 -} __packed; - -/* command request */ -struct gb_sdio_command_request { - __u8 cmd; - __u8 cmd_flags; -#define GB_SDIO_RSP_NONE 0x00 -#define GB_SDIO_RSP_PRESENT 0x01 -#define GB_SDIO_RSP_136 0x02 -#define GB_SDIO_RSP_CRC 0x04 -#define GB_SDIO_RSP_BUSY 0x08 -#define GB_SDIO_RSP_OPCODE 0x10 - - __u8 cmd_type; -#define GB_SDIO_CMD_AC 0x00 -#define GB_SDIO_CMD_ADTC 0x01 -#define GB_SDIO_CMD_BC 0x02 -#define GB_SDIO_CMD_BCR 0x03 - - __le32 cmd_arg; - __le16 data_blocks; - __le16 data_blksz; -} __packed; - -struct gb_sdio_command_response { - __le32 resp[4]; -} __packed; - -/* transfer request */ -struct gb_sdio_transfer_request { - __u8 data_flags; -#define GB_SDIO_DATA_WRITE 0x01 -#define GB_SDIO_DATA_READ 0x02 -#define GB_SDIO_DATA_STREAM 0x04 - - __le16 data_blocks; - __le16 data_blksz; - __u8 data[0]; -} __packed; - -struct gb_sdio_transfer_response { - __le16 data_blocks; - __le16 data_blksz; - __u8 data[0]; -} __packed; - -/* event request: generated by module and is defined as unidirectional */ -struct gb_sdio_event_request { - __u8 event; -#define GB_SDIO_CARD_INSERTED 0x01 -#define GB_SDIO_CARD_REMOVED 0x02 -#define GB_SDIO_WP 0x04 -} __packed; - -/* Camera */ - -/* Greybus Camera request types */ -#define GB_CAMERA_TYPE_CAPABILITIES 0x02 -#define GB_CAMERA_TYPE_CONFIGURE_STREAMS 0x03 -#define GB_CAMERA_TYPE_CAPTURE 0x04 -#define GB_CAMERA_TYPE_FLUSH 0x05 -#define GB_CAMERA_TYPE_METADATA 0x06 - -#define GB_CAMERA_MAX_STREAMS 4 -#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 - -/* Greybus Camera Configure Streams request payload */ -struct gb_camera_stream_config_request { - __le16 width; - __le16 height; - __le16 format; - __le16 padding; -} __packed; - -struct gb_camera_configure_streams_request { - __u8 num_streams; - __u8 flags; -#define GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY 0x01 - __le16 padding; - struct gb_camera_stream_config_request config[0]; -} __packed; - -/* Greybus Camera Configure Streams response payload */ -struct gb_camera_stream_config_response { - __le16 width; - __le16 height; - __le16 format; - __u8 virtual_channel; - __u8 data_type[2]; - __le16 max_pkt_size; - __u8 padding; - __le32 max_size; -} __packed; - -struct gb_camera_configure_streams_response { - __u8 num_streams; -#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 - __u8 flags; - __u8 padding[2]; - __le32 data_rate; - struct gb_camera_stream_config_response config[0]; -}; - -/* Greybus Camera Capture request payload - response has no payload */ -struct gb_camera_capture_request { - __le32 request_id; - __u8 streams; - __u8 padding; - __le16 num_frames; - __u8 settings[0]; -} __packed; - -/* Greybus Camera Flush response payload - request has no payload */ -struct gb_camera_flush_response { - __le32 request_id; -} __packed; - -/* Greybus Camera Metadata request payload - operation has no response */ -struct gb_camera_metadata_request { - __le32 request_id; - __le16 frame_number; - __u8 stream; - __u8 padding; - __u8 metadata[0]; -} __packed; - -/* Lights */ - -/* Greybus Lights request types */ -#define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 -#define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 -#define GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG 0x04 -#define GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG 0x05 -#define GB_LIGHTS_TYPE_SET_BRIGHTNESS 0x06 -#define GB_LIGHTS_TYPE_SET_BLINK 0x07 -#define GB_LIGHTS_TYPE_SET_COLOR 0x08 -#define GB_LIGHTS_TYPE_SET_FADE 0x09 -#define GB_LIGHTS_TYPE_EVENT 0x0A -#define GB_LIGHTS_TYPE_SET_FLASH_INTENSITY 0x0B -#define GB_LIGHTS_TYPE_SET_FLASH_STROBE 0x0C -#define GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT 0x0D -#define GB_LIGHTS_TYPE_GET_FLASH_FAULT 0x0E - -/* Greybus Light modes */ - -/* - * if you add any specific mode below, update also the - * GB_CHANNEL_MODE_DEFINED_RANGE value accordingly - */ -#define GB_CHANNEL_MODE_NONE 0x00000000 -#define GB_CHANNEL_MODE_BATTERY 0x00000001 -#define GB_CHANNEL_MODE_POWER 0x00000002 -#define GB_CHANNEL_MODE_WIRELESS 0x00000004 -#define GB_CHANNEL_MODE_BLUETOOTH 0x00000008 -#define GB_CHANNEL_MODE_KEYBOARD 0x00000010 -#define GB_CHANNEL_MODE_BUTTONS 0x00000020 -#define GB_CHANNEL_MODE_NOTIFICATION 0x00000040 -#define GB_CHANNEL_MODE_ATTENTION 0x00000080 -#define GB_CHANNEL_MODE_FLASH 0x00000100 -#define GB_CHANNEL_MODE_TORCH 0x00000200 -#define GB_CHANNEL_MODE_INDICATOR 0x00000400 - -/* Lights Mode valid bit values */ -#define GB_CHANNEL_MODE_DEFINED_RANGE 0x000004FF -#define GB_CHANNEL_MODE_VENDOR_RANGE 0x00F00000 - -/* Greybus Light Channels Flags */ -#define GB_LIGHT_CHANNEL_MULTICOLOR 0x00000001 -#define GB_LIGHT_CHANNEL_FADER 0x00000002 -#define GB_LIGHT_CHANNEL_BLINK 0x00000004 - -/* get count of lights in module */ -struct gb_lights_get_lights_response { - __u8 lights_count; -} __packed; - -/* light config request payload */ -struct gb_lights_get_light_config_request { - __u8 id; -} __packed; - -/* light config response payload */ -struct gb_lights_get_light_config_response { - __u8 channel_count; - __u8 name[32]; -} __packed; - -/* channel config request payload */ -struct gb_lights_get_channel_config_request { - __u8 light_id; - __u8 channel_id; -} __packed; - -/* channel flash config request payload */ -struct gb_lights_get_channel_flash_config_request { - __u8 light_id; - __u8 channel_id; -} __packed; - -/* channel config response payload */ -struct gb_lights_get_channel_config_response { - __u8 max_brightness; - __le32 flags; - __le32 color; - __u8 color_name[32]; - __le32 mode; - __u8 mode_name[32]; -} __packed; - -/* channel flash config response payload */ -struct gb_lights_get_channel_flash_config_response { - __le32 intensity_min_uA; - __le32 intensity_max_uA; - __le32 intensity_step_uA; - __le32 timeout_min_us; - __le32 timeout_max_us; - __le32 timeout_step_us; -} __packed; - -/* blink request payload: response have no payload */ -struct gb_lights_blink_request { - __u8 light_id; - __u8 channel_id; - __le16 time_on_ms; - __le16 time_off_ms; -} __packed; - -/* set brightness request payload: response have no payload */ -struct gb_lights_set_brightness_request { - __u8 light_id; - __u8 channel_id; - __u8 brightness; -} __packed; - -/* set color request payload: response have no payload */ -struct gb_lights_set_color_request { - __u8 light_id; - __u8 channel_id; - __le32 color; -} __packed; - -/* set fade request payload: response have no payload */ -struct gb_lights_set_fade_request { - __u8 light_id; - __u8 channel_id; - __u8 fade_in; - __u8 fade_out; -} __packed; - -/* event request: generated by module */ -struct gb_lights_event_request { - __u8 light_id; - __u8 event; -#define GB_LIGHTS_LIGHT_CONFIG 0x01 -} __packed; - -/* set flash intensity request payload: response have no payload */ -struct gb_lights_set_flash_intensity_request { - __u8 light_id; - __u8 channel_id; - __le32 intensity_uA; -} __packed; - -/* set flash strobe state request payload: response have no payload */ -struct gb_lights_set_flash_strobe_request { - __u8 light_id; - __u8 channel_id; - __u8 state; -} __packed; - -/* set flash timeout request payload: response have no payload */ -struct gb_lights_set_flash_timeout_request { - __u8 light_id; - __u8 channel_id; - __le32 timeout_us; -} __packed; - -/* get flash fault request payload */ -struct gb_lights_get_flash_fault_request { - __u8 light_id; - __u8 channel_id; -} __packed; - -/* get flash fault response payload */ -struct gb_lights_get_flash_fault_response { - __le32 fault; -#define GB_LIGHTS_FLASH_FAULT_OVER_VOLTAGE 0x00000000 -#define GB_LIGHTS_FLASH_FAULT_TIMEOUT 0x00000001 -#define GB_LIGHTS_FLASH_FAULT_OVER_TEMPERATURE 0x00000002 -#define GB_LIGHTS_FLASH_FAULT_SHORT_CIRCUIT 0x00000004 -#define GB_LIGHTS_FLASH_FAULT_OVER_CURRENT 0x00000008 -#define GB_LIGHTS_FLASH_FAULT_INDICATOR 0x00000010 -#define GB_LIGHTS_FLASH_FAULT_UNDER_VOLTAGE 0x00000020 -#define GB_LIGHTS_FLASH_FAULT_INPUT_VOLTAGE 0x00000040 -#define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 -} __packed; - -/* Audio */ - -#define GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE 0x02 -#define GB_AUDIO_TYPE_GET_TOPOLOGY 0x03 -#define GB_AUDIO_TYPE_GET_CONTROL 0x04 -#define GB_AUDIO_TYPE_SET_CONTROL 0x05 -#define GB_AUDIO_TYPE_ENABLE_WIDGET 0x06 -#define GB_AUDIO_TYPE_DISABLE_WIDGET 0x07 -#define GB_AUDIO_TYPE_GET_PCM 0x08 -#define GB_AUDIO_TYPE_SET_PCM 0x09 -#define GB_AUDIO_TYPE_SET_TX_DATA_SIZE 0x0a - /* 0x0b unused */ -#define GB_AUDIO_TYPE_ACTIVATE_TX 0x0c -#define GB_AUDIO_TYPE_DEACTIVATE_TX 0x0d -#define GB_AUDIO_TYPE_SET_RX_DATA_SIZE 0x0e - /* 0x0f unused */ -#define GB_AUDIO_TYPE_ACTIVATE_RX 0x10 -#define GB_AUDIO_TYPE_DEACTIVATE_RX 0x11 -#define GB_AUDIO_TYPE_JACK_EVENT 0x12 -#define GB_AUDIO_TYPE_BUTTON_EVENT 0x13 -#define GB_AUDIO_TYPE_STREAMING_EVENT 0x14 -#define GB_AUDIO_TYPE_SEND_DATA 0x15 - -/* Module must be able to buffer 10ms of audio data, minimum */ -#define GB_AUDIO_SAMPLE_BUFFER_MIN_US 10000 - -#define GB_AUDIO_PCM_NAME_MAX 32 -#define AUDIO_DAI_NAME_MAX 32 -#define AUDIO_CONTROL_NAME_MAX 32 -#define AUDIO_CTL_ELEM_NAME_MAX 44 -#define AUDIO_ENUM_NAME_MAX 64 -#define AUDIO_WIDGET_NAME_MAX 32 - -/* See SNDRV_PCM_FMTBIT_* in Linux source */ -#define GB_AUDIO_PCM_FMT_S8 BIT(0) -#define GB_AUDIO_PCM_FMT_U8 BIT(1) -#define GB_AUDIO_PCM_FMT_S16_LE BIT(2) -#define GB_AUDIO_PCM_FMT_S16_BE BIT(3) -#define GB_AUDIO_PCM_FMT_U16_LE BIT(4) -#define GB_AUDIO_PCM_FMT_U16_BE BIT(5) -#define GB_AUDIO_PCM_FMT_S24_LE BIT(6) -#define GB_AUDIO_PCM_FMT_S24_BE BIT(7) -#define GB_AUDIO_PCM_FMT_U24_LE BIT(8) -#define GB_AUDIO_PCM_FMT_U24_BE BIT(9) -#define GB_AUDIO_PCM_FMT_S32_LE BIT(10) -#define GB_AUDIO_PCM_FMT_S32_BE BIT(11) -#define GB_AUDIO_PCM_FMT_U32_LE BIT(12) -#define GB_AUDIO_PCM_FMT_U32_BE BIT(13) - -/* See SNDRV_PCM_RATE_* in Linux source */ -#define GB_AUDIO_PCM_RATE_5512 BIT(0) -#define GB_AUDIO_PCM_RATE_8000 BIT(1) -#define GB_AUDIO_PCM_RATE_11025 BIT(2) -#define GB_AUDIO_PCM_RATE_16000 BIT(3) -#define GB_AUDIO_PCM_RATE_22050 BIT(4) -#define GB_AUDIO_PCM_RATE_32000 BIT(5) -#define GB_AUDIO_PCM_RATE_44100 BIT(6) -#define GB_AUDIO_PCM_RATE_48000 BIT(7) -#define GB_AUDIO_PCM_RATE_64000 BIT(8) -#define GB_AUDIO_PCM_RATE_88200 BIT(9) -#define GB_AUDIO_PCM_RATE_96000 BIT(10) -#define GB_AUDIO_PCM_RATE_176400 BIT(11) -#define GB_AUDIO_PCM_RATE_192000 BIT(12) - -#define GB_AUDIO_STREAM_TYPE_CAPTURE 0x1 -#define GB_AUDIO_STREAM_TYPE_PLAYBACK 0x2 - -#define GB_AUDIO_CTL_ELEM_ACCESS_READ BIT(0) -#define GB_AUDIO_CTL_ELEM_ACCESS_WRITE BIT(1) - -/* See SNDRV_CTL_ELEM_TYPE_* in Linux source */ -#define GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN 0x01 -#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER 0x02 -#define GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED 0x03 -#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER64 0x06 - -/* See SNDRV_CTL_ELEM_IFACE_* in Linux source */ -#define GB_AUDIO_CTL_ELEM_IFACE_CARD 0x00 -#define GB_AUDIO_CTL_ELEM_IFACE_HWDEP 0x01 -#define GB_AUDIO_CTL_ELEM_IFACE_MIXER 0x02 -#define GB_AUDIO_CTL_ELEM_IFACE_PCM 0x03 -#define GB_AUDIO_CTL_ELEM_IFACE_RAWMIDI 0x04 -#define GB_AUDIO_CTL_ELEM_IFACE_TIMER 0x05 -#define GB_AUDIO_CTL_ELEM_IFACE_SEQUENCER 0x06 - -/* SNDRV_CTL_ELEM_ACCESS_* in Linux source */ -#define GB_AUDIO_ACCESS_READ BIT(0) -#define GB_AUDIO_ACCESS_WRITE BIT(1) -#define GB_AUDIO_ACCESS_VOLATILE BIT(2) -#define GB_AUDIO_ACCESS_TIMESTAMP BIT(3) -#define GB_AUDIO_ACCESS_TLV_READ BIT(4) -#define GB_AUDIO_ACCESS_TLV_WRITE BIT(5) -#define GB_AUDIO_ACCESS_TLV_COMMAND BIT(6) -#define GB_AUDIO_ACCESS_INACTIVE BIT(7) -#define GB_AUDIO_ACCESS_LOCK BIT(8) -#define GB_AUDIO_ACCESS_OWNER BIT(9) - -/* enum snd_soc_dapm_type */ -#define GB_AUDIO_WIDGET_TYPE_INPUT 0x0 -#define GB_AUDIO_WIDGET_TYPE_OUTPUT 0x1 -#define GB_AUDIO_WIDGET_TYPE_MUX 0x2 -#define GB_AUDIO_WIDGET_TYPE_VIRT_MUX 0x3 -#define GB_AUDIO_WIDGET_TYPE_VALUE_MUX 0x4 -#define GB_AUDIO_WIDGET_TYPE_MIXER 0x5 -#define GB_AUDIO_WIDGET_TYPE_MIXER_NAMED_CTL 0x6 -#define GB_AUDIO_WIDGET_TYPE_PGA 0x7 -#define GB_AUDIO_WIDGET_TYPE_OUT_DRV 0x8 -#define GB_AUDIO_WIDGET_TYPE_ADC 0x9 -#define GB_AUDIO_WIDGET_TYPE_DAC 0xa -#define GB_AUDIO_WIDGET_TYPE_MICBIAS 0xb -#define GB_AUDIO_WIDGET_TYPE_MIC 0xc -#define GB_AUDIO_WIDGET_TYPE_HP 0xd -#define GB_AUDIO_WIDGET_TYPE_SPK 0xe -#define GB_AUDIO_WIDGET_TYPE_LINE 0xf -#define GB_AUDIO_WIDGET_TYPE_SWITCH 0x10 -#define GB_AUDIO_WIDGET_TYPE_VMID 0x11 -#define GB_AUDIO_WIDGET_TYPE_PRE 0x12 -#define GB_AUDIO_WIDGET_TYPE_POST 0x13 -#define GB_AUDIO_WIDGET_TYPE_SUPPLY 0x14 -#define GB_AUDIO_WIDGET_TYPE_REGULATOR_SUPPLY 0x15 -#define GB_AUDIO_WIDGET_TYPE_CLOCK_SUPPLY 0x16 -#define GB_AUDIO_WIDGET_TYPE_AIF_IN 0x17 -#define GB_AUDIO_WIDGET_TYPE_AIF_OUT 0x18 -#define GB_AUDIO_WIDGET_TYPE_SIGGEN 0x19 -#define GB_AUDIO_WIDGET_TYPE_DAI_IN 0x1a -#define GB_AUDIO_WIDGET_TYPE_DAI_OUT 0x1b -#define GB_AUDIO_WIDGET_TYPE_DAI_LINK 0x1c - -#define GB_AUDIO_WIDGET_STATE_DISABLED 0x01 -#define GB_AUDIO_WIDGET_STATE_ENAABLED 0x02 - -#define GB_AUDIO_JACK_EVENT_INSERTION 0x1 -#define GB_AUDIO_JACK_EVENT_REMOVAL 0x2 - -#define GB_AUDIO_BUTTON_EVENT_PRESS 0x1 -#define GB_AUDIO_BUTTON_EVENT_RELEASE 0x2 - -#define GB_AUDIO_STREAMING_EVENT_UNSPECIFIED 0x1 -#define GB_AUDIO_STREAMING_EVENT_HALT 0x2 -#define GB_AUDIO_STREAMING_EVENT_INTERNAL_ERROR 0x3 -#define GB_AUDIO_STREAMING_EVENT_PROTOCOL_ERROR 0x4 -#define GB_AUDIO_STREAMING_EVENT_FAILURE 0x5 -#define GB_AUDIO_STREAMING_EVENT_UNDERRUN 0x6 -#define GB_AUDIO_STREAMING_EVENT_OVERRUN 0x7 -#define GB_AUDIO_STREAMING_EVENT_CLOCKING 0x8 -#define GB_AUDIO_STREAMING_EVENT_DATA_LEN 0x9 - -#define GB_AUDIO_INVALID_INDEX 0xff - -/* enum snd_jack_types */ -#define GB_AUDIO_JACK_HEADPHONE 0x0000001 -#define GB_AUDIO_JACK_MICROPHONE 0x0000002 -#define GB_AUDIO_JACK_HEADSET (GB_AUDIO_JACK_HEADPHONE | \ - GB_AUDIO_JACK_MICROPHONE) -#define GB_AUDIO_JACK_LINEOUT 0x0000004 -#define GB_AUDIO_JACK_MECHANICAL 0x0000008 -#define GB_AUDIO_JACK_VIDEOOUT 0x0000010 -#define GB_AUDIO_JACK_AVOUT (GB_AUDIO_JACK_LINEOUT | \ - GB_AUDIO_JACK_VIDEOOUT) -#define GB_AUDIO_JACK_LINEIN 0x0000020 -#define GB_AUDIO_JACK_OC_HPHL 0x0000040 -#define GB_AUDIO_JACK_OC_HPHR 0x0000080 -#define GB_AUDIO_JACK_MICROPHONE2 0x0000200 -#define GB_AUDIO_JACK_ANC_HEADPHONE (GB_AUDIO_JACK_HEADPHONE | \ - GB_AUDIO_JACK_MICROPHONE | \ - GB_AUDIO_JACK_MICROPHONE2) -/* Kept separate from switches to facilitate implementation */ -#define GB_AUDIO_JACK_BTN_0 0x4000000 -#define GB_AUDIO_JACK_BTN_1 0x2000000 -#define GB_AUDIO_JACK_BTN_2 0x1000000 -#define GB_AUDIO_JACK_BTN_3 0x0800000 - -struct gb_audio_pcm { - __u8 stream_name[GB_AUDIO_PCM_NAME_MAX]; - __le32 formats; /* GB_AUDIO_PCM_FMT_* */ - __le32 rates; /* GB_AUDIO_PCM_RATE_* */ - __u8 chan_min; - __u8 chan_max; - __u8 sig_bits; /* number of bits of content */ -} __packed; - -struct gb_audio_dai { - __u8 name[AUDIO_DAI_NAME_MAX]; - __le16 data_cport; - struct gb_audio_pcm capture; - struct gb_audio_pcm playback; -} __packed; - -struct gb_audio_integer { - __le32 min; - __le32 max; - __le32 step; -} __packed; - -struct gb_audio_integer64 { - __le64 min; - __le64 max; - __le64 step; -} __packed; - -struct gb_audio_enumerated { - __le32 items; - __le16 names_length; - __u8 names[0]; -} __packed; - -struct gb_audio_ctl_elem_info { /* See snd_ctl_elem_info in Linux source */ - __u8 type; /* GB_AUDIO_CTL_ELEM_TYPE_* */ - __le16 dimen[4]; - union { - struct gb_audio_integer integer; - struct gb_audio_integer64 integer64; - struct gb_audio_enumerated enumerated; - } value; -} __packed; - -struct gb_audio_ctl_elem_value { /* See snd_ctl_elem_value in Linux source */ - __le64 timestamp; /* XXX needed? */ - union { - __le32 integer_value[2]; /* consider CTL_DOUBLE_xxx */ - __le64 integer64_value[2]; - __le32 enumerated_item[2]; - } value; -} __packed; - -struct gb_audio_control { - __u8 name[AUDIO_CONTROL_NAME_MAX]; - __u8 id; /* 0-63 */ - __u8 iface; /* GB_AUDIO_IFACE_* */ - __le16 data_cport; - __le32 access; /* GB_AUDIO_ACCESS_* */ - __u8 count; /* count of same elements */ - __u8 count_values; /* count of values, max=2 for CTL_DOUBLE_xxx */ - struct gb_audio_ctl_elem_info info; -} __packed; - -struct gb_audio_widget { - __u8 name[AUDIO_WIDGET_NAME_MAX]; - __u8 sname[AUDIO_WIDGET_NAME_MAX]; - __u8 id; - __u8 type; /* GB_AUDIO_WIDGET_TYPE_* */ - __u8 state; /* GB_AUDIO_WIDGET_STATE_* */ - __u8 ncontrols; - struct gb_audio_control ctl[0]; /* 'ncontrols' entries */ -} __packed; - -struct gb_audio_route { - __u8 source_id; /* widget id */ - __u8 destination_id; /* widget id */ - __u8 control_id; /* 0-63 */ - __u8 index; /* Selection within the control */ -} __packed; - -struct gb_audio_topology { - __u8 num_dais; - __u8 num_controls; - __u8 num_widgets; - __u8 num_routes; - __le32 size_dais; - __le32 size_controls; - __le32 size_widgets; - __le32 size_routes; - __le32 jack_type; - /* - * struct gb_audio_dai dai[num_dais]; - * struct gb_audio_control controls[num_controls]; - * struct gb_audio_widget widgets[num_widgets]; - * struct gb_audio_route routes[num_routes]; - */ - __u8 data[0]; -} __packed; - -struct gb_audio_get_topology_size_response { - __le16 size; -} __packed; - -struct gb_audio_get_topology_response { - struct gb_audio_topology topology; -} __packed; - -struct gb_audio_get_control_request { - __u8 control_id; - __u8 index; -} __packed; - -struct gb_audio_get_control_response { - struct gb_audio_ctl_elem_value value; -} __packed; - -struct gb_audio_set_control_request { - __u8 control_id; - __u8 index; - struct gb_audio_ctl_elem_value value; -} __packed; - -struct gb_audio_enable_widget_request { - __u8 widget_id; -} __packed; - -struct gb_audio_disable_widget_request { - __u8 widget_id; -} __packed; - -struct gb_audio_get_pcm_request { - __le16 data_cport; -} __packed; - -struct gb_audio_get_pcm_response { - __le32 format; - __le32 rate; - __u8 channels; - __u8 sig_bits; -} __packed; - -struct gb_audio_set_pcm_request { - __le16 data_cport; - __le32 format; - __le32 rate; - __u8 channels; - __u8 sig_bits; -} __packed; - -struct gb_audio_set_tx_data_size_request { - __le16 data_cport; - __le16 size; -} __packed; - -struct gb_audio_activate_tx_request { - __le16 data_cport; -} __packed; - -struct gb_audio_deactivate_tx_request { - __le16 data_cport; -} __packed; - -struct gb_audio_set_rx_data_size_request { - __le16 data_cport; - __le16 size; -} __packed; - -struct gb_audio_activate_rx_request { - __le16 data_cport; -} __packed; - -struct gb_audio_deactivate_rx_request { - __le16 data_cport; -} __packed; - -struct gb_audio_jack_event_request { - __u8 widget_id; - __u8 jack_attribute; - __u8 event; -} __packed; - -struct gb_audio_button_event_request { - __u8 widget_id; - __u8 button_id; - __u8 event; -} __packed; - -struct gb_audio_streaming_event_request { - __le16 data_cport; - __u8 event; -} __packed; - -struct gb_audio_send_data_request { - __le64 timestamp; - __u8 data[0]; -} __packed; - - -/* Log */ - -/* operations */ -#define GB_LOG_TYPE_SEND_LOG 0x02 - -/* length */ -#define GB_LOG_MAX_LEN 1024 - -struct gb_log_send_log_request { - __le16 len; - __u8 msg[0]; -} __packed; - -#endif /* __GREYBUS_PROTOCOLS_H */ - diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index e2b9ab5f6ec2..72b21bf2d7d3 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -8,8 +8,8 @@ #include #include +#include -#include "greybus.h" #include "greybus_trace.h" EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h deleted file mode 100644 index 348b76fabc9a..000000000000 --- a/drivers/staging/greybus/hd.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus Host Device - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#ifndef __HD_H -#define __HD_H - -struct gb_host_device; -struct gb_message; - -struct gb_hd_driver { - size_t hd_priv_size; - - int (*cport_allocate)(struct gb_host_device *hd, int cport_id, - unsigned long flags); - void (*cport_release)(struct gb_host_device *hd, u16 cport_id); - int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, - unsigned long flags); - int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); - int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); - int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); - int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, - u8 phase, unsigned int timeout); - int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, - size_t peer_space, unsigned int timeout); - int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); - - int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, - struct gb_message *message, gfp_t gfp_mask); - void (*message_cancel)(struct gb_message *message); - int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); - int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); - int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, - bool async); -}; - -struct gb_host_device { - struct device dev; - int bus_id; - const struct gb_hd_driver *driver; - - struct list_head modules; - struct list_head connections; - struct ida cport_id_map; - - /* Number of CPorts supported by the UniPro IP */ - size_t num_cports; - - /* Host device buffer constraints */ - size_t buffer_size_max; - - struct gb_svc *svc; - /* Private data for the host driver */ - unsigned long hd_priv[0] __aligned(sizeof(s64)); -}; -#define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) - -int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); -void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id); -int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, - unsigned long flags); -void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); - -struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports); -int gb_hd_add(struct gb_host_device *hd); -void gb_hd_del(struct gb_host_device *hd); -void gb_hd_shutdown(struct gb_host_device *hd); -void gb_hd_put(struct gb_host_device *hd); -int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, - bool in_irq); - -int gb_hd_init(void); -void gb_hd_exit(void); - -#endif /* __HD_H */ diff --git a/drivers/staging/greybus/hid.c b/drivers/staging/greybus/hid.c index 8ab810bf5716..04bfd9110502 100644 --- a/drivers/staging/greybus/hid.c +++ b/drivers/staging/greybus/hid.c @@ -12,8 +12,7 @@ #include #include #include - -#include "greybus.h" +#include /* Greybus HID device's structure */ struct gb_hid { diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index b2522043a1a4..ab06fc3b9e7e 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -10,8 +10,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" struct gb_i2c_device { diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index d7b5b89a2f40..67dbe6fda9a1 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -7,8 +7,8 @@ */ #include +#include -#include "greybus.h" #include "greybus_trace.h" #define GB_INTERFACE_MODE_SWITCH_TIMEOUT 2000 diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h deleted file mode 100644 index 8fb1eacda302..000000000000 --- a/drivers/staging/greybus/interface.h +++ /dev/null @@ -1,82 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus Interface Block code - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#ifndef __INTERFACE_H -#define __INTERFACE_H - -enum gb_interface_type { - GB_INTERFACE_TYPE_INVALID = 0, - GB_INTERFACE_TYPE_UNKNOWN, - GB_INTERFACE_TYPE_DUMMY, - GB_INTERFACE_TYPE_UNIPRO, - GB_INTERFACE_TYPE_GREYBUS, -}; - -#define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) -#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) -#define GB_INTERFACE_QUIRK_NO_GMP_IDS BIT(2) -#define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) -#define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) -#define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) -#define GB_INTERFACE_QUIRK_NO_PM BIT(6) - -struct gb_interface { - struct device dev; - struct gb_control *control; - - struct list_head bundles; - struct list_head module_node; - struct list_head manifest_descs; - u8 interface_id; /* Physical location within the Endo */ - u8 device_id; - u8 features; /* Feature flags set in the manifest */ - - enum gb_interface_type type; - - u32 ddbl1_manufacturer_id; - u32 ddbl1_product_id; - u32 vendor_id; - u32 product_id; - u64 serial_number; - - struct gb_host_device *hd; - struct gb_module *module; - - unsigned long quirks; - - struct mutex mutex; - - bool disconnected; - - bool ejected; - bool removed; - bool active; - bool enabled; - bool mode_switch; - bool dme_read; - - struct work_struct mode_switch_work; - struct completion mode_switch_completion; -}; -#define to_gb_interface(d) container_of(d, struct gb_interface, dev) - -struct gb_interface *gb_interface_create(struct gb_module *module, - u8 interface_id); -int gb_interface_activate(struct gb_interface *intf); -void gb_interface_deactivate(struct gb_interface *intf); -int gb_interface_enable(struct gb_interface *intf); -void gb_interface_disable(struct gb_interface *intf); -int gb_interface_add(struct gb_interface *intf); -void gb_interface_del(struct gb_interface *intf); -void gb_interface_put(struct gb_interface *intf); -void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, - u32 mailbox); - -int gb_interface_request_mode_switch(struct gb_interface *intf); - -#endif /* __INTERFACE_H */ diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 010ae1e9c7fb..b3b1b253d112 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -11,11 +11,9 @@ #include #include #include +#include #include -#include "greybus.h" -#include "greybus_protocols.h" - #define NAMES_MAX 32 struct gb_channel { diff --git a/drivers/staging/greybus/log.c b/drivers/staging/greybus/log.c index 4f1f161ff11c..971f36dccac6 100644 --- a/drivers/staging/greybus/log.c +++ b/drivers/staging/greybus/log.c @@ -9,8 +9,7 @@ #include #include #include - -#include "greybus.h" +#include struct gb_log { struct gb_connection *connection; diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index b0ab0eed5c18..583d9708a191 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -25,12 +25,9 @@ #include #include #include - +#include #include -#include "greybus.h" -#include "connection.h" - #define NSEC_PER_DAY 86400000000000ULL struct gb_loopback_stats { diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c index 4ebbba52b07c..dd7040697bde 100644 --- a/drivers/staging/greybus/manifest.c +++ b/drivers/staging/greybus/manifest.c @@ -6,7 +6,7 @@ * Copyright 2014-2015 Linaro Ltd. */ -#include "greybus.h" +#include static const char *get_descriptor_type_string(u8 type) { diff --git a/drivers/staging/greybus/manifest.h b/drivers/staging/greybus/manifest.h deleted file mode 100644 index 88aa7e44cad5..000000000000 --- a/drivers/staging/greybus/manifest.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus manifest parsing - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#ifndef __MANIFEST_H -#define __MANIFEST_H - -struct gb_interface; -bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); - -#endif /* __MANIFEST_H */ diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c index b251a53d0e8e..36f77f9e1d74 100644 --- a/drivers/staging/greybus/module.c +++ b/drivers/staging/greybus/module.c @@ -6,7 +6,7 @@ * Copyright 2016 Linaro Ltd. */ -#include "greybus.h" +#include #include "greybus_trace.h" static ssize_t eject_store(struct device *dev, diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h deleted file mode 100644 index 2a27e520ee94..000000000000 --- a/drivers/staging/greybus/module.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus Module code - * - * Copyright 2016 Google Inc. - * Copyright 2016 Linaro Ltd. - */ - -#ifndef __MODULE_H -#define __MODULE_H - -struct gb_module { - struct device dev; - struct gb_host_device *hd; - - struct list_head hd_node; - - u8 module_id; - size_t num_interfaces; - - bool disconnected; - - struct gb_interface *interfaces[0]; -}; -#define to_gb_module(d) container_of(d, struct gb_module, dev) - -struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, - size_t num_interfaces); -int gb_module_add(struct gb_module *module); -void gb_module_del(struct gb_module *module); -void gb_module_put(struct gb_module *module); - -#endif /* __MODULE_H */ diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c index fe268f7b63ed..8459e9bc0749 100644 --- a/drivers/staging/greybus/operation.c +++ b/drivers/staging/greybus/operation.c @@ -12,8 +12,8 @@ #include #include #include +#include -#include "greybus.h" #include "greybus_trace.h" static struct kmem_cache *gb_operation_cache; diff --git a/drivers/staging/greybus/operation.h b/drivers/staging/greybus/operation.h deleted file mode 100644 index 17ba3daf111b..000000000000 --- a/drivers/staging/greybus/operation.h +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus operations - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#ifndef __OPERATION_H -#define __OPERATION_H - -#include - -struct gb_operation; - -/* The default amount of time a request is given to complete */ -#define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ - -/* - * The top bit of the type in an operation message header indicates - * whether the message is a request (bit clear) or response (bit set) - */ -#define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) - -enum gb_operation_result { - GB_OP_SUCCESS = 0x00, - GB_OP_INTERRUPTED = 0x01, - GB_OP_TIMEOUT = 0x02, - GB_OP_NO_MEMORY = 0x03, - GB_OP_PROTOCOL_BAD = 0x04, - GB_OP_OVERFLOW = 0x05, - GB_OP_INVALID = 0x06, - GB_OP_RETRY = 0x07, - GB_OP_NONEXISTENT = 0x08, - GB_OP_UNKNOWN_ERROR = 0xfe, - GB_OP_MALFUNCTION = 0xff, -}; - -#define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) -#define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX - -/* - * Protocol code should only examine the payload and payload_size fields, and - * host-controller drivers may use the hcpriv field. All other fields are - * intended to be private to the operations core code. - */ -struct gb_message { - struct gb_operation *operation; - struct gb_operation_msg_hdr *header; - - void *payload; - size_t payload_size; - - void *buffer; - - void *hcpriv; -}; - -#define GB_OPERATION_FLAG_INCOMING BIT(0) -#define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) -#define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) -#define GB_OPERATION_FLAG_CORE BIT(3) - -#define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ - GB_OPERATION_FLAG_UNIDIRECTIONAL) - -/* - * A Greybus operation is a remote procedure call performed over a - * connection between two UniPro interfaces. - * - * Every operation consists of a request message sent to the other - * end of the connection coupled with a reply message returned to - * the sender. Every operation has a type, whose interpretation is - * dependent on the protocol associated with the connection. - * - * Only four things in an operation structure are intended to be - * directly usable by protocol handlers: the operation's connection - * pointer; the operation type; the request message payload (and - * size); and the response message payload (and size). Note that a - * message with a 0-byte payload has a null message payload pointer. - * - * In addition, every operation has a result, which is an errno - * value. Protocol handlers access the operation result using - * gb_operation_result(). - */ -typedef void (*gb_operation_callback)(struct gb_operation *); -struct gb_operation { - struct gb_connection *connection; - struct gb_message *request; - struct gb_message *response; - - unsigned long flags; - u8 type; - u16 id; - int errno; /* Operation result */ - - struct work_struct work; - gb_operation_callback callback; - struct completion completion; - struct timer_list timer; - - struct kref kref; - atomic_t waiters; - - int active; - struct list_head links; /* connection->operations */ - - void *private; -}; - -static inline bool -gb_operation_is_incoming(struct gb_operation *operation) -{ - return operation->flags & GB_OPERATION_FLAG_INCOMING; -} - -static inline bool -gb_operation_is_unidirectional(struct gb_operation *operation) -{ - return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; -} - -static inline bool -gb_operation_short_response_allowed(struct gb_operation *operation) -{ - return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; -} - -static inline bool gb_operation_is_core(struct gb_operation *operation) -{ - return operation->flags & GB_OPERATION_FLAG_CORE; -} - -void gb_connection_recv(struct gb_connection *connection, - void *data, size_t size); - -int gb_operation_result(struct gb_operation *operation); - -size_t gb_operation_get_payload_size_max(struct gb_connection *connection); -struct gb_operation * -gb_operation_create_flags(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, unsigned long flags, - gfp_t gfp); - -static inline struct gb_operation * -gb_operation_create(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, gfp_t gfp) -{ - return gb_operation_create_flags(connection, type, request_size, - response_size, 0, gfp); -} - -struct gb_operation * -gb_operation_create_core(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, unsigned long flags, - gfp_t gfp); - -void gb_operation_get(struct gb_operation *operation); -void gb_operation_put(struct gb_operation *operation); - -bool gb_operation_response_alloc(struct gb_operation *operation, - size_t response_size, gfp_t gfp); - -int gb_operation_request_send(struct gb_operation *operation, - gb_operation_callback callback, - unsigned int timeout, - gfp_t gfp); -int gb_operation_request_send_sync_timeout(struct gb_operation *operation, - unsigned int timeout); -static inline int -gb_operation_request_send_sync(struct gb_operation *operation) -{ - return gb_operation_request_send_sync_timeout(operation, - GB_OPERATION_TIMEOUT_DEFAULT); -} - -void gb_operation_cancel(struct gb_operation *operation, int errno); -void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); - -void greybus_message_sent(struct gb_host_device *hd, - struct gb_message *message, int status); - -int gb_operation_sync_timeout(struct gb_connection *connection, int type, - void *request, int request_size, - void *response, int response_size, - unsigned int timeout); -int gb_operation_unidirectional_timeout(struct gb_connection *connection, - int type, void *request, int request_size, - unsigned int timeout); - -static inline int gb_operation_sync(struct gb_connection *connection, int type, - void *request, int request_size, - void *response, int response_size) -{ - return gb_operation_sync_timeout(connection, type, - request, request_size, response, response_size, - GB_OPERATION_TIMEOUT_DEFAULT); -} - -static inline int gb_operation_unidirectional(struct gb_connection *connection, - int type, void *request, int request_size) -{ - return gb_operation_unidirectional_timeout(connection, type, - request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); -} - -static inline void *gb_operation_get_data(struct gb_operation *operation) -{ - return operation->private; -} - -static inline void gb_operation_set_data(struct gb_operation *operation, - void *data) -{ - operation->private = data; -} - -int gb_operation_init(void); -void gb_operation_exit(void); - -#endif /* !__OPERATION_H */ diff --git a/drivers/staging/greybus/power_supply.c b/drivers/staging/greybus/power_supply.c index 34b40a409ea3..ec96f28887f9 100644 --- a/drivers/staging/greybus/power_supply.c +++ b/drivers/staging/greybus/power_supply.c @@ -10,8 +10,7 @@ #include #include #include - -#include "greybus.h" +#include #define PROP_MAX 32 diff --git a/drivers/staging/greybus/pwm.c b/drivers/staging/greybus/pwm.c index 4a6d394b6c44..891a6a672378 100644 --- a/drivers/staging/greybus/pwm.c +++ b/drivers/staging/greybus/pwm.c @@ -10,8 +10,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" struct gb_pwm_chip { diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c index 838acbe84ca0..64a17dfe3b6e 100644 --- a/drivers/staging/greybus/raw.c +++ b/drivers/staging/greybus/raw.c @@ -13,8 +13,7 @@ #include #include #include - -#include "greybus.h" +#include struct gb_raw { struct gb_connection *connection; diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index a097a8916b3b..68c5718be827 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -12,8 +12,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" struct gb_sdio_host { diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 47d896992b35..68e8d272db6d 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -7,8 +7,8 @@ */ #include +#include -#include "greybus.h" #include "gbphy.h" #include "spilib.h" diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index 2e07c6b41334..fc27c52de74a 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -10,9 +10,9 @@ #include #include #include +#include #include -#include "greybus.h" #include "spilib.h" struct gb_spilib { diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 05bc45287b87..ce7740ef449b 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -8,8 +8,7 @@ #include #include - -#include "greybus.h" +#include #define SVC_INTF_EJECT_TIMEOUT 9000 #define SVC_INTF_ACTIVATE_TIMEOUT 6000 diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h deleted file mode 100644 index e7452057cfe4..000000000000 --- a/drivers/staging/greybus/svc.h +++ /dev/null @@ -1,101 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus SVC code - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - */ - -#ifndef __SVC_H -#define __SVC_H - -#define GB_SVC_CPORT_FLAG_E2EFC BIT(0) -#define GB_SVC_CPORT_FLAG_CSD_N BIT(1) -#define GB_SVC_CPORT_FLAG_CSV_N BIT(2) - -enum gb_svc_state { - GB_SVC_STATE_RESET, - GB_SVC_STATE_PROTOCOL_VERSION, - GB_SVC_STATE_SVC_HELLO, -}; - -enum gb_svc_watchdog_bite { - GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, - GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, -}; - -struct gb_svc_watchdog; - -struct svc_debugfs_pwrmon_rail { - u8 id; - struct gb_svc *svc; -}; - -struct gb_svc { - struct device dev; - - struct gb_host_device *hd; - struct gb_connection *connection; - enum gb_svc_state state; - struct ida device_id_map; - struct workqueue_struct *wq; - - u16 endo_id; - u8 ap_intf_id; - - u8 protocol_major; - u8 protocol_minor; - - struct gb_svc_watchdog *watchdog; - enum gb_svc_watchdog_bite action; - - struct dentry *debugfs_dentry; - struct svc_debugfs_pwrmon_rail *pwrmon_rails; -}; -#define to_gb_svc(d) container_of(d, struct gb_svc, dev) - -struct gb_svc *gb_svc_create(struct gb_host_device *hd); -int gb_svc_add(struct gb_svc *svc); -void gb_svc_del(struct gb_svc *svc); -void gb_svc_put(struct gb_svc *svc); - -int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, - u8 measurement_type, u32 *value); -int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); -int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id); -void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); -int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id, u8 cport_flags); -void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id); -int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); -int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); -int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); -int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); -int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); -int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id); - -int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, - u32 *value); -int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, - u32 value); -int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, - u8 tx_mode, u8 tx_gear, u8 tx_nlanes, - u8 tx_amplitude, u8 tx_hs_equalizer, - u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks, - struct gb_svc_l2_timer_cfg *local, - struct gb_svc_l2_timer_cfg *remote); -int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id); -int gb_svc_ping(struct gb_svc *svc); -int gb_svc_watchdog_create(struct gb_svc *svc); -void gb_svc_watchdog_destroy(struct gb_svc *svc); -bool gb_svc_watchdog_enabled(struct gb_svc *svc); -int gb_svc_watchdog_enable(struct gb_svc *svc); -int gb_svc_watchdog_disable(struct gb_svc *svc); - -int gb_svc_protocol_init(void); -void gb_svc_protocol_exit(void); - -#endif /* __SVC_H */ diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c index 7868ad8211c5..b6b1682c19c4 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/staging/greybus/svc_watchdog.c @@ -8,7 +8,7 @@ #include #include #include -#include "greybus.h" +#include #define SVC_WATCHDOG_PERIOD (2 * HZ) diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index b3bffe91ae99..55c51143bb09 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -28,8 +28,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" #define GB_NUM_MINORS 16 /* 16 is more than enough */ diff --git a/drivers/staging/greybus/usb.c b/drivers/staging/greybus/usb.c index 1c246c73a085..8e9d9d59a357 100644 --- a/drivers/staging/greybus/usb.c +++ b/drivers/staging/greybus/usb.c @@ -10,8 +10,8 @@ #include #include #include +#include -#include "greybus.h" #include "gbphy.h" /* Greybus USB request types */ diff --git a/drivers/staging/greybus/vibrator.c b/drivers/staging/greybus/vibrator.c index 3e5dedeacd5c..0e2b188e5ca3 100644 --- a/drivers/staging/greybus/vibrator.c +++ b/drivers/staging/greybus/vibrator.c @@ -13,8 +13,7 @@ #include #include #include - -#include "greybus.h" +#include struct gb_vibrator_device { struct gb_connection *connection; diff --git a/include/linux/greybus.h b/include/linux/greybus.h new file mode 100644 index 000000000000..18c0fb958b74 --- /dev/null +++ b/include/linux/greybus.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus driver and device API + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#ifndef __LINUX_GREYBUS_H +#define __LINUX_GREYBUS_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Matches up with the Greybus Protocol specification document */ +#define GREYBUS_VERSION_MAJOR 0x00 +#define GREYBUS_VERSION_MINOR 0x01 + +#define GREYBUS_ID_MATCH_DEVICE \ + (GREYBUS_ID_MATCH_VENDOR | GREYBUS_ID_MATCH_PRODUCT) + +#define GREYBUS_DEVICE(v, p) \ + .match_flags = GREYBUS_ID_MATCH_DEVICE, \ + .vendor = (v), \ + .product = (p), + +#define GREYBUS_DEVICE_CLASS(c) \ + .match_flags = GREYBUS_ID_MATCH_CLASS, \ + .class = (c), + +/* Maximum number of CPorts */ +#define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */ +#define CPORT_ID_BAD U16_MAX + +struct greybus_driver { + const char *name; + + int (*probe)(struct gb_bundle *bundle, + const struct greybus_bundle_id *id); + void (*disconnect)(struct gb_bundle *bundle); + + const struct greybus_bundle_id *id_table; + + struct device_driver driver; +}; +#define to_greybus_driver(d) container_of(d, struct greybus_driver, driver) + +static inline void greybus_set_drvdata(struct gb_bundle *bundle, void *data) +{ + dev_set_drvdata(&bundle->dev, data); +} + +static inline void *greybus_get_drvdata(struct gb_bundle *bundle) +{ + return dev_get_drvdata(&bundle->dev); +} + +/* Don't call these directly, use the module_greybus_driver() macro instead */ +int greybus_register_driver(struct greybus_driver *driver, + struct module *module, const char *mod_name); +void greybus_deregister_driver(struct greybus_driver *driver); + +/* define to get proper THIS_MODULE and KBUILD_MODNAME values */ +#define greybus_register(driver) \ + greybus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) +#define greybus_deregister(driver) \ + greybus_deregister_driver(driver) + +/** + * module_greybus_driver() - Helper macro for registering a Greybus driver + * @__greybus_driver: greybus_driver structure + * + * Helper macro for Greybus drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_greybus_driver(__greybus_driver) \ + module_driver(__greybus_driver, greybus_register, greybus_deregister) + +int greybus_disabled(void); + +void gb_debugfs_init(void); +void gb_debugfs_cleanup(void); +struct dentry *gb_debugfs_get(void); + +extern struct bus_type greybus_bus_type; + +extern struct device_type greybus_hd_type; +extern struct device_type greybus_module_type; +extern struct device_type greybus_interface_type; +extern struct device_type greybus_control_type; +extern struct device_type greybus_bundle_type; +extern struct device_type greybus_svc_type; + +static inline int is_gb_host_device(const struct device *dev) +{ + return dev->type == &greybus_hd_type; +} + +static inline int is_gb_module(const struct device *dev) +{ + return dev->type == &greybus_module_type; +} + +static inline int is_gb_interface(const struct device *dev) +{ + return dev->type == &greybus_interface_type; +} + +static inline int is_gb_control(const struct device *dev) +{ + return dev->type == &greybus_control_type; +} + +static inline int is_gb_bundle(const struct device *dev) +{ + return dev->type == &greybus_bundle_type; +} + +static inline int is_gb_svc(const struct device *dev) +{ + return dev->type == &greybus_svc_type; +} + +static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id) +{ + return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports; +} + +#endif /* __KERNEL__ */ +#endif /* __LINUX_GREYBUS_H */ diff --git a/include/linux/greybus/bundle.h b/include/linux/greybus/bundle.h new file mode 100644 index 000000000000..8734d2055657 --- /dev/null +++ b/include/linux/greybus/bundle.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus bundles + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __BUNDLE_H +#define __BUNDLE_H + +#include + +#define BUNDLE_ID_NONE U8_MAX + +/* Greybus "public" definitions" */ +struct gb_bundle { + struct device dev; + struct gb_interface *intf; + + u8 id; + u8 class; + u8 class_major; + u8 class_minor; + + size_t num_cports; + struct greybus_descriptor_cport *cport_desc; + + struct list_head connections; + u8 *state; + + struct list_head links; /* interface->bundles */ +}; +#define to_gb_bundle(d) container_of(d, struct gb_bundle, dev) + +/* Greybus "private" definitions" */ +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class); +int gb_bundle_add(struct gb_bundle *bundle); +void gb_bundle_destroy(struct gb_bundle *bundle); + +/* Bundle Runtime PM wrappers */ +#ifdef CONFIG_PM +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ + int retval; + + retval = pm_runtime_get_sync(&bundle->dev); + if (retval < 0) { + dev_err(&bundle->dev, + "pm_runtime_get_sync failed: %d\n", retval); + pm_runtime_put_noidle(&bundle->dev); + return retval; + } + + return 0; +} + +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ + int retval; + + pm_runtime_mark_last_busy(&bundle->dev); + retval = pm_runtime_put_autosuspend(&bundle->dev); + + return retval; +} + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) +{ + pm_runtime_get_noresume(&bundle->dev); +} + +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) +{ + pm_runtime_put_noidle(&bundle->dev); +} + +#else +static inline int gb_pm_runtime_get_sync(struct gb_bundle *bundle) +{ return 0; } +static inline int gb_pm_runtime_put_autosuspend(struct gb_bundle *bundle) +{ return 0; } + +static inline void gb_pm_runtime_get_noresume(struct gb_bundle *bundle) {} +static inline void gb_pm_runtime_put_noidle(struct gb_bundle *bundle) {} +#endif + +#endif /* __BUNDLE_H */ diff --git a/include/linux/greybus/connection.h b/include/linux/greybus/connection.h new file mode 100644 index 000000000000..5ca3befc0636 --- /dev/null +++ b/include/linux/greybus/connection.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __CONNECTION_H +#define __CONNECTION_H + +#include +#include + +#define GB_CONNECTION_FLAG_CSD BIT(0) +#define GB_CONNECTION_FLAG_NO_FLOWCTRL BIT(1) +#define GB_CONNECTION_FLAG_OFFLOADED BIT(2) +#define GB_CONNECTION_FLAG_CDSI1 BIT(3) +#define GB_CONNECTION_FLAG_CONTROL BIT(4) +#define GB_CONNECTION_FLAG_HIGH_PRIO BIT(5) + +#define GB_CONNECTION_FLAG_CORE_MASK GB_CONNECTION_FLAG_CONTROL + +enum gb_connection_state { + GB_CONNECTION_STATE_DISABLED = 0, + GB_CONNECTION_STATE_ENABLED_TX = 1, + GB_CONNECTION_STATE_ENABLED = 2, + GB_CONNECTION_STATE_DISCONNECTING = 3, +}; + +struct gb_operation; + +typedef int (*gb_request_handler_t)(struct gb_operation *); + +struct gb_connection { + struct gb_host_device *hd; + struct gb_interface *intf; + struct gb_bundle *bundle; + struct kref kref; + u16 hd_cport_id; + u16 intf_cport_id; + + struct list_head hd_links; + struct list_head bundle_links; + + gb_request_handler_t handler; + unsigned long flags; + + struct mutex mutex; + spinlock_t lock; + enum gb_connection_state state; + struct list_head operations; + + char name[16]; + struct workqueue_struct *wq; + + atomic_t op_cycle; + + void *private; + + bool mode_switch; +}; + +struct gb_connection *gb_connection_create_static(struct gb_host_device *hd, + u16 hd_cport_id, gb_request_handler_t handler); +struct gb_connection *gb_connection_create_control(struct gb_interface *intf); +struct gb_connection *gb_connection_create(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler); +struct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle, + u16 cport_id, gb_request_handler_t handler, + unsigned long flags); +struct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle, + u16 cport_id, unsigned long flags); +void gb_connection_destroy(struct gb_connection *connection); + +static inline bool gb_connection_is_static(struct gb_connection *connection) +{ + return !connection->intf; +} + +int gb_connection_enable(struct gb_connection *connection); +int gb_connection_enable_tx(struct gb_connection *connection); +void gb_connection_disable_rx(struct gb_connection *connection); +void gb_connection_disable(struct gb_connection *connection); +void gb_connection_disable_forced(struct gb_connection *connection); + +void gb_connection_mode_switch_prepare(struct gb_connection *connection); +void gb_connection_mode_switch_complete(struct gb_connection *connection); + +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, + u8 *data, size_t length); + +void gb_connection_latency_tag_enable(struct gb_connection *connection); +void gb_connection_latency_tag_disable(struct gb_connection *connection); + +static inline bool gb_connection_e2efc_enabled(struct gb_connection *connection) +{ + return !(connection->flags & GB_CONNECTION_FLAG_CSD); +} + +static inline bool +gb_connection_flow_control_disabled(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL; +} + +static inline bool gb_connection_is_offloaded(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_OFFLOADED; +} + +static inline bool gb_connection_is_control(struct gb_connection *connection) +{ + return connection->flags & GB_CONNECTION_FLAG_CONTROL; +} + +static inline void *gb_connection_get_data(struct gb_connection *connection) +{ + return connection->private; +} + +static inline void gb_connection_set_data(struct gb_connection *connection, + void *data) +{ + connection->private = data; +} + +#endif /* __CONNECTION_H */ diff --git a/include/linux/greybus/control.h b/include/linux/greybus/control.h new file mode 100644 index 000000000000..3a29ec05f631 --- /dev/null +++ b/include/linux/greybus/control.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus CPort control protocol + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ + +#ifndef __CONTROL_H +#define __CONTROL_H + +struct gb_control { + struct device dev; + struct gb_interface *intf; + + struct gb_connection *connection; + + u8 protocol_major; + u8 protocol_minor; + + bool has_bundle_activate; + bool has_bundle_version; + + char *vendor_string; + char *product_string; +}; +#define to_gb_control(d) container_of(d, struct gb_control, dev) + +struct gb_control *gb_control_create(struct gb_interface *intf); +int gb_control_enable(struct gb_control *control); +void gb_control_disable(struct gb_control *control); +int gb_control_suspend(struct gb_control *control); +int gb_control_resume(struct gb_control *control); +int gb_control_add(struct gb_control *control); +void gb_control_del(struct gb_control *control); +struct gb_control *gb_control_get(struct gb_control *control); +void gb_control_put(struct gb_control *control); + +int gb_control_get_bundle_versions(struct gb_control *control); +int gb_control_connected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id); +int gb_control_mode_switch_operation(struct gb_control *control); +void gb_control_mode_switch_prepare(struct gb_control *control); +void gb_control_mode_switch_complete(struct gb_control *control); +int gb_control_get_manifest_size_operation(struct gb_interface *intf); +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size); +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id); +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id); +int gb_control_interface_suspend_prepare(struct gb_control *control); +int gb_control_interface_deactivate_prepare(struct gb_control *control); +int gb_control_interface_hibernate_abort(struct gb_control *control); +#endif /* __CONTROL_H */ diff --git a/include/linux/greybus/greybus_id.h b/include/linux/greybus/greybus_id.h new file mode 100644 index 000000000000..f4c8440093e4 --- /dev/null +++ b/include/linux/greybus/greybus_id.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* FIXME + * move this to include/linux/mod_devicetable.h when merging + */ + +#ifndef __LINUX_GREYBUS_ID_H +#define __LINUX_GREYBUS_ID_H + +#include +#include + + +struct greybus_bundle_id { + __u16 match_flags; + __u32 vendor; + __u32 product; + __u8 class; + + kernel_ulong_t driver_info __aligned(sizeof(kernel_ulong_t)); +}; + +/* Used to match the greybus_bundle_id */ +#define GREYBUS_ID_MATCH_VENDOR BIT(0) +#define GREYBUS_ID_MATCH_PRODUCT BIT(1) +#define GREYBUS_ID_MATCH_CLASS BIT(2) + +#endif /* __LINUX_GREYBUS_ID_H */ diff --git a/include/linux/greybus/greybus_manifest.h b/include/linux/greybus/greybus_manifest.h new file mode 100644 index 000000000000..db68f7e7d5a7 --- /dev/null +++ b/include/linux/greybus/greybus_manifest.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus manifest definition + * + * See "Greybus Application Protocol" document (version 0.1) for + * details on these values and structures. + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 and BSD licenses. + */ + +#ifndef __GREYBUS_MANIFEST_H +#define __GREYBUS_MANIFEST_H + +enum greybus_descriptor_type { + GREYBUS_TYPE_INVALID = 0x00, + GREYBUS_TYPE_INTERFACE = 0x01, + GREYBUS_TYPE_STRING = 0x02, + GREYBUS_TYPE_BUNDLE = 0x03, + GREYBUS_TYPE_CPORT = 0x04, +}; + +enum greybus_protocol { + GREYBUS_PROTOCOL_CONTROL = 0x00, + /* 0x01 is unused */ + GREYBUS_PROTOCOL_GPIO = 0x02, + GREYBUS_PROTOCOL_I2C = 0x03, + GREYBUS_PROTOCOL_UART = 0x04, + GREYBUS_PROTOCOL_HID = 0x05, + GREYBUS_PROTOCOL_USB = 0x06, + GREYBUS_PROTOCOL_SDIO = 0x07, + GREYBUS_PROTOCOL_POWER_SUPPLY = 0x08, + GREYBUS_PROTOCOL_PWM = 0x09, + /* 0x0a is unused */ + GREYBUS_PROTOCOL_SPI = 0x0b, + GREYBUS_PROTOCOL_DISPLAY = 0x0c, + GREYBUS_PROTOCOL_CAMERA_MGMT = 0x0d, + GREYBUS_PROTOCOL_SENSOR = 0x0e, + GREYBUS_PROTOCOL_LIGHTS = 0x0f, + GREYBUS_PROTOCOL_VIBRATOR = 0x10, + GREYBUS_PROTOCOL_LOOPBACK = 0x11, + GREYBUS_PROTOCOL_AUDIO_MGMT = 0x12, + GREYBUS_PROTOCOL_AUDIO_DATA = 0x13, + GREYBUS_PROTOCOL_SVC = 0x14, + GREYBUS_PROTOCOL_BOOTROM = 0x15, + GREYBUS_PROTOCOL_CAMERA_DATA = 0x16, + GREYBUS_PROTOCOL_FW_DOWNLOAD = 0x17, + GREYBUS_PROTOCOL_FW_MANAGEMENT = 0x18, + GREYBUS_PROTOCOL_AUTHENTICATION = 0x19, + GREYBUS_PROTOCOL_LOG = 0x1a, + /* ... */ + GREYBUS_PROTOCOL_RAW = 0xfe, + GREYBUS_PROTOCOL_VENDOR = 0xff, +}; + +enum greybus_class_type { + GREYBUS_CLASS_CONTROL = 0x00, + /* 0x01 is unused */ + /* 0x02 is unused */ + /* 0x03 is unused */ + /* 0x04 is unused */ + GREYBUS_CLASS_HID = 0x05, + /* 0x06 is unused */ + /* 0x07 is unused */ + GREYBUS_CLASS_POWER_SUPPLY = 0x08, + /* 0x09 is unused */ + GREYBUS_CLASS_BRIDGED_PHY = 0x0a, + /* 0x0b is unused */ + GREYBUS_CLASS_DISPLAY = 0x0c, + GREYBUS_CLASS_CAMERA = 0x0d, + GREYBUS_CLASS_SENSOR = 0x0e, + GREYBUS_CLASS_LIGHTS = 0x0f, + GREYBUS_CLASS_VIBRATOR = 0x10, + GREYBUS_CLASS_LOOPBACK = 0x11, + GREYBUS_CLASS_AUDIO = 0x12, + /* 0x13 is unused */ + /* 0x14 is unused */ + GREYBUS_CLASS_BOOTROM = 0x15, + GREYBUS_CLASS_FW_MANAGEMENT = 0x16, + GREYBUS_CLASS_LOG = 0x17, + /* ... */ + GREYBUS_CLASS_RAW = 0xfe, + GREYBUS_CLASS_VENDOR = 0xff, +}; + +enum { + GREYBUS_INTERFACE_FEATURE_TIMESYNC = BIT(0), +}; + +/* + * The string in a string descriptor is not NUL-terminated. The + * size of the descriptor will be rounded up to a multiple of 4 + * bytes, by padding the string with 0x00 bytes if necessary. + */ +struct greybus_descriptor_string { + __u8 length; + __u8 id; + __u8 string[0]; +} __packed; + +/* + * An interface descriptor describes information about an interface as a whole, + * *not* the functions within it. + */ +struct greybus_descriptor_interface { + __u8 vendor_stringid; + __u8 product_stringid; + __u8 features; + __u8 pad; +} __packed; + +/* + * An bundle descriptor defines an identification number and a class for + * each bundle. + * + * @id: Uniquely identifies a bundle within a interface, its sole purpose is to + * allow CPort descriptors to specify which bundle they are associated with. + * The first bundle will have id 0, second will have 1 and so on. + * + * The largest CPort id associated with an bundle (defined by a + * CPort descriptor in the manifest) is used to determine how to + * encode the device id and module number in UniPro packets + * that use the bundle. + * + * @class: It is used by kernel to know the functionality provided by the + * bundle and will be matched against drivers functinality while probing greybus + * driver. It should contain one of the values defined in + * 'enum greybus_class_type'. + * + */ +struct greybus_descriptor_bundle { + __u8 id; /* interface-relative id (0..) */ + __u8 class; + __u8 pad[2]; +} __packed; + +/* + * A CPort descriptor indicates the id of the bundle within the + * module it's associated with, along with the CPort id used to + * address the CPort. The protocol id defines the format of messages + * exchanged using the CPort. + */ +struct greybus_descriptor_cport { + __le16 id; + __u8 bundle; + __u8 protocol_id; /* enum greybus_protocol */ +} __packed; + +struct greybus_descriptor_header { + __le16 size; + __u8 type; /* enum greybus_descriptor_type */ + __u8 pad; +} __packed; + +struct greybus_descriptor { + struct greybus_descriptor_header header; + union { + struct greybus_descriptor_string string; + struct greybus_descriptor_interface interface; + struct greybus_descriptor_bundle bundle; + struct greybus_descriptor_cport cport; + }; +} __packed; + +struct greybus_manifest_header { + __le16 size; + __u8 version_major; + __u8 version_minor; +} __packed; + +struct greybus_manifest { + struct greybus_manifest_header header; + struct greybus_descriptor descriptors[0]; +} __packed; + +#endif /* __GREYBUS_MANIFEST_H */ diff --git a/include/linux/greybus/greybus_protocols.h b/include/linux/greybus/greybus_protocols.h new file mode 100644 index 000000000000..5f34d1effb59 --- /dev/null +++ b/include/linux/greybus/greybus_protocols.h @@ -0,0 +1,2176 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2014 - 2015 Google Inc. All rights reserved. + * Copyright(c) 2014 - 2015 Linaro Ltd. All rights reserved. + */ + +#ifndef __GREYBUS_PROTOCOLS_H +#define __GREYBUS_PROTOCOLS_H + +/* Fixed IDs for control/svc protocols */ + +/* SVC switch-port device ids */ +#define GB_SVC_DEVICE_ID_SVC 0 +#define GB_SVC_DEVICE_ID_AP 1 +#define GB_SVC_DEVICE_ID_MIN 2 +#define GB_SVC_DEVICE_ID_MAX 31 + +#define GB_SVC_CPORT_ID 0 +#define GB_CONTROL_BUNDLE_ID 0 +#define GB_CONTROL_CPORT_ID 0 + + +/* + * All operation messages (both requests and responses) begin with + * a header that encodes the size of the message (header included). + * This header also contains a unique identifier, that associates a + * response message with its operation. The header contains an + * operation type field, whose interpretation is dependent on what + * type of protocol is used over the connection. The high bit + * (0x80) of the operation type field is used to indicate whether + * the message is a request (clear) or a response (set). + * + * Response messages include an additional result byte, which + * communicates the result of the corresponding request. A zero + * result value means the operation completed successfully. Any + * other value indicates an error; in this case, the payload of the + * response message (if any) is ignored. The result byte must be + * zero in the header for a request message. + * + * The wire format for all numeric fields in the header is little + * endian. Any operation-specific data begins immediately after the + * header. + */ +struct gb_operation_msg_hdr { + __le16 size; /* Size in bytes of header + payload */ + __le16 operation_id; /* Operation unique id */ + __u8 type; /* E.g GB_I2C_TYPE_* or GB_GPIO_TYPE_* */ + __u8 result; /* Result of request (in responses only) */ + __u8 pad[2]; /* must be zero (ignore when read) */ +} __packed; + + +/* Generic request types */ +#define GB_REQUEST_TYPE_CPORT_SHUTDOWN 0x00 +#define GB_REQUEST_TYPE_INVALID 0x7f + +struct gb_cport_shutdown_request { + __u8 phase; +} __packed; + + +/* Control Protocol */ + +/* Greybus control request types */ +#define GB_CONTROL_TYPE_VERSION 0x01 +#define GB_CONTROL_TYPE_PROBE_AP 0x02 +#define GB_CONTROL_TYPE_GET_MANIFEST_SIZE 0x03 +#define GB_CONTROL_TYPE_GET_MANIFEST 0x04 +#define GB_CONTROL_TYPE_CONNECTED 0x05 +#define GB_CONTROL_TYPE_DISCONNECTED 0x06 +#define GB_CONTROL_TYPE_TIMESYNC_ENABLE 0x07 +#define GB_CONTROL_TYPE_TIMESYNC_DISABLE 0x08 +#define GB_CONTROL_TYPE_TIMESYNC_AUTHORITATIVE 0x09 +/* Unused 0x0a */ +#define GB_CONTROL_TYPE_BUNDLE_VERSION 0x0b +#define GB_CONTROL_TYPE_DISCONNECTING 0x0c +#define GB_CONTROL_TYPE_TIMESYNC_GET_LAST_EVENT 0x0d +#define GB_CONTROL_TYPE_MODE_SWITCH 0x0e +#define GB_CONTROL_TYPE_BUNDLE_SUSPEND 0x0f +#define GB_CONTROL_TYPE_BUNDLE_RESUME 0x10 +#define GB_CONTROL_TYPE_BUNDLE_DEACTIVATE 0x11 +#define GB_CONTROL_TYPE_BUNDLE_ACTIVATE 0x12 +#define GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE 0x13 +#define GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE 0x14 +#define GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT 0x15 + +struct gb_control_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_version_response { + __u8 major; + __u8 minor; +} __packed; + +struct gb_control_bundle_version_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* Control protocol manifest get size request has no payload*/ +struct gb_control_get_manifest_size_response { + __le16 size; +} __packed; + +/* Control protocol manifest get request has no payload */ +struct gb_control_get_manifest_response { + __u8 data[0]; +} __packed; + +/* Control protocol [dis]connected request */ +struct gb_control_connected_request { + __le16 cport_id; +} __packed; + +struct gb_control_disconnecting_request { + __le16 cport_id; +} __packed; +/* disconnecting response has no payload */ + +struct gb_control_disconnected_request { + __le16 cport_id; +} __packed; +/* Control protocol [dis]connected response has no payload */ + +/* + * All Bundle power management operations use the same request and response + * layout and status codes. + */ + +#define GB_CONTROL_BUNDLE_PM_OK 0x00 +#define GB_CONTROL_BUNDLE_PM_INVAL 0x01 +#define GB_CONTROL_BUNDLE_PM_BUSY 0x02 +#define GB_CONTROL_BUNDLE_PM_FAIL 0x03 +#define GB_CONTROL_BUNDLE_PM_NA 0x04 + +struct gb_control_bundle_pm_request { + __u8 bundle_id; +} __packed; + +struct gb_control_bundle_pm_response { + __u8 status; +} __packed; + +/* + * Interface Suspend Prepare and Deactivate Prepare operations use the same + * response layout and error codes. Define a single response structure and reuse + * it. Both operations have no payload. + */ + +#define GB_CONTROL_INTF_PM_OK 0x00 +#define GB_CONTROL_INTF_PM_BUSY 0x01 +#define GB_CONTROL_INTF_PM_NA 0x02 + +struct gb_control_intf_pm_response { + __u8 status; +} __packed; + +/* APBridge protocol */ + +/* request APB1 log */ +#define GB_APB_REQUEST_LOG 0x02 + +/* request to map a cport to bulk in and bulk out endpoints */ +#define GB_APB_REQUEST_EP_MAPPING 0x03 + +/* request to get the number of cports available */ +#define GB_APB_REQUEST_CPORT_COUNT 0x04 + +/* request to reset a cport state */ +#define GB_APB_REQUEST_RESET_CPORT 0x05 + +/* request to time the latency of messages on a given cport */ +#define GB_APB_REQUEST_LATENCY_TAG_EN 0x06 +#define GB_APB_REQUEST_LATENCY_TAG_DIS 0x07 + +/* request to control the CSI transmitter */ +#define GB_APB_REQUEST_CSI_TX_CONTROL 0x08 + +/* request to control audio streaming */ +#define GB_APB_REQUEST_AUDIO_CONTROL 0x09 + +/* TimeSync requests */ +#define GB_APB_REQUEST_TIMESYNC_ENABLE 0x0d +#define GB_APB_REQUEST_TIMESYNC_DISABLE 0x0e +#define GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT 0x10 + +/* requests to set Greybus CPort flags */ +#define GB_APB_REQUEST_CPORT_FLAGS 0x11 + +/* ARPC request */ +#define GB_APB_REQUEST_ARPC_RUN 0x12 + +struct gb_apb_request_cport_flags { + __le32 flags; +#define GB_APB_CPORT_FLAG_CONTROL 0x01 +#define GB_APB_CPORT_FLAG_HIGH_PRIO 0x02 +} __packed; + + +/* Firmware Download Protocol */ + +/* Request Types */ +#define GB_FW_DOWNLOAD_TYPE_FIND_FIRMWARE 0x01 +#define GB_FW_DOWNLOAD_TYPE_FETCH_FIRMWARE 0x02 +#define GB_FW_DOWNLOAD_TYPE_RELEASE_FIRMWARE 0x03 + +#define GB_FIRMWARE_TAG_MAX_SIZE 10 + +/* firmware download find firmware request/response */ +struct gb_fw_download_find_firmware_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; + +struct gb_fw_download_find_firmware_response { + __u8 firmware_id; + __le32 size; +} __packed; + +/* firmware download fetch firmware request/response */ +struct gb_fw_download_fetch_firmware_request { + __u8 firmware_id; + __le32 offset; + __le32 size; +} __packed; + +struct gb_fw_download_fetch_firmware_response { + __u8 data[0]; +} __packed; + +/* firmware download release firmware request */ +struct gb_fw_download_release_firmware_request { + __u8 firmware_id; +} __packed; +/* firmware download release firmware response has no payload */ + + +/* Firmware Management Protocol */ + +/* Request Types */ +#define GB_FW_MGMT_TYPE_INTERFACE_FW_VERSION 0x01 +#define GB_FW_MGMT_TYPE_LOAD_AND_VALIDATE_FW 0x02 +#define GB_FW_MGMT_TYPE_LOADED_FW 0x03 +#define GB_FW_MGMT_TYPE_BACKEND_FW_VERSION 0x04 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATE 0x05 +#define GB_FW_MGMT_TYPE_BACKEND_FW_UPDATED 0x06 + +#define GB_FW_LOAD_METHOD_UNIPRO 0x01 +#define GB_FW_LOAD_METHOD_INTERNAL 0x02 + +#define GB_FW_LOAD_STATUS_FAILED 0x00 +#define GB_FW_LOAD_STATUS_UNVALIDATED 0x01 +#define GB_FW_LOAD_STATUS_VALIDATED 0x02 +#define GB_FW_LOAD_STATUS_VALIDATION_FAILED 0x03 + +#define GB_FW_BACKEND_FW_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FIND 0x02 +#define GB_FW_BACKEND_FW_STATUS_FAIL_FETCH 0x03 +#define GB_FW_BACKEND_FW_STATUS_FAIL_WRITE 0x04 +#define GB_FW_BACKEND_FW_STATUS_INT 0x05 +#define GB_FW_BACKEND_FW_STATUS_RETRY 0x06 +#define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED 0x07 + +#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS 0x01 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE 0x02 +#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED 0x03 +#define GB_FW_BACKEND_VERSION_STATUS_RETRY 0x04 +#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT 0x05 + +/* firmware management interface firmware version request has no payload */ +struct gb_fw_mgmt_interface_fw_version_response { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; + __le16 major; + __le16 minor; +} __packed; + +/* firmware management load and validate firmware request/response */ +struct gb_fw_mgmt_load_and_validate_fw_request { + __u8 request_id; + __u8 load_method; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; +/* firmware management load and validate firmware response has no payload*/ + +/* firmware management loaded firmware request */ +struct gb_fw_mgmt_loaded_fw_request { + __u8 request_id; + __u8 status; + __le16 major; + __le16 minor; +} __packed; +/* firmware management loaded firmware response has no payload */ + +/* firmware management backend firmware version request/response */ +struct gb_fw_mgmt_backend_fw_version_request { + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; + +struct gb_fw_mgmt_backend_fw_version_response { + __le16 major; + __le16 minor; + __u8 status; +} __packed; + +/* firmware management backend firmware update request */ +struct gb_fw_mgmt_backend_fw_update_request { + __u8 request_id; + __u8 firmware_tag[GB_FIRMWARE_TAG_MAX_SIZE]; +} __packed; +/* firmware management backend firmware update response has no payload */ + +/* firmware management backend firmware updated request */ +struct gb_fw_mgmt_backend_fw_updated_request { + __u8 request_id; + __u8 status; +} __packed; +/* firmware management backend firmware updated response has no payload */ + + +/* Component Authentication Protocol (CAP) */ + +/* Request Types */ +#define GB_CAP_TYPE_GET_ENDPOINT_UID 0x01 +#define GB_CAP_TYPE_GET_IMS_CERTIFICATE 0x02 +#define GB_CAP_TYPE_AUTHENTICATE 0x03 + +/* CAP get endpoint uid request has no payload */ +struct gb_cap_get_endpoint_uid_response { + __u8 uid[8]; +} __packed; + +/* CAP get endpoint ims certificate request/response */ +struct gb_cap_get_ims_certificate_request { + __le32 certificate_class; + __le32 certificate_id; +} __packed; + +struct gb_cap_get_ims_certificate_response { + __u8 result_code; + __u8 certificate[0]; +} __packed; + +/* CAP authenticate request/response */ +struct gb_cap_authenticate_request { + __le32 auth_type; + __u8 uid[8]; + __u8 challenge[32]; +} __packed; + +struct gb_cap_authenticate_response { + __u8 result_code; + __u8 response[64]; + __u8 signature[0]; +} __packed; + + +/* Bootrom Protocol */ + +/* Version of the Greybus bootrom protocol we support */ +#define GB_BOOTROM_VERSION_MAJOR 0x00 +#define GB_BOOTROM_VERSION_MINOR 0x01 + +/* Greybus bootrom request types */ +#define GB_BOOTROM_TYPE_VERSION 0x01 +#define GB_BOOTROM_TYPE_FIRMWARE_SIZE 0x02 +#define GB_BOOTROM_TYPE_GET_FIRMWARE 0x03 +#define GB_BOOTROM_TYPE_READY_TO_BOOT 0x04 +#define GB_BOOTROM_TYPE_AP_READY 0x05 /* Request with no-payload */ +#define GB_BOOTROM_TYPE_GET_VID_PID 0x06 /* Request with no-payload */ + +/* Greybus bootrom boot stages */ +#define GB_BOOTROM_BOOT_STAGE_ONE 0x01 /* Reserved for the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_TWO 0x02 /* Bootrom package to be loaded by the boot ROM */ +#define GB_BOOTROM_BOOT_STAGE_THREE 0x03 /* Module personality package loaded by Stage 2 firmware */ + +/* Greybus bootrom ready to boot status */ +#define GB_BOOTROM_BOOT_STATUS_INVALID 0x00 /* Firmware blob could not be validated */ +#define GB_BOOTROM_BOOT_STATUS_INSECURE 0x01 /* Firmware blob is valid but insecure */ +#define GB_BOOTROM_BOOT_STATUS_SECURE 0x02 /* Firmware blob is valid and secure */ + +/* Max bootrom data fetch size in bytes */ +#define GB_BOOTROM_FETCH_MAX 2000 + +struct gb_bootrom_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_bootrom_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* Bootrom protocol firmware size request/response */ +struct gb_bootrom_firmware_size_request { + __u8 stage; +} __packed; + +struct gb_bootrom_firmware_size_response { + __le32 size; +} __packed; + +/* Bootrom protocol get firmware request/response */ +struct gb_bootrom_get_firmware_request { + __le32 offset; + __le32 size; +} __packed; + +struct gb_bootrom_get_firmware_response { + __u8 data[0]; +} __packed; + +/* Bootrom protocol Ready to boot request */ +struct gb_bootrom_ready_to_boot_request { + __u8 status; +} __packed; +/* Bootrom protocol Ready to boot response has no payload */ + +/* Bootrom protocol get VID/PID request has no payload */ +struct gb_bootrom_get_vid_pid_response { + __le32 vendor_id; + __le32 product_id; +} __packed; + + +/* Power Supply */ + +/* Greybus power supply request types */ +#define GB_POWER_SUPPLY_TYPE_GET_SUPPLIES 0x02 +#define GB_POWER_SUPPLY_TYPE_GET_DESCRIPTION 0x03 +#define GB_POWER_SUPPLY_TYPE_GET_PROP_DESCRIPTORS 0x04 +#define GB_POWER_SUPPLY_TYPE_GET_PROPERTY 0x05 +#define GB_POWER_SUPPLY_TYPE_SET_PROPERTY 0x06 +#define GB_POWER_SUPPLY_TYPE_EVENT 0x07 + +/* Greybus power supply battery technologies types */ +#define GB_POWER_SUPPLY_TECH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_TECH_NiMH 0x0001 +#define GB_POWER_SUPPLY_TECH_LION 0x0002 +#define GB_POWER_SUPPLY_TECH_LIPO 0x0003 +#define GB_POWER_SUPPLY_TECH_LiFe 0x0004 +#define GB_POWER_SUPPLY_TECH_NiCd 0x0005 +#define GB_POWER_SUPPLY_TECH_LiMn 0x0006 + +/* Greybus power supply types */ +#define GB_POWER_SUPPLY_UNKNOWN_TYPE 0x0000 +#define GB_POWER_SUPPLY_BATTERY_TYPE 0x0001 +#define GB_POWER_SUPPLY_UPS_TYPE 0x0002 +#define GB_POWER_SUPPLY_MAINS_TYPE 0x0003 +#define GB_POWER_SUPPLY_USB_TYPE 0x0004 +#define GB_POWER_SUPPLY_USB_DCP_TYPE 0x0005 +#define GB_POWER_SUPPLY_USB_CDP_TYPE 0x0006 +#define GB_POWER_SUPPLY_USB_ACA_TYPE 0x0007 + +/* Greybus power supply health values */ +#define GB_POWER_SUPPLY_HEALTH_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_HEALTH_GOOD 0x0001 +#define GB_POWER_SUPPLY_HEALTH_OVERHEAT 0x0002 +#define GB_POWER_SUPPLY_HEALTH_DEAD 0x0003 +#define GB_POWER_SUPPLY_HEALTH_OVERVOLTAGE 0x0004 +#define GB_POWER_SUPPLY_HEALTH_UNSPEC_FAILURE 0x0005 +#define GB_POWER_SUPPLY_HEALTH_COLD 0x0006 +#define GB_POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE 0x0007 +#define GB_POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE 0x0008 + +/* Greybus power supply status values */ +#define GB_POWER_SUPPLY_STATUS_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_STATUS_CHARGING 0x0001 +#define GB_POWER_SUPPLY_STATUS_DISCHARGING 0x0002 +#define GB_POWER_SUPPLY_STATUS_NOT_CHARGING 0x0003 +#define GB_POWER_SUPPLY_STATUS_FULL 0x0004 + +/* Greybus power supply capacity level values */ +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL 0x0001 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_LOW 0x0002 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_NORMAL 0x0003 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_HIGH 0x0004 +#define GB_POWER_SUPPLY_CAPACITY_LEVEL_FULL 0x0005 + +/* Greybus power supply scope values */ +#define GB_POWER_SUPPLY_SCOPE_UNKNOWN 0x0000 +#define GB_POWER_SUPPLY_SCOPE_SYSTEM 0x0001 +#define GB_POWER_SUPPLY_SCOPE_DEVICE 0x0002 + +struct gb_power_supply_get_supplies_response { + __u8 supplies_count; +} __packed; + +struct gb_power_supply_get_description_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_description_response { + __u8 manufacturer[32]; + __u8 model[32]; + __u8 serial_number[32]; + __le16 type; + __u8 properties_count; +} __packed; + +struct gb_power_supply_props_desc { + __u8 property; +#define GB_POWER_SUPPLY_PROP_STATUS 0x00 +#define GB_POWER_SUPPLY_PROP_CHARGE_TYPE 0x01 +#define GB_POWER_SUPPLY_PROP_HEALTH 0x02 +#define GB_POWER_SUPPLY_PROP_PRESENT 0x03 +#define GB_POWER_SUPPLY_PROP_ONLINE 0x04 +#define GB_POWER_SUPPLY_PROP_AUTHENTIC 0x05 +#define GB_POWER_SUPPLY_PROP_TECHNOLOGY 0x06 +#define GB_POWER_SUPPLY_PROP_CYCLE_COUNT 0x07 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX 0x08 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN 0x09 +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN 0x0A +#define GB_POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN 0x0B +#define GB_POWER_SUPPLY_PROP_VOLTAGE_NOW 0x0C +#define GB_POWER_SUPPLY_PROP_VOLTAGE_AVG 0x0D +#define GB_POWER_SUPPLY_PROP_VOLTAGE_OCV 0x0E +#define GB_POWER_SUPPLY_PROP_VOLTAGE_BOOT 0x0F +#define GB_POWER_SUPPLY_PROP_CURRENT_MAX 0x10 +#define GB_POWER_SUPPLY_PROP_CURRENT_NOW 0x11 +#define GB_POWER_SUPPLY_PROP_CURRENT_AVG 0x12 +#define GB_POWER_SUPPLY_PROP_CURRENT_BOOT 0x13 +#define GB_POWER_SUPPLY_PROP_POWER_NOW 0x14 +#define GB_POWER_SUPPLY_PROP_POWER_AVG 0x15 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN 0x16 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN 0x17 +#define GB_POWER_SUPPLY_PROP_CHARGE_FULL 0x18 +#define GB_POWER_SUPPLY_PROP_CHARGE_EMPTY 0x19 +#define GB_POWER_SUPPLY_PROP_CHARGE_NOW 0x1A +#define GB_POWER_SUPPLY_PROP_CHARGE_AVG 0x1B +#define GB_POWER_SUPPLY_PROP_CHARGE_COUNTER 0x1C +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT 0x1D +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX 0x1E +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE 0x1F +#define GB_POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX 0x20 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT 0x21 +#define GB_POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX 0x22 +#define GB_POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT 0x23 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN 0x24 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN 0x25 +#define GB_POWER_SUPPLY_PROP_ENERGY_FULL 0x26 +#define GB_POWER_SUPPLY_PROP_ENERGY_EMPTY 0x27 +#define GB_POWER_SUPPLY_PROP_ENERGY_NOW 0x28 +#define GB_POWER_SUPPLY_PROP_ENERGY_AVG 0x29 +#define GB_POWER_SUPPLY_PROP_CAPACITY 0x2A +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN 0x2B +#define GB_POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX 0x2C +#define GB_POWER_SUPPLY_PROP_CAPACITY_LEVEL 0x2D +#define GB_POWER_SUPPLY_PROP_TEMP 0x2E +#define GB_POWER_SUPPLY_PROP_TEMP_MAX 0x2F +#define GB_POWER_SUPPLY_PROP_TEMP_MIN 0x30 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MIN 0x31 +#define GB_POWER_SUPPLY_PROP_TEMP_ALERT_MAX 0x32 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT 0x33 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN 0x34 +#define GB_POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX 0x35 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW 0x36 +#define GB_POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG 0x37 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_NOW 0x38 +#define GB_POWER_SUPPLY_PROP_TIME_TO_FULL_AVG 0x39 +#define GB_POWER_SUPPLY_PROP_TYPE 0x3A +#define GB_POWER_SUPPLY_PROP_SCOPE 0x3B +#define GB_POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT 0x3C +#define GB_POWER_SUPPLY_PROP_CALIBRATE 0x3D + __u8 is_writeable; +} __packed; + +struct gb_power_supply_get_property_descriptors_request { + __u8 psy_id; +} __packed; + +struct gb_power_supply_get_property_descriptors_response { + __u8 properties_count; + struct gb_power_supply_props_desc props[]; +} __packed; + +struct gb_power_supply_get_property_request { + __u8 psy_id; + __u8 property; +} __packed; + +struct gb_power_supply_get_property_response { + __le32 prop_val; +}; + +struct gb_power_supply_set_property_request { + __u8 psy_id; + __u8 property; + __le32 prop_val; +} __packed; + +struct gb_power_supply_event_request { + __u8 psy_id; + __u8 event; +#define GB_POWER_SUPPLY_UPDATE 0x01 +} __packed; + + +/* HID */ + +/* Greybus HID operation types */ +#define GB_HID_TYPE_GET_DESC 0x02 +#define GB_HID_TYPE_GET_REPORT_DESC 0x03 +#define GB_HID_TYPE_PWR_ON 0x04 +#define GB_HID_TYPE_PWR_OFF 0x05 +#define GB_HID_TYPE_GET_REPORT 0x06 +#define GB_HID_TYPE_SET_REPORT 0x07 +#define GB_HID_TYPE_IRQ_EVENT 0x08 + +/* Report type */ +#define GB_HID_INPUT_REPORT 0 +#define GB_HID_OUTPUT_REPORT 1 +#define GB_HID_FEATURE_REPORT 2 + +/* Different request/response structures */ +/* HID get descriptor response */ +struct gb_hid_desc_response { + __u8 bLength; + __le16 wReportDescLength; + __le16 bcdHID; + __le16 wProductID; + __le16 wVendorID; + __u8 bCountryCode; +} __packed; + +/* HID get report request/response */ +struct gb_hid_get_report_request { + __u8 report_type; + __u8 report_id; +} __packed; + +/* HID set report request */ +struct gb_hid_set_report_request { + __u8 report_type; + __u8 report_id; + __u8 report[0]; +} __packed; + +/* HID input report request, via interrupt pipe */ +struct gb_hid_input_report_request { + __u8 report[0]; +} __packed; + + +/* I2C */ + +/* Greybus i2c request types */ +#define GB_I2C_TYPE_FUNCTIONALITY 0x02 +#define GB_I2C_TYPE_TRANSFER 0x05 + +/* functionality request has no payload */ +struct gb_i2c_functionality_response { + __le32 functionality; +} __packed; + +/* + * Outgoing data immediately follows the op count and ops array. + * The data for each write (master -> slave) op in the array is sent + * in order, with no (e.g. pad) bytes separating them. + * + * Short reads cause the entire transfer request to fail So response + * payload consists only of bytes read, and the number of bytes is + * exactly what was specified in the corresponding op. Like + * outgoing data, the incoming data is in order and contiguous. + */ +struct gb_i2c_transfer_op { + __le16 addr; + __le16 flags; + __le16 size; +} __packed; + +struct gb_i2c_transfer_request { + __le16 op_count; + struct gb_i2c_transfer_op ops[0]; /* op_count of these */ +} __packed; +struct gb_i2c_transfer_response { + __u8 data[0]; /* inbound data */ +} __packed; + + +/* GPIO */ + +/* Greybus GPIO request types */ +#define GB_GPIO_TYPE_LINE_COUNT 0x02 +#define GB_GPIO_TYPE_ACTIVATE 0x03 +#define GB_GPIO_TYPE_DEACTIVATE 0x04 +#define GB_GPIO_TYPE_GET_DIRECTION 0x05 +#define GB_GPIO_TYPE_DIRECTION_IN 0x06 +#define GB_GPIO_TYPE_DIRECTION_OUT 0x07 +#define GB_GPIO_TYPE_GET_VALUE 0x08 +#define GB_GPIO_TYPE_SET_VALUE 0x09 +#define GB_GPIO_TYPE_SET_DEBOUNCE 0x0a +#define GB_GPIO_TYPE_IRQ_TYPE 0x0b +#define GB_GPIO_TYPE_IRQ_MASK 0x0c +#define GB_GPIO_TYPE_IRQ_UNMASK 0x0d +#define GB_GPIO_TYPE_IRQ_EVENT 0x0e + +#define GB_GPIO_IRQ_TYPE_NONE 0x00 +#define GB_GPIO_IRQ_TYPE_EDGE_RISING 0x01 +#define GB_GPIO_IRQ_TYPE_EDGE_FALLING 0x02 +#define GB_GPIO_IRQ_TYPE_EDGE_BOTH 0x03 +#define GB_GPIO_IRQ_TYPE_LEVEL_HIGH 0x04 +#define GB_GPIO_IRQ_TYPE_LEVEL_LOW 0x08 + +/* line count request has no payload */ +struct gb_gpio_line_count_response { + __u8 count; +} __packed; + +struct gb_gpio_activate_request { + __u8 which; +} __packed; +/* activate response has no payload */ + +struct gb_gpio_deactivate_request { + __u8 which; +} __packed; +/* deactivate response has no payload */ + +struct gb_gpio_get_direction_request { + __u8 which; +} __packed; +struct gb_gpio_get_direction_response { + __u8 direction; +} __packed; + +struct gb_gpio_direction_in_request { + __u8 which; +} __packed; +/* direction in response has no payload */ + +struct gb_gpio_direction_out_request { + __u8 which; + __u8 value; +} __packed; +/* direction out response has no payload */ + +struct gb_gpio_get_value_request { + __u8 which; +} __packed; +struct gb_gpio_get_value_response { + __u8 value; +} __packed; + +struct gb_gpio_set_value_request { + __u8 which; + __u8 value; +} __packed; +/* set value response has no payload */ + +struct gb_gpio_set_debounce_request { + __u8 which; + __le16 usec; +} __packed; +/* debounce response has no payload */ + +struct gb_gpio_irq_type_request { + __u8 which; + __u8 type; +} __packed; +/* irq type response has no payload */ + +struct gb_gpio_irq_mask_request { + __u8 which; +} __packed; +/* irq mask response has no payload */ + +struct gb_gpio_irq_unmask_request { + __u8 which; +} __packed; +/* irq unmask response has no payload */ + +/* irq event requests originate on another module and are handled on the AP */ +struct gb_gpio_irq_event_request { + __u8 which; +} __packed; +/* irq event has no response */ + + +/* PWM */ + +/* Greybus PWM operation types */ +#define GB_PWM_TYPE_PWM_COUNT 0x02 +#define GB_PWM_TYPE_ACTIVATE 0x03 +#define GB_PWM_TYPE_DEACTIVATE 0x04 +#define GB_PWM_TYPE_CONFIG 0x05 +#define GB_PWM_TYPE_POLARITY 0x06 +#define GB_PWM_TYPE_ENABLE 0x07 +#define GB_PWM_TYPE_DISABLE 0x08 + +/* pwm count request has no payload */ +struct gb_pwm_count_response { + __u8 count; +} __packed; + +struct gb_pwm_activate_request { + __u8 which; +} __packed; + +struct gb_pwm_deactivate_request { + __u8 which; +} __packed; + +struct gb_pwm_config_request { + __u8 which; + __le32 duty; + __le32 period; +} __packed; + +struct gb_pwm_polarity_request { + __u8 which; + __u8 polarity; +} __packed; + +struct gb_pwm_enable_request { + __u8 which; +} __packed; + +struct gb_pwm_disable_request { + __u8 which; +} __packed; + +/* SPI */ + +/* Should match up with modes in linux/spi/spi.h */ +#define GB_SPI_MODE_CPHA 0x01 /* clock phase */ +#define GB_SPI_MODE_CPOL 0x02 /* clock polarity */ +#define GB_SPI_MODE_MODE_0 (0 | 0) /* (original MicroWire) */ +#define GB_SPI_MODE_MODE_1 (0 | GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_MODE_2 (GB_SPI_MODE_CPOL | 0) +#define GB_SPI_MODE_MODE_3 (GB_SPI_MODE_CPOL | GB_SPI_MODE_CPHA) +#define GB_SPI_MODE_CS_HIGH 0x04 /* chipselect active high? */ +#define GB_SPI_MODE_LSB_FIRST 0x08 /* per-word bits-on-wire */ +#define GB_SPI_MODE_3WIRE 0x10 /* SI/SO signals shared */ +#define GB_SPI_MODE_LOOP 0x20 /* loopback mode */ +#define GB_SPI_MODE_NO_CS 0x40 /* 1 dev/bus, no chipselect */ +#define GB_SPI_MODE_READY 0x80 /* slave pulls low to pause */ + +/* Should match up with flags in linux/spi/spi.h */ +#define GB_SPI_FLAG_HALF_DUPLEX BIT(0) /* can't do full duplex */ +#define GB_SPI_FLAG_NO_RX BIT(1) /* can't do buffer read */ +#define GB_SPI_FLAG_NO_TX BIT(2) /* can't do buffer write */ + +/* Greybus spi operation types */ +#define GB_SPI_TYPE_MASTER_CONFIG 0x02 +#define GB_SPI_TYPE_DEVICE_CONFIG 0x03 +#define GB_SPI_TYPE_TRANSFER 0x04 + +/* mode request has no payload */ +struct gb_spi_master_config_response { + __le32 bits_per_word_mask; + __le32 min_speed_hz; + __le32 max_speed_hz; + __le16 mode; + __le16 flags; + __u8 num_chipselect; +} __packed; + +struct gb_spi_device_config_request { + __u8 chip_select; +} __packed; + +struct gb_spi_device_config_response { + __le16 mode; + __u8 bits_per_word; + __le32 max_speed_hz; + __u8 device_type; +#define GB_SPI_SPI_DEV 0x00 +#define GB_SPI_SPI_NOR 0x01 +#define GB_SPI_SPI_MODALIAS 0x02 + __u8 name[32]; +} __packed; + +/** + * struct gb_spi_transfer - a read/write buffer pair + * @speed_hz: Select a speed other than the device default for this transfer. If + * 0 the default (from @spi_device) is used. + * @len: size of rx and tx buffers (in bytes) + * @delay_usecs: microseconds to delay after this transfer before (optionally) + * changing the chipselect status, then starting the next transfer or + * completing this spi_message. + * @cs_change: affects chipselect after this transfer completes + * @bits_per_word: select a bits_per_word other than the device default for this + * transfer. If 0 the default (from @spi_device) is used. + */ +struct gb_spi_transfer { + __le32 speed_hz; + __le32 len; + __le16 delay_usecs; + __u8 cs_change; + __u8 bits_per_word; + __u8 xfer_flags; +#define GB_SPI_XFER_READ 0x01 +#define GB_SPI_XFER_WRITE 0x02 +#define GB_SPI_XFER_INPROGRESS 0x04 +} __packed; + +struct gb_spi_transfer_request { + __u8 chip_select; /* of the spi device */ + __u8 mode; /* of the spi device */ + __le16 count; + struct gb_spi_transfer transfers[0]; /* count of these */ +} __packed; + +struct gb_spi_transfer_response { + __u8 data[0]; /* inbound data */ +} __packed; + +/* Version of the Greybus SVC protocol we support */ +#define GB_SVC_VERSION_MAJOR 0x00 +#define GB_SVC_VERSION_MINOR 0x01 + +/* Greybus SVC request types */ +#define GB_SVC_TYPE_PROTOCOL_VERSION 0x01 +#define GB_SVC_TYPE_SVC_HELLO 0x02 +#define GB_SVC_TYPE_INTF_DEVICE_ID 0x03 +#define GB_SVC_TYPE_INTF_RESET 0x06 +#define GB_SVC_TYPE_CONN_CREATE 0x07 +#define GB_SVC_TYPE_CONN_DESTROY 0x08 +#define GB_SVC_TYPE_DME_PEER_GET 0x09 +#define GB_SVC_TYPE_DME_PEER_SET 0x0a +#define GB_SVC_TYPE_ROUTE_CREATE 0x0b +#define GB_SVC_TYPE_ROUTE_DESTROY 0x0c +#define GB_SVC_TYPE_TIMESYNC_ENABLE 0x0d +#define GB_SVC_TYPE_TIMESYNC_DISABLE 0x0e +#define GB_SVC_TYPE_TIMESYNC_AUTHORITATIVE 0x0f +#define GB_SVC_TYPE_INTF_SET_PWRM 0x10 +#define GB_SVC_TYPE_INTF_EJECT 0x11 +#define GB_SVC_TYPE_PING 0x13 +#define GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET 0x14 +#define GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET 0x15 +#define GB_SVC_TYPE_PWRMON_SAMPLE_GET 0x16 +#define GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET 0x17 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_ACQUIRE 0x18 +#define GB_SVC_TYPE_TIMESYNC_WAKE_PINS_RELEASE 0x19 +#define GB_SVC_TYPE_TIMESYNC_PING 0x1a +#define GB_SVC_TYPE_MODULE_INSERTED 0x1f +#define GB_SVC_TYPE_MODULE_REMOVED 0x20 +#define GB_SVC_TYPE_INTF_VSYS_ENABLE 0x21 +#define GB_SVC_TYPE_INTF_VSYS_DISABLE 0x22 +#define GB_SVC_TYPE_INTF_REFCLK_ENABLE 0x23 +#define GB_SVC_TYPE_INTF_REFCLK_DISABLE 0x24 +#define GB_SVC_TYPE_INTF_UNIPRO_ENABLE 0x25 +#define GB_SVC_TYPE_INTF_UNIPRO_DISABLE 0x26 +#define GB_SVC_TYPE_INTF_ACTIVATE 0x27 +#define GB_SVC_TYPE_INTF_RESUME 0x28 +#define GB_SVC_TYPE_INTF_MAILBOX_EVENT 0x29 +#define GB_SVC_TYPE_INTF_OOPS 0x2a + +/* Greybus SVC protocol status values */ +#define GB_SVC_OP_SUCCESS 0x00 +#define GB_SVC_OP_UNKNOWN_ERROR 0x01 +#define GB_SVC_INTF_NOT_DETECTED 0x02 +#define GB_SVC_INTF_NO_UPRO_LINK 0x03 +#define GB_SVC_INTF_UPRO_NOT_DOWN 0x04 +#define GB_SVC_INTF_UPRO_NOT_HIBERNATED 0x05 +#define GB_SVC_INTF_NO_V_SYS 0x06 +#define GB_SVC_INTF_V_CHG 0x07 +#define GB_SVC_INTF_WAKE_BUSY 0x08 +#define GB_SVC_INTF_NO_REFCLK 0x09 +#define GB_SVC_INTF_RELEASING 0x0a +#define GB_SVC_INTF_NO_ORDER 0x0b +#define GB_SVC_INTF_MBOX_SET 0x0c +#define GB_SVC_INTF_BAD_MBOX 0x0d +#define GB_SVC_INTF_OP_TIMEOUT 0x0e +#define GB_SVC_PWRMON_OP_NOT_PRESENT 0x0f + +struct gb_svc_version_request { + __u8 major; + __u8 minor; +} __packed; + +struct gb_svc_version_response { + __u8 major; + __u8 minor; +} __packed; + +/* SVC protocol hello request */ +struct gb_svc_hello_request { + __le16 endo_id; + __u8 interface_id; +} __packed; +/* hello response has no payload */ + +struct gb_svc_intf_device_id_request { + __u8 intf_id; + __u8 device_id; +} __packed; +/* device id response has no payload */ + +struct gb_svc_intf_reset_request { + __u8 intf_id; +} __packed; +/* interface reset response has no payload */ + +struct gb_svc_intf_eject_request { + __u8 intf_id; +} __packed; +/* interface eject response has no payload */ + +struct gb_svc_conn_create_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; + __u8 tc; + __u8 flags; +} __packed; +/* connection create response has no payload */ + +struct gb_svc_conn_destroy_request { + __u8 intf1_id; + __le16 cport1_id; + __u8 intf2_id; + __le16 cport2_id; +} __packed; +/* connection destroy response has no payload */ + +struct gb_svc_dme_peer_get_request { + __u8 intf_id; + __le16 attr; + __le16 selector; +} __packed; + +struct gb_svc_dme_peer_get_response { + __le16 result_code; + __le32 attr_value; +} __packed; + +struct gb_svc_dme_peer_set_request { + __u8 intf_id; + __le16 attr; + __le16 selector; + __le32 value; +} __packed; + +struct gb_svc_dme_peer_set_response { + __le16 result_code; +} __packed; + +/* Greybus init-status values, currently retrieved using DME peer gets. */ +#define GB_INIT_SPI_BOOT_STARTED 0x02 +#define GB_INIT_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define GB_INIT_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED 0x06 +#define GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED 0x09 +#define GB_INIT_S2_LOADER_BOOT_STARTED 0x0D + +struct gb_svc_route_create_request { + __u8 intf1_id; + __u8 dev1_id; + __u8 intf2_id; + __u8 dev2_id; +} __packed; +/* route create response has no payload */ + +struct gb_svc_route_destroy_request { + __u8 intf1_id; + __u8 intf2_id; +} __packed; +/* route destroy response has no payload */ + +/* used for svc_intf_vsys_{enable,disable} */ +struct gb_svc_intf_vsys_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_vsys_response { + __u8 result_code; +#define GB_SVC_INTF_VSYS_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_VSYS_FAIL 0x02 +} __packed; + +/* used for svc_intf_refclk_{enable,disable} */ +struct gb_svc_intf_refclk_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_refclk_response { + __u8 result_code; +#define GB_SVC_INTF_REFCLK_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_REFCLK_FAIL 0x02 +} __packed; + +/* used for svc_intf_unipro_{enable,disable} */ +struct gb_svc_intf_unipro_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_unipro_response { + __u8 result_code; +#define GB_SVC_INTF_UNIPRO_OK 0x00 + /* 0x01 is reserved */ +#define GB_SVC_INTF_UNIPRO_FAIL 0x02 +#define GB_SVC_INTF_UNIPRO_NOT_OFF 0x03 +} __packed; + +#define GB_SVC_UNIPRO_FAST_MODE 0x01 +#define GB_SVC_UNIPRO_SLOW_MODE 0x02 +#define GB_SVC_UNIPRO_FAST_AUTO_MODE 0x04 +#define GB_SVC_UNIPRO_SLOW_AUTO_MODE 0x05 +#define GB_SVC_UNIPRO_MODE_UNCHANGED 0x07 +#define GB_SVC_UNIPRO_HIBERNATE_MODE 0x11 +#define GB_SVC_UNIPRO_OFF_MODE 0x12 + +#define GB_SVC_SMALL_AMPLITUDE 0x01 +#define GB_SVC_LARGE_AMPLITUDE 0x02 + +#define GB_SVC_NO_DE_EMPHASIS 0x00 +#define GB_SVC_SMALL_DE_EMPHASIS 0x01 +#define GB_SVC_LARGE_DE_EMPHASIS 0x02 + +#define GB_SVC_PWRM_RXTERMINATION 0x01 +#define GB_SVC_PWRM_TXTERMINATION 0x02 +#define GB_SVC_PWRM_LINE_RESET 0x04 +#define GB_SVC_PWRM_SCRAMBLING 0x20 + +#define GB_SVC_PWRM_QUIRK_HSSER 0x00000001 + +#define GB_SVC_UNIPRO_HS_SERIES_A 0x01 +#define GB_SVC_UNIPRO_HS_SERIES_B 0x02 + +#define GB_SVC_SETPWRM_PWR_OK 0x00 +#define GB_SVC_SETPWRM_PWR_LOCAL 0x01 +#define GB_SVC_SETPWRM_PWR_REMOTE 0x02 +#define GB_SVC_SETPWRM_PWR_BUSY 0x03 +#define GB_SVC_SETPWRM_PWR_ERROR_CAP 0x04 +#define GB_SVC_SETPWRM_PWR_FATAL_ERROR 0x05 + +struct gb_svc_l2_timer_cfg { + __le16 tsb_fc0_protection_timeout; + __le16 tsb_tc0_replay_timeout; + __le16 tsb_afc0_req_timeout; + __le16 tsb_fc1_protection_timeout; + __le16 tsb_tc1_replay_timeout; + __le16 tsb_afc1_req_timeout; + __le16 reserved_for_tc2[3]; + __le16 reserved_for_tc3[3]; +} __packed; + +struct gb_svc_intf_set_pwrm_request { + __u8 intf_id; + __u8 hs_series; + __u8 tx_mode; + __u8 tx_gear; + __u8 tx_nlanes; + __u8 tx_amplitude; + __u8 tx_hs_equalizer; + __u8 rx_mode; + __u8 rx_gear; + __u8 rx_nlanes; + __u8 flags; + __le32 quirks; + struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata; +} __packed; + +struct gb_svc_intf_set_pwrm_response { + __u8 result_code; +} __packed; + +struct gb_svc_key_event_request { + __le16 key_code; +#define GB_KEYCODE_ARA 0x00 + + __u8 key_event; +#define GB_SVC_KEY_RELEASED 0x00 +#define GB_SVC_KEY_PRESSED 0x01 +} __packed; + +#define GB_SVC_PWRMON_MAX_RAIL_COUNT 254 + +struct gb_svc_pwrmon_rail_count_get_response { + __u8 rail_count; +} __packed; + +#define GB_SVC_PWRMON_RAIL_NAME_BUFSIZE 32 + +struct gb_svc_pwrmon_rail_names_get_response { + __u8 status; + __u8 name[0][GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; +} __packed; + +#define GB_SVC_PWRMON_TYPE_CURR 0x01 +#define GB_SVC_PWRMON_TYPE_VOL 0x02 +#define GB_SVC_PWRMON_TYPE_PWR 0x03 + +#define GB_SVC_PWRMON_GET_SAMPLE_OK 0x00 +#define GB_SVC_PWRMON_GET_SAMPLE_INVAL 0x01 +#define GB_SVC_PWRMON_GET_SAMPLE_NOSUPP 0x02 +#define GB_SVC_PWRMON_GET_SAMPLE_HWERR 0x03 + +struct gb_svc_pwrmon_sample_get_request { + __u8 rail_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_request { + __u8 intf_id; + __u8 measurement_type; +} __packed; + +struct gb_svc_pwrmon_intf_sample_get_response { + __u8 result; + __le32 measurement; +} __packed; + +#define GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY 0x0001 + +struct gb_svc_module_inserted_request { + __u8 primary_intf_id; + __u8 intf_count; + __le16 flags; +} __packed; +/* module_inserted response has no payload */ + +struct gb_svc_module_removed_request { + __u8 primary_intf_id; +} __packed; +/* module_removed response has no payload */ + +struct gb_svc_intf_activate_request { + __u8 intf_id; +} __packed; + +#define GB_SVC_INTF_TYPE_UNKNOWN 0x00 +#define GB_SVC_INTF_TYPE_DUMMY 0x01 +#define GB_SVC_INTF_TYPE_UNIPRO 0x02 +#define GB_SVC_INTF_TYPE_GREYBUS 0x03 + +struct gb_svc_intf_activate_response { + __u8 status; + __u8 intf_type; +} __packed; + +struct gb_svc_intf_resume_request { + __u8 intf_id; +} __packed; + +struct gb_svc_intf_resume_response { + __u8 status; +} __packed; + +#define GB_SVC_INTF_MAILBOX_NONE 0x00 +#define GB_SVC_INTF_MAILBOX_AP 0x01 +#define GB_SVC_INTF_MAILBOX_GREYBUS 0x02 + +struct gb_svc_intf_mailbox_event_request { + __u8 intf_id; + __le16 result_code; + __le32 mailbox; +} __packed; +/* intf_mailbox_event response has no payload */ + +struct gb_svc_intf_oops_request { + __u8 intf_id; + __u8 reason; +} __packed; +/* intf_oops response has no payload */ + + +/* RAW */ + +/* Greybus raw request types */ +#define GB_RAW_TYPE_SEND 0x02 + +struct gb_raw_send_request { + __le32 len; + __u8 data[0]; +} __packed; + + +/* UART */ + +/* Greybus UART operation types */ +#define GB_UART_TYPE_SEND_DATA 0x02 +#define GB_UART_TYPE_RECEIVE_DATA 0x03 /* Unsolicited data */ +#define GB_UART_TYPE_SET_LINE_CODING 0x04 +#define GB_UART_TYPE_SET_CONTROL_LINE_STATE 0x05 +#define GB_UART_TYPE_SEND_BREAK 0x06 +#define GB_UART_TYPE_SERIAL_STATE 0x07 /* Unsolicited data */ +#define GB_UART_TYPE_RECEIVE_CREDITS 0x08 +#define GB_UART_TYPE_FLUSH_FIFOS 0x09 + +/* Represents data from AP -> Module */ +struct gb_uart_send_data_request { + __le16 size; + __u8 data[0]; +} __packed; + +/* recv-data-request flags */ +#define GB_UART_RECV_FLAG_FRAMING 0x01 /* Framing error */ +#define GB_UART_RECV_FLAG_PARITY 0x02 /* Parity error */ +#define GB_UART_RECV_FLAG_OVERRUN 0x04 /* Overrun error */ +#define GB_UART_RECV_FLAG_BREAK 0x08 /* Break */ + +/* Represents data from Module -> AP */ +struct gb_uart_recv_data_request { + __le16 size; + __u8 flags; + __u8 data[0]; +} __packed; + +struct gb_uart_receive_credits_request { + __le16 count; +} __packed; + +struct gb_uart_set_line_coding_request { + __le32 rate; + __u8 format; +#define GB_SERIAL_1_STOP_BITS 0 +#define GB_SERIAL_1_5_STOP_BITS 1 +#define GB_SERIAL_2_STOP_BITS 2 + + __u8 parity; +#define GB_SERIAL_NO_PARITY 0 +#define GB_SERIAL_ODD_PARITY 1 +#define GB_SERIAL_EVEN_PARITY 2 +#define GB_SERIAL_MARK_PARITY 3 +#define GB_SERIAL_SPACE_PARITY 4 + + __u8 data_bits; + + __u8 flow_control; +#define GB_SERIAL_AUTO_RTSCTS_EN 0x1 +} __packed; + +/* output control lines */ +#define GB_UART_CTRL_DTR 0x01 +#define GB_UART_CTRL_RTS 0x02 + +struct gb_uart_set_control_line_state_request { + __u8 control; +} __packed; + +struct gb_uart_set_break_request { + __u8 state; +} __packed; + +/* input control lines and line errors */ +#define GB_UART_CTRL_DCD 0x01 +#define GB_UART_CTRL_DSR 0x02 +#define GB_UART_CTRL_RI 0x04 + +struct gb_uart_serial_state_request { + __u8 control; +} __packed; + +struct gb_uart_serial_flush_request { + __u8 flags; +#define GB_SERIAL_FLAG_FLUSH_TRANSMITTER 0x01 +#define GB_SERIAL_FLAG_FLUSH_RECEIVER 0x02 +} __packed; + +/* Loopback */ + +/* Greybus loopback request types */ +#define GB_LOOPBACK_TYPE_PING 0x02 +#define GB_LOOPBACK_TYPE_TRANSFER 0x03 +#define GB_LOOPBACK_TYPE_SINK 0x04 + +/* + * Loopback request/response header format should be identical + * to simplify bandwidth and data movement analysis. + */ +struct gb_loopback_transfer_request { + __le32 len; + __le32 reserved0; + __le32 reserved1; + __u8 data[0]; +} __packed; + +struct gb_loopback_transfer_response { + __le32 len; + __le32 reserved0; + __le32 reserved1; + __u8 data[0]; +} __packed; + +/* SDIO */ +/* Greybus SDIO operation types */ +#define GB_SDIO_TYPE_GET_CAPABILITIES 0x02 +#define GB_SDIO_TYPE_SET_IOS 0x03 +#define GB_SDIO_TYPE_COMMAND 0x04 +#define GB_SDIO_TYPE_TRANSFER 0x05 +#define GB_SDIO_TYPE_EVENT 0x06 + +/* get caps response: request has no payload */ +struct gb_sdio_get_caps_response { + __le32 caps; +#define GB_SDIO_CAP_NONREMOVABLE 0x00000001 +#define GB_SDIO_CAP_4_BIT_DATA 0x00000002 +#define GB_SDIO_CAP_8_BIT_DATA 0x00000004 +#define GB_SDIO_CAP_MMC_HS 0x00000008 +#define GB_SDIO_CAP_SD_HS 0x00000010 +#define GB_SDIO_CAP_ERASE 0x00000020 +#define GB_SDIO_CAP_1_2V_DDR 0x00000040 +#define GB_SDIO_CAP_1_8V_DDR 0x00000080 +#define GB_SDIO_CAP_POWER_OFF_CARD 0x00000100 +#define GB_SDIO_CAP_UHS_SDR12 0x00000200 +#define GB_SDIO_CAP_UHS_SDR25 0x00000400 +#define GB_SDIO_CAP_UHS_SDR50 0x00000800 +#define GB_SDIO_CAP_UHS_SDR104 0x00001000 +#define GB_SDIO_CAP_UHS_DDR50 0x00002000 +#define GB_SDIO_CAP_DRIVER_TYPE_A 0x00004000 +#define GB_SDIO_CAP_DRIVER_TYPE_C 0x00008000 +#define GB_SDIO_CAP_DRIVER_TYPE_D 0x00010000 +#define GB_SDIO_CAP_HS200_1_2V 0x00020000 +#define GB_SDIO_CAP_HS200_1_8V 0x00040000 +#define GB_SDIO_CAP_HS400_1_2V 0x00080000 +#define GB_SDIO_CAP_HS400_1_8V 0x00100000 + + /* see possible values below at vdd */ + __le32 ocr; + __le32 f_min; + __le32 f_max; + __le16 max_blk_count; + __le16 max_blk_size; +} __packed; + +/* set ios request: response has no payload */ +struct gb_sdio_set_ios_request { + __le32 clock; + __le32 vdd; +#define GB_SDIO_VDD_165_195 0x00000001 +#define GB_SDIO_VDD_20_21 0x00000002 +#define GB_SDIO_VDD_21_22 0x00000004 +#define GB_SDIO_VDD_22_23 0x00000008 +#define GB_SDIO_VDD_23_24 0x00000010 +#define GB_SDIO_VDD_24_25 0x00000020 +#define GB_SDIO_VDD_25_26 0x00000040 +#define GB_SDIO_VDD_26_27 0x00000080 +#define GB_SDIO_VDD_27_28 0x00000100 +#define GB_SDIO_VDD_28_29 0x00000200 +#define GB_SDIO_VDD_29_30 0x00000400 +#define GB_SDIO_VDD_30_31 0x00000800 +#define GB_SDIO_VDD_31_32 0x00001000 +#define GB_SDIO_VDD_32_33 0x00002000 +#define GB_SDIO_VDD_33_34 0x00004000 +#define GB_SDIO_VDD_34_35 0x00008000 +#define GB_SDIO_VDD_35_36 0x00010000 + + __u8 bus_mode; +#define GB_SDIO_BUSMODE_OPENDRAIN 0x00 +#define GB_SDIO_BUSMODE_PUSHPULL 0x01 + + __u8 power_mode; +#define GB_SDIO_POWER_OFF 0x00 +#define GB_SDIO_POWER_UP 0x01 +#define GB_SDIO_POWER_ON 0x02 +#define GB_SDIO_POWER_UNDEFINED 0x03 + + __u8 bus_width; +#define GB_SDIO_BUS_WIDTH_1 0x00 +#define GB_SDIO_BUS_WIDTH_4 0x02 +#define GB_SDIO_BUS_WIDTH_8 0x03 + + __u8 timing; +#define GB_SDIO_TIMING_LEGACY 0x00 +#define GB_SDIO_TIMING_MMC_HS 0x01 +#define GB_SDIO_TIMING_SD_HS 0x02 +#define GB_SDIO_TIMING_UHS_SDR12 0x03 +#define GB_SDIO_TIMING_UHS_SDR25 0x04 +#define GB_SDIO_TIMING_UHS_SDR50 0x05 +#define GB_SDIO_TIMING_UHS_SDR104 0x06 +#define GB_SDIO_TIMING_UHS_DDR50 0x07 +#define GB_SDIO_TIMING_MMC_DDR52 0x08 +#define GB_SDIO_TIMING_MMC_HS200 0x09 +#define GB_SDIO_TIMING_MMC_HS400 0x0A + + __u8 signal_voltage; +#define GB_SDIO_SIGNAL_VOLTAGE_330 0x00 +#define GB_SDIO_SIGNAL_VOLTAGE_180 0x01 +#define GB_SDIO_SIGNAL_VOLTAGE_120 0x02 + + __u8 drv_type; +#define GB_SDIO_SET_DRIVER_TYPE_B 0x00 +#define GB_SDIO_SET_DRIVER_TYPE_A 0x01 +#define GB_SDIO_SET_DRIVER_TYPE_C 0x02 +#define GB_SDIO_SET_DRIVER_TYPE_D 0x03 +} __packed; + +/* command request */ +struct gb_sdio_command_request { + __u8 cmd; + __u8 cmd_flags; +#define GB_SDIO_RSP_NONE 0x00 +#define GB_SDIO_RSP_PRESENT 0x01 +#define GB_SDIO_RSP_136 0x02 +#define GB_SDIO_RSP_CRC 0x04 +#define GB_SDIO_RSP_BUSY 0x08 +#define GB_SDIO_RSP_OPCODE 0x10 + + __u8 cmd_type; +#define GB_SDIO_CMD_AC 0x00 +#define GB_SDIO_CMD_ADTC 0x01 +#define GB_SDIO_CMD_BC 0x02 +#define GB_SDIO_CMD_BCR 0x03 + + __le32 cmd_arg; + __le16 data_blocks; + __le16 data_blksz; +} __packed; + +struct gb_sdio_command_response { + __le32 resp[4]; +} __packed; + +/* transfer request */ +struct gb_sdio_transfer_request { + __u8 data_flags; +#define GB_SDIO_DATA_WRITE 0x01 +#define GB_SDIO_DATA_READ 0x02 +#define GB_SDIO_DATA_STREAM 0x04 + + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +} __packed; + +struct gb_sdio_transfer_response { + __le16 data_blocks; + __le16 data_blksz; + __u8 data[0]; +} __packed; + +/* event request: generated by module and is defined as unidirectional */ +struct gb_sdio_event_request { + __u8 event; +#define GB_SDIO_CARD_INSERTED 0x01 +#define GB_SDIO_CARD_REMOVED 0x02 +#define GB_SDIO_WP 0x04 +} __packed; + +/* Camera */ + +/* Greybus Camera request types */ +#define GB_CAMERA_TYPE_CAPABILITIES 0x02 +#define GB_CAMERA_TYPE_CONFIGURE_STREAMS 0x03 +#define GB_CAMERA_TYPE_CAPTURE 0x04 +#define GB_CAMERA_TYPE_FLUSH 0x05 +#define GB_CAMERA_TYPE_METADATA 0x06 + +#define GB_CAMERA_MAX_STREAMS 4 +#define GB_CAMERA_MAX_SETTINGS_SIZE 8192 + +/* Greybus Camera Configure Streams request payload */ +struct gb_camera_stream_config_request { + __le16 width; + __le16 height; + __le16 format; + __le16 padding; +} __packed; + +struct gb_camera_configure_streams_request { + __u8 num_streams; + __u8 flags; +#define GB_CAMERA_CONFIGURE_STREAMS_TEST_ONLY 0x01 + __le16 padding; + struct gb_camera_stream_config_request config[0]; +} __packed; + +/* Greybus Camera Configure Streams response payload */ +struct gb_camera_stream_config_response { + __le16 width; + __le16 height; + __le16 format; + __u8 virtual_channel; + __u8 data_type[2]; + __le16 max_pkt_size; + __u8 padding; + __le32 max_size; +} __packed; + +struct gb_camera_configure_streams_response { + __u8 num_streams; +#define GB_CAMERA_CONFIGURE_STREAMS_ADJUSTED 0x01 + __u8 flags; + __u8 padding[2]; + __le32 data_rate; + struct gb_camera_stream_config_response config[0]; +}; + +/* Greybus Camera Capture request payload - response has no payload */ +struct gb_camera_capture_request { + __le32 request_id; + __u8 streams; + __u8 padding; + __le16 num_frames; + __u8 settings[0]; +} __packed; + +/* Greybus Camera Flush response payload - request has no payload */ +struct gb_camera_flush_response { + __le32 request_id; +} __packed; + +/* Greybus Camera Metadata request payload - operation has no response */ +struct gb_camera_metadata_request { + __le32 request_id; + __le16 frame_number; + __u8 stream; + __u8 padding; + __u8 metadata[0]; +} __packed; + +/* Lights */ + +/* Greybus Lights request types */ +#define GB_LIGHTS_TYPE_GET_LIGHTS 0x02 +#define GB_LIGHTS_TYPE_GET_LIGHT_CONFIG 0x03 +#define GB_LIGHTS_TYPE_GET_CHANNEL_CONFIG 0x04 +#define GB_LIGHTS_TYPE_GET_CHANNEL_FLASH_CONFIG 0x05 +#define GB_LIGHTS_TYPE_SET_BRIGHTNESS 0x06 +#define GB_LIGHTS_TYPE_SET_BLINK 0x07 +#define GB_LIGHTS_TYPE_SET_COLOR 0x08 +#define GB_LIGHTS_TYPE_SET_FADE 0x09 +#define GB_LIGHTS_TYPE_EVENT 0x0A +#define GB_LIGHTS_TYPE_SET_FLASH_INTENSITY 0x0B +#define GB_LIGHTS_TYPE_SET_FLASH_STROBE 0x0C +#define GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT 0x0D +#define GB_LIGHTS_TYPE_GET_FLASH_FAULT 0x0E + +/* Greybus Light modes */ + +/* + * if you add any specific mode below, update also the + * GB_CHANNEL_MODE_DEFINED_RANGE value accordingly + */ +#define GB_CHANNEL_MODE_NONE 0x00000000 +#define GB_CHANNEL_MODE_BATTERY 0x00000001 +#define GB_CHANNEL_MODE_POWER 0x00000002 +#define GB_CHANNEL_MODE_WIRELESS 0x00000004 +#define GB_CHANNEL_MODE_BLUETOOTH 0x00000008 +#define GB_CHANNEL_MODE_KEYBOARD 0x00000010 +#define GB_CHANNEL_MODE_BUTTONS 0x00000020 +#define GB_CHANNEL_MODE_NOTIFICATION 0x00000040 +#define GB_CHANNEL_MODE_ATTENTION 0x00000080 +#define GB_CHANNEL_MODE_FLASH 0x00000100 +#define GB_CHANNEL_MODE_TORCH 0x00000200 +#define GB_CHANNEL_MODE_INDICATOR 0x00000400 + +/* Lights Mode valid bit values */ +#define GB_CHANNEL_MODE_DEFINED_RANGE 0x000004FF +#define GB_CHANNEL_MODE_VENDOR_RANGE 0x00F00000 + +/* Greybus Light Channels Flags */ +#define GB_LIGHT_CHANNEL_MULTICOLOR 0x00000001 +#define GB_LIGHT_CHANNEL_FADER 0x00000002 +#define GB_LIGHT_CHANNEL_BLINK 0x00000004 + +/* get count of lights in module */ +struct gb_lights_get_lights_response { + __u8 lights_count; +} __packed; + +/* light config request payload */ +struct gb_lights_get_light_config_request { + __u8 id; +} __packed; + +/* light config response payload */ +struct gb_lights_get_light_config_response { + __u8 channel_count; + __u8 name[32]; +} __packed; + +/* channel config request payload */ +struct gb_lights_get_channel_config_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* channel flash config request payload */ +struct gb_lights_get_channel_flash_config_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* channel config response payload */ +struct gb_lights_get_channel_config_response { + __u8 max_brightness; + __le32 flags; + __le32 color; + __u8 color_name[32]; + __le32 mode; + __u8 mode_name[32]; +} __packed; + +/* channel flash config response payload */ +struct gb_lights_get_channel_flash_config_response { + __le32 intensity_min_uA; + __le32 intensity_max_uA; + __le32 intensity_step_uA; + __le32 timeout_min_us; + __le32 timeout_max_us; + __le32 timeout_step_us; +} __packed; + +/* blink request payload: response have no payload */ +struct gb_lights_blink_request { + __u8 light_id; + __u8 channel_id; + __le16 time_on_ms; + __le16 time_off_ms; +} __packed; + +/* set brightness request payload: response have no payload */ +struct gb_lights_set_brightness_request { + __u8 light_id; + __u8 channel_id; + __u8 brightness; +} __packed; + +/* set color request payload: response have no payload */ +struct gb_lights_set_color_request { + __u8 light_id; + __u8 channel_id; + __le32 color; +} __packed; + +/* set fade request payload: response have no payload */ +struct gb_lights_set_fade_request { + __u8 light_id; + __u8 channel_id; + __u8 fade_in; + __u8 fade_out; +} __packed; + +/* event request: generated by module */ +struct gb_lights_event_request { + __u8 light_id; + __u8 event; +#define GB_LIGHTS_LIGHT_CONFIG 0x01 +} __packed; + +/* set flash intensity request payload: response have no payload */ +struct gb_lights_set_flash_intensity_request { + __u8 light_id; + __u8 channel_id; + __le32 intensity_uA; +} __packed; + +/* set flash strobe state request payload: response have no payload */ +struct gb_lights_set_flash_strobe_request { + __u8 light_id; + __u8 channel_id; + __u8 state; +} __packed; + +/* set flash timeout request payload: response have no payload */ +struct gb_lights_set_flash_timeout_request { + __u8 light_id; + __u8 channel_id; + __le32 timeout_us; +} __packed; + +/* get flash fault request payload */ +struct gb_lights_get_flash_fault_request { + __u8 light_id; + __u8 channel_id; +} __packed; + +/* get flash fault response payload */ +struct gb_lights_get_flash_fault_response { + __le32 fault; +#define GB_LIGHTS_FLASH_FAULT_OVER_VOLTAGE 0x00000000 +#define GB_LIGHTS_FLASH_FAULT_TIMEOUT 0x00000001 +#define GB_LIGHTS_FLASH_FAULT_OVER_TEMPERATURE 0x00000002 +#define GB_LIGHTS_FLASH_FAULT_SHORT_CIRCUIT 0x00000004 +#define GB_LIGHTS_FLASH_FAULT_OVER_CURRENT 0x00000008 +#define GB_LIGHTS_FLASH_FAULT_INDICATOR 0x00000010 +#define GB_LIGHTS_FLASH_FAULT_UNDER_VOLTAGE 0x00000020 +#define GB_LIGHTS_FLASH_FAULT_INPUT_VOLTAGE 0x00000040 +#define GB_LIGHTS_FLASH_FAULT_LED_OVER_TEMPERATURE 0x00000080 +} __packed; + +/* Audio */ + +#define GB_AUDIO_TYPE_GET_TOPOLOGY_SIZE 0x02 +#define GB_AUDIO_TYPE_GET_TOPOLOGY 0x03 +#define GB_AUDIO_TYPE_GET_CONTROL 0x04 +#define GB_AUDIO_TYPE_SET_CONTROL 0x05 +#define GB_AUDIO_TYPE_ENABLE_WIDGET 0x06 +#define GB_AUDIO_TYPE_DISABLE_WIDGET 0x07 +#define GB_AUDIO_TYPE_GET_PCM 0x08 +#define GB_AUDIO_TYPE_SET_PCM 0x09 +#define GB_AUDIO_TYPE_SET_TX_DATA_SIZE 0x0a + /* 0x0b unused */ +#define GB_AUDIO_TYPE_ACTIVATE_TX 0x0c +#define GB_AUDIO_TYPE_DEACTIVATE_TX 0x0d +#define GB_AUDIO_TYPE_SET_RX_DATA_SIZE 0x0e + /* 0x0f unused */ +#define GB_AUDIO_TYPE_ACTIVATE_RX 0x10 +#define GB_AUDIO_TYPE_DEACTIVATE_RX 0x11 +#define GB_AUDIO_TYPE_JACK_EVENT 0x12 +#define GB_AUDIO_TYPE_BUTTON_EVENT 0x13 +#define GB_AUDIO_TYPE_STREAMING_EVENT 0x14 +#define GB_AUDIO_TYPE_SEND_DATA 0x15 + +/* Module must be able to buffer 10ms of audio data, minimum */ +#define GB_AUDIO_SAMPLE_BUFFER_MIN_US 10000 + +#define GB_AUDIO_PCM_NAME_MAX 32 +#define AUDIO_DAI_NAME_MAX 32 +#define AUDIO_CONTROL_NAME_MAX 32 +#define AUDIO_CTL_ELEM_NAME_MAX 44 +#define AUDIO_ENUM_NAME_MAX 64 +#define AUDIO_WIDGET_NAME_MAX 32 + +/* See SNDRV_PCM_FMTBIT_* in Linux source */ +#define GB_AUDIO_PCM_FMT_S8 BIT(0) +#define GB_AUDIO_PCM_FMT_U8 BIT(1) +#define GB_AUDIO_PCM_FMT_S16_LE BIT(2) +#define GB_AUDIO_PCM_FMT_S16_BE BIT(3) +#define GB_AUDIO_PCM_FMT_U16_LE BIT(4) +#define GB_AUDIO_PCM_FMT_U16_BE BIT(5) +#define GB_AUDIO_PCM_FMT_S24_LE BIT(6) +#define GB_AUDIO_PCM_FMT_S24_BE BIT(7) +#define GB_AUDIO_PCM_FMT_U24_LE BIT(8) +#define GB_AUDIO_PCM_FMT_U24_BE BIT(9) +#define GB_AUDIO_PCM_FMT_S32_LE BIT(10) +#define GB_AUDIO_PCM_FMT_S32_BE BIT(11) +#define GB_AUDIO_PCM_FMT_U32_LE BIT(12) +#define GB_AUDIO_PCM_FMT_U32_BE BIT(13) + +/* See SNDRV_PCM_RATE_* in Linux source */ +#define GB_AUDIO_PCM_RATE_5512 BIT(0) +#define GB_AUDIO_PCM_RATE_8000 BIT(1) +#define GB_AUDIO_PCM_RATE_11025 BIT(2) +#define GB_AUDIO_PCM_RATE_16000 BIT(3) +#define GB_AUDIO_PCM_RATE_22050 BIT(4) +#define GB_AUDIO_PCM_RATE_32000 BIT(5) +#define GB_AUDIO_PCM_RATE_44100 BIT(6) +#define GB_AUDIO_PCM_RATE_48000 BIT(7) +#define GB_AUDIO_PCM_RATE_64000 BIT(8) +#define GB_AUDIO_PCM_RATE_88200 BIT(9) +#define GB_AUDIO_PCM_RATE_96000 BIT(10) +#define GB_AUDIO_PCM_RATE_176400 BIT(11) +#define GB_AUDIO_PCM_RATE_192000 BIT(12) + +#define GB_AUDIO_STREAM_TYPE_CAPTURE 0x1 +#define GB_AUDIO_STREAM_TYPE_PLAYBACK 0x2 + +#define GB_AUDIO_CTL_ELEM_ACCESS_READ BIT(0) +#define GB_AUDIO_CTL_ELEM_ACCESS_WRITE BIT(1) + +/* See SNDRV_CTL_ELEM_TYPE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_TYPE_BOOLEAN 0x01 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER 0x02 +#define GB_AUDIO_CTL_ELEM_TYPE_ENUMERATED 0x03 +#define GB_AUDIO_CTL_ELEM_TYPE_INTEGER64 0x06 + +/* See SNDRV_CTL_ELEM_IFACE_* in Linux source */ +#define GB_AUDIO_CTL_ELEM_IFACE_CARD 0x00 +#define GB_AUDIO_CTL_ELEM_IFACE_HWDEP 0x01 +#define GB_AUDIO_CTL_ELEM_IFACE_MIXER 0x02 +#define GB_AUDIO_CTL_ELEM_IFACE_PCM 0x03 +#define GB_AUDIO_CTL_ELEM_IFACE_RAWMIDI 0x04 +#define GB_AUDIO_CTL_ELEM_IFACE_TIMER 0x05 +#define GB_AUDIO_CTL_ELEM_IFACE_SEQUENCER 0x06 + +/* SNDRV_CTL_ELEM_ACCESS_* in Linux source */ +#define GB_AUDIO_ACCESS_READ BIT(0) +#define GB_AUDIO_ACCESS_WRITE BIT(1) +#define GB_AUDIO_ACCESS_VOLATILE BIT(2) +#define GB_AUDIO_ACCESS_TIMESTAMP BIT(3) +#define GB_AUDIO_ACCESS_TLV_READ BIT(4) +#define GB_AUDIO_ACCESS_TLV_WRITE BIT(5) +#define GB_AUDIO_ACCESS_TLV_COMMAND BIT(6) +#define GB_AUDIO_ACCESS_INACTIVE BIT(7) +#define GB_AUDIO_ACCESS_LOCK BIT(8) +#define GB_AUDIO_ACCESS_OWNER BIT(9) + +/* enum snd_soc_dapm_type */ +#define GB_AUDIO_WIDGET_TYPE_INPUT 0x0 +#define GB_AUDIO_WIDGET_TYPE_OUTPUT 0x1 +#define GB_AUDIO_WIDGET_TYPE_MUX 0x2 +#define GB_AUDIO_WIDGET_TYPE_VIRT_MUX 0x3 +#define GB_AUDIO_WIDGET_TYPE_VALUE_MUX 0x4 +#define GB_AUDIO_WIDGET_TYPE_MIXER 0x5 +#define GB_AUDIO_WIDGET_TYPE_MIXER_NAMED_CTL 0x6 +#define GB_AUDIO_WIDGET_TYPE_PGA 0x7 +#define GB_AUDIO_WIDGET_TYPE_OUT_DRV 0x8 +#define GB_AUDIO_WIDGET_TYPE_ADC 0x9 +#define GB_AUDIO_WIDGET_TYPE_DAC 0xa +#define GB_AUDIO_WIDGET_TYPE_MICBIAS 0xb +#define GB_AUDIO_WIDGET_TYPE_MIC 0xc +#define GB_AUDIO_WIDGET_TYPE_HP 0xd +#define GB_AUDIO_WIDGET_TYPE_SPK 0xe +#define GB_AUDIO_WIDGET_TYPE_LINE 0xf +#define GB_AUDIO_WIDGET_TYPE_SWITCH 0x10 +#define GB_AUDIO_WIDGET_TYPE_VMID 0x11 +#define GB_AUDIO_WIDGET_TYPE_PRE 0x12 +#define GB_AUDIO_WIDGET_TYPE_POST 0x13 +#define GB_AUDIO_WIDGET_TYPE_SUPPLY 0x14 +#define GB_AUDIO_WIDGET_TYPE_REGULATOR_SUPPLY 0x15 +#define GB_AUDIO_WIDGET_TYPE_CLOCK_SUPPLY 0x16 +#define GB_AUDIO_WIDGET_TYPE_AIF_IN 0x17 +#define GB_AUDIO_WIDGET_TYPE_AIF_OUT 0x18 +#define GB_AUDIO_WIDGET_TYPE_SIGGEN 0x19 +#define GB_AUDIO_WIDGET_TYPE_DAI_IN 0x1a +#define GB_AUDIO_WIDGET_TYPE_DAI_OUT 0x1b +#define GB_AUDIO_WIDGET_TYPE_DAI_LINK 0x1c + +#define GB_AUDIO_WIDGET_STATE_DISABLED 0x01 +#define GB_AUDIO_WIDGET_STATE_ENAABLED 0x02 + +#define GB_AUDIO_JACK_EVENT_INSERTION 0x1 +#define GB_AUDIO_JACK_EVENT_REMOVAL 0x2 + +#define GB_AUDIO_BUTTON_EVENT_PRESS 0x1 +#define GB_AUDIO_BUTTON_EVENT_RELEASE 0x2 + +#define GB_AUDIO_STREAMING_EVENT_UNSPECIFIED 0x1 +#define GB_AUDIO_STREAMING_EVENT_HALT 0x2 +#define GB_AUDIO_STREAMING_EVENT_INTERNAL_ERROR 0x3 +#define GB_AUDIO_STREAMING_EVENT_PROTOCOL_ERROR 0x4 +#define GB_AUDIO_STREAMING_EVENT_FAILURE 0x5 +#define GB_AUDIO_STREAMING_EVENT_UNDERRUN 0x6 +#define GB_AUDIO_STREAMING_EVENT_OVERRUN 0x7 +#define GB_AUDIO_STREAMING_EVENT_CLOCKING 0x8 +#define GB_AUDIO_STREAMING_EVENT_DATA_LEN 0x9 + +#define GB_AUDIO_INVALID_INDEX 0xff + +/* enum snd_jack_types */ +#define GB_AUDIO_JACK_HEADPHONE 0x0000001 +#define GB_AUDIO_JACK_MICROPHONE 0x0000002 +#define GB_AUDIO_JACK_HEADSET (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE) +#define GB_AUDIO_JACK_LINEOUT 0x0000004 +#define GB_AUDIO_JACK_MECHANICAL 0x0000008 +#define GB_AUDIO_JACK_VIDEOOUT 0x0000010 +#define GB_AUDIO_JACK_AVOUT (GB_AUDIO_JACK_LINEOUT | \ + GB_AUDIO_JACK_VIDEOOUT) +#define GB_AUDIO_JACK_LINEIN 0x0000020 +#define GB_AUDIO_JACK_OC_HPHL 0x0000040 +#define GB_AUDIO_JACK_OC_HPHR 0x0000080 +#define GB_AUDIO_JACK_MICROPHONE2 0x0000200 +#define GB_AUDIO_JACK_ANC_HEADPHONE (GB_AUDIO_JACK_HEADPHONE | \ + GB_AUDIO_JACK_MICROPHONE | \ + GB_AUDIO_JACK_MICROPHONE2) +/* Kept separate from switches to facilitate implementation */ +#define GB_AUDIO_JACK_BTN_0 0x4000000 +#define GB_AUDIO_JACK_BTN_1 0x2000000 +#define GB_AUDIO_JACK_BTN_2 0x1000000 +#define GB_AUDIO_JACK_BTN_3 0x0800000 + +struct gb_audio_pcm { + __u8 stream_name[GB_AUDIO_PCM_NAME_MAX]; + __le32 formats; /* GB_AUDIO_PCM_FMT_* */ + __le32 rates; /* GB_AUDIO_PCM_RATE_* */ + __u8 chan_min; + __u8 chan_max; + __u8 sig_bits; /* number of bits of content */ +} __packed; + +struct gb_audio_dai { + __u8 name[AUDIO_DAI_NAME_MAX]; + __le16 data_cport; + struct gb_audio_pcm capture; + struct gb_audio_pcm playback; +} __packed; + +struct gb_audio_integer { + __le32 min; + __le32 max; + __le32 step; +} __packed; + +struct gb_audio_integer64 { + __le64 min; + __le64 max; + __le64 step; +} __packed; + +struct gb_audio_enumerated { + __le32 items; + __le16 names_length; + __u8 names[0]; +} __packed; + +struct gb_audio_ctl_elem_info { /* See snd_ctl_elem_info in Linux source */ + __u8 type; /* GB_AUDIO_CTL_ELEM_TYPE_* */ + __le16 dimen[4]; + union { + struct gb_audio_integer integer; + struct gb_audio_integer64 integer64; + struct gb_audio_enumerated enumerated; + } value; +} __packed; + +struct gb_audio_ctl_elem_value { /* See snd_ctl_elem_value in Linux source */ + __le64 timestamp; /* XXX needed? */ + union { + __le32 integer_value[2]; /* consider CTL_DOUBLE_xxx */ + __le64 integer64_value[2]; + __le32 enumerated_item[2]; + } value; +} __packed; + +struct gb_audio_control { + __u8 name[AUDIO_CONTROL_NAME_MAX]; + __u8 id; /* 0-63 */ + __u8 iface; /* GB_AUDIO_IFACE_* */ + __le16 data_cport; + __le32 access; /* GB_AUDIO_ACCESS_* */ + __u8 count; /* count of same elements */ + __u8 count_values; /* count of values, max=2 for CTL_DOUBLE_xxx */ + struct gb_audio_ctl_elem_info info; +} __packed; + +struct gb_audio_widget { + __u8 name[AUDIO_WIDGET_NAME_MAX]; + __u8 sname[AUDIO_WIDGET_NAME_MAX]; + __u8 id; + __u8 type; /* GB_AUDIO_WIDGET_TYPE_* */ + __u8 state; /* GB_AUDIO_WIDGET_STATE_* */ + __u8 ncontrols; + struct gb_audio_control ctl[0]; /* 'ncontrols' entries */ +} __packed; + +struct gb_audio_route { + __u8 source_id; /* widget id */ + __u8 destination_id; /* widget id */ + __u8 control_id; /* 0-63 */ + __u8 index; /* Selection within the control */ +} __packed; + +struct gb_audio_topology { + __u8 num_dais; + __u8 num_controls; + __u8 num_widgets; + __u8 num_routes; + __le32 size_dais; + __le32 size_controls; + __le32 size_widgets; + __le32 size_routes; + __le32 jack_type; + /* + * struct gb_audio_dai dai[num_dais]; + * struct gb_audio_control controls[num_controls]; + * struct gb_audio_widget widgets[num_widgets]; + * struct gb_audio_route routes[num_routes]; + */ + __u8 data[0]; +} __packed; + +struct gb_audio_get_topology_size_response { + __le16 size; +} __packed; + +struct gb_audio_get_topology_response { + struct gb_audio_topology topology; +} __packed; + +struct gb_audio_get_control_request { + __u8 control_id; + __u8 index; +} __packed; + +struct gb_audio_get_control_response { + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_set_control_request { + __u8 control_id; + __u8 index; + struct gb_audio_ctl_elem_value value; +} __packed; + +struct gb_audio_enable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_disable_widget_request { + __u8 widget_id; +} __packed; + +struct gb_audio_get_pcm_request { + __le16 data_cport; +} __packed; + +struct gb_audio_get_pcm_response { + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_pcm_request { + __le16 data_cport; + __le32 format; + __le32 rate; + __u8 channels; + __u8 sig_bits; +} __packed; + +struct gb_audio_set_tx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_activate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_tx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_set_rx_data_size_request { + __le16 data_cport; + __le16 size; +} __packed; + +struct gb_audio_activate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_deactivate_rx_request { + __le16 data_cport; +} __packed; + +struct gb_audio_jack_event_request { + __u8 widget_id; + __u8 jack_attribute; + __u8 event; +} __packed; + +struct gb_audio_button_event_request { + __u8 widget_id; + __u8 button_id; + __u8 event; +} __packed; + +struct gb_audio_streaming_event_request { + __le16 data_cport; + __u8 event; +} __packed; + +struct gb_audio_send_data_request { + __le64 timestamp; + __u8 data[0]; +} __packed; + + +/* Log */ + +/* operations */ +#define GB_LOG_TYPE_SEND_LOG 0x02 + +/* length */ +#define GB_LOG_MAX_LEN 1024 + +struct gb_log_send_log_request { + __le16 len; + __u8 msg[0]; +} __packed; + +#endif /* __GREYBUS_PROTOCOLS_H */ + diff --git a/include/linux/greybus/hd.h b/include/linux/greybus/hd.h new file mode 100644 index 000000000000..348b76fabc9a --- /dev/null +++ b/include/linux/greybus/hd.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#ifndef __HD_H +#define __HD_H + +struct gb_host_device; +struct gb_message; + +struct gb_hd_driver { + size_t hd_priv_size; + + int (*cport_allocate)(struct gb_host_device *hd, int cport_id, + unsigned long flags); + void (*cport_release)(struct gb_host_device *hd, u16 cport_id); + int (*cport_enable)(struct gb_host_device *hd, u16 cport_id, + unsigned long flags); + int (*cport_disable)(struct gb_host_device *hd, u16 cport_id); + int (*cport_connected)(struct gb_host_device *hd, u16 cport_id); + int (*cport_flush)(struct gb_host_device *hd, u16 cport_id); + int (*cport_shutdown)(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout); + int (*cport_quiesce)(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout); + int (*cport_clear)(struct gb_host_device *hd, u16 cport_id); + + int (*message_send)(struct gb_host_device *hd, u16 dest_cport_id, + struct gb_message *message, gfp_t gfp_mask); + void (*message_cancel)(struct gb_message *message); + int (*latency_tag_enable)(struct gb_host_device *hd, u16 cport_id); + int (*latency_tag_disable)(struct gb_host_device *hd, u16 cport_id); + int (*output)(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async); +}; + +struct gb_host_device { + struct device dev; + int bus_id; + const struct gb_hd_driver *driver; + + struct list_head modules; + struct list_head connections; + struct ida cport_id_map; + + /* Number of CPorts supported by the UniPro IP */ + size_t num_cports; + + /* Host device buffer constraints */ + size_t buffer_size_max; + + struct gb_svc *svc; + /* Private data for the host driver */ + unsigned long hd_priv[0] __aligned(sizeof(s64)); +}; +#define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) + +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id); +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id); +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags); +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); + +struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports); +int gb_hd_add(struct gb_host_device *hd); +void gb_hd_del(struct gb_host_device *hd); +void gb_hd_shutdown(struct gb_host_device *hd); +void gb_hd_put(struct gb_host_device *hd); +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool in_irq); + +int gb_hd_init(void); +void gb_hd_exit(void); + +#endif /* __HD_H */ diff --git a/include/linux/greybus/interface.h b/include/linux/greybus/interface.h new file mode 100644 index 000000000000..8fb1eacda302 --- /dev/null +++ b/include/linux/greybus/interface.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Interface Block code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __INTERFACE_H +#define __INTERFACE_H + +enum gb_interface_type { + GB_INTERFACE_TYPE_INVALID = 0, + GB_INTERFACE_TYPE_UNKNOWN, + GB_INTERFACE_TYPE_DUMMY, + GB_INTERFACE_TYPE_UNIPRO, + GB_INTERFACE_TYPE_GREYBUS, +}; + +#define GB_INTERFACE_QUIRK_NO_CPORT_FEATURES BIT(0) +#define GB_INTERFACE_QUIRK_NO_INIT_STATUS BIT(1) +#define GB_INTERFACE_QUIRK_NO_GMP_IDS BIT(2) +#define GB_INTERFACE_QUIRK_FORCED_DISABLE BIT(3) +#define GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH BIT(4) +#define GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE BIT(5) +#define GB_INTERFACE_QUIRK_NO_PM BIT(6) + +struct gb_interface { + struct device dev; + struct gb_control *control; + + struct list_head bundles; + struct list_head module_node; + struct list_head manifest_descs; + u8 interface_id; /* Physical location within the Endo */ + u8 device_id; + u8 features; /* Feature flags set in the manifest */ + + enum gb_interface_type type; + + u32 ddbl1_manufacturer_id; + u32 ddbl1_product_id; + u32 vendor_id; + u32 product_id; + u64 serial_number; + + struct gb_host_device *hd; + struct gb_module *module; + + unsigned long quirks; + + struct mutex mutex; + + bool disconnected; + + bool ejected; + bool removed; + bool active; + bool enabled; + bool mode_switch; + bool dme_read; + + struct work_struct mode_switch_work; + struct completion mode_switch_completion; +}; +#define to_gb_interface(d) container_of(d, struct gb_interface, dev) + +struct gb_interface *gb_interface_create(struct gb_module *module, + u8 interface_id); +int gb_interface_activate(struct gb_interface *intf); +void gb_interface_deactivate(struct gb_interface *intf); +int gb_interface_enable(struct gb_interface *intf); +void gb_interface_disable(struct gb_interface *intf); +int gb_interface_add(struct gb_interface *intf); +void gb_interface_del(struct gb_interface *intf); +void gb_interface_put(struct gb_interface *intf); +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox); + +int gb_interface_request_mode_switch(struct gb_interface *intf); + +#endif /* __INTERFACE_H */ diff --git a/include/linux/greybus/manifest.h b/include/linux/greybus/manifest.h new file mode 100644 index 000000000000..88aa7e44cad5 --- /dev/null +++ b/include/linux/greybus/manifest.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus manifest parsing + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __MANIFEST_H +#define __MANIFEST_H + +struct gb_interface; +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size); + +#endif /* __MANIFEST_H */ diff --git a/include/linux/greybus/module.h b/include/linux/greybus/module.h new file mode 100644 index 000000000000..2a27e520ee94 --- /dev/null +++ b/include/linux/greybus/module.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + */ + +#ifndef __MODULE_H +#define __MODULE_H + +struct gb_module { + struct device dev; + struct gb_host_device *hd; + + struct list_head hd_node; + + u8 module_id; + size_t num_interfaces; + + bool disconnected; + + struct gb_interface *interfaces[0]; +}; +#define to_gb_module(d) container_of(d, struct gb_module, dev) + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces); +int gb_module_add(struct gb_module *module); +void gb_module_del(struct gb_module *module); +void gb_module_put(struct gb_module *module); + +#endif /* __MODULE_H */ diff --git a/include/linux/greybus/operation.h b/include/linux/greybus/operation.h new file mode 100644 index 000000000000..17ba3daf111b --- /dev/null +++ b/include/linux/greybus/operation.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus operations + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#ifndef __OPERATION_H +#define __OPERATION_H + +#include + +struct gb_operation; + +/* The default amount of time a request is given to complete */ +#define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ + +/* + * The top bit of the type in an operation message header indicates + * whether the message is a request (bit clear) or response (bit set) + */ +#define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) + +enum gb_operation_result { + GB_OP_SUCCESS = 0x00, + GB_OP_INTERRUPTED = 0x01, + GB_OP_TIMEOUT = 0x02, + GB_OP_NO_MEMORY = 0x03, + GB_OP_PROTOCOL_BAD = 0x04, + GB_OP_OVERFLOW = 0x05, + GB_OP_INVALID = 0x06, + GB_OP_RETRY = 0x07, + GB_OP_NONEXISTENT = 0x08, + GB_OP_UNKNOWN_ERROR = 0xfe, + GB_OP_MALFUNCTION = 0xff, +}; + +#define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) +#define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX + +/* + * Protocol code should only examine the payload and payload_size fields, and + * host-controller drivers may use the hcpriv field. All other fields are + * intended to be private to the operations core code. + */ +struct gb_message { + struct gb_operation *operation; + struct gb_operation_msg_hdr *header; + + void *payload; + size_t payload_size; + + void *buffer; + + void *hcpriv; +}; + +#define GB_OPERATION_FLAG_INCOMING BIT(0) +#define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) +#define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) +#define GB_OPERATION_FLAG_CORE BIT(3) + +#define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ + GB_OPERATION_FLAG_UNIDIRECTIONAL) + +/* + * A Greybus operation is a remote procedure call performed over a + * connection between two UniPro interfaces. + * + * Every operation consists of a request message sent to the other + * end of the connection coupled with a reply message returned to + * the sender. Every operation has a type, whose interpretation is + * dependent on the protocol associated with the connection. + * + * Only four things in an operation structure are intended to be + * directly usable by protocol handlers: the operation's connection + * pointer; the operation type; the request message payload (and + * size); and the response message payload (and size). Note that a + * message with a 0-byte payload has a null message payload pointer. + * + * In addition, every operation has a result, which is an errno + * value. Protocol handlers access the operation result using + * gb_operation_result(). + */ +typedef void (*gb_operation_callback)(struct gb_operation *); +struct gb_operation { + struct gb_connection *connection; + struct gb_message *request; + struct gb_message *response; + + unsigned long flags; + u8 type; + u16 id; + int errno; /* Operation result */ + + struct work_struct work; + gb_operation_callback callback; + struct completion completion; + struct timer_list timer; + + struct kref kref; + atomic_t waiters; + + int active; + struct list_head links; /* connection->operations */ + + void *private; +}; + +static inline bool +gb_operation_is_incoming(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_INCOMING; +} + +static inline bool +gb_operation_is_unidirectional(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; +} + +static inline bool +gb_operation_short_response_allowed(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; +} + +static inline bool gb_operation_is_core(struct gb_operation *operation) +{ + return operation->flags & GB_OPERATION_FLAG_CORE; +} + +void gb_connection_recv(struct gb_connection *connection, + void *data, size_t size); + +int gb_operation_result(struct gb_operation *operation); + +size_t gb_operation_get_payload_size_max(struct gb_connection *connection); +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +static inline struct gb_operation * +gb_operation_create(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, gfp_t gfp) +{ + return gb_operation_create_flags(connection, type, request_size, + response_size, 0, gfp); +} + +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp); + +void gb_operation_get(struct gb_operation *operation); +void gb_operation_put(struct gb_operation *operation); + +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size, gfp_t gfp); + +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback, + unsigned int timeout, + gfp_t gfp); +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout); +static inline int +gb_operation_request_send_sync(struct gb_operation *operation) +{ + return gb_operation_request_send_sync_timeout(operation, + GB_OPERATION_TIMEOUT_DEFAULT); +} + +void gb_operation_cancel(struct gb_operation *operation, int errno); +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); + +void greybus_message_sent(struct gb_host_device *hd, + struct gb_message *message, int status); + +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout); +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, int request_size, + unsigned int timeout); + +static inline int gb_operation_sync(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size) +{ + return gb_operation_sync_timeout(connection, type, + request, request_size, response, response_size, + GB_OPERATION_TIMEOUT_DEFAULT); +} + +static inline int gb_operation_unidirectional(struct gb_connection *connection, + int type, void *request, int request_size) +{ + return gb_operation_unidirectional_timeout(connection, type, + request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); +} + +static inline void *gb_operation_get_data(struct gb_operation *operation) +{ + return operation->private; +} + +static inline void gb_operation_set_data(struct gb_operation *operation, + void *data) +{ + operation->private = data; +} + +int gb_operation_init(void); +void gb_operation_exit(void); + +#endif /* !__OPERATION_H */ diff --git a/include/linux/greybus/svc.h b/include/linux/greybus/svc.h new file mode 100644 index 000000000000..e7452057cfe4 --- /dev/null +++ b/include/linux/greybus/svc.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus SVC code + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ + +#ifndef __SVC_H +#define __SVC_H + +#define GB_SVC_CPORT_FLAG_E2EFC BIT(0) +#define GB_SVC_CPORT_FLAG_CSD_N BIT(1) +#define GB_SVC_CPORT_FLAG_CSV_N BIT(2) + +enum gb_svc_state { + GB_SVC_STATE_RESET, + GB_SVC_STATE_PROTOCOL_VERSION, + GB_SVC_STATE_SVC_HELLO, +}; + +enum gb_svc_watchdog_bite { + GB_SVC_WATCHDOG_BITE_RESET_UNIPRO = 0, + GB_SVC_WATCHDOG_BITE_PANIC_KERNEL, +}; + +struct gb_svc_watchdog; + +struct svc_debugfs_pwrmon_rail { + u8 id; + struct gb_svc *svc; +}; + +struct gb_svc { + struct device dev; + + struct gb_host_device *hd; + struct gb_connection *connection; + enum gb_svc_state state; + struct ida device_id_map; + struct workqueue_struct *wq; + + u16 endo_id; + u8 ap_intf_id; + + u8 protocol_major; + u8 protocol_minor; + + struct gb_svc_watchdog *watchdog; + enum gb_svc_watchdog_bite action; + + struct dentry *debugfs_dentry; + struct svc_debugfs_pwrmon_rail *pwrmon_rails; +}; +#define to_gb_svc(d) container_of(d, struct gb_svc, dev) + +struct gb_svc *gb_svc_create(struct gb_host_device *hd); +int gb_svc_add(struct gb_svc *svc); +void gb_svc_del(struct gb_svc *svc); +void gb_svc_put(struct gb_svc *svc); + +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value); +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id); +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id); +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id); +int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id, u8 cport_flags); +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id); +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id); +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable); +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type); +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id); + +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value); +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value); +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote); +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id); +int gb_svc_ping(struct gb_svc *svc); +int gb_svc_watchdog_create(struct gb_svc *svc); +void gb_svc_watchdog_destroy(struct gb_svc *svc); +bool gb_svc_watchdog_enabled(struct gb_svc *svc); +int gb_svc_watchdog_enable(struct gb_svc *svc); +int gb_svc_watchdog_disable(struct gb_svc *svc); + +int gb_svc_protocol_init(void); +void gb_svc_protocol_exit(void); + +#endif /* __SVC_H */ -- cgit v1.2.3-59-g8ed1b From 8465def499c70d041a234087eff380108da7e830 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:28 +0200 Subject: staging: greybus: move the greybus core to drivers/greybus The Greybus core code has been stable for a long time, and has been shipping for many years in millions of phones. With the advent of a recent Google Summer of Code project, and a number of new devices in the works from various companies, it is time to get the core greybus code out of staging as it really is going to be with us for a while. Cc: Johan Hovold Cc: linux-kernel@vger.kernel.org Cc: greybus-dev@lists.linaro.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-9-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 3 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/greybus/Kconfig | 16 + drivers/greybus/Makefile | 19 + drivers/greybus/bundle.c | 252 ++++++ drivers/greybus/connection.c | 942 +++++++++++++++++++++ drivers/greybus/control.c | 584 +++++++++++++ drivers/greybus/core.c | 349 ++++++++ drivers/greybus/debugfs.c | 29 + drivers/greybus/greybus_trace.h | 502 +++++++++++ drivers/greybus/hd.c | 256 ++++++ drivers/greybus/interface.c | 1263 ++++++++++++++++++++++++++++ drivers/greybus/manifest.c | 533 ++++++++++++ drivers/greybus/module.c | 236 ++++++ drivers/greybus/operation.c | 1264 ++++++++++++++++++++++++++++ drivers/greybus/svc.c | 1397 +++++++++++++++++++++++++++++++ drivers/greybus/svc_watchdog.c | 197 +++++ drivers/staging/greybus/Kconfig | 16 - drivers/staging/greybus/Makefile | 17 - drivers/staging/greybus/bundle.c | 252 ------ drivers/staging/greybus/connection.c | 942 --------------------- drivers/staging/greybus/control.c | 584 ------------- drivers/staging/greybus/core.c | 349 -------- drivers/staging/greybus/debugfs.c | 29 - drivers/staging/greybus/es2.c | 2 +- drivers/staging/greybus/greybus_trace.h | 502 ----------- drivers/staging/greybus/hd.c | 256 ------ drivers/staging/greybus/interface.c | 1263 ---------------------------- drivers/staging/greybus/manifest.c | 533 ------------ drivers/staging/greybus/module.c | 236 ------ drivers/staging/greybus/operation.c | 1264 ---------------------------- drivers/staging/greybus/svc.c | 1397 ------------------------------- drivers/staging/greybus/svc_watchdog.c | 197 ----- 34 files changed, 7846 insertions(+), 7838 deletions(-) create mode 100644 drivers/greybus/Kconfig create mode 100644 drivers/greybus/Makefile create mode 100644 drivers/greybus/bundle.c create mode 100644 drivers/greybus/connection.c create mode 100644 drivers/greybus/control.c create mode 100644 drivers/greybus/core.c create mode 100644 drivers/greybus/debugfs.c create mode 100644 drivers/greybus/greybus_trace.h create mode 100644 drivers/greybus/hd.c create mode 100644 drivers/greybus/interface.c create mode 100644 drivers/greybus/manifest.c create mode 100644 drivers/greybus/module.c create mode 100644 drivers/greybus/operation.c create mode 100644 drivers/greybus/svc.c create mode 100644 drivers/greybus/svc_watchdog.c delete mode 100644 drivers/staging/greybus/bundle.c delete mode 100644 drivers/staging/greybus/connection.c delete mode 100644 drivers/staging/greybus/control.c delete mode 100644 drivers/staging/greybus/core.c delete mode 100644 drivers/staging/greybus/debugfs.c delete mode 100644 drivers/staging/greybus/greybus_trace.h delete mode 100644 drivers/staging/greybus/hd.c delete mode 100644 drivers/staging/greybus/interface.c delete mode 100644 drivers/staging/greybus/manifest.c delete mode 100644 drivers/staging/greybus/module.c delete mode 100644 drivers/staging/greybus/operation.c delete mode 100644 drivers/staging/greybus/svc.c delete mode 100644 drivers/staging/greybus/svc_watchdog.c (limited to 'drivers/staging') diff --git a/MAINTAINERS b/MAINTAINERS index 0f38cba2c581..e3242687cd19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7003,6 +7003,9 @@ M: Alex Elder M: Greg Kroah-Hartman S: Maintained F: drivers/staging/greybus/ +F: drivers/greybus/ +F: include/linux/greybus.h +F: include/linux/greybus/ L: greybus-dev@lists.linaro.org (moderated for non-subscribers) GREYBUS UART PROTOCOLS DRIVERS diff --git a/drivers/Kconfig b/drivers/Kconfig index 61cf4ea2c229..7dce76ae7369 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -146,6 +146,8 @@ source "drivers/hv/Kconfig" source "drivers/xen/Kconfig" +source "drivers/greybus/Kconfig" + source "drivers/staging/Kconfig" source "drivers/platform/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 6d37564e783c..73df8e5a2fce 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -148,6 +148,7 @@ obj-$(CONFIG_BCMA) += bcma/ obj-$(CONFIG_VHOST_RING) += vhost/ obj-$(CONFIG_VHOST) += vhost/ obj-$(CONFIG_VLYNQ) += vlynq/ +obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_STAGING) += staging/ obj-y += platform/ diff --git a/drivers/greybus/Kconfig b/drivers/greybus/Kconfig new file mode 100644 index 000000000000..158d8893114c --- /dev/null +++ b/drivers/greybus/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +menuconfig GREYBUS + tristate "Greybus support" + depends on SYSFS + ---help--- + This option enables the Greybus driver core. Greybus is an + hardware protocol that was designed to provide Unipro with a + sane application layer. It was originally designed for the + ARA project, a module phone system, but has shown up in other + phones, and can be tunneled over other busses in order to + control hardware devices. + + Say Y here to enable support for these types of drivers. + + To compile this code as a module, chose M here: the module + will be called greybus.ko diff --git a/drivers/greybus/Makefile b/drivers/greybus/Makefile new file mode 100644 index 000000000000..03b22616ec7d --- /dev/null +++ b/drivers/greybus/Makefile @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +# Greybus core +greybus-y := core.o \ + debugfs.o \ + hd.o \ + manifest.o \ + module.o \ + interface.o \ + bundle.o \ + connection.o \ + control.o \ + svc.o \ + svc_watchdog.o \ + operation.o + +obj-$(CONFIG_GREYBUS) += greybus.o + +# needed for trace events +ccflags-y += -I$(src) diff --git a/drivers/greybus/bundle.c b/drivers/greybus/bundle.c new file mode 100644 index 000000000000..84660729538b --- /dev/null +++ b/drivers/greybus/bundle.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus bundles + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#include +#include "greybus_trace.h" + +static ssize_t bundle_class_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + return sprintf(buf, "0x%02x\n", bundle->class); +} +static DEVICE_ATTR_RO(bundle_class); + +static ssize_t bundle_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + return sprintf(buf, "%u\n", bundle->id); +} +static DEVICE_ATTR_RO(bundle_id); + +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + if (!bundle->state) + return sprintf(buf, "\n"); + + return sprintf(buf, "%s\n", bundle->state); +} + +static ssize_t state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + kfree(bundle->state); + bundle->state = kstrdup(buf, GFP_KERNEL); + if (!bundle->state) + return -ENOMEM; + + /* Tell userspace that the file contents changed */ + sysfs_notify(&bundle->dev.kobj, NULL, "state"); + + return size; +} +static DEVICE_ATTR_RW(state); + +static struct attribute *bundle_attrs[] = { + &dev_attr_bundle_class.attr, + &dev_attr_bundle_id.attr, + &dev_attr_state.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(bundle); + +static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, + u8 bundle_id) +{ + struct gb_bundle *bundle; + + list_for_each_entry(bundle, &intf->bundles, links) { + if (bundle->id == bundle_id) + return bundle; + } + + return NULL; +} + +static void gb_bundle_release(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + + trace_gb_bundle_release(bundle); + + kfree(bundle->state); + kfree(bundle->cport_desc); + kfree(bundle); +} + +#ifdef CONFIG_PM +static void gb_bundle_disable_all_connections(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_disable(connection); +} + +static void gb_bundle_enable_all_connections(struct gb_bundle *bundle) +{ + struct gb_connection *connection; + + list_for_each_entry(connection, &bundle->connections, bundle_links) + gb_connection_enable(connection); +} + +static int gb_bundle_suspend(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct dev_pm_ops *pm = dev->driver->pm; + int ret; + + if (pm && pm->runtime_suspend) { + ret = pm->runtime_suspend(&bundle->dev); + if (ret) + return ret; + } else { + gb_bundle_disable_all_connections(bundle); + } + + ret = gb_control_bundle_suspend(bundle->intf->control, bundle->id); + if (ret) { + if (pm && pm->runtime_resume) + ret = pm->runtime_resume(dev); + else + gb_bundle_enable_all_connections(bundle); + + return ret; + } + + return 0; +} + +static int gb_bundle_resume(struct device *dev) +{ + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct dev_pm_ops *pm = dev->driver->pm; + int ret; + + ret = gb_control_bundle_resume(bundle->intf->control, bundle->id); + if (ret) + return ret; + + if (pm && pm->runtime_resume) { + ret = pm->runtime_resume(dev); + if (ret) + return ret; + } else { + gb_bundle_enable_all_connections(bundle); + } + + return 0; +} + +static int gb_bundle_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} +#endif + +static const struct dev_pm_ops gb_bundle_pm_ops = { + SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle) +}; + +struct device_type greybus_bundle_type = { + .name = "greybus_bundle", + .release = gb_bundle_release, + .pm = &gb_bundle_pm_ops, +}; + +/* + * Create a gb_bundle structure to represent a discovered + * bundle. Returns a pointer to the new bundle or a null + * pointer if a failure occurs due to memory exhaustion. + */ +struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, + u8 class) +{ + struct gb_bundle *bundle; + + if (bundle_id == BUNDLE_ID_NONE) { + dev_err(&intf->dev, "can't use bundle id %u\n", bundle_id); + return NULL; + } + + /* + * Reject any attempt to reuse a bundle id. We initialize + * these serially, so there's no need to worry about keeping + * the interface bundle list locked here. + */ + if (gb_bundle_find(intf, bundle_id)) { + dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id); + return NULL; + } + + bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); + if (!bundle) + return NULL; + + bundle->intf = intf; + bundle->id = bundle_id; + bundle->class = class; + INIT_LIST_HEAD(&bundle->connections); + + bundle->dev.parent = &intf->dev; + bundle->dev.bus = &greybus_bus_type; + bundle->dev.type = &greybus_bundle_type; + bundle->dev.groups = bundle_groups; + bundle->dev.dma_mask = intf->dev.dma_mask; + device_initialize(&bundle->dev); + dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); + + list_add(&bundle->links, &intf->bundles); + + trace_gb_bundle_create(bundle); + + return bundle; +} + +int gb_bundle_add(struct gb_bundle *bundle) +{ + int ret; + + ret = device_add(&bundle->dev); + if (ret) { + dev_err(&bundle->dev, "failed to register bundle: %d\n", ret); + return ret; + } + + trace_gb_bundle_add(bundle); + + return 0; +} + +/* + * Tear down a previously set up bundle. + */ +void gb_bundle_destroy(struct gb_bundle *bundle) +{ + trace_gb_bundle_destroy(bundle); + + if (device_is_registered(&bundle->dev)) + device_del(&bundle->dev); + + list_del(&bundle->links); + + put_device(&bundle->dev); +} diff --git a/drivers/greybus/connection.c b/drivers/greybus/connection.c new file mode 100644 index 000000000000..fc8f57f97ce6 --- /dev/null +++ b/drivers/greybus/connection.c @@ -0,0 +1,942 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus connections + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#include +#include + +#include "greybus_trace.h" + +#define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT 1000 + +static void gb_connection_kref_release(struct kref *kref); + +static DEFINE_SPINLOCK(gb_connections_lock); +static DEFINE_MUTEX(gb_connection_mutex); + +/* Caller holds gb_connection_mutex. */ +static bool gb_connection_cport_in_use(struct gb_interface *intf, u16 cport_id) +{ + struct gb_host_device *hd = intf->hd; + struct gb_connection *connection; + + list_for_each_entry(connection, &hd->connections, hd_links) { + if (connection->intf == intf && + connection->intf_cport_id == cport_id) + return true; + } + + return false; +} + +static void gb_connection_get(struct gb_connection *connection) +{ + kref_get(&connection->kref); + + trace_gb_connection_get(connection); +} + +static void gb_connection_put(struct gb_connection *connection) +{ + trace_gb_connection_put(connection); + + kref_put(&connection->kref, gb_connection_kref_release); +} + +/* + * Returns a reference-counted pointer to the connection if found. + */ +static struct gb_connection * +gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) +{ + struct gb_connection *connection; + unsigned long flags; + + spin_lock_irqsave(&gb_connections_lock, flags); + list_for_each_entry(connection, &hd->connections, hd_links) + if (connection->hd_cport_id == cport_id) { + gb_connection_get(connection); + goto found; + } + connection = NULL; +found: + spin_unlock_irqrestore(&gb_connections_lock, flags); + + return connection; +} + +/* + * Callback from the host driver to let us know that data has been + * received on the bundle. + */ +void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, + u8 *data, size_t length) +{ + struct gb_connection *connection; + + trace_gb_hd_in(hd); + + connection = gb_connection_hd_find(hd, cport_id); + if (!connection) { + dev_err(&hd->dev, + "nonexistent connection (%zu bytes dropped)\n", length); + return; + } + gb_connection_recv(connection, data, length); + gb_connection_put(connection); +} +EXPORT_SYMBOL_GPL(greybus_data_rcvd); + +static void gb_connection_kref_release(struct kref *kref) +{ + struct gb_connection *connection; + + connection = container_of(kref, struct gb_connection, kref); + + trace_gb_connection_release(connection); + + kfree(connection); +} + +static void gb_connection_init_name(struct gb_connection *connection) +{ + u16 hd_cport_id = connection->hd_cport_id; + u16 cport_id = 0; + u8 intf_id = 0; + + if (connection->intf) { + intf_id = connection->intf->interface_id; + cport_id = connection->intf_cport_id; + } + + snprintf(connection->name, sizeof(connection->name), + "%u/%u:%u", hd_cport_id, intf_id, cport_id); +} + +/* + * _gb_connection_create() - create a Greybus connection + * @hd: host device of the connection + * @hd_cport_id: host-device cport id, or -1 for dynamic allocation + * @intf: remote interface, or NULL for static connections + * @bundle: remote-interface bundle (may be NULL) + * @cport_id: remote-interface cport id, or 0 for static connections + * @handler: request handler (may be NULL) + * @flags: connection flags + * + * Create a Greybus connection, representing the bidirectional link + * between a CPort on a (local) Greybus host device and a CPort on + * another Greybus interface. + * + * A connection also maintains the state of operations sent over the + * connection. + * + * Serialised against concurrent create and destroy using the + * gb_connection_mutex. + * + * Return: A pointer to the new connection if successful, or an ERR_PTR + * otherwise. + */ +static struct gb_connection * +_gb_connection_create(struct gb_host_device *hd, int hd_cport_id, + struct gb_interface *intf, + struct gb_bundle *bundle, int cport_id, + gb_request_handler_t handler, + unsigned long flags) +{ + struct gb_connection *connection; + int ret; + + mutex_lock(&gb_connection_mutex); + + if (intf && gb_connection_cport_in_use(intf, cport_id)) { + dev_err(&intf->dev, "cport %u already in use\n", cport_id); + ret = -EBUSY; + goto err_unlock; + } + + ret = gb_hd_cport_allocate(hd, hd_cport_id, flags); + if (ret < 0) { + dev_err(&hd->dev, "failed to allocate cport: %d\n", ret); + goto err_unlock; + } + hd_cport_id = ret; + + connection = kzalloc(sizeof(*connection), GFP_KERNEL); + if (!connection) { + ret = -ENOMEM; + goto err_hd_cport_release; + } + + connection->hd_cport_id = hd_cport_id; + connection->intf_cport_id = cport_id; + connection->hd = hd; + connection->intf = intf; + connection->bundle = bundle; + connection->handler = handler; + connection->flags = flags; + if (intf && (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES)) + connection->flags |= GB_CONNECTION_FLAG_NO_FLOWCTRL; + connection->state = GB_CONNECTION_STATE_DISABLED; + + atomic_set(&connection->op_cycle, 0); + mutex_init(&connection->mutex); + spin_lock_init(&connection->lock); + INIT_LIST_HEAD(&connection->operations); + + connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, + dev_name(&hd->dev), hd_cport_id); + if (!connection->wq) { + ret = -ENOMEM; + goto err_free_connection; + } + + kref_init(&connection->kref); + + gb_connection_init_name(connection); + + spin_lock_irq(&gb_connections_lock); + list_add(&connection->hd_links, &hd->connections); + + if (bundle) + list_add(&connection->bundle_links, &bundle->connections); + else + INIT_LIST_HEAD(&connection->bundle_links); + + spin_unlock_irq(&gb_connections_lock); + + mutex_unlock(&gb_connection_mutex); + + trace_gb_connection_create(connection); + + return connection; + +err_free_connection: + kfree(connection); +err_hd_cport_release: + gb_hd_cport_release(hd, hd_cport_id); +err_unlock: + mutex_unlock(&gb_connection_mutex); + + return ERR_PTR(ret); +} + +struct gb_connection * +gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, + gb_request_handler_t handler) +{ + return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler, + GB_CONNECTION_FLAG_HIGH_PRIO); +} + +struct gb_connection * +gb_connection_create_control(struct gb_interface *intf) +{ + return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, + GB_CONNECTION_FLAG_CONTROL | + GB_CONNECTION_FLAG_HIGH_PRIO); +} + +struct gb_connection * +gb_connection_create(struct gb_bundle *bundle, u16 cport_id, + gb_request_handler_t handler) +{ + struct gb_interface *intf = bundle->intf; + + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + handler, 0); +} +EXPORT_SYMBOL_GPL(gb_connection_create); + +struct gb_connection * +gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, + gb_request_handler_t handler, + unsigned long flags) +{ + struct gb_interface *intf = bundle->intf; + + if (WARN_ON_ONCE(flags & GB_CONNECTION_FLAG_CORE_MASK)) + flags &= ~GB_CONNECTION_FLAG_CORE_MASK; + + return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, + handler, flags); +} +EXPORT_SYMBOL_GPL(gb_connection_create_flags); + +struct gb_connection * +gb_connection_create_offloaded(struct gb_bundle *bundle, u16 cport_id, + unsigned long flags) +{ + flags |= GB_CONNECTION_FLAG_OFFLOADED; + + return gb_connection_create_flags(bundle, cport_id, NULL, flags); +} +EXPORT_SYMBOL_GPL(gb_connection_create_offloaded); + +static int gb_connection_hd_cport_enable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_enable) + return 0; + + ret = hd->driver->cport_enable(hd, connection->hd_cport_id, + connection->flags); + if (ret) { + dev_err(&hd->dev, "%s: failed to enable host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static void gb_connection_hd_cport_disable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_disable) + return; + + ret = hd->driver->cport_disable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to disable host cport: %d\n", + connection->name, ret); + } +} + +static int gb_connection_hd_cport_connected(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_connected) + return 0; + + ret = hd->driver->cport_connected(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to set connected state: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int gb_connection_hd_cport_flush(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_flush) + return 0; + + ret = hd->driver->cport_flush(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to flush host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int gb_connection_hd_cport_quiesce(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + size_t peer_space; + int ret; + + if (!hd->driver->cport_quiesce) + return 0; + + peer_space = sizeof(struct gb_operation_msg_hdr) + + sizeof(struct gb_cport_shutdown_request); + + if (connection->mode_switch) + peer_space += sizeof(struct gb_operation_msg_hdr); + + if (!hd->driver->cport_quiesce) + return 0; + + ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id, + peer_space, + GB_CONNECTION_CPORT_QUIESCE_TIMEOUT); + if (ret) { + dev_err(&hd->dev, "%s: failed to quiesce host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static int gb_connection_hd_cport_clear(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->cport_clear) + return 0; + + ret = hd->driver->cport_clear(hd, connection->hd_cport_id); + if (ret) { + dev_err(&hd->dev, "%s: failed to clear host cport: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +/* + * Request the SVC to create a connection from AP's cport to interface's + * cport. + */ +static int +gb_connection_svc_connection_create(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + struct gb_interface *intf; + u8 cport_flags; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + intf = connection->intf; + + /* + * Enable either E2EFC or CSD, unless no flow control is requested. + */ + cport_flags = GB_SVC_CPORT_FLAG_CSV_N; + if (gb_connection_flow_control_disabled(connection)) { + cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; + } else if (gb_connection_e2efc_enabled(connection)) { + cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | + GB_SVC_CPORT_FLAG_E2EFC; + } + + ret = gb_svc_connection_create(hd->svc, + hd->svc->ap_intf_id, + connection->hd_cport_id, + intf->interface_id, + connection->intf_cport_id, + cport_flags); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to create svc connection: %d\n", + connection->name, ret); + return ret; + } + + return 0; +} + +static void +gb_connection_svc_connection_destroy(struct gb_connection *connection) +{ + if (gb_connection_is_static(connection)) + return; + + gb_svc_connection_destroy(connection->hd->svc, + connection->hd->svc->ap_intf_id, + connection->hd_cport_id, + connection->intf->interface_id, + connection->intf_cport_id); +} + +/* Inform Interface about active CPorts */ +static int gb_connection_control_connected(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + if (gb_connection_is_control(connection)) + return 0; + + control = connection->intf->control; + + ret = gb_control_connected_operation(control, cport_id); + if (ret) { + dev_err(&connection->bundle->dev, + "failed to connect cport: %d\n", ret); + return ret; + } + + return 0; +} + +static void +gb_connection_control_disconnecting(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return; + + control = connection->intf->control; + + ret = gb_control_disconnecting_operation(control, cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to send disconnecting: %d\n", + connection->name, ret); + } +} + +static void +gb_connection_control_disconnected(struct gb_connection *connection) +{ + struct gb_control *control; + u16 cport_id = connection->intf_cport_id; + int ret; + + if (gb_connection_is_static(connection)) + return; + + control = connection->intf->control; + + if (gb_connection_is_control(connection)) { + if (connection->mode_switch) { + ret = gb_control_mode_switch_operation(control); + if (ret) { + /* + * Allow mode switch to time out waiting for + * mailbox event. + */ + return; + } + } + + return; + } + + ret = gb_control_disconnected_operation(control, cport_id); + if (ret) { + dev_warn(&connection->bundle->dev, + "failed to disconnect cport: %d\n", ret); + } +} + +static int gb_connection_shutdown_operation(struct gb_connection *connection, + u8 phase) +{ + struct gb_cport_shutdown_request *req; + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(connection, + GB_REQUEST_TYPE_CPORT_SHUTDOWN, + sizeof(*req), 0, 0, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + req = operation->request->payload; + req->phase = phase; + + ret = gb_operation_request_send_sync(operation); + + gb_operation_put(operation); + + return ret; +} + +static int gb_connection_cport_shutdown(struct gb_connection *connection, + u8 phase) +{ + struct gb_host_device *hd = connection->hd; + const struct gb_hd_driver *drv = hd->driver; + int ret; + + if (gb_connection_is_static(connection)) + return 0; + + if (gb_connection_is_offloaded(connection)) { + if (!drv->cport_shutdown) + return 0; + + ret = drv->cport_shutdown(hd, connection->hd_cport_id, phase, + GB_OPERATION_TIMEOUT_DEFAULT); + } else { + ret = gb_connection_shutdown_operation(connection, phase); + } + + if (ret) { + dev_err(&hd->dev, "%s: failed to send cport shutdown (phase %d): %d\n", + connection->name, phase, ret); + return ret; + } + + return 0; +} + +static int +gb_connection_cport_shutdown_phase_1(struct gb_connection *connection) +{ + return gb_connection_cport_shutdown(connection, 1); +} + +static int +gb_connection_cport_shutdown_phase_2(struct gb_connection *connection) +{ + return gb_connection_cport_shutdown(connection, 2); +} + +/* + * Cancel all active operations on a connection. + * + * Locking: Called with connection lock held and state set to DISABLED or + * DISCONNECTING. + */ +static void gb_connection_cancel_operations(struct gb_connection *connection, + int errno) + __must_hold(&connection->lock) +{ + struct gb_operation *operation; + + while (!list_empty(&connection->operations)) { + operation = list_last_entry(&connection->operations, + struct gb_operation, links); + gb_operation_get(operation); + spin_unlock_irq(&connection->lock); + + if (gb_operation_is_incoming(operation)) + gb_operation_cancel_incoming(operation, errno); + else + gb_operation_cancel(operation, errno); + + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } +} + +/* + * Cancel all active incoming operations on a connection. + * + * Locking: Called with connection lock held and state set to ENABLED_TX. + */ +static void +gb_connection_flush_incoming_operations(struct gb_connection *connection, + int errno) + __must_hold(&connection->lock) +{ + struct gb_operation *operation; + bool incoming; + + while (!list_empty(&connection->operations)) { + incoming = false; + list_for_each_entry(operation, &connection->operations, + links) { + if (gb_operation_is_incoming(operation)) { + gb_operation_get(operation); + incoming = true; + break; + } + } + + if (!incoming) + break; + + spin_unlock_irq(&connection->lock); + + /* FIXME: flush, not cancel? */ + gb_operation_cancel_incoming(operation, errno); + gb_operation_put(operation); + + spin_lock_irq(&connection->lock); + } +} + +/* + * _gb_connection_enable() - enable a connection + * @connection: connection to enable + * @rx: whether to enable incoming requests + * + * Connection-enable helper for DISABLED->ENABLED, DISABLED->ENABLED_TX, and + * ENABLED_TX->ENABLED state transitions. + * + * Locking: Caller holds connection->mutex. + */ +static int _gb_connection_enable(struct gb_connection *connection, bool rx) +{ + int ret; + + /* Handle ENABLED_TX -> ENABLED transitions. */ + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { + if (!(connection->handler && rx)) + return 0; + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_ENABLED; + spin_unlock_irq(&connection->lock); + + return 0; + } + + ret = gb_connection_hd_cport_enable(connection); + if (ret) + return ret; + + ret = gb_connection_svc_connection_create(connection); + if (ret) + goto err_hd_cport_clear; + + ret = gb_connection_hd_cport_connected(connection); + if (ret) + goto err_svc_connection_destroy; + + spin_lock_irq(&connection->lock); + if (connection->handler && rx) + connection->state = GB_CONNECTION_STATE_ENABLED; + else + connection->state = GB_CONNECTION_STATE_ENABLED_TX; + spin_unlock_irq(&connection->lock); + + ret = gb_connection_control_connected(connection); + if (ret) + goto err_control_disconnecting; + + return 0; + +err_control_disconnecting: + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISCONNECTING; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + /* Transmit queue should already be empty. */ + gb_connection_hd_cport_flush(connection); + + gb_connection_control_disconnecting(connection); + gb_connection_cport_shutdown_phase_1(connection); + gb_connection_hd_cport_quiesce(connection); + gb_connection_cport_shutdown_phase_2(connection); + gb_connection_control_disconnected(connection); + connection->state = GB_CONNECTION_STATE_DISABLED; +err_svc_connection_destroy: + gb_connection_svc_connection_destroy(connection); +err_hd_cport_clear: + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); + + return ret; +} + +int gb_connection_enable(struct gb_connection *connection) +{ + int ret = 0; + + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) + goto out_unlock; + + ret = _gb_connection_enable(connection, true); + if (!ret) + trace_gb_connection_enable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_connection_enable); + +int gb_connection_enable_tx(struct gb_connection *connection) +{ + int ret = 0; + + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_ENABLED) { + ret = -EINVAL; + goto out_unlock; + } + + if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) + goto out_unlock; + + ret = _gb_connection_enable(connection, false); + if (!ret) + trace_gb_connection_enable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_connection_enable_tx); + +void gb_connection_disable_rx(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + spin_lock_irq(&connection->lock); + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + spin_unlock_irq(&connection->lock); + goto out_unlock; + } + connection->state = GB_CONNECTION_STATE_ENABLED_TX; + gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + trace_gb_connection_disable(connection); + +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable_rx); + +void gb_connection_mode_switch_prepare(struct gb_connection *connection) +{ + connection->mode_switch = true; +} + +void gb_connection_mode_switch_complete(struct gb_connection *connection) +{ + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); + + connection->mode_switch = false; +} + +void gb_connection_disable(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_DISABLED) + goto out_unlock; + + trace_gb_connection_disable(connection); + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISCONNECTING; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + gb_connection_hd_cport_flush(connection); + + gb_connection_control_disconnecting(connection); + gb_connection_cport_shutdown_phase_1(connection); + gb_connection_hd_cport_quiesce(connection); + gb_connection_cport_shutdown_phase_2(connection); + gb_connection_control_disconnected(connection); + + connection->state = GB_CONNECTION_STATE_DISABLED; + + /* control-connection tear down is deferred when mode switching */ + if (!connection->mode_switch) { + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); + } + +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable); + +/* Disable a connection without communicating with the remote end. */ +void gb_connection_disable_forced(struct gb_connection *connection) +{ + mutex_lock(&connection->mutex); + + if (connection->state == GB_CONNECTION_STATE_DISABLED) + goto out_unlock; + + trace_gb_connection_disable(connection); + + spin_lock_irq(&connection->lock); + connection->state = GB_CONNECTION_STATE_DISABLED; + gb_connection_cancel_operations(connection, -ESHUTDOWN); + spin_unlock_irq(&connection->lock); + + gb_connection_hd_cport_flush(connection); + + gb_connection_svc_connection_destroy(connection); + gb_connection_hd_cport_clear(connection); + + gb_connection_hd_cport_disable(connection); +out_unlock: + mutex_unlock(&connection->mutex); +} +EXPORT_SYMBOL_GPL(gb_connection_disable_forced); + +/* Caller must have disabled the connection before destroying it. */ +void gb_connection_destroy(struct gb_connection *connection) +{ + if (!connection) + return; + + if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED)) + gb_connection_disable(connection); + + mutex_lock(&gb_connection_mutex); + + spin_lock_irq(&gb_connections_lock); + list_del(&connection->bundle_links); + list_del(&connection->hd_links); + spin_unlock_irq(&gb_connections_lock); + + destroy_workqueue(connection->wq); + + gb_hd_cport_release(connection->hd, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; + + mutex_unlock(&gb_connection_mutex); + + gb_connection_put(connection); +} +EXPORT_SYMBOL_GPL(gb_connection_destroy); + +void gb_connection_latency_tag_enable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->latency_tag_enable) + return; + + ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to enable latency tag: %d\n", + connection->name, ret); + } +} +EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable); + +void gb_connection_latency_tag_disable(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + int ret; + + if (!hd->driver->latency_tag_disable) + return; + + ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to disable latency tag: %d\n", + connection->name, ret); + } +} +EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); diff --git a/drivers/greybus/control.c b/drivers/greybus/control.c new file mode 100644 index 000000000000..359a25841973 --- /dev/null +++ b/drivers/greybus/control.c @@ -0,0 +1,584 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus CPort control protocol. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ + +#include +#include +#include +#include + +/* Highest control-protocol version supported */ +#define GB_CONTROL_VERSION_MAJOR 0 +#define GB_CONTROL_VERSION_MINOR 1 + +static int gb_control_get_version(struct gb_control *control) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_control_version_request request; + struct gb_control_version_response response; + int ret; + + request.major = GB_CONTROL_VERSION_MAJOR; + request.minor = GB_CONTROL_VERSION_MINOR; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_VERSION, + &request, sizeof(request), &response, + sizeof(response)); + if (ret) { + dev_err(&intf->dev, + "failed to get control-protocol version: %d\n", + ret); + return ret; + } + + if (response.major > request.major) { + dev_err(&intf->dev, + "unsupported major control-protocol version (%u > %u)\n", + response.major, request.major); + return -ENOTSUPP; + } + + control->protocol_major = response.major; + control->protocol_minor = response.minor; + + dev_dbg(&intf->dev, "%s - %u.%u\n", __func__, response.major, + response.minor); + + return 0; +} + +static int gb_control_get_bundle_version(struct gb_control *control, + struct gb_bundle *bundle) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_control_bundle_version_request request; + struct gb_control_bundle_version_response response; + int ret; + + request.bundle_id = bundle->id; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_VERSION, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&intf->dev, + "failed to get bundle %u class version: %d\n", + bundle->id, ret); + return ret; + } + + bundle->class_major = response.major; + bundle->class_minor = response.minor; + + dev_dbg(&intf->dev, "%s - %u: %u.%u\n", __func__, bundle->id, + response.major, response.minor); + + return 0; +} + +int gb_control_get_bundle_versions(struct gb_control *control) +{ + struct gb_interface *intf = control->connection->intf; + struct gb_bundle *bundle; + int ret; + + if (!control->has_bundle_version) + return 0; + + list_for_each_entry(bundle, &intf->bundles, links) { + ret = gb_control_get_bundle_version(control, bundle); + if (ret) + return ret; + } + + return 0; +} + +/* Get Manifest's size from the interface */ +int gb_control_get_manifest_size_operation(struct gb_interface *intf) +{ + struct gb_control_get_manifest_size_response response; + struct gb_connection *connection = intf->control->connection; + int ret; + + ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->intf->dev, + "failed to get manifest size: %d\n", ret); + return ret; + } + + return le16_to_cpu(response.size); +} + +/* Reads Manifest from the interface */ +int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, + size_t size) +{ + struct gb_connection *connection = intf->control->connection; + + return gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST, + NULL, 0, manifest, size); +} + +int gb_control_connected_operation(struct gb_control *control, u16 cport_id) +{ + struct gb_control_connected_request request; + + request.cport_id = cpu_to_le16(cport_id); + return gb_operation_sync(control->connection, GB_CONTROL_TYPE_CONNECTED, + &request, sizeof(request), NULL, 0); +} + +int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) +{ + struct gb_control_disconnected_request request; + + request.cport_id = cpu_to_le16(cport_id); + return gb_operation_sync(control->connection, + GB_CONTROL_TYPE_DISCONNECTED, &request, + sizeof(request), NULL, 0); +} + +int gb_control_disconnecting_operation(struct gb_control *control, + u16 cport_id) +{ + struct gb_control_disconnecting_request *request; + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(control->connection, + GB_CONTROL_TYPE_DISCONNECTING, + sizeof(*request), 0, 0, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + request = operation->request->payload; + request->cport_id = cpu_to_le16(cport_id); + + ret = gb_operation_request_send_sync(operation); + if (ret) { + dev_err(&control->dev, "failed to send disconnecting: %d\n", + ret); + } + + gb_operation_put(operation); + + return ret; +} + +int gb_control_mode_switch_operation(struct gb_control *control) +{ + struct gb_operation *operation; + int ret; + + operation = gb_operation_create_core(control->connection, + GB_CONTROL_TYPE_MODE_SWITCH, + 0, 0, + GB_OPERATION_FLAG_UNIDIRECTIONAL, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + ret = gb_operation_request_send_sync(operation); + if (ret) + dev_err(&control->dev, "failed to send mode switch: %d\n", ret); + + gb_operation_put(operation); + + return ret; +} + +static int gb_control_bundle_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_BUNDLE_PM_INVAL: + return -EINVAL; + case GB_CONTROL_BUNDLE_PM_BUSY: + return -EBUSY; + case GB_CONTROL_BUNDLE_PM_NA: + return -ENOMSG; + case GB_CONTROL_BUNDLE_PM_FAIL: + default: + return -EREMOTEIO; + } +} + +int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_SUSPEND, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send bundle %u suspend: %d\n", + bundle_id, ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to suspend bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_RESUME, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send bundle %u resume: %d\n", + bundle_id, ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to resume bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_DEACTIVATE, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle %u deactivate: %d\n", bundle_id, + ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to deactivate bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) +{ + struct gb_control_bundle_pm_request request; + struct gb_control_bundle_pm_response response; + int ret; + + if (!control->has_bundle_activate) + return 0; + + request.bundle_id = bundle_id; + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_BUNDLE_ACTIVATE, &request, + sizeof(request), &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send bundle %u activate: %d\n", bundle_id, + ret); + return ret; + } + + if (response.status != GB_CONTROL_BUNDLE_PM_OK) { + dev_err(&control->dev, "failed to activate bundle %u: %d\n", + bundle_id, response.status); + return gb_control_bundle_pm_status_map(response.status); + } + + return 0; +} + +static int gb_control_interface_pm_status_map(u8 status) +{ + switch (status) { + case GB_CONTROL_INTF_PM_BUSY: + return -EBUSY; + case GB_CONTROL_INTF_PM_NA: + return -ENOMSG; + default: + return -EREMOTEIO; + } +} + +int gb_control_interface_suspend_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface suspend prepare: %d\n", ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing suspend: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_interface_deactivate_prepare(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE, NULL, + 0, &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, "failed to send interface deactivate prepare: %d\n", + ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while preparing deactivate: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + +int gb_control_interface_hibernate_abort(struct gb_control *control) +{ + struct gb_control_intf_pm_response response; + int ret; + + ret = gb_operation_sync(control->connection, + GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&control->dev, + "failed to send interface aborting hibernate: %d\n", + ret); + return ret; + } + + if (response.status != GB_CONTROL_INTF_PM_OK) { + dev_err(&control->dev, "interface error while aborting hibernate: %d\n", + response.status); + return gb_control_interface_pm_status_map(response.status); + } + + return 0; +} + +static ssize_t vendor_string_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_control *control = to_gb_control(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", control->vendor_string); +} +static DEVICE_ATTR_RO(vendor_string); + +static ssize_t product_string_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_control *control = to_gb_control(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", control->product_string); +} +static DEVICE_ATTR_RO(product_string); + +static struct attribute *control_attrs[] = { + &dev_attr_vendor_string.attr, + &dev_attr_product_string.attr, + NULL, +}; +ATTRIBUTE_GROUPS(control); + +static void gb_control_release(struct device *dev) +{ + struct gb_control *control = to_gb_control(dev); + + gb_connection_destroy(control->connection); + + kfree(control->vendor_string); + kfree(control->product_string); + + kfree(control); +} + +struct device_type greybus_control_type = { + .name = "greybus_control", + .release = gb_control_release, +}; + +struct gb_control *gb_control_create(struct gb_interface *intf) +{ + struct gb_connection *connection; + struct gb_control *control; + + control = kzalloc(sizeof(*control), GFP_KERNEL); + if (!control) + return ERR_PTR(-ENOMEM); + + control->intf = intf; + + connection = gb_connection_create_control(intf); + if (IS_ERR(connection)) { + dev_err(&intf->dev, + "failed to create control connection: %ld\n", + PTR_ERR(connection)); + kfree(control); + return ERR_CAST(connection); + } + + control->connection = connection; + + control->dev.parent = &intf->dev; + control->dev.bus = &greybus_bus_type; + control->dev.type = &greybus_control_type; + control->dev.groups = control_groups; + control->dev.dma_mask = intf->dev.dma_mask; + device_initialize(&control->dev); + dev_set_name(&control->dev, "%s.ctrl", dev_name(&intf->dev)); + + gb_connection_set_data(control->connection, control); + + return control; +} + +int gb_control_enable(struct gb_control *control) +{ + int ret; + + dev_dbg(&control->connection->intf->dev, "%s\n", __func__); + + ret = gb_connection_enable_tx(control->connection); + if (ret) { + dev_err(&control->connection->intf->dev, + "failed to enable control connection: %d\n", + ret); + return ret; + } + + ret = gb_control_get_version(control); + if (ret) + goto err_disable_connection; + + if (control->protocol_major > 0 || control->protocol_minor > 1) + control->has_bundle_version = true; + + /* FIXME: use protocol version instead */ + if (!(control->intf->quirks & GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE)) + control->has_bundle_activate = true; + + return 0; + +err_disable_connection: + gb_connection_disable(control->connection); + + return ret; +} + +void gb_control_disable(struct gb_control *control) +{ + dev_dbg(&control->connection->intf->dev, "%s\n", __func__); + + if (control->intf->disconnected) + gb_connection_disable_forced(control->connection); + else + gb_connection_disable(control->connection); +} + +int gb_control_suspend(struct gb_control *control) +{ + gb_connection_disable(control->connection); + + return 0; +} + +int gb_control_resume(struct gb_control *control) +{ + int ret; + + ret = gb_connection_enable_tx(control->connection); + if (ret) { + dev_err(&control->connection->intf->dev, + "failed to enable control connection: %d\n", ret); + return ret; + } + + return 0; +} + +int gb_control_add(struct gb_control *control) +{ + int ret; + + ret = device_add(&control->dev); + if (ret) { + dev_err(&control->dev, + "failed to register control device: %d\n", + ret); + return ret; + } + + return 0; +} + +void gb_control_del(struct gb_control *control) +{ + if (device_is_registered(&control->dev)) + device_del(&control->dev); +} + +struct gb_control *gb_control_get(struct gb_control *control) +{ + get_device(&control->dev); + + return control; +} + +void gb_control_put(struct gb_control *control) +{ + put_device(&control->dev); +} + +void gb_control_mode_switch_prepare(struct gb_control *control) +{ + gb_connection_mode_switch_prepare(control->connection); +} + +void gb_control_mode_switch_complete(struct gb_control *control) +{ + gb_connection_mode_switch_complete(control->connection); +} diff --git a/drivers/greybus/core.c b/drivers/greybus/core.c new file mode 100644 index 000000000000..e546c6431877 --- /dev/null +++ b/drivers/greybus/core.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus "Core" + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#define CREATE_TRACE_POINTS +#include +#include "greybus_trace.h" + +#define GB_BUNDLE_AUTOSUSPEND_MS 3000 + +/* Allow greybus to be disabled at boot if needed */ +static bool nogreybus; +#ifdef MODULE +module_param(nogreybus, bool, 0444); +#else +core_param(nogreybus, nogreybus, bool, 0444); +#endif +int greybus_disabled(void) +{ + return nogreybus; +} +EXPORT_SYMBOL_GPL(greybus_disabled); + +static bool greybus_match_one_id(struct gb_bundle *bundle, + const struct greybus_bundle_id *id) +{ + if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && + (id->vendor != bundle->intf->vendor_id)) + return false; + + if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && + (id->product != bundle->intf->product_id)) + return false; + + if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && + (id->class != bundle->class)) + return false; + + return true; +} + +static const struct greybus_bundle_id * +greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) +{ + if (!id) + return NULL; + + for (; id->vendor || id->product || id->class || id->driver_info; + id++) { + if (greybus_match_one_id(bundle, id)) + return id; + } + + return NULL; +} + +static int greybus_match_device(struct device *dev, struct device_driver *drv) +{ + struct greybus_driver *driver = to_greybus_driver(drv); + struct gb_bundle *bundle; + const struct greybus_bundle_id *id; + + if (!is_gb_bundle(dev)) + return 0; + + bundle = to_gb_bundle(dev); + + id = greybus_match_id(bundle, driver->id_table); + if (id) + return 1; + /* FIXME - Dynamic ids? */ + return 0; +} + +static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct gb_host_device *hd; + struct gb_module *module = NULL; + struct gb_interface *intf = NULL; + struct gb_control *control = NULL; + struct gb_bundle *bundle = NULL; + struct gb_svc *svc = NULL; + + if (is_gb_host_device(dev)) { + hd = to_gb_host_device(dev); + } else if (is_gb_module(dev)) { + module = to_gb_module(dev); + hd = module->hd; + } else if (is_gb_interface(dev)) { + intf = to_gb_interface(dev); + module = intf->module; + hd = intf->hd; + } else if (is_gb_control(dev)) { + control = to_gb_control(dev); + intf = control->intf; + module = intf->module; + hd = intf->hd; + } else if (is_gb_bundle(dev)) { + bundle = to_gb_bundle(dev); + intf = bundle->intf; + module = intf->module; + hd = intf->hd; + } else if (is_gb_svc(dev)) { + svc = to_gb_svc(dev); + hd = svc->hd; + } else { + dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); + return -EINVAL; + } + + if (add_uevent_var(env, "BUS=%u", hd->bus_id)) + return -ENOMEM; + + if (module) { + if (add_uevent_var(env, "MODULE=%u", module->module_id)) + return -ENOMEM; + } + + if (intf) { + if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) + return -ENOMEM; + if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", + intf->vendor_id, intf->product_id)) + return -ENOMEM; + } + + if (bundle) { + // FIXME + // add a uevent that can "load" a bundle type + // This is what we need to bind a driver to so use the info + // in gmod here as well + + if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) + return -ENOMEM; + if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) + return -ENOMEM; + } + + return 0; +} + +static void greybus_shutdown(struct device *dev) +{ + if (is_gb_host_device(dev)) { + struct gb_host_device *hd; + + hd = to_gb_host_device(dev); + gb_hd_shutdown(hd); + } +} + +struct bus_type greybus_bus_type = { + .name = "greybus", + .match = greybus_match_device, + .uevent = greybus_uevent, + .shutdown = greybus_shutdown, +}; + +static int greybus_probe(struct device *dev) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct gb_bundle *bundle = to_gb_bundle(dev); + const struct greybus_bundle_id *id; + int retval; + + /* match id */ + id = greybus_match_id(bundle, driver->id_table); + if (!id) + return -ENODEV; + + retval = pm_runtime_get_sync(&bundle->intf->dev); + if (retval < 0) { + pm_runtime_put_noidle(&bundle->intf->dev); + return retval; + } + + retval = gb_control_bundle_activate(bundle->intf->control, bundle->id); + if (retval) { + pm_runtime_put(&bundle->intf->dev); + return retval; + } + + /* + * Unbound bundle devices are always deactivated. During probe, the + * Runtime PM is set to enabled and active and the usage count is + * incremented. If the driver supports runtime PM, it should call + * pm_runtime_put() in its probe routine and pm_runtime_get_sync() + * in remove routine. + */ + pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + retval = driver->probe(bundle, id); + if (retval) { + /* + * Catch buggy drivers that fail to destroy their connections. + */ + WARN_ON(!list_empty(&bundle->connections)); + + gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_put(&bundle->intf->dev); + + return retval; + } + + pm_runtime_put(&bundle->intf->dev); + + return 0; +} + +static int greybus_remove(struct device *dev) +{ + struct greybus_driver *driver = to_greybus_driver(dev->driver); + struct gb_bundle *bundle = to_gb_bundle(dev); + struct gb_connection *connection; + int retval; + + retval = pm_runtime_get_sync(dev); + if (retval < 0) + dev_err(dev, "failed to resume bundle: %d\n", retval); + + /* + * Disable (non-offloaded) connections early in case the interface is + * already gone to avoid unceccessary operation timeouts during + * driver disconnect. Otherwise, only disable incoming requests. + */ + list_for_each_entry(connection, &bundle->connections, bundle_links) { + if (gb_connection_is_offloaded(connection)) + continue; + + if (bundle->intf->disconnected) + gb_connection_disable_forced(connection); + else + gb_connection_disable_rx(connection); + } + + driver->disconnect(bundle); + + /* Catch buggy drivers that fail to destroy their connections. */ + WARN_ON(!list_empty(&bundle->connections)); + + if (!bundle->intf->disconnected) + gb_control_bundle_deactivate(bundle->intf->control, bundle->id); + + pm_runtime_put_noidle(dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_put_noidle(dev); + + return 0; +} + +int greybus_register_driver(struct greybus_driver *driver, struct module *owner, + const char *mod_name) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + driver->driver.bus = &greybus_bus_type; + driver->driver.name = driver->name; + driver->driver.probe = greybus_probe; + driver->driver.remove = greybus_remove; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + + retval = driver_register(&driver->driver); + if (retval) + return retval; + + pr_info("registered new driver %s\n", driver->name); + return 0; +} +EXPORT_SYMBOL_GPL(greybus_register_driver); + +void greybus_deregister_driver(struct greybus_driver *driver) +{ + driver_unregister(&driver->driver); +} +EXPORT_SYMBOL_GPL(greybus_deregister_driver); + +static int __init gb_init(void) +{ + int retval; + + if (greybus_disabled()) + return -ENODEV; + + BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD); + + gb_debugfs_init(); + + retval = bus_register(&greybus_bus_type); + if (retval) { + pr_err("bus_register failed (%d)\n", retval); + goto error_bus; + } + + retval = gb_hd_init(); + if (retval) { + pr_err("gb_hd_init failed (%d)\n", retval); + goto error_hd; + } + + retval = gb_operation_init(); + if (retval) { + pr_err("gb_operation_init failed (%d)\n", retval); + goto error_operation; + } + return 0; /* Success */ + +error_operation: + gb_hd_exit(); +error_hd: + bus_unregister(&greybus_bus_type); +error_bus: + gb_debugfs_cleanup(); + + return retval; +} +module_init(gb_init); + +static void __exit gb_exit(void) +{ + gb_operation_exit(); + gb_hd_exit(); + bus_unregister(&greybus_bus_type); + gb_debugfs_cleanup(); + tracepoint_synchronize_unregister(); +} +module_exit(gb_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/greybus/debugfs.c b/drivers/greybus/debugfs.c new file mode 100644 index 000000000000..e102d7badb9d --- /dev/null +++ b/drivers/greybus/debugfs.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus debugfs code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#include +#include + +static struct dentry *gb_debug_root; + +void __init gb_debugfs_init(void) +{ + gb_debug_root = debugfs_create_dir("greybus", NULL); +} + +void gb_debugfs_cleanup(void) +{ + debugfs_remove_recursive(gb_debug_root); + gb_debug_root = NULL; +} + +struct dentry *gb_debugfs_get(void) +{ + return gb_debug_root; +} +EXPORT_SYMBOL_GPL(gb_debugfs_get); diff --git a/drivers/greybus/greybus_trace.h b/drivers/greybus/greybus_trace.h new file mode 100644 index 000000000000..1bc9f1275c65 --- /dev/null +++ b/drivers/greybus/greybus_trace.h @@ -0,0 +1,502 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Greybus driver and device API + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM greybus + +#if !defined(_TRACE_GREYBUS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_GREYBUS_H + +#include + +struct gb_message; +struct gb_operation; +struct gb_connection; +struct gb_bundle; +struct gb_host_device; + +DECLARE_EVENT_CLASS(gb_message, + + TP_PROTO(struct gb_message *message), + + TP_ARGS(message), + + TP_STRUCT__entry( + __field(u16, size) + __field(u16, operation_id) + __field(u8, type) + __field(u8, result) + ), + + TP_fast_assign( + __entry->size = le16_to_cpu(message->header->size); + __entry->operation_id = + le16_to_cpu(message->header->operation_id); + __entry->type = message->header->type; + __entry->result = message->header->result; + ), + + TP_printk("size=%hu operation_id=0x%04x type=0x%02x result=0x%02x", + __entry->size, __entry->operation_id, + __entry->type, __entry->result) +); + +#define DEFINE_MESSAGE_EVENT(name) \ + DEFINE_EVENT(gb_message, name, \ + TP_PROTO(struct gb_message *message), \ + TP_ARGS(message)) + +/* + * Occurs immediately before calling a host device's message_send() + * method. + */ +DEFINE_MESSAGE_EVENT(gb_message_send); + +/* + * Occurs after an incoming request message has been received + */ +DEFINE_MESSAGE_EVENT(gb_message_recv_request); + +/* + * Occurs after an incoming response message has been received, + * after its matching request has been found. + */ +DEFINE_MESSAGE_EVENT(gb_message_recv_response); + +/* + * Occurs after an operation has been canceled, possibly before the + * cancellation is complete. + */ +DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); + +/* + * Occurs when an incoming request is cancelled; if the response has + * been queued for sending, this occurs after it is sent. + */ +DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); + +/* + * Occurs in the host driver message_send() function just prior to + * handing off the data to be processed by hardware. + */ +DEFINE_MESSAGE_EVENT(gb_message_submit); + +#undef DEFINE_MESSAGE_EVENT + +DECLARE_EVENT_CLASS(gb_operation, + + TP_PROTO(struct gb_operation *operation), + + TP_ARGS(operation), + + TP_STRUCT__entry( + __field(u16, cport_id) /* CPort of HD side of connection */ + __field(u16, id) /* Operation ID */ + __field(u8, type) + __field(unsigned long, flags) + __field(int, active) + __field(int, waiters) + __field(int, errno) + ), + + TP_fast_assign( + __entry->cport_id = operation->connection->hd_cport_id; + __entry->id = operation->id; + __entry->type = operation->type; + __entry->flags = operation->flags; + __entry->active = operation->active; + __entry->waiters = atomic_read(&operation->waiters); + __entry->errno = operation->errno; + ), + + TP_printk("id=%04x type=0x%02x cport_id=%04x flags=0x%lx active=%d waiters=%d errno=%d", + __entry->id, __entry->cport_id, __entry->type, __entry->flags, + __entry->active, __entry->waiters, __entry->errno) +); + +#define DEFINE_OPERATION_EVENT(name) \ + DEFINE_EVENT(gb_operation, name, \ + TP_PROTO(struct gb_operation *operation), \ + TP_ARGS(operation)) + +/* + * Occurs after a new operation is created for an outgoing request + * has been successfully created. + */ +DEFINE_OPERATION_EVENT(gb_operation_create); + +/* + * Occurs after a new core operation has been created. + */ +DEFINE_OPERATION_EVENT(gb_operation_create_core); + +/* + * Occurs after a new operation has been created for an incoming + * request has been successfully created and initialized. + */ +DEFINE_OPERATION_EVENT(gb_operation_create_incoming); + +/* + * Occurs when the last reference to an operation has been dropped, + * prior to freeing resources. + */ +DEFINE_OPERATION_EVENT(gb_operation_destroy); + +/* + * Occurs when an operation has been marked active, after updating + * its active count. + */ +DEFINE_OPERATION_EVENT(gb_operation_get_active); + +/* + * Occurs when an operation has been marked active, before updating + * its active count. + */ +DEFINE_OPERATION_EVENT(gb_operation_put_active); + +#undef DEFINE_OPERATION_EVENT + +DECLARE_EVENT_CLASS(gb_connection, + + TP_PROTO(struct gb_connection *connection), + + TP_ARGS(connection), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, bundle_id) + /* name contains "hd_cport_id/intf_id:cport_id" */ + __dynamic_array(char, name, sizeof(connection->name)) + __field(enum gb_connection_state, state) + __field(unsigned long, flags) + ), + + TP_fast_assign( + __entry->hd_bus_id = connection->hd->bus_id; + __entry->bundle_id = connection->bundle ? + connection->bundle->id : BUNDLE_ID_NONE; + memcpy(__get_str(name), connection->name, + sizeof(connection->name)); + __entry->state = connection->state; + __entry->flags = connection->flags; + ), + + TP_printk("hd_bus_id=%d bundle_id=0x%02x name=\"%s\" state=%u flags=0x%lx", + __entry->hd_bus_id, __entry->bundle_id, __get_str(name), + (unsigned int)__entry->state, __entry->flags) +); + +#define DEFINE_CONNECTION_EVENT(name) \ + DEFINE_EVENT(gb_connection, name, \ + TP_PROTO(struct gb_connection *connection), \ + TP_ARGS(connection)) + +/* + * Occurs after a new connection is successfully created. + */ +DEFINE_CONNECTION_EVENT(gb_connection_create); + +/* + * Occurs when the last reference to a connection has been dropped, + * before its resources are freed. + */ +DEFINE_CONNECTION_EVENT(gb_connection_release); + +/* + * Occurs when a new reference to connection is added, currently + * only when a message over the connection is received. + */ +DEFINE_CONNECTION_EVENT(gb_connection_get); + +/* + * Occurs when a new reference to connection is dropped, after a + * a received message is handled, or when the connection is + * destroyed. + */ +DEFINE_CONNECTION_EVENT(gb_connection_put); + +/* + * Occurs when a request to enable a connection is made, either for + * transmit only, or for both transmit and receive. + */ +DEFINE_CONNECTION_EVENT(gb_connection_enable); + +/* + * Occurs when a request to disable a connection is made, either for + * receive only, or for both transmit and receive. Also occurs when + * a request to forcefully disable a connection is made. + */ +DEFINE_CONNECTION_EVENT(gb_connection_disable); + +#undef DEFINE_CONNECTION_EVENT + +DECLARE_EVENT_CLASS(gb_bundle, + + TP_PROTO(struct gb_bundle *bundle), + + TP_ARGS(bundle), + + TP_STRUCT__entry( + __field(u8, intf_id) + __field(u8, id) + __field(u8, class) + __field(size_t, num_cports) + ), + + TP_fast_assign( + __entry->intf_id = bundle->intf->interface_id; + __entry->id = bundle->id; + __entry->class = bundle->class; + __entry->num_cports = bundle->num_cports; + ), + + TP_printk("intf_id=0x%02x id=%02x class=0x%02x num_cports=%zu", + __entry->intf_id, __entry->id, __entry->class, + __entry->num_cports) +); + +#define DEFINE_BUNDLE_EVENT(name) \ + DEFINE_EVENT(gb_bundle, name, \ + TP_PROTO(struct gb_bundle *bundle), \ + TP_ARGS(bundle)) + +/* + * Occurs after a new bundle is successfully created. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_create); + +/* + * Occurs when the last reference to a bundle has been dropped, + * before its resources are freed. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_release); + +/* + * Occurs when a bundle is added to an interface when the interface + * is enabled. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_add); + +/* + * Occurs when a registered bundle gets destroyed, normally at the + * time an interface is disabled. + */ +DEFINE_BUNDLE_EVENT(gb_bundle_destroy); + +#undef DEFINE_BUNDLE_EVENT + +DECLARE_EVENT_CLASS(gb_interface, + + TP_PROTO(struct gb_interface *intf), + + TP_ARGS(intf), + + TP_STRUCT__entry( + __field(u8, module_id) + __field(u8, id) /* Interface id */ + __field(u8, device_id) + __field(int, disconnected) /* bool */ + __field(int, ejected) /* bool */ + __field(int, active) /* bool */ + __field(int, enabled) /* bool */ + __field(int, mode_switch) /* bool */ + ), + + TP_fast_assign( + __entry->module_id = intf->module->module_id; + __entry->id = intf->interface_id; + __entry->device_id = intf->device_id; + __entry->disconnected = intf->disconnected; + __entry->ejected = intf->ejected; + __entry->active = intf->active; + __entry->enabled = intf->enabled; + __entry->mode_switch = intf->mode_switch; + ), + + TP_printk("intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d M=%d", + __entry->id, __entry->device_id, __entry->module_id, + __entry->disconnected, __entry->ejected, __entry->active, + __entry->enabled, __entry->mode_switch) +); + +#define DEFINE_INTERFACE_EVENT(name) \ + DEFINE_EVENT(gb_interface, name, \ + TP_PROTO(struct gb_interface *intf), \ + TP_ARGS(intf)) + +/* + * Occurs after a new interface is successfully created. + */ +DEFINE_INTERFACE_EVENT(gb_interface_create); + +/* + * Occurs after the last reference to an interface has been dropped. + */ +DEFINE_INTERFACE_EVENT(gb_interface_release); + +/* + * Occurs after an interface been registerd. + */ +DEFINE_INTERFACE_EVENT(gb_interface_add); + +/* + * Occurs when a registered interface gets deregisterd. + */ +DEFINE_INTERFACE_EVENT(gb_interface_del); + +/* + * Occurs when a registered interface has been successfully + * activated. + */ +DEFINE_INTERFACE_EVENT(gb_interface_activate); + +/* + * Occurs when an activated interface is being deactivated. + */ +DEFINE_INTERFACE_EVENT(gb_interface_deactivate); + +/* + * Occurs when an interface has been successfully enabled. + */ +DEFINE_INTERFACE_EVENT(gb_interface_enable); + +/* + * Occurs when an enabled interface is being disabled. + */ +DEFINE_INTERFACE_EVENT(gb_interface_disable); + +#undef DEFINE_INTERFACE_EVENT + +DECLARE_EVENT_CLASS(gb_module, + + TP_PROTO(struct gb_module *module), + + TP_ARGS(module), + + TP_STRUCT__entry( + __field(int, hd_bus_id) + __field(u8, module_id) + __field(size_t, num_interfaces) + __field(int, disconnected) /* bool */ + ), + + TP_fast_assign( + __entry->hd_bus_id = module->hd->bus_id; + __entry->module_id = module->module_id; + __entry->num_interfaces = module->num_interfaces; + __entry->disconnected = module->disconnected; + ), + + TP_printk("hd_bus_id=%d module_id=%hhu num_interfaces=%zu disconnected=%d", + __entry->hd_bus_id, __entry->module_id, + __entry->num_interfaces, __entry->disconnected) +); + +#define DEFINE_MODULE_EVENT(name) \ + DEFINE_EVENT(gb_module, name, \ + TP_PROTO(struct gb_module *module), \ + TP_ARGS(module)) + +/* + * Occurs after a new module is successfully created, before + * creating any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_create); + +/* + * Occurs after the last reference to a module has been dropped. + */ +DEFINE_MODULE_EVENT(gb_module_release); + +/* + * Occurs after a module is successfully created, before registering + * any of its interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_add); + +/* + * Occurs when a module is deleted, before deregistering its + * interfaces. + */ +DEFINE_MODULE_EVENT(gb_module_del); + +#undef DEFINE_MODULE_EVENT + +DECLARE_EVENT_CLASS(gb_host_device, + + TP_PROTO(struct gb_host_device *hd), + + TP_ARGS(hd), + + TP_STRUCT__entry( + __field(int, bus_id) + __field(size_t, num_cports) + __field(size_t, buffer_size_max) + ), + + TP_fast_assign( + __entry->bus_id = hd->bus_id; + __entry->num_cports = hd->num_cports; + __entry->buffer_size_max = hd->buffer_size_max; + ), + + TP_printk("bus_id=%d num_cports=%zu mtu=%zu", + __entry->bus_id, __entry->num_cports, + __entry->buffer_size_max) +); + +#define DEFINE_HD_EVENT(name) \ + DEFINE_EVENT(gb_host_device, name, \ + TP_PROTO(struct gb_host_device *hd), \ + TP_ARGS(hd)) + +/* + * Occurs after a new host device is successfully created, before + * its SVC has been set up. + */ +DEFINE_HD_EVENT(gb_hd_create); + +/* + * Occurs after the last reference to a host device has been + * dropped. + */ +DEFINE_HD_EVENT(gb_hd_release); + +/* + * Occurs after a new host device has been added, after the + * connection to its SVC has been enabled. + */ +DEFINE_HD_EVENT(gb_hd_add); + +/* + * Occurs when a host device is being disconnected from the AP USB + * host controller. + */ +DEFINE_HD_EVENT(gb_hd_del); + +/* + * Occurs when a host device has passed received data to the Greybus + * core, after it has been determined it is destined for a valid + * CPort. + */ +DEFINE_HD_EVENT(gb_hd_in); + +#undef DEFINE_HD_EVENT + +#endif /* _TRACE_GREYBUS_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +/* + * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal + */ +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE greybus_trace +#include + diff --git a/drivers/greybus/hd.c b/drivers/greybus/hd.c new file mode 100644 index 000000000000..72b21bf2d7d3 --- /dev/null +++ b/drivers/greybus/hd.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus Host Device + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#include +#include +#include + +#include "greybus_trace.h" + +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in); +EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); + +static struct ida gb_hd_bus_id_map; + +int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async) +{ + if (!hd || !hd->driver || !hd->driver->output) + return -EINVAL; + return hd->driver->output(hd, req, size, cmd, async); +} +EXPORT_SYMBOL_GPL(gb_hd_output); + +static ssize_t bus_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_host_device *hd = to_gb_host_device(dev); + + return sprintf(buf, "%d\n", hd->bus_id); +} +static DEVICE_ATTR_RO(bus_id); + +static struct attribute *bus_attrs[] = { + &dev_attr_bus_id.attr, + NULL +}; +ATTRIBUTE_GROUPS(bus); + +int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + int ret; + + ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL); + if (ret < 0) { + dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); + +void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + + ida_simple_remove(id_map, cport_id); +} +EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved); + +/* Locking: Caller guarantees serialisation */ +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags) +{ + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + if (hd->driver->cport_allocate) + return hd->driver->cport_allocate(hd, cport_id, flags); + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +/* Locking: Caller guarantees serialisation */ +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + if (hd->driver->cport_release) { + hd->driver->cport_release(hd, cport_id); + return; + } + + ida_simple_remove(&hd->cport_id_map, cport_id); +} + +static void gb_hd_release(struct device *dev) +{ + struct gb_host_device *hd = to_gb_host_device(dev); + + trace_gb_hd_release(hd); + + if (hd->svc) + gb_svc_put(hd->svc); + ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); + ida_destroy(&hd->cport_id_map); + kfree(hd); +} + +struct device_type greybus_hd_type = { + .name = "greybus_host_device", + .release = gb_hd_release, +}; + +struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, + struct device *parent, + size_t buffer_size_max, + size_t num_cports) +{ + struct gb_host_device *hd; + int ret; + + /* + * Validate that the driver implements all of the callbacks + * so that we don't have to every time we make them. + */ + if ((!driver->message_send) || (!driver->message_cancel)) { + dev_err(parent, "mandatory hd-callbacks missing\n"); + return ERR_PTR(-EINVAL); + } + + if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { + dev_err(parent, "greybus host-device buffers too small\n"); + return ERR_PTR(-EINVAL); + } + + if (num_cports == 0 || num_cports > CPORT_ID_MAX + 1) { + dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); + return ERR_PTR(-EINVAL); + } + + /* + * Make sure to never allocate messages larger than what the Greybus + * protocol supports. + */ + if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { + dev_warn(parent, "limiting buffer size to %u\n", + GB_OPERATION_MESSAGE_SIZE_MAX); + buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; + } + + hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); + if (!hd) + return ERR_PTR(-ENOMEM); + + ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); + if (ret < 0) { + kfree(hd); + return ERR_PTR(ret); + } + hd->bus_id = ret; + + hd->driver = driver; + INIT_LIST_HEAD(&hd->modules); + INIT_LIST_HEAD(&hd->connections); + ida_init(&hd->cport_id_map); + hd->buffer_size_max = buffer_size_max; + hd->num_cports = num_cports; + + hd->dev.parent = parent; + hd->dev.bus = &greybus_bus_type; + hd->dev.type = &greybus_hd_type; + hd->dev.groups = bus_groups; + hd->dev.dma_mask = hd->dev.parent->dma_mask; + device_initialize(&hd->dev); + dev_set_name(&hd->dev, "greybus%d", hd->bus_id); + + trace_gb_hd_create(hd); + + hd->svc = gb_svc_create(hd); + if (!hd->svc) { + dev_err(&hd->dev, "failed to create svc\n"); + put_device(&hd->dev); + return ERR_PTR(-ENOMEM); + } + + return hd; +} +EXPORT_SYMBOL_GPL(gb_hd_create); + +int gb_hd_add(struct gb_host_device *hd) +{ + int ret; + + ret = device_add(&hd->dev); + if (ret) + return ret; + + ret = gb_svc_add(hd->svc); + if (ret) { + device_del(&hd->dev); + return ret; + } + + trace_gb_hd_add(hd); + + return 0; +} +EXPORT_SYMBOL_GPL(gb_hd_add); + +void gb_hd_del(struct gb_host_device *hd) +{ + trace_gb_hd_del(hd); + + /* + * Tear down the svc and flush any on-going hotplug processing before + * removing the remaining interfaces. + */ + gb_svc_del(hd->svc); + + device_del(&hd->dev); +} +EXPORT_SYMBOL_GPL(gb_hd_del); + +void gb_hd_shutdown(struct gb_host_device *hd) +{ + gb_svc_del(hd->svc); +} +EXPORT_SYMBOL_GPL(gb_hd_shutdown); + +void gb_hd_put(struct gb_host_device *hd) +{ + put_device(&hd->dev); +} +EXPORT_SYMBOL_GPL(gb_hd_put); + +int __init gb_hd_init(void) +{ + ida_init(&gb_hd_bus_id_map); + + return 0; +} + +void gb_hd_exit(void) +{ + ida_destroy(&gb_hd_bus_id_map); +} diff --git a/drivers/greybus/interface.c b/drivers/greybus/interface.c new file mode 100644 index 000000000000..67dbe6fda9a1 --- /dev/null +++ b/drivers/greybus/interface.c @@ -0,0 +1,1263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus interface code + * + * Copyright 2014 Google Inc. + * Copyright 2014 Linaro Ltd. + */ + +#include +#include + +#include "greybus_trace.h" + +#define GB_INTERFACE_MODE_SWITCH_TIMEOUT 2000 + +#define GB_INTERFACE_DEVICE_ID_BAD 0xff + +#define GB_INTERFACE_AUTOSUSPEND_MS 3000 + +/* Time required for interface to enter standby before disabling REFCLK */ +#define GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS 20 + +/* Don't-care selector index */ +#define DME_SELECTOR_INDEX_NULL 0 + +/* DME attributes */ +/* FIXME: remove ES2 support and DME_T_TST_SRC_INCREMENT */ +#define DME_T_TST_SRC_INCREMENT 0x4083 + +#define DME_DDBL1_MANUFACTURERID 0x5003 +#define DME_DDBL1_PRODUCTID 0x5004 + +#define DME_TOSHIBA_GMP_VID 0x6000 +#define DME_TOSHIBA_GMP_PID 0x6001 +#define DME_TOSHIBA_GMP_SN0 0x6002 +#define DME_TOSHIBA_GMP_SN1 0x6003 +#define DME_TOSHIBA_GMP_INIT_STATUS 0x6101 + +/* DDBL1 Manufacturer and Product ids */ +#define TOSHIBA_DMID 0x0126 +#define TOSHIBA_ES2_BRIDGE_DPID 0x1000 +#define TOSHIBA_ES3_APBRIDGE_DPID 0x1001 +#define TOSHIBA_ES3_GBPHY_DPID 0x1002 + +static int gb_interface_hibernate_link(struct gb_interface *intf); +static int gb_interface_refclk_set(struct gb_interface *intf, bool enable); + +static int gb_interface_dme_attr_get(struct gb_interface *intf, + u16 attr, u32 *val) +{ + return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id, + attr, DME_SELECTOR_INDEX_NULL, val); +} + +static int gb_interface_read_ara_dme(struct gb_interface *intf) +{ + u32 sn0, sn1; + int ret; + + /* + * Unless this is a Toshiba bridge, bail out until we have defined + * standard GMP attributes. + */ + if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) { + dev_err(&intf->dev, "unknown manufacturer %08x\n", + intf->ddbl1_manufacturer_id); + return -ENODEV; + } + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_VID, + &intf->vendor_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_PID, + &intf->product_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN0, &sn0); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN1, &sn1); + if (ret) + return ret; + + intf->serial_number = (u64)sn1 << 32 | sn0; + + return 0; +} + +static int gb_interface_read_dme(struct gb_interface *intf) +{ + int ret; + + /* DME attributes have already been read */ + if (intf->dme_read) + return 0; + + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID, + &intf->ddbl1_manufacturer_id); + if (ret) + return ret; + + ret = gb_interface_dme_attr_get(intf, DME_DDBL1_PRODUCTID, + &intf->ddbl1_product_id); + if (ret) + return ret; + + if (intf->ddbl1_manufacturer_id == TOSHIBA_DMID && + intf->ddbl1_product_id == TOSHIBA_ES2_BRIDGE_DPID) { + intf->quirks |= GB_INTERFACE_QUIRK_NO_GMP_IDS; + intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; + } + + ret = gb_interface_read_ara_dme(intf); + if (ret) + return ret; + + intf->dme_read = true; + + return 0; +} + +static int gb_interface_route_create(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + u8 intf_id = intf->interface_id; + u8 device_id; + int ret; + + /* Allocate an interface device id. */ + ret = ida_simple_get(&svc->device_id_map, + GB_SVC_DEVICE_ID_MIN, GB_SVC_DEVICE_ID_MAX + 1, + GFP_KERNEL); + if (ret < 0) { + dev_err(&intf->dev, "failed to allocate device id: %d\n", ret); + return ret; + } + device_id = ret; + + ret = gb_svc_intf_device_id(svc, intf_id, device_id); + if (ret) { + dev_err(&intf->dev, "failed to set device id %u: %d\n", + device_id, ret); + goto err_ida_remove; + } + + /* FIXME: Hard-coded AP device id. */ + ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_SVC_DEVICE_ID_AP, + intf_id, device_id); + if (ret) { + dev_err(&intf->dev, "failed to create route: %d\n", ret); + goto err_svc_id_free; + } + + intf->device_id = device_id; + + return 0; + +err_svc_id_free: + /* + * XXX Should we tell SVC that this id doesn't belong to interface + * XXX anymore. + */ +err_ida_remove: + ida_simple_remove(&svc->device_id_map, device_id); + + return ret; +} + +static void gb_interface_route_destroy(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + + if (intf->device_id == GB_INTERFACE_DEVICE_ID_BAD) + return; + + gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); + ida_simple_remove(&svc->device_id_map, intf->device_id); + intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; +} + +/* Locking: Caller holds the interface mutex. */ +static int gb_interface_legacy_mode_switch(struct gb_interface *intf) +{ + int ret; + + dev_info(&intf->dev, "legacy mode switch detected\n"); + + /* Mark as disconnected to prevent I/O during disable. */ + intf->disconnected = true; + gb_interface_disable(intf); + intf->disconnected = false; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, "failed to re-enable interface: %d\n", ret); + gb_interface_deactivate(intf); + } + + return ret; +} + +void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, + u32 mailbox) +{ + mutex_lock(&intf->mutex); + + if (result) { + dev_warn(&intf->dev, + "mailbox event with UniPro error: 0x%04x\n", + result); + goto err_disable; + } + + if (mailbox != GB_SVC_INTF_MAILBOX_GREYBUS) { + dev_warn(&intf->dev, + "mailbox event with unexpected value: 0x%08x\n", + mailbox); + goto err_disable; + } + + if (intf->quirks & GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH) { + gb_interface_legacy_mode_switch(intf); + goto out_unlock; + } + + if (!intf->mode_switch) { + dev_warn(&intf->dev, "unexpected mailbox event: 0x%08x\n", + mailbox); + goto err_disable; + } + + dev_info(&intf->dev, "mode switch detected\n"); + + complete(&intf->mode_switch_completion); + +out_unlock: + mutex_unlock(&intf->mutex); + + return; + +err_disable: + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + +static void gb_interface_mode_switch_work(struct work_struct *work) +{ + struct gb_interface *intf; + struct gb_control *control; + unsigned long timeout; + int ret; + + intf = container_of(work, struct gb_interface, mode_switch_work); + + mutex_lock(&intf->mutex); + /* Make sure interface is still enabled. */ + if (!intf->enabled) { + dev_dbg(&intf->dev, "mode switch aborted\n"); + intf->mode_switch = false; + mutex_unlock(&intf->mutex); + goto out_interface_put; + } + + /* + * Prepare the control device for mode switch and make sure to get an + * extra reference before it goes away during interface disable. + */ + control = gb_control_get(intf->control); + gb_control_mode_switch_prepare(control); + gb_interface_disable(intf); + mutex_unlock(&intf->mutex); + + timeout = msecs_to_jiffies(GB_INTERFACE_MODE_SWITCH_TIMEOUT); + ret = wait_for_completion_interruptible_timeout( + &intf->mode_switch_completion, timeout); + + /* Finalise control-connection mode switch. */ + gb_control_mode_switch_complete(control); + gb_control_put(control); + + if (ret < 0) { + dev_err(&intf->dev, "mode switch interrupted\n"); + goto err_deactivate; + } else if (ret == 0) { + dev_err(&intf->dev, "mode switch timed out\n"); + goto err_deactivate; + } + + /* Re-enable (re-enumerate) interface if still active. */ + mutex_lock(&intf->mutex); + intf->mode_switch = false; + if (intf->active) { + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, "failed to re-enable interface: %d\n", + ret); + gb_interface_deactivate(intf); + } + } + mutex_unlock(&intf->mutex); + +out_interface_put: + gb_interface_put(intf); + + return; + +err_deactivate: + mutex_lock(&intf->mutex); + intf->mode_switch = false; + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + + gb_interface_put(intf); +} + +int gb_interface_request_mode_switch(struct gb_interface *intf) +{ + int ret = 0; + + mutex_lock(&intf->mutex); + if (intf->mode_switch) { + ret = -EBUSY; + goto out_unlock; + } + + intf->mode_switch = true; + reinit_completion(&intf->mode_switch_completion); + + /* + * Get a reference to the interface device, which will be put once the + * mode switch is complete. + */ + get_device(&intf->dev); + + if (!queue_work(system_long_wq, &intf->mode_switch_work)) { + put_device(&intf->dev); + ret = -EBUSY; + goto out_unlock; + } + +out_unlock: + mutex_unlock(&intf->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_interface_request_mode_switch); + +/* + * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the + * init-status attribute DME_TOSHIBA_INIT_STATUS. The AP needs to read and + * clear it after reading a non-zero value from it. + * + * FIXME: This is module-hardware dependent and needs to be extended for every + * type of module we want to support. + */ +static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) +{ + struct gb_host_device *hd = intf->hd; + unsigned long bootrom_quirks; + unsigned long s2l_quirks; + int ret; + u32 value; + u16 attr; + u8 init_status; + + /* + * ES2 bridges use T_TstSrcIncrement for the init status. + * + * FIXME: Remove ES2 support + */ + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) + attr = DME_T_TST_SRC_INCREMENT; + else + attr = DME_TOSHIBA_GMP_INIT_STATUS; + + ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, + DME_SELECTOR_INDEX_NULL, &value); + if (ret) + return ret; + + /* + * A nonzero init status indicates the module has finished + * initializing. + */ + if (!value) { + dev_err(&intf->dev, "invalid init status\n"); + return -ENODEV; + } + + /* + * Extract the init status. + * + * For ES2: We need to check lowest 8 bits of 'value'. + * For ES3: We need to check highest 8 bits out of 32 of 'value'. + * + * FIXME: Remove ES2 support + */ + if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) + init_status = value & 0xff; + else + init_status = value >> 24; + + /* + * Check if the interface is executing the quirky ES3 bootrom that, + * for example, requires E2EFC, CSD and CSV to be disabled. + */ + bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | + GB_INTERFACE_QUIRK_FORCED_DISABLE | + GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH | + GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE; + + s2l_quirks = GB_INTERFACE_QUIRK_NO_PM; + + switch (init_status) { + case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: + case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: + intf->quirks |= bootrom_quirks; + break; + case GB_INIT_S2_LOADER_BOOT_STARTED: + /* S2 Loader doesn't support runtime PM */ + intf->quirks &= ~bootrom_quirks; + intf->quirks |= s2l_quirks; + break; + default: + intf->quirks &= ~bootrom_quirks; + intf->quirks &= ~s2l_quirks; + } + + /* Clear the init status. */ + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, + DME_SELECTOR_INDEX_NULL, 0); +} + +/* interface sysfs attributes */ +#define gb_interface_attr(field, type) \ +static ssize_t field##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct gb_interface *intf = to_gb_interface(dev); \ + return scnprintf(buf, PAGE_SIZE, type"\n", intf->field); \ +} \ +static DEVICE_ATTR_RO(field) + +gb_interface_attr(ddbl1_manufacturer_id, "0x%08x"); +gb_interface_attr(ddbl1_product_id, "0x%08x"); +gb_interface_attr(interface_id, "%u"); +gb_interface_attr(vendor_id, "0x%08x"); +gb_interface_attr(product_id, "0x%08x"); +gb_interface_attr(serial_number, "0x%016llx"); + +static ssize_t voltage_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_VOL, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get voltage sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(voltage_now); + +static ssize_t current_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_CURR, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get current sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(current_now); + +static ssize_t power_now_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + u32 measurement; + + ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, + GB_SVC_PWRMON_TYPE_PWR, + &measurement); + if (ret) { + dev_err(&intf->dev, "failed to get power sample (%d)\n", ret); + return ret; + } + + return sprintf(buf, "%u\n", measurement); +} +static DEVICE_ATTR_RO(power_now); + +static ssize_t power_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + if (intf->active) + return scnprintf(buf, PAGE_SIZE, "on\n"); + else + return scnprintf(buf, PAGE_SIZE, "off\n"); +} + +static ssize_t power_state_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_interface *intf = to_gb_interface(dev); + bool activate; + int ret = 0; + + if (kstrtobool(buf, &activate)) + return -EINVAL; + + mutex_lock(&intf->mutex); + + if (activate == intf->active) + goto unlock; + + if (activate) { + ret = gb_interface_activate(intf); + if (ret) { + dev_err(&intf->dev, + "failed to activate interface: %d\n", ret); + goto unlock; + } + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&intf->dev, + "failed to enable interface: %d\n", ret); + gb_interface_deactivate(intf); + goto unlock; + } + } else { + gb_interface_disable(intf); + gb_interface_deactivate(intf); + } + +unlock: + mutex_unlock(&intf->mutex); + + if (ret) + return ret; + + return len; +} +static DEVICE_ATTR_RW(power_state); + +static const char *gb_interface_type_string(struct gb_interface *intf) +{ + static const char * const types[] = { + [GB_INTERFACE_TYPE_INVALID] = "invalid", + [GB_INTERFACE_TYPE_UNKNOWN] = "unknown", + [GB_INTERFACE_TYPE_DUMMY] = "dummy", + [GB_INTERFACE_TYPE_UNIPRO] = "unipro", + [GB_INTERFACE_TYPE_GREYBUS] = "greybus", + }; + + return types[intf->type]; +} + +static ssize_t interface_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + return sprintf(buf, "%s\n", gb_interface_type_string(intf)); +} +static DEVICE_ATTR_RO(interface_type); + +static struct attribute *interface_unipro_attrs[] = { + &dev_attr_ddbl1_manufacturer_id.attr, + &dev_attr_ddbl1_product_id.attr, + NULL +}; + +static struct attribute *interface_greybus_attrs[] = { + &dev_attr_vendor_id.attr, + &dev_attr_product_id.attr, + &dev_attr_serial_number.attr, + NULL +}; + +static struct attribute *interface_power_attrs[] = { + &dev_attr_voltage_now.attr, + &dev_attr_current_now.attr, + &dev_attr_power_now.attr, + &dev_attr_power_state.attr, + NULL +}; + +static struct attribute *interface_common_attrs[] = { + &dev_attr_interface_id.attr, + &dev_attr_interface_type.attr, + NULL +}; + +static umode_t interface_unipro_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static umode_t interface_greybus_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_INTERFACE_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static umode_t interface_power_is_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct gb_interface *intf = to_gb_interface(dev); + + switch (intf->type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + return attr->mode; + default: + return 0; + } +} + +static const struct attribute_group interface_unipro_group = { + .is_visible = interface_unipro_is_visible, + .attrs = interface_unipro_attrs, +}; + +static const struct attribute_group interface_greybus_group = { + .is_visible = interface_greybus_is_visible, + .attrs = interface_greybus_attrs, +}; + +static const struct attribute_group interface_power_group = { + .is_visible = interface_power_is_visible, + .attrs = interface_power_attrs, +}; + +static const struct attribute_group interface_common_group = { + .attrs = interface_common_attrs, +}; + +static const struct attribute_group *interface_groups[] = { + &interface_unipro_group, + &interface_greybus_group, + &interface_power_group, + &interface_common_group, + NULL +}; + +static void gb_interface_release(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + + trace_gb_interface_release(intf); + + kfree(intf); +} + +#ifdef CONFIG_PM +static int gb_interface_suspend(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + int ret; + + ret = gb_control_interface_suspend_prepare(intf->control); + if (ret) + return ret; + + ret = gb_control_suspend(intf->control); + if (ret) + goto err_hibernate_abort; + + ret = gb_interface_hibernate_link(intf); + if (ret) + return ret; + + /* Delay to allow interface to enter standby before disabling refclk */ + msleep(GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS); + + ret = gb_interface_refclk_set(intf, false); + if (ret) + return ret; + + return 0; + +err_hibernate_abort: + gb_control_interface_hibernate_abort(intf->control); + + return ret; +} + +static int gb_interface_resume(struct device *dev) +{ + struct gb_interface *intf = to_gb_interface(dev); + struct gb_svc *svc = intf->hd->svc; + int ret; + + ret = gb_interface_refclk_set(intf, true); + if (ret) + return ret; + + ret = gb_svc_intf_resume(svc, intf->interface_id); + if (ret) + return ret; + + ret = gb_control_resume(intf->control); + if (ret) + return ret; + + return 0; +} + +static int gb_interface_runtime_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} +#endif + +static const struct dev_pm_ops gb_interface_pm_ops = { + SET_RUNTIME_PM_OPS(gb_interface_suspend, gb_interface_resume, + gb_interface_runtime_idle) +}; + +struct device_type greybus_interface_type = { + .name = "greybus_interface", + .release = gb_interface_release, + .pm = &gb_interface_pm_ops, +}; + +/* + * A Greybus module represents a user-replaceable component on a GMP + * phone. An interface is the physical connection on that module. A + * module may have more than one interface. + * + * Create a gb_interface structure to represent a discovered interface. + * The position of interface within the Endo is encoded in "interface_id" + * argument. + * + * Returns a pointer to the new interfce or a null pointer if a + * failure occurs due to memory exhaustion. + */ +struct gb_interface *gb_interface_create(struct gb_module *module, + u8 interface_id) +{ + struct gb_host_device *hd = module->hd; + struct gb_interface *intf; + + intf = kzalloc(sizeof(*intf), GFP_KERNEL); + if (!intf) + return NULL; + + intf->hd = hd; /* XXX refcount? */ + intf->module = module; + intf->interface_id = interface_id; + INIT_LIST_HEAD(&intf->bundles); + INIT_LIST_HEAD(&intf->manifest_descs); + mutex_init(&intf->mutex); + INIT_WORK(&intf->mode_switch_work, gb_interface_mode_switch_work); + init_completion(&intf->mode_switch_completion); + + /* Invalid device id to start with */ + intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; + + intf->dev.parent = &module->dev; + intf->dev.bus = &greybus_bus_type; + intf->dev.type = &greybus_interface_type; + intf->dev.groups = interface_groups; + intf->dev.dma_mask = module->dev.dma_mask; + device_initialize(&intf->dev); + dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev), + interface_id); + + pm_runtime_set_autosuspend_delay(&intf->dev, + GB_INTERFACE_AUTOSUSPEND_MS); + + trace_gb_interface_create(intf); + + return intf; +} + +static int gb_interface_vsys_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_vsys_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to set v_sys: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_refclk_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_refclk_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to set refclk: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_unipro_set(struct gb_interface *intf, bool enable) +{ + struct gb_svc *svc = intf->hd->svc; + int ret; + + dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); + + ret = gb_svc_intf_unipro_set(svc, intf->interface_id, enable); + if (ret) { + dev_err(&intf->dev, "failed to set UniPro: %d\n", ret); + return ret; + } + + return 0; +} + +static int gb_interface_activate_operation(struct gb_interface *intf, + enum gb_interface_type *intf_type) +{ + struct gb_svc *svc = intf->hd->svc; + u8 type; + int ret; + + dev_dbg(&intf->dev, "%s\n", __func__); + + ret = gb_svc_intf_activate(svc, intf->interface_id, &type); + if (ret) { + dev_err(&intf->dev, "failed to activate: %d\n", ret); + return ret; + } + + switch (type) { + case GB_SVC_INTF_TYPE_DUMMY: + *intf_type = GB_INTERFACE_TYPE_DUMMY; + /* FIXME: handle as an error for now */ + return -ENODEV; + case GB_SVC_INTF_TYPE_UNIPRO: + *intf_type = GB_INTERFACE_TYPE_UNIPRO; + dev_err(&intf->dev, "interface type UniPro not supported\n"); + /* FIXME: handle as an error for now */ + return -ENODEV; + case GB_SVC_INTF_TYPE_GREYBUS: + *intf_type = GB_INTERFACE_TYPE_GREYBUS; + break; + default: + dev_err(&intf->dev, "unknown interface type: %u\n", type); + *intf_type = GB_INTERFACE_TYPE_UNKNOWN; + return -ENODEV; + } + + return 0; +} + +static int gb_interface_hibernate_link(struct gb_interface *intf) +{ + struct gb_svc *svc = intf->hd->svc; + + return gb_svc_intf_set_power_mode_hibernate(svc, intf->interface_id); +} + +static int _gb_interface_activate(struct gb_interface *intf, + enum gb_interface_type *type) +{ + int ret; + + *type = GB_INTERFACE_TYPE_UNKNOWN; + + if (intf->ejected || intf->removed) + return -ENODEV; + + ret = gb_interface_vsys_set(intf, true); + if (ret) + return ret; + + ret = gb_interface_refclk_set(intf, true); + if (ret) + goto err_vsys_disable; + + ret = gb_interface_unipro_set(intf, true); + if (ret) + goto err_refclk_disable; + + ret = gb_interface_activate_operation(intf, type); + if (ret) { + switch (*type) { + case GB_INTERFACE_TYPE_UNIPRO: + case GB_INTERFACE_TYPE_GREYBUS: + goto err_hibernate_link; + default: + goto err_unipro_disable; + } + } + + ret = gb_interface_read_dme(intf); + if (ret) + goto err_hibernate_link; + + ret = gb_interface_route_create(intf); + if (ret) + goto err_hibernate_link; + + intf->active = true; + + trace_gb_interface_activate(intf); + + return 0; + +err_hibernate_link: + gb_interface_hibernate_link(intf); +err_unipro_disable: + gb_interface_unipro_set(intf, false); +err_refclk_disable: + gb_interface_refclk_set(intf, false); +err_vsys_disable: + gb_interface_vsys_set(intf, false); + + return ret; +} + +/* + * At present, we assume a UniPro-only module to be a Greybus module that + * failed to send its mailbox poke. There is some reason to believe that this + * is because of a bug in the ES3 bootrom. + * + * FIXME: Check if this is a Toshiba bridge before retrying? + */ +static int _gb_interface_activate_es3_hack(struct gb_interface *intf, + enum gb_interface_type *type) +{ + int retries = 3; + int ret; + + while (retries--) { + ret = _gb_interface_activate(intf, type); + if (ret == -ENODEV && *type == GB_INTERFACE_TYPE_UNIPRO) + continue; + + break; + } + + return ret; +} + +/* + * Activate an interface. + * + * Locking: Caller holds the interface mutex. + */ +int gb_interface_activate(struct gb_interface *intf) +{ + enum gb_interface_type type; + int ret; + + switch (intf->type) { + case GB_INTERFACE_TYPE_INVALID: + case GB_INTERFACE_TYPE_GREYBUS: + ret = _gb_interface_activate_es3_hack(intf, &type); + break; + default: + ret = _gb_interface_activate(intf, &type); + } + + /* Make sure type is detected correctly during reactivation. */ + if (intf->type != GB_INTERFACE_TYPE_INVALID) { + if (type != intf->type) { + dev_err(&intf->dev, "failed to detect interface type\n"); + + if (!ret) + gb_interface_deactivate(intf); + + return -EIO; + } + } else { + intf->type = type; + } + + return ret; +} + +/* + * Deactivate an interface. + * + * Locking: Caller holds the interface mutex. + */ +void gb_interface_deactivate(struct gb_interface *intf) +{ + if (!intf->active) + return; + + trace_gb_interface_deactivate(intf); + + /* Abort any ongoing mode switch. */ + if (intf->mode_switch) + complete(&intf->mode_switch_completion); + + gb_interface_route_destroy(intf); + gb_interface_hibernate_link(intf); + gb_interface_unipro_set(intf, false); + gb_interface_refclk_set(intf, false); + gb_interface_vsys_set(intf, false); + + intf->active = false; +} + +/* + * Enable an interface by enabling its control connection, fetching the + * manifest and other information over it, and finally registering its child + * devices. + * + * Locking: Caller holds the interface mutex. + */ +int gb_interface_enable(struct gb_interface *intf) +{ + struct gb_control *control; + struct gb_bundle *bundle, *tmp; + int ret, size; + void *manifest; + + ret = gb_interface_read_and_clear_init_status(intf); + if (ret) { + dev_err(&intf->dev, "failed to clear init status: %d\n", ret); + return ret; + } + + /* Establish control connection */ + control = gb_control_create(intf); + if (IS_ERR(control)) { + dev_err(&intf->dev, "failed to create control device: %ld\n", + PTR_ERR(control)); + return PTR_ERR(control); + } + intf->control = control; + + ret = gb_control_enable(intf->control); + if (ret) + goto err_put_control; + + /* Get manifest size using control protocol on CPort */ + size = gb_control_get_manifest_size_operation(intf); + if (size <= 0) { + dev_err(&intf->dev, "failed to get manifest size: %d\n", size); + + if (size) + ret = size; + else + ret = -EINVAL; + + goto err_disable_control; + } + + manifest = kmalloc(size, GFP_KERNEL); + if (!manifest) { + ret = -ENOMEM; + goto err_disable_control; + } + + /* Get manifest using control protocol on CPort */ + ret = gb_control_get_manifest_operation(intf, manifest, size); + if (ret) { + dev_err(&intf->dev, "failed to get manifest: %d\n", ret); + goto err_free_manifest; + } + + /* + * Parse the manifest and build up our data structures representing + * what's in it. + */ + if (!gb_manifest_parse(intf, manifest, size)) { + dev_err(&intf->dev, "failed to parse manifest\n"); + ret = -EINVAL; + goto err_destroy_bundles; + } + + ret = gb_control_get_bundle_versions(intf->control); + if (ret) + goto err_destroy_bundles; + + /* Register the control device and any bundles */ + ret = gb_control_add(intf->control); + if (ret) + goto err_destroy_bundles; + + pm_runtime_use_autosuspend(&intf->dev); + pm_runtime_get_noresume(&intf->dev); + pm_runtime_set_active(&intf->dev); + pm_runtime_enable(&intf->dev); + + list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { + ret = gb_bundle_add(bundle); + if (ret) { + gb_bundle_destroy(bundle); + continue; + } + } + + kfree(manifest); + + intf->enabled = true; + + pm_runtime_put(&intf->dev); + + trace_gb_interface_enable(intf); + + return 0; + +err_destroy_bundles: + list_for_each_entry_safe(bundle, tmp, &intf->bundles, links) + gb_bundle_destroy(bundle); +err_free_manifest: + kfree(manifest); +err_disable_control: + gb_control_disable(intf->control); +err_put_control: + gb_control_put(intf->control); + intf->control = NULL; + + return ret; +} + +/* + * Disable an interface and destroy its bundles. + * + * Locking: Caller holds the interface mutex. + */ +void gb_interface_disable(struct gb_interface *intf) +{ + struct gb_bundle *bundle; + struct gb_bundle *next; + + if (!intf->enabled) + return; + + trace_gb_interface_disable(intf); + + pm_runtime_get_sync(&intf->dev); + + /* Set disconnected flag to avoid I/O during connection tear down. */ + if (intf->quirks & GB_INTERFACE_QUIRK_FORCED_DISABLE) + intf->disconnected = true; + + list_for_each_entry_safe(bundle, next, &intf->bundles, links) + gb_bundle_destroy(bundle); + + if (!intf->mode_switch && !intf->disconnected) + gb_control_interface_deactivate_prepare(intf->control); + + gb_control_del(intf->control); + gb_control_disable(intf->control); + gb_control_put(intf->control); + intf->control = NULL; + + intf->enabled = false; + + pm_runtime_disable(&intf->dev); + pm_runtime_set_suspended(&intf->dev); + pm_runtime_dont_use_autosuspend(&intf->dev); + pm_runtime_put_noidle(&intf->dev); +} + +/* Register an interface. */ +int gb_interface_add(struct gb_interface *intf) +{ + int ret; + + ret = device_add(&intf->dev); + if (ret) { + dev_err(&intf->dev, "failed to register interface: %d\n", ret); + return ret; + } + + trace_gb_interface_add(intf); + + dev_info(&intf->dev, "Interface added (%s)\n", + gb_interface_type_string(intf)); + + switch (intf->type) { + case GB_INTERFACE_TYPE_GREYBUS: + dev_info(&intf->dev, "GMP VID=0x%08x, PID=0x%08x\n", + intf->vendor_id, intf->product_id); + /* fall-through */ + case GB_INTERFACE_TYPE_UNIPRO: + dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", + intf->ddbl1_manufacturer_id, + intf->ddbl1_product_id); + break; + default: + break; + } + + return 0; +} + +/* Deregister an interface. */ +void gb_interface_del(struct gb_interface *intf) +{ + if (device_is_registered(&intf->dev)) { + trace_gb_interface_del(intf); + + device_del(&intf->dev); + dev_info(&intf->dev, "Interface removed\n"); + } +} + +void gb_interface_put(struct gb_interface *intf) +{ + put_device(&intf->dev); +} diff --git a/drivers/greybus/manifest.c b/drivers/greybus/manifest.c new file mode 100644 index 000000000000..dd7040697bde --- /dev/null +++ b/drivers/greybus/manifest.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus manifest parsing + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#include + +static const char *get_descriptor_type_string(u8 type) +{ + switch (type) { + case GREYBUS_TYPE_INVALID: + return "invalid"; + case GREYBUS_TYPE_STRING: + return "string"; + case GREYBUS_TYPE_INTERFACE: + return "interface"; + case GREYBUS_TYPE_CPORT: + return "cport"; + case GREYBUS_TYPE_BUNDLE: + return "bundle"; + default: + WARN_ON(1); + return "unknown"; + } +} + +/* + * We scan the manifest once to identify where all the descriptors + * are. The result is a list of these manifest_desc structures. We + * then pick through them for what we're looking for (starting with + * the interface descriptor). As each is processed we remove it from + * the list. When we're done the list should (probably) be empty. + */ +struct manifest_desc { + struct list_head links; + + size_t size; + void *data; + enum greybus_descriptor_type type; +}; + +static void release_manifest_descriptor(struct manifest_desc *descriptor) +{ + list_del(&descriptor->links); + kfree(descriptor); +} + +static void release_manifest_descriptors(struct gb_interface *intf) +{ + struct manifest_desc *descriptor; + struct manifest_desc *next; + + list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) + release_manifest_descriptor(descriptor); +} + +static void release_cport_descriptors(struct list_head *head, u8 bundle_id) +{ + struct manifest_desc *desc, *tmp; + struct greybus_descriptor_cport *desc_cport; + + list_for_each_entry_safe(desc, tmp, head, links) { + desc_cport = desc->data; + + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + + if (desc_cport->bundle == bundle_id) + release_manifest_descriptor(desc); + } +} + +static struct manifest_desc *get_next_bundle_desc(struct gb_interface *intf) +{ + struct manifest_desc *descriptor; + struct manifest_desc *next; + + list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) + if (descriptor->type == GREYBUS_TYPE_BUNDLE) + return descriptor; + + return NULL; +} + +/* + * Validate the given descriptor. Its reported size must fit within + * the number of bytes remaining, and it must have a recognized + * type. Check that the reported size is at least as big as what + * we expect to see. (It could be bigger, perhaps for a new version + * of the format.) + * + * Returns the (non-zero) number of bytes consumed by the descriptor, + * or a negative errno. + */ +static int identify_descriptor(struct gb_interface *intf, + struct greybus_descriptor *desc, size_t size) +{ + struct greybus_descriptor_header *desc_header = &desc->header; + struct manifest_desc *descriptor; + size_t desc_size; + size_t expected_size; + + if (size < sizeof(*desc_header)) { + dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", size, + sizeof(*desc_header)); + return -EINVAL; /* Must at least have header */ + } + + desc_size = le16_to_cpu(desc_header->size); + if (desc_size > size) { + dev_err(&intf->dev, "descriptor too big (%zu > %zu)\n", + desc_size, size); + return -EINVAL; + } + + /* Descriptor needs to at least have a header */ + expected_size = sizeof(*desc_header); + + switch (desc_header->type) { + case GREYBUS_TYPE_STRING: + expected_size += sizeof(struct greybus_descriptor_string); + expected_size += desc->string.length; + + /* String descriptors are padded to 4 byte boundaries */ + expected_size = ALIGN(expected_size, 4); + break; + case GREYBUS_TYPE_INTERFACE: + expected_size += sizeof(struct greybus_descriptor_interface); + break; + case GREYBUS_TYPE_BUNDLE: + expected_size += sizeof(struct greybus_descriptor_bundle); + break; + case GREYBUS_TYPE_CPORT: + expected_size += sizeof(struct greybus_descriptor_cport); + break; + case GREYBUS_TYPE_INVALID: + default: + dev_err(&intf->dev, "invalid descriptor type (%u)\n", + desc_header->type); + return -EINVAL; + } + + if (desc_size < expected_size) { + dev_err(&intf->dev, "%s descriptor too small (%zu < %zu)\n", + get_descriptor_type_string(desc_header->type), + desc_size, expected_size); + return -EINVAL; + } + + /* Descriptor bigger than what we expect */ + if (desc_size > expected_size) { + dev_warn(&intf->dev, "%s descriptor size mismatch (want %zu got %zu)\n", + get_descriptor_type_string(desc_header->type), + expected_size, desc_size); + } + + descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); + if (!descriptor) + return -ENOMEM; + + descriptor->size = desc_size; + descriptor->data = (char *)desc + sizeof(*desc_header); + descriptor->type = desc_header->type; + list_add_tail(&descriptor->links, &intf->manifest_descs); + + /* desc_size is positive and is known to fit in a signed int */ + + return desc_size; +} + +/* + * Find the string descriptor having the given id, validate it, and + * allocate a duplicate copy of it. The duplicate has an extra byte + * which guarantees the returned string is NUL-terminated. + * + * String index 0 is valid (it represents "no string"), and for + * that a null pointer is returned. + * + * Otherwise returns a pointer to a newly-allocated copy of the + * descriptor string, or an error-coded pointer on failure. + */ +static char *gb_string_get(struct gb_interface *intf, u8 string_id) +{ + struct greybus_descriptor_string *desc_string; + struct manifest_desc *descriptor; + bool found = false; + char *string; + + /* A zero string id means no string (but no error) */ + if (!string_id) + return NULL; + + list_for_each_entry(descriptor, &intf->manifest_descs, links) { + if (descriptor->type != GREYBUS_TYPE_STRING) + continue; + + desc_string = descriptor->data; + if (desc_string->id == string_id) { + found = true; + break; + } + } + if (!found) + return ERR_PTR(-ENOENT); + + /* Allocate an extra byte so we can guarantee it's NUL-terminated */ + string = kmemdup(&desc_string->string, desc_string->length + 1, + GFP_KERNEL); + if (!string) + return ERR_PTR(-ENOMEM); + string[desc_string->length] = '\0'; + + /* Ok we've used this string, so we're done with it */ + release_manifest_descriptor(descriptor); + + return string; +} + +/* + * Find cport descriptors in the manifest associated with the given + * bundle, and set up data structures for the functions that use + * them. Returns the number of cports set up for the bundle, or 0 + * if there is an error. + */ +static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) +{ + struct gb_interface *intf = bundle->intf; + struct greybus_descriptor_cport *desc_cport; + struct manifest_desc *desc, *next, *tmp; + LIST_HEAD(list); + u8 bundle_id = bundle->id; + u16 cport_id; + u32 count = 0; + int i; + + /* Set up all cport descriptors associated with this bundle */ + list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { + if (desc->type != GREYBUS_TYPE_CPORT) + continue; + + desc_cport = desc->data; + if (desc_cport->bundle != bundle_id) + continue; + + cport_id = le16_to_cpu(desc_cport->id); + if (cport_id > CPORT_ID_MAX) + goto exit; + + /* Nothing else should have its cport_id as control cport id */ + if (cport_id == GB_CONTROL_CPORT_ID) { + dev_err(&bundle->dev, "invalid cport id found (%02u)\n", + cport_id); + goto exit; + } + + /* + * Found one, move it to our temporary list after checking for + * duplicates. + */ + list_for_each_entry(tmp, &list, links) { + desc_cport = tmp->data; + if (cport_id == le16_to_cpu(desc_cport->id)) { + dev_err(&bundle->dev, + "duplicate CPort %u found\n", cport_id); + goto exit; + } + } + list_move_tail(&desc->links, &list); + count++; + } + + if (!count) + return 0; + + bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), + GFP_KERNEL); + if (!bundle->cport_desc) + goto exit; + + bundle->num_cports = count; + + i = 0; + list_for_each_entry_safe(desc, next, &list, links) { + desc_cport = desc->data; + memcpy(&bundle->cport_desc[i++], desc_cport, + sizeof(*desc_cport)); + + /* Release the cport descriptor */ + release_manifest_descriptor(desc); + } + + return count; +exit: + release_cport_descriptors(&list, bundle_id); + /* + * Free all cports for this bundle to avoid 'excess descriptors' + * warnings. + */ + release_cport_descriptors(&intf->manifest_descs, bundle_id); + + return 0; /* Error; count should also be 0 */ +} + +/* + * Find bundle descriptors in the manifest and set up their data + * structures. Returns the number of bundles set up for the + * given interface. + */ +static u32 gb_manifest_parse_bundles(struct gb_interface *intf) +{ + struct manifest_desc *desc; + struct gb_bundle *bundle; + struct gb_bundle *bundle_next; + u32 count = 0; + u8 bundle_id; + u8 class; + + while ((desc = get_next_bundle_desc(intf))) { + struct greybus_descriptor_bundle *desc_bundle; + + /* Found one. Set up its bundle structure*/ + desc_bundle = desc->data; + bundle_id = desc_bundle->id; + class = desc_bundle->class; + + /* Done with this bundle descriptor */ + release_manifest_descriptor(desc); + + /* Ignore any legacy control bundles */ + if (bundle_id == GB_CONTROL_BUNDLE_ID) { + dev_dbg(&intf->dev, "%s - ignoring control bundle\n", + __func__); + release_cport_descriptors(&intf->manifest_descs, + bundle_id); + continue; + } + + /* Nothing else should have its class set to control class */ + if (class == GREYBUS_CLASS_CONTROL) { + dev_err(&intf->dev, + "bundle %u cannot use control class\n", + bundle_id); + goto cleanup; + } + + bundle = gb_bundle_create(intf, bundle_id, class); + if (!bundle) + goto cleanup; + + /* + * Now go set up this bundle's functions and cports. + * + * A 'bundle' represents a device in greybus. It may require + * multiple cports for its functioning. If we fail to setup any + * cport of a bundle, we better reject the complete bundle as + * the device may not be able to function properly then. + * + * But, failing to setup a cport of bundle X doesn't mean that + * the device corresponding to bundle Y will not work properly. + * Bundles should be treated as separate independent devices. + * + * While parsing manifest for an interface, treat bundles as + * separate entities and don't reject entire interface and its + * bundles on failing to initialize a cport. But make sure the + * bundle which needs the cport, gets destroyed properly. + */ + if (!gb_manifest_parse_cports(bundle)) { + gb_bundle_destroy(bundle); + continue; + } + + count++; + } + + return count; +cleanup: + /* An error occurred; undo any changes we've made */ + list_for_each_entry_safe(bundle, bundle_next, &intf->bundles, links) { + gb_bundle_destroy(bundle); + count--; + } + return 0; /* Error; count should also be 0 */ +} + +static bool gb_manifest_parse_interface(struct gb_interface *intf, + struct manifest_desc *interface_desc) +{ + struct greybus_descriptor_interface *desc_intf = interface_desc->data; + struct gb_control *control = intf->control; + char *str; + + /* Handle the strings first--they can fail */ + str = gb_string_get(intf, desc_intf->vendor_stringid); + if (IS_ERR(str)) + return false; + control->vendor_string = str; + + str = gb_string_get(intf, desc_intf->product_stringid); + if (IS_ERR(str)) + goto out_free_vendor_string; + control->product_string = str; + + /* Assign feature flags communicated via manifest */ + intf->features = desc_intf->features; + + /* Release the interface descriptor, now that we're done with it */ + release_manifest_descriptor(interface_desc); + + /* An interface must have at least one bundle descriptor */ + if (!gb_manifest_parse_bundles(intf)) { + dev_err(&intf->dev, "manifest bundle descriptors not valid\n"); + goto out_err; + } + + return true; +out_err: + kfree(control->product_string); + control->product_string = NULL; +out_free_vendor_string: + kfree(control->vendor_string); + control->vendor_string = NULL; + + return false; +} + +/* + * Parse a buffer containing an interface manifest. + * + * If we find anything wrong with the content/format of the buffer + * we reject it. + * + * The first requirement is that the manifest's version is + * one we can parse. + * + * We make an initial pass through the buffer and identify all of + * the descriptors it contains, keeping track for each its type + * and the location size of its data in the buffer. + * + * Next we scan the descriptors, looking for an interface descriptor; + * there must be exactly one of those. When found, we record the + * information it contains, and then remove that descriptor (and any + * string descriptors it refers to) from further consideration. + * + * After that we look for the interface's bundles--there must be at + * least one of those. + * + * Returns true if parsing was successful, false otherwise. + */ +bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) +{ + struct greybus_manifest *manifest; + struct greybus_manifest_header *header; + struct greybus_descriptor *desc; + struct manifest_desc *descriptor; + struct manifest_desc *interface_desc = NULL; + u16 manifest_size; + u32 found = 0; + bool result; + + /* Manifest descriptor list should be empty here */ + if (WARN_ON(!list_empty(&intf->manifest_descs))) + return false; + + /* we have to have at _least_ the manifest header */ + if (size < sizeof(*header)) { + dev_err(&intf->dev, "short manifest (%zu < %zu)\n", + size, sizeof(*header)); + return false; + } + + /* Make sure the size is right */ + manifest = data; + header = &manifest->header; + manifest_size = le16_to_cpu(header->size); + if (manifest_size != size) { + dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", + size, manifest_size); + return false; + } + + /* Validate major/minor number */ + if (header->version_major > GREYBUS_VERSION_MAJOR) { + dev_err(&intf->dev, "manifest version too new (%u.%u > %u.%u)\n", + header->version_major, header->version_minor, + GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); + return false; + } + + /* OK, find all the descriptors */ + desc = manifest->descriptors; + size -= sizeof(*header); + while (size) { + int desc_size; + + desc_size = identify_descriptor(intf, desc, size); + if (desc_size < 0) { + result = false; + goto out; + } + desc = (struct greybus_descriptor *)((char *)desc + desc_size); + size -= desc_size; + } + + /* There must be a single interface descriptor */ + list_for_each_entry(descriptor, &intf->manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_INTERFACE) + if (!found++) + interface_desc = descriptor; + } + if (found != 1) { + dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", + found); + result = false; + goto out; + } + + /* Parse the manifest, starting with the interface descriptor */ + result = gb_manifest_parse_interface(intf, interface_desc); + + /* + * We really should have no remaining descriptors, but we + * don't know what newer format manifests might leave. + */ + if (result && !list_empty(&intf->manifest_descs)) + dev_info(&intf->dev, "excess descriptors in interface manifest\n"); +out: + release_manifest_descriptors(intf); + + return result; +} diff --git a/drivers/greybus/module.c b/drivers/greybus/module.c new file mode 100644 index 000000000000..36f77f9e1d74 --- /dev/null +++ b/drivers/greybus/module.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus Module code + * + * Copyright 2016 Google Inc. + * Copyright 2016 Linaro Ltd. + */ + +#include +#include "greybus_trace.h" + +static ssize_t eject_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct gb_module *module = to_gb_module(dev); + struct gb_interface *intf; + size_t i; + long val; + int ret; + + ret = kstrtol(buf, 0, &val); + if (ret) + return ret; + + if (!val) + return len; + + for (i = 0; i < module->num_interfaces; ++i) { + intf = module->interfaces[i]; + + mutex_lock(&intf->mutex); + /* Set flag to prevent concurrent activation. */ + intf->ejected = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + } + + /* Tell the SVC to eject the primary interface. */ + ret = gb_svc_intf_eject(module->hd->svc, module->module_id); + if (ret) + return ret; + + return len; +} +static DEVICE_ATTR_WO(eject); + +static ssize_t module_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_module *module = to_gb_module(dev); + + return sprintf(buf, "%u\n", module->module_id); +} +static DEVICE_ATTR_RO(module_id); + +static ssize_t num_interfaces_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_module *module = to_gb_module(dev); + + return sprintf(buf, "%zu\n", module->num_interfaces); +} +static DEVICE_ATTR_RO(num_interfaces); + +static struct attribute *module_attrs[] = { + &dev_attr_eject.attr, + &dev_attr_module_id.attr, + &dev_attr_num_interfaces.attr, + NULL, +}; +ATTRIBUTE_GROUPS(module); + +static void gb_module_release(struct device *dev) +{ + struct gb_module *module = to_gb_module(dev); + + trace_gb_module_release(module); + + kfree(module); +} + +struct device_type greybus_module_type = { + .name = "greybus_module", + .release = gb_module_release, +}; + +struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, + size_t num_interfaces) +{ + struct gb_interface *intf; + struct gb_module *module; + int i; + + module = kzalloc(struct_size(module, interfaces, num_interfaces), + GFP_KERNEL); + if (!module) + return NULL; + + module->hd = hd; + module->module_id = module_id; + module->num_interfaces = num_interfaces; + + module->dev.parent = &hd->dev; + module->dev.bus = &greybus_bus_type; + module->dev.type = &greybus_module_type; + module->dev.groups = module_groups; + module->dev.dma_mask = hd->dev.dma_mask; + device_initialize(&module->dev); + dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); + + trace_gb_module_create(module); + + for (i = 0; i < num_interfaces; ++i) { + intf = gb_interface_create(module, module_id + i); + if (!intf) { + dev_err(&module->dev, "failed to create interface %u\n", + module_id + i); + goto err_put_interfaces; + } + module->interfaces[i] = intf; + } + + return module; + +err_put_interfaces: + for (--i; i >= 0; --i) + gb_interface_put(module->interfaces[i]); + + put_device(&module->dev); + + return NULL; +} + +/* + * Register and enable an interface after first attempting to activate it. + */ +static void gb_module_register_interface(struct gb_interface *intf) +{ + struct gb_module *module = intf->module; + u8 intf_id = intf->interface_id; + int ret; + + mutex_lock(&intf->mutex); + + ret = gb_interface_activate(intf); + if (ret) { + if (intf->type != GB_INTERFACE_TYPE_DUMMY) { + dev_err(&module->dev, + "failed to activate interface %u: %d\n", + intf_id, ret); + } + + gb_interface_add(intf); + goto err_unlock; + } + + ret = gb_interface_add(intf); + if (ret) + goto err_interface_deactivate; + + ret = gb_interface_enable(intf); + if (ret) { + dev_err(&module->dev, "failed to enable interface %u: %d\n", + intf_id, ret); + goto err_interface_deactivate; + } + + mutex_unlock(&intf->mutex); + + return; + +err_interface_deactivate: + gb_interface_deactivate(intf); +err_unlock: + mutex_unlock(&intf->mutex); +} + +static void gb_module_deregister_interface(struct gb_interface *intf) +{ + /* Mark as disconnected to prevent I/O during disable. */ + if (intf->module->disconnected) + intf->disconnected = true; + + mutex_lock(&intf->mutex); + intf->removed = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); + + gb_interface_del(intf); +} + +/* Register a module and its interfaces. */ +int gb_module_add(struct gb_module *module) +{ + size_t i; + int ret; + + ret = device_add(&module->dev); + if (ret) { + dev_err(&module->dev, "failed to register module: %d\n", ret); + return ret; + } + + trace_gb_module_add(module); + + for (i = 0; i < module->num_interfaces; ++i) + gb_module_register_interface(module->interfaces[i]); + + return 0; +} + +/* Deregister a module and its interfaces. */ +void gb_module_del(struct gb_module *module) +{ + size_t i; + + for (i = 0; i < module->num_interfaces; ++i) + gb_module_deregister_interface(module->interfaces[i]); + + trace_gb_module_del(module); + + device_del(&module->dev); +} + +void gb_module_put(struct gb_module *module) +{ + size_t i; + + for (i = 0; i < module->num_interfaces; ++i) + gb_interface_put(module->interfaces[i]); + + put_device(&module->dev); +} diff --git a/drivers/greybus/operation.c b/drivers/greybus/operation.c new file mode 100644 index 000000000000..8459e9bc0749 --- /dev/null +++ b/drivers/greybus/operation.c @@ -0,0 +1,1264 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus operations + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "greybus_trace.h" + +static struct kmem_cache *gb_operation_cache; +static struct kmem_cache *gb_message_cache; + +/* Workqueue to handle Greybus operation completions. */ +static struct workqueue_struct *gb_operation_completion_wq; + +/* Wait queue for synchronous cancellations. */ +static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); + +/* + * Protects updates to operation->errno. + */ +static DEFINE_SPINLOCK(gb_operations_lock); + +static int gb_operation_response_send(struct gb_operation *operation, + int errno); + +/* + * Increment operation active count and add to connection list unless the + * connection is going away. + * + * Caller holds operation reference. + */ +static int gb_operation_get_active(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + unsigned long flags; + + spin_lock_irqsave(&connection->lock, flags); + switch (connection->state) { + case GB_CONNECTION_STATE_ENABLED: + break; + case GB_CONNECTION_STATE_ENABLED_TX: + if (gb_operation_is_incoming(operation)) + goto err_unlock; + break; + case GB_CONNECTION_STATE_DISCONNECTING: + if (!gb_operation_is_core(operation)) + goto err_unlock; + break; + default: + goto err_unlock; + } + + if (operation->active++ == 0) + list_add_tail(&operation->links, &connection->operations); + + trace_gb_operation_get_active(operation); + + spin_unlock_irqrestore(&connection->lock, flags); + + return 0; + +err_unlock: + spin_unlock_irqrestore(&connection->lock, flags); + + return -ENOTCONN; +} + +/* Caller holds operation reference. */ +static void gb_operation_put_active(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + unsigned long flags; + + spin_lock_irqsave(&connection->lock, flags); + + trace_gb_operation_put_active(operation); + + if (--operation->active == 0) { + list_del(&operation->links); + if (atomic_read(&operation->waiters)) + wake_up(&gb_operation_cancellation_queue); + } + spin_unlock_irqrestore(&connection->lock, flags); +} + +static bool gb_operation_is_active(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + unsigned long flags; + bool ret; + + spin_lock_irqsave(&connection->lock, flags); + ret = operation->active; + spin_unlock_irqrestore(&connection->lock, flags); + + return ret; +} + +/* + * Set an operation's result. + * + * Initially an outgoing operation's errno value is -EBADR. + * If no error occurs before sending the request message the only + * valid value operation->errno can be set to is -EINPROGRESS, + * indicating the request has been (or rather is about to be) sent. + * At that point nobody should be looking at the result until the + * response arrives. + * + * The first time the result gets set after the request has been + * sent, that result "sticks." That is, if two concurrent threads + * race to set the result, the first one wins. The return value + * tells the caller whether its result was recorded; if not the + * caller has nothing more to do. + * + * The result value -EILSEQ is reserved to signal an implementation + * error; if it's ever observed, the code performing the request has + * done something fundamentally wrong. It is an error to try to set + * the result to -EBADR, and attempts to do so result in a warning, + * and -EILSEQ is used instead. Similarly, the only valid result + * value to set for an operation in initial state is -EINPROGRESS. + * Attempts to do otherwise will also record a (successful) -EILSEQ + * operation result. + */ +static bool gb_operation_result_set(struct gb_operation *operation, int result) +{ + unsigned long flags; + int prev; + + if (result == -EINPROGRESS) { + /* + * -EINPROGRESS is used to indicate the request is + * in flight. It should be the first result value + * set after the initial -EBADR. Issue a warning + * and record an implementation error if it's + * set at any other time. + */ + spin_lock_irqsave(&gb_operations_lock, flags); + prev = operation->errno; + if (prev == -EBADR) + operation->errno = result; + else + operation->errno = -EILSEQ; + spin_unlock_irqrestore(&gb_operations_lock, flags); + WARN_ON(prev != -EBADR); + + return true; + } + + /* + * The first result value set after a request has been sent + * will be the final result of the operation. Subsequent + * attempts to set the result are ignored. + * + * Note that -EBADR is a reserved "initial state" result + * value. Attempts to set this value result in a warning, + * and the result code is set to -EILSEQ instead. + */ + if (WARN_ON(result == -EBADR)) + result = -EILSEQ; /* Nobody should be setting -EBADR */ + + spin_lock_irqsave(&gb_operations_lock, flags); + prev = operation->errno; + if (prev == -EINPROGRESS) + operation->errno = result; /* First and final result */ + spin_unlock_irqrestore(&gb_operations_lock, flags); + + return prev == -EINPROGRESS; +} + +int gb_operation_result(struct gb_operation *operation) +{ + int result = operation->errno; + + WARN_ON(result == -EBADR); + WARN_ON(result == -EINPROGRESS); + + return result; +} +EXPORT_SYMBOL_GPL(gb_operation_result); + +/* + * Looks up an outgoing operation on a connection and returns a refcounted + * pointer if found, or NULL otherwise. + */ +static struct gb_operation * +gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id) +{ + struct gb_operation *operation; + unsigned long flags; + bool found = false; + + spin_lock_irqsave(&connection->lock, flags); + list_for_each_entry(operation, &connection->operations, links) + if (operation->id == operation_id && + !gb_operation_is_incoming(operation)) { + gb_operation_get(operation); + found = true; + break; + } + spin_unlock_irqrestore(&connection->lock, flags); + + return found ? operation : NULL; +} + +static int gb_message_send(struct gb_message *message, gfp_t gfp) +{ + struct gb_connection *connection = message->operation->connection; + + trace_gb_message_send(message); + return connection->hd->driver->message_send(connection->hd, + connection->hd_cport_id, + message, + gfp); +} + +/* + * Cancel a message we have passed to the host device layer to be sent. + */ +static void gb_message_cancel(struct gb_message *message) +{ + struct gb_host_device *hd = message->operation->connection->hd; + + hd->driver->message_cancel(message); +} + +static void gb_operation_request_handle(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + int status; + int ret; + + if (connection->handler) { + status = connection->handler(operation); + } else { + dev_err(&connection->hd->dev, + "%s: unexpected incoming request of type 0x%02x\n", + connection->name, operation->type); + + status = -EPROTONOSUPPORT; + } + + ret = gb_operation_response_send(operation, status); + if (ret) { + dev_err(&connection->hd->dev, + "%s: failed to send response %d for type 0x%02x: %d\n", + connection->name, status, operation->type, ret); + return; + } +} + +/* + * Process operation work. + * + * For incoming requests, call the protocol request handler. The operation + * result should be -EINPROGRESS at this point. + * + * For outgoing requests, the operation result value should have + * been set before queueing this. The operation callback function + * allows the original requester to know the request has completed + * and its result is available. + */ +static void gb_operation_work(struct work_struct *work) +{ + struct gb_operation *operation; + int ret; + + operation = container_of(work, struct gb_operation, work); + + if (gb_operation_is_incoming(operation)) { + gb_operation_request_handle(operation); + } else { + ret = del_timer_sync(&operation->timer); + if (!ret) { + /* Cancel request message if scheduled by timeout. */ + if (gb_operation_result(operation) == -ETIMEDOUT) + gb_message_cancel(operation->request); + } + + operation->callback(operation); + } + + gb_operation_put_active(operation); + gb_operation_put(operation); +} + +static void gb_operation_timeout(struct timer_list *t) +{ + struct gb_operation *operation = from_timer(operation, t, timer); + + if (gb_operation_result_set(operation, -ETIMEDOUT)) { + /* + * A stuck request message will be cancelled from the + * workqueue. + */ + queue_work(gb_operation_completion_wq, &operation->work); + } +} + +static void gb_operation_message_init(struct gb_host_device *hd, + struct gb_message *message, + u16 operation_id, + size_t payload_size, u8 type) +{ + struct gb_operation_msg_hdr *header; + + header = message->buffer; + + message->header = header; + message->payload = payload_size ? header + 1 : NULL; + message->payload_size = payload_size; + + /* + * The type supplied for incoming message buffers will be + * GB_REQUEST_TYPE_INVALID. Such buffers will be overwritten by + * arriving data so there's no need to initialize the message header. + */ + if (type != GB_REQUEST_TYPE_INVALID) { + u16 message_size = (u16)(sizeof(*header) + payload_size); + + /* + * For a request, the operation id gets filled in + * when the message is sent. For a response, it + * will be copied from the request by the caller. + * + * The result field in a request message must be + * zero. It will be set just prior to sending for + * a response. + */ + header->size = cpu_to_le16(message_size); + header->operation_id = 0; + header->type = type; + header->result = 0; + } +} + +/* + * Allocate a message to be used for an operation request or response. + * Both types of message contain a common header. The request message + * for an outgoing operation is outbound, as is the response message + * for an incoming operation. The message header for an outbound + * message is partially initialized here. + * + * The headers for inbound messages don't need to be initialized; + * they'll be filled in by arriving data. + * + * Our message buffers have the following layout: + * message header \_ these combined are + * message payload / the message size + */ +static struct gb_message * +gb_operation_message_alloc(struct gb_host_device *hd, u8 type, + size_t payload_size, gfp_t gfp_flags) +{ + struct gb_message *message; + struct gb_operation_msg_hdr *header; + size_t message_size = payload_size + sizeof(*header); + + if (message_size > hd->buffer_size_max) { + dev_warn(&hd->dev, "requested message size too big (%zu > %zu)\n", + message_size, hd->buffer_size_max); + return NULL; + } + + /* Allocate the message structure and buffer. */ + message = kmem_cache_zalloc(gb_message_cache, gfp_flags); + if (!message) + return NULL; + + message->buffer = kzalloc(message_size, gfp_flags); + if (!message->buffer) + goto err_free_message; + + /* Initialize the message. Operation id is filled in later. */ + gb_operation_message_init(hd, message, 0, payload_size, type); + + return message; + +err_free_message: + kmem_cache_free(gb_message_cache, message); + + return NULL; +} + +static void gb_operation_message_free(struct gb_message *message) +{ + kfree(message->buffer); + kmem_cache_free(gb_message_cache, message); +} + +/* + * Map an enum gb_operation_status value (which is represented in a + * message as a single byte) to an appropriate Linux negative errno. + */ +static int gb_operation_status_map(u8 status) +{ + switch (status) { + case GB_OP_SUCCESS: + return 0; + case GB_OP_INTERRUPTED: + return -EINTR; + case GB_OP_TIMEOUT: + return -ETIMEDOUT; + case GB_OP_NO_MEMORY: + return -ENOMEM; + case GB_OP_PROTOCOL_BAD: + return -EPROTONOSUPPORT; + case GB_OP_OVERFLOW: + return -EMSGSIZE; + case GB_OP_INVALID: + return -EINVAL; + case GB_OP_RETRY: + return -EAGAIN; + case GB_OP_NONEXISTENT: + return -ENODEV; + case GB_OP_MALFUNCTION: + return -EILSEQ; + case GB_OP_UNKNOWN_ERROR: + default: + return -EIO; + } +} + +/* + * Map a Linux errno value (from operation->errno) into the value + * that should represent it in a response message status sent + * over the wire. Returns an enum gb_operation_status value (which + * is represented in a message as a single byte). + */ +static u8 gb_operation_errno_map(int errno) +{ + switch (errno) { + case 0: + return GB_OP_SUCCESS; + case -EINTR: + return GB_OP_INTERRUPTED; + case -ETIMEDOUT: + return GB_OP_TIMEOUT; + case -ENOMEM: + return GB_OP_NO_MEMORY; + case -EPROTONOSUPPORT: + return GB_OP_PROTOCOL_BAD; + case -EMSGSIZE: + return GB_OP_OVERFLOW; /* Could be underflow too */ + case -EINVAL: + return GB_OP_INVALID; + case -EAGAIN: + return GB_OP_RETRY; + case -EILSEQ: + return GB_OP_MALFUNCTION; + case -ENODEV: + return GB_OP_NONEXISTENT; + case -EIO: + default: + return GB_OP_UNKNOWN_ERROR; + } +} + +bool gb_operation_response_alloc(struct gb_operation *operation, + size_t response_size, gfp_t gfp) +{ + struct gb_host_device *hd = operation->connection->hd; + struct gb_operation_msg_hdr *request_header; + struct gb_message *response; + u8 type; + + type = operation->type | GB_MESSAGE_TYPE_RESPONSE; + response = gb_operation_message_alloc(hd, type, response_size, gfp); + if (!response) + return false; + response->operation = operation; + + /* + * Size and type get initialized when the message is + * allocated. The errno will be set before sending. All + * that's left is the operation id, which we copy from the + * request message header (as-is, in little-endian order). + */ + request_header = operation->request->header; + response->header->operation_id = request_header->operation_id; + operation->response = response; + + return true; +} +EXPORT_SYMBOL_GPL(gb_operation_response_alloc); + +/* + * Create a Greybus operation to be sent over the given connection. + * The request buffer will be big enough for a payload of the given + * size. + * + * For outgoing requests, the request message's header will be + * initialized with the type of the request and the message size. + * Outgoing operations must also specify the response buffer size, + * which must be sufficient to hold all expected response data. The + * response message header will eventually be overwritten, so there's + * no need to initialize it here. + * + * Request messages for incoming operations can arrive in interrupt + * context, so they must be allocated with GFP_ATOMIC. In this case + * the request buffer will be immediately overwritten, so there is + * no need to initialize the message header. Responsibility for + * allocating a response buffer lies with the incoming request + * handler for a protocol. So we don't allocate that here. + * + * Returns a pointer to the new operation or a null pointer if an + * error occurs. + */ +static struct gb_operation * +gb_operation_create_common(struct gb_connection *connection, u8 type, + size_t request_size, size_t response_size, + unsigned long op_flags, gfp_t gfp_flags) +{ + struct gb_host_device *hd = connection->hd; + struct gb_operation *operation; + + operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); + if (!operation) + return NULL; + operation->connection = connection; + + operation->request = gb_operation_message_alloc(hd, type, request_size, + gfp_flags); + if (!operation->request) + goto err_cache; + operation->request->operation = operation; + + /* Allocate the response buffer for outgoing operations */ + if (!(op_flags & GB_OPERATION_FLAG_INCOMING)) { + if (!gb_operation_response_alloc(operation, response_size, + gfp_flags)) { + goto err_request; + } + + timer_setup(&operation->timer, gb_operation_timeout, 0); + } + + operation->flags = op_flags; + operation->type = type; + operation->errno = -EBADR; /* Initial value--means "never set" */ + + INIT_WORK(&operation->work, gb_operation_work); + init_completion(&operation->completion); + kref_init(&operation->kref); + atomic_set(&operation->waiters, 0); + + return operation; + +err_request: + gb_operation_message_free(operation->request); +err_cache: + kmem_cache_free(gb_operation_cache, operation); + + return NULL; +} + +/* + * Create a new operation associated with the given connection. The + * request and response sizes provided are the number of bytes + * required to hold the request/response payload only. Both of + * these are allowed to be 0. Note that 0x00 is reserved as an + * invalid operation type for all protocols, and this is enforced + * here. + */ +struct gb_operation * +gb_operation_create_flags(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp) +{ + struct gb_operation *operation; + + if (WARN_ON_ONCE(type == GB_REQUEST_TYPE_INVALID)) + return NULL; + if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) + type &= ~GB_MESSAGE_TYPE_RESPONSE; + + if (WARN_ON_ONCE(flags & ~GB_OPERATION_FLAG_USER_MASK)) + flags &= GB_OPERATION_FLAG_USER_MASK; + + operation = gb_operation_create_common(connection, type, + request_size, response_size, + flags, gfp); + if (operation) + trace_gb_operation_create(operation); + + return operation; +} +EXPORT_SYMBOL_GPL(gb_operation_create_flags); + +struct gb_operation * +gb_operation_create_core(struct gb_connection *connection, + u8 type, size_t request_size, + size_t response_size, unsigned long flags, + gfp_t gfp) +{ + struct gb_operation *operation; + + flags |= GB_OPERATION_FLAG_CORE; + + operation = gb_operation_create_common(connection, type, + request_size, response_size, + flags, gfp); + if (operation) + trace_gb_operation_create_core(operation); + + return operation; +} + +/* Do not export this function. */ + +size_t gb_operation_get_payload_size_max(struct gb_connection *connection) +{ + struct gb_host_device *hd = connection->hd; + + return hd->buffer_size_max - sizeof(struct gb_operation_msg_hdr); +} +EXPORT_SYMBOL_GPL(gb_operation_get_payload_size_max); + +static struct gb_operation * +gb_operation_create_incoming(struct gb_connection *connection, u16 id, + u8 type, void *data, size_t size) +{ + struct gb_operation *operation; + size_t request_size; + unsigned long flags = GB_OPERATION_FLAG_INCOMING; + + /* Caller has made sure we at least have a message header. */ + request_size = size - sizeof(struct gb_operation_msg_hdr); + + if (!id) + flags |= GB_OPERATION_FLAG_UNIDIRECTIONAL; + + operation = gb_operation_create_common(connection, type, + request_size, + GB_REQUEST_TYPE_INVALID, + flags, GFP_ATOMIC); + if (!operation) + return NULL; + + operation->id = id; + memcpy(operation->request->header, data, size); + trace_gb_operation_create_incoming(operation); + + return operation; +} + +/* + * Get an additional reference on an operation. + */ +void gb_operation_get(struct gb_operation *operation) +{ + kref_get(&operation->kref); +} +EXPORT_SYMBOL_GPL(gb_operation_get); + +/* + * Destroy a previously created operation. + */ +static void _gb_operation_destroy(struct kref *kref) +{ + struct gb_operation *operation; + + operation = container_of(kref, struct gb_operation, kref); + + trace_gb_operation_destroy(operation); + + if (operation->response) + gb_operation_message_free(operation->response); + gb_operation_message_free(operation->request); + + kmem_cache_free(gb_operation_cache, operation); +} + +/* + * Drop a reference on an operation, and destroy it when the last + * one is gone. + */ +void gb_operation_put(struct gb_operation *operation) +{ + if (WARN_ON(!operation)) + return; + + kref_put(&operation->kref, _gb_operation_destroy); +} +EXPORT_SYMBOL_GPL(gb_operation_put); + +/* Tell the requester we're done */ +static void gb_operation_sync_callback(struct gb_operation *operation) +{ + complete(&operation->completion); +} + +/** + * gb_operation_request_send() - send an operation request message + * @operation: the operation to initiate + * @callback: the operation completion callback + * @timeout: operation timeout in milliseconds, or zero for no timeout + * @gfp: the memory flags to use for any allocations + * + * The caller has filled in any payload so the request message is ready to go. + * The callback function supplied will be called when the response message has + * arrived, a unidirectional request has been sent, or the operation is + * cancelled, indicating that the operation is complete. The callback function + * can fetch the result of the operation using gb_operation_result() if + * desired. + * + * Return: 0 if the request was successfully queued in the host-driver queues, + * or a negative errno. + */ +int gb_operation_request_send(struct gb_operation *operation, + gb_operation_callback callback, + unsigned int timeout, + gfp_t gfp) +{ + struct gb_connection *connection = operation->connection; + struct gb_operation_msg_hdr *header; + unsigned int cycle; + int ret; + + if (gb_connection_is_offloaded(connection)) + return -EBUSY; + + if (!callback) + return -EINVAL; + + /* + * Record the callback function, which is executed in + * non-atomic (workqueue) context when the final result + * of an operation has been set. + */ + operation->callback = callback; + + /* + * Assign the operation's id, and store it in the request header. + * Zero is a reserved operation id for unidirectional operations. + */ + if (gb_operation_is_unidirectional(operation)) { + operation->id = 0; + } else { + cycle = (unsigned int)atomic_inc_return(&connection->op_cycle); + operation->id = (u16)(cycle % U16_MAX + 1); + } + + header = operation->request->header; + header->operation_id = cpu_to_le16(operation->id); + + gb_operation_result_set(operation, -EINPROGRESS); + + /* + * Get an extra reference on the operation. It'll be dropped when the + * operation completes. + */ + gb_operation_get(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; + + ret = gb_message_send(operation->request, gfp); + if (ret) + goto err_put_active; + + if (timeout) { + operation->timer.expires = jiffies + msecs_to_jiffies(timeout); + add_timer(&operation->timer); + } + + return 0; + +err_put_active: + gb_operation_put_active(operation); +err_put: + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_request_send); + +/* + * Send a synchronous operation. This function is expected to + * block, returning only when the response has arrived, (or when an + * error is detected. The return value is the result of the + * operation. + */ +int gb_operation_request_send_sync_timeout(struct gb_operation *operation, + unsigned int timeout) +{ + int ret; + + ret = gb_operation_request_send(operation, gb_operation_sync_callback, + timeout, GFP_KERNEL); + if (ret) + return ret; + + ret = wait_for_completion_interruptible(&operation->completion); + if (ret < 0) { + /* Cancel the operation if interrupted */ + gb_operation_cancel(operation, -ECANCELED); + } + + return gb_operation_result(operation); +} +EXPORT_SYMBOL_GPL(gb_operation_request_send_sync_timeout); + +/* + * Send a response for an incoming operation request. A non-zero + * errno indicates a failed operation. + * + * If there is any response payload, the incoming request handler is + * responsible for allocating the response message. Otherwise the + * it can simply supply the result errno; this function will + * allocate the response message if necessary. + */ +static int gb_operation_response_send(struct gb_operation *operation, + int errno) +{ + struct gb_connection *connection = operation->connection; + int ret; + + if (!operation->response && + !gb_operation_is_unidirectional(operation)) { + if (!gb_operation_response_alloc(operation, 0, GFP_KERNEL)) + return -ENOMEM; + } + + /* Record the result */ + if (!gb_operation_result_set(operation, errno)) { + dev_err(&connection->hd->dev, "request result already set\n"); + return -EIO; /* Shouldn't happen */ + } + + /* Sender of request does not care about response. */ + if (gb_operation_is_unidirectional(operation)) + return 0; + + /* Reference will be dropped when message has been sent. */ + gb_operation_get(operation); + ret = gb_operation_get_active(operation); + if (ret) + goto err_put; + + /* Fill in the response header and send it */ + operation->response->header->result = gb_operation_errno_map(errno); + + ret = gb_message_send(operation->response, GFP_KERNEL); + if (ret) + goto err_put_active; + + return 0; + +err_put_active: + gb_operation_put_active(operation); +err_put: + gb_operation_put(operation); + + return ret; +} + +/* + * This function is called when a message send request has completed. + */ +void greybus_message_sent(struct gb_host_device *hd, + struct gb_message *message, int status) +{ + struct gb_operation *operation = message->operation; + struct gb_connection *connection = operation->connection; + + /* + * If the message was a response, we just need to drop our + * reference to the operation. If an error occurred, report + * it. + * + * For requests, if there's no error and the operation in not + * unidirectional, there's nothing more to do until the response + * arrives. If an error occurred attempting to send it, or if the + * operation is unidrectional, record the result of the operation and + * schedule its completion. + */ + if (message == operation->response) { + if (status) { + dev_err(&connection->hd->dev, + "%s: error sending response 0x%02x: %d\n", + connection->name, operation->type, status); + } + + gb_operation_put_active(operation); + gb_operation_put(operation); + } else if (status || gb_operation_is_unidirectional(operation)) { + if (gb_operation_result_set(operation, status)) { + queue_work(gb_operation_completion_wq, + &operation->work); + } + } +} +EXPORT_SYMBOL_GPL(greybus_message_sent); + +/* + * We've received data on a connection, and it doesn't look like a + * response, so we assume it's a request. + * + * This is called in interrupt context, so just copy the incoming + * data into the request buffer and handle the rest via workqueue. + */ +static void gb_connection_recv_request(struct gb_connection *connection, + const struct gb_operation_msg_hdr *header, + void *data, size_t size) +{ + struct gb_operation *operation; + u16 operation_id; + u8 type; + int ret; + + operation_id = le16_to_cpu(header->operation_id); + type = header->type; + + operation = gb_operation_create_incoming(connection, operation_id, + type, data, size); + if (!operation) { + dev_err(&connection->hd->dev, + "%s: can't create incoming operation\n", + connection->name); + return; + } + + ret = gb_operation_get_active(operation); + if (ret) { + gb_operation_put(operation); + return; + } + trace_gb_message_recv_request(operation->request); + + /* + * The initial reference to the operation will be dropped when the + * request handler returns. + */ + if (gb_operation_result_set(operation, -EINPROGRESS)) + queue_work(connection->wq, &operation->work); +} + +/* + * We've received data that appears to be an operation response + * message. Look up the operation, and record that we've received + * its response. + * + * This is called in interrupt context, so just copy the incoming + * data into the response buffer and handle the rest via workqueue. + */ +static void gb_connection_recv_response(struct gb_connection *connection, + const struct gb_operation_msg_hdr *header, + void *data, size_t size) +{ + struct gb_operation *operation; + struct gb_message *message; + size_t message_size; + u16 operation_id; + int errno; + + operation_id = le16_to_cpu(header->operation_id); + + if (!operation_id) { + dev_err_ratelimited(&connection->hd->dev, + "%s: invalid response id 0 received\n", + connection->name); + return; + } + + operation = gb_operation_find_outgoing(connection, operation_id); + if (!operation) { + dev_err_ratelimited(&connection->hd->dev, + "%s: unexpected response id 0x%04x received\n", + connection->name, operation_id); + return; + } + + errno = gb_operation_status_map(header->result); + message = operation->response; + message_size = sizeof(*header) + message->payload_size; + if (!errno && size > message_size) { + dev_err_ratelimited(&connection->hd->dev, + "%s: malformed response 0x%02x received (%zu > %zu)\n", + connection->name, header->type, + size, message_size); + errno = -EMSGSIZE; + } else if (!errno && size < message_size) { + if (gb_operation_short_response_allowed(operation)) { + message->payload_size = size - sizeof(*header); + } else { + dev_err_ratelimited(&connection->hd->dev, + "%s: short response 0x%02x received (%zu < %zu)\n", + connection->name, header->type, + size, message_size); + errno = -EMSGSIZE; + } + } + + /* We must ignore the payload if a bad status is returned */ + if (errno) + size = sizeof(*header); + + /* The rest will be handled in work queue context */ + if (gb_operation_result_set(operation, errno)) { + memcpy(message->buffer, data, size); + + trace_gb_message_recv_response(message); + + queue_work(gb_operation_completion_wq, &operation->work); + } + + gb_operation_put(operation); +} + +/* + * Handle data arriving on a connection. As soon as we return the + * supplied data buffer will be reused (so unless we do something + * with, it's effectively dropped). + */ +void gb_connection_recv(struct gb_connection *connection, + void *data, size_t size) +{ + struct gb_operation_msg_hdr header; + struct device *dev = &connection->hd->dev; + size_t msg_size; + + if (connection->state == GB_CONNECTION_STATE_DISABLED || + gb_connection_is_offloaded(connection)) { + dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n", + connection->name, size); + return; + } + + if (size < sizeof(header)) { + dev_err_ratelimited(dev, "%s: short message received\n", + connection->name); + return; + } + + /* Use memcpy as data may be unaligned */ + memcpy(&header, data, sizeof(header)); + msg_size = le16_to_cpu(header.size); + if (size < msg_size) { + dev_err_ratelimited(dev, + "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n", + connection->name, + le16_to_cpu(header.operation_id), + header.type, size, msg_size); + return; /* XXX Should still complete operation */ + } + + if (header.type & GB_MESSAGE_TYPE_RESPONSE) { + gb_connection_recv_response(connection, &header, data, + msg_size); + } else { + gb_connection_recv_request(connection, &header, data, + msg_size); + } +} + +/* + * Cancel an outgoing operation synchronously, and record the given error to + * indicate why. + */ +void gb_operation_cancel(struct gb_operation *operation, int errno) +{ + if (WARN_ON(gb_operation_is_incoming(operation))) + return; + + if (gb_operation_result_set(operation, errno)) { + gb_message_cancel(operation->request); + queue_work(gb_operation_completion_wq, &operation->work); + } + trace_gb_message_cancel_outgoing(operation->request); + + atomic_inc(&operation->waiters); + wait_event(gb_operation_cancellation_queue, + !gb_operation_is_active(operation)); + atomic_dec(&operation->waiters); +} +EXPORT_SYMBOL_GPL(gb_operation_cancel); + +/* + * Cancel an incoming operation synchronously. Called during connection tear + * down. + */ +void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) +{ + if (WARN_ON(!gb_operation_is_incoming(operation))) + return; + + if (!gb_operation_is_unidirectional(operation)) { + /* + * Make sure the request handler has submitted the response + * before cancelling it. + */ + flush_work(&operation->work); + if (!gb_operation_result_set(operation, errno)) + gb_message_cancel(operation->response); + } + trace_gb_message_cancel_incoming(operation->response); + + atomic_inc(&operation->waiters); + wait_event(gb_operation_cancellation_queue, + !gb_operation_is_active(operation)); + atomic_dec(&operation->waiters); +} + +/** + * gb_operation_sync_timeout() - implement a "simple" synchronous operation + * @connection: the Greybus connection to send this to + * @type: the type of operation to send + * @request: pointer to a memory buffer to copy the request from + * @request_size: size of @request + * @response: pointer to a memory buffer to copy the response to + * @response_size: the size of @response. + * @timeout: operation timeout in milliseconds + * + * This function implements a simple synchronous Greybus operation. It sends + * the provided operation request and waits (sleeps) until the corresponding + * operation response message has been successfully received, or an error + * occurs. @request and @response are buffers to hold the request and response + * data respectively, and if they are not NULL, their size must be specified in + * @request_size and @response_size. + * + * If a response payload is to come back, and @response is not NULL, + * @response_size number of bytes will be copied into @response if the operation + * is successful. + * + * If there is an error, the response buffer is left alone. + */ +int gb_operation_sync_timeout(struct gb_connection *connection, int type, + void *request, int request_size, + void *response, int response_size, + unsigned int timeout) +{ + struct gb_operation *operation; + int ret; + + if ((response_size && !response) || + (request_size && !request)) + return -EINVAL; + + operation = gb_operation_create(connection, type, + request_size, response_size, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync_timeout(operation, timeout); + if (ret) { + dev_err(&connection->hd->dev, + "%s: synchronous operation id 0x%04x of type 0x%02x failed: %d\n", + connection->name, operation->id, type, ret); + } else { + if (response_size) { + memcpy(response, operation->response->payload, + response_size); + } + } + + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_sync_timeout); + +/** + * gb_operation_unidirectional_timeout() - initiate a unidirectional operation + * @connection: connection to use + * @type: type of operation to send + * @request: memory buffer to copy the request from + * @request_size: size of @request + * @timeout: send timeout in milliseconds + * + * Initiate a unidirectional operation by sending a request message and + * waiting for it to be acknowledged as sent by the host device. + * + * Note that successful send of a unidirectional operation does not imply that + * the request as actually reached the remote end of the connection. + */ +int gb_operation_unidirectional_timeout(struct gb_connection *connection, + int type, void *request, + int request_size, + unsigned int timeout) +{ + struct gb_operation *operation; + int ret; + + if (request_size && !request) + return -EINVAL; + + operation = gb_operation_create_flags(connection, type, + request_size, 0, + GB_OPERATION_FLAG_UNIDIRECTIONAL, + GFP_KERNEL); + if (!operation) + return -ENOMEM; + + if (request_size) + memcpy(operation->request->payload, request, request_size); + + ret = gb_operation_request_send_sync_timeout(operation, timeout); + if (ret) { + dev_err(&connection->hd->dev, + "%s: unidirectional operation of type 0x%02x failed: %d\n", + connection->name, type, ret); + } + + gb_operation_put(operation); + + return ret; +} +EXPORT_SYMBOL_GPL(gb_operation_unidirectional_timeout); + +int __init gb_operation_init(void) +{ + gb_message_cache = kmem_cache_create("gb_message_cache", + sizeof(struct gb_message), 0, 0, + NULL); + if (!gb_message_cache) + return -ENOMEM; + + gb_operation_cache = kmem_cache_create("gb_operation_cache", + sizeof(struct gb_operation), 0, + 0, NULL); + if (!gb_operation_cache) + goto err_destroy_message_cache; + + gb_operation_completion_wq = alloc_workqueue("greybus_completion", + 0, 0); + if (!gb_operation_completion_wq) + goto err_destroy_operation_cache; + + return 0; + +err_destroy_operation_cache: + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; +err_destroy_message_cache: + kmem_cache_destroy(gb_message_cache); + gb_message_cache = NULL; + + return -ENOMEM; +} + +void gb_operation_exit(void) +{ + destroy_workqueue(gb_operation_completion_wq); + gb_operation_completion_wq = NULL; + kmem_cache_destroy(gb_operation_cache); + gb_operation_cache = NULL; + kmem_cache_destroy(gb_message_cache); + gb_message_cache = NULL; +} diff --git a/drivers/greybus/svc.c b/drivers/greybus/svc.c new file mode 100644 index 000000000000..ce7740ef449b --- /dev/null +++ b/drivers/greybus/svc.c @@ -0,0 +1,1397 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SVC Greybus driver. + * + * Copyright 2015 Google Inc. + * Copyright 2015 Linaro Ltd. + */ + +#include +#include +#include + +#define SVC_INTF_EJECT_TIMEOUT 9000 +#define SVC_INTF_ACTIVATE_TIMEOUT 6000 +#define SVC_INTF_RESUME_TIMEOUT 3000 + +struct gb_svc_deferred_request { + struct work_struct work; + struct gb_operation *operation; +}; + +static int gb_svc_queue_deferred_request(struct gb_operation *operation); + +static ssize_t endo_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "0x%04x\n", svc->endo_id); +} +static DEVICE_ATTR_RO(endo_id); + +static ssize_t ap_intf_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "%u\n", svc->ap_intf_id); +} +static DEVICE_ATTR_RO(ap_intf_id); + +// FIXME +// This is a hack, we need to do this "right" and clean the interface up +// properly, not just forcibly yank the thing out of the system and hope for the +// best. But for now, people want their modules to come out without having to +// throw the thing to the ground or get out a screwdriver. +static ssize_t intf_eject_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + unsigned short intf_id; + int ret; + + ret = kstrtou16(buf, 10, &intf_id); + if (ret < 0) + return ret; + + dev_warn(dev, "Forcibly trying to eject interface %d\n", intf_id); + + ret = gb_svc_intf_eject(svc, intf_id); + if (ret < 0) + return ret; + + return len; +} +static DEVICE_ATTR_WO(intf_eject); + +static ssize_t watchdog_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + return sprintf(buf, "%s\n", + gb_svc_watchdog_enabled(svc) ? "enabled" : "disabled"); +} + +static ssize_t watchdog_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + int retval; + bool user_request; + + retval = strtobool(buf, &user_request); + if (retval) + return retval; + + if (user_request) + retval = gb_svc_watchdog_enable(svc); + else + retval = gb_svc_watchdog_disable(svc); + if (retval) + return retval; + return len; +} +static DEVICE_ATTR_RW(watchdog); + +static ssize_t watchdog_action_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) + return sprintf(buf, "panic\n"); + else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) + return sprintf(buf, "reset\n"); + + return -EINVAL; +} + +static ssize_t watchdog_action_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (sysfs_streq(buf, "panic")) + svc->action = GB_SVC_WATCHDOG_BITE_PANIC_KERNEL; + else if (sysfs_streq(buf, "reset")) + svc->action = GB_SVC_WATCHDOG_BITE_RESET_UNIPRO; + else + return -EINVAL; + + return len; +} +static DEVICE_ATTR_RW(watchdog_action); + +static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) +{ + struct gb_svc_pwrmon_rail_count_get_response response; + int ret; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET, NULL, 0, + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get rail count: %d\n", ret); + return ret; + } + + *value = response.rail_count; + + return 0; +} + +static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, + struct gb_svc_pwrmon_rail_names_get_response *response, + size_t bufsize) +{ + int ret; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET, NULL, 0, + response, bufsize); + if (ret) { + dev_err(&svc->dev, "failed to get rail names: %d\n", ret); + return ret; + } + + if (response->status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, + "SVC error while getting rail names: %u\n", + response->status); + return -EREMOTEIO; + } + + return 0; +} + +static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, + u8 measurement_type, u32 *value) +{ + struct gb_svc_pwrmon_sample_get_request request; + struct gb_svc_pwrmon_sample_get_response response; + int ret; + + request.rail_id = rail_id; + request.measurement_type = measurement_type; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_PWRMON_SAMPLE_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get rail sample: %d\n", ret); + return ret; + } + + if (response.result) { + dev_err(&svc->dev, + "UniPro error while getting rail power sample (%d %d): %d\n", + rail_id, measurement_type, response.result); + switch (response.result) { + case GB_SVC_PWRMON_GET_SAMPLE_INVAL: + return -EINVAL; + case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: + return -ENOMSG; + default: + return -EREMOTEIO; + } + } + + *value = le32_to_cpu(response.measurement); + + return 0; +} + +int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, + u8 measurement_type, u32 *value) +{ + struct gb_svc_pwrmon_intf_sample_get_request request; + struct gb_svc_pwrmon_intf_sample_get_response response; + int ret; + + request.intf_id = intf_id; + request.measurement_type = measurement_type; + + ret = gb_operation_sync(svc->connection, + GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get intf sample: %d\n", ret); + return ret; + } + + if (response.result) { + dev_err(&svc->dev, + "UniPro error while getting intf power sample (%d %d): %d\n", + intf_id, measurement_type, response.result); + switch (response.result) { + case GB_SVC_PWRMON_GET_SAMPLE_INVAL: + return -EINVAL; + case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: + return -ENOMSG; + default: + return -EREMOTEIO; + } + } + + *value = le32_to_cpu(response.measurement); + + return 0; +} + +static struct attribute *svc_attrs[] = { + &dev_attr_endo_id.attr, + &dev_attr_ap_intf_id.attr, + &dev_attr_intf_eject.attr, + &dev_attr_watchdog.attr, + &dev_attr_watchdog_action.attr, + NULL, +}; +ATTRIBUTE_GROUPS(svc); + +int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) +{ + struct gb_svc_intf_device_id_request request; + + request.intf_id = intf_id; + request.device_id = device_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_DEVICE_ID, + &request, sizeof(request), NULL, 0); +} + +int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_eject_request request; + int ret; + + request.intf_id = intf_id; + + /* + * The pulse width for module release in svc is long so we need to + * increase the timeout so the operation will not return to soon. + */ + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_EJECT, &request, + sizeof(request), NULL, 0, + SVC_INTF_EJECT_TIMEOUT); + if (ret) { + dev_err(&svc->dev, "failed to eject interface %u\n", intf_id); + return ret; + } + + return 0; +} + +int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + struct gb_svc_intf_vsys_request request; + struct gb_svc_intf_vsys_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_VSYS_ENABLE; + else + type = GB_SVC_TYPE_INTF_VSYS_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_VSYS_OK) + return -EREMOTEIO; + return 0; +} + +int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + struct gb_svc_intf_refclk_request request; + struct gb_svc_intf_refclk_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_REFCLK_ENABLE; + else + type = GB_SVC_TYPE_INTF_REFCLK_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_REFCLK_OK) + return -EREMOTEIO; + return 0; +} + +int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) +{ + struct gb_svc_intf_unipro_request request; + struct gb_svc_intf_unipro_response response; + int type, ret; + + request.intf_id = intf_id; + + if (enable) + type = GB_SVC_TYPE_INTF_UNIPRO_ENABLE; + else + type = GB_SVC_TYPE_INTF_UNIPRO_DISABLE; + + ret = gb_operation_sync(svc->connection, type, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + if (response.result_code != GB_SVC_INTF_UNIPRO_OK) + return -EREMOTEIO; + return 0; +} + +int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) +{ + struct gb_svc_intf_activate_request request; + struct gb_svc_intf_activate_response response; + int ret; + + request.intf_id = intf_id; + + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_ACTIVATE, + &request, sizeof(request), + &response, sizeof(response), + SVC_INTF_ACTIVATE_TIMEOUT); + if (ret < 0) + return ret; + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "failed to activate interface %u: %u\n", + intf_id, response.status); + return -EREMOTEIO; + } + + *intf_type = response.intf_type; + + return 0; +} + +int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_resume_request request; + struct gb_svc_intf_resume_response response; + int ret; + + request.intf_id = intf_id; + + ret = gb_operation_sync_timeout(svc->connection, + GB_SVC_TYPE_INTF_RESUME, + &request, sizeof(request), + &response, sizeof(response), + SVC_INTF_RESUME_TIMEOUT); + if (ret < 0) { + dev_err(&svc->dev, "failed to send interface resume %u: %d\n", + intf_id, ret); + return ret; + } + + if (response.status != GB_SVC_OP_SUCCESS) { + dev_err(&svc->dev, "failed to resume interface %u: %u\n", + intf_id, response.status); + return -EREMOTEIO; + } + + return 0; +} + +int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 *value) +{ + struct gb_svc_dme_peer_get_request request; + struct gb_svc_dme_peer_get_response response; + u16 result; + int ret; + + request.intf_id = intf_id; + request.attr = cpu_to_le16(attr); + request.selector = cpu_to_le16(selector); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_GET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to get DME attribute (%u 0x%04x %u): %d\n", + intf_id, attr, selector, ret); + return ret; + } + + result = le16_to_cpu(response.result_code); + if (result) { + dev_err(&svc->dev, "UniPro error while getting DME attribute (%u 0x%04x %u): %u\n", + intf_id, attr, selector, result); + return -EREMOTEIO; + } + + if (value) + *value = le32_to_cpu(response.attr_value); + + return 0; +} + +int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, + u32 value) +{ + struct gb_svc_dme_peer_set_request request; + struct gb_svc_dme_peer_set_response response; + u16 result; + int ret; + + request.intf_id = intf_id; + request.attr = cpu_to_le16(attr); + request.selector = cpu_to_le16(selector); + request.value = cpu_to_le32(value); + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_SET, + &request, sizeof(request), + &response, sizeof(response)); + if (ret) { + dev_err(&svc->dev, "failed to set DME attribute (%u 0x%04x %u %u): %d\n", + intf_id, attr, selector, value, ret); + return ret; + } + + result = le16_to_cpu(response.result_code); + if (result) { + dev_err(&svc->dev, "UniPro error while setting DME attribute (%u 0x%04x %u %u): %u\n", + intf_id, attr, selector, value, result); + return -EREMOTEIO; + } + + return 0; +} + +int gb_svc_connection_create(struct gb_svc *svc, + u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id, + u8 cport_flags) +{ + struct gb_svc_conn_create_request request; + + request.intf1_id = intf1_id; + request.cport1_id = cpu_to_le16(cport1_id); + request.intf2_id = intf2_id; + request.cport2_id = cpu_to_le16(cport2_id); + request.tc = 0; /* TC0 */ + request.flags = cport_flags; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, + &request, sizeof(request), NULL, 0); +} + +void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, + u8 intf2_id, u16 cport2_id) +{ + struct gb_svc_conn_destroy_request request; + struct gb_connection *connection = svc->connection; + int ret; + + request.intf1_id = intf1_id; + request.cport1_id = cpu_to_le16(cport1_id); + request.intf2_id = intf2_id; + request.cport2_id = cpu_to_le16(cport2_id); + + ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(&svc->dev, "failed to destroy connection (%u:%u %u:%u): %d\n", + intf1_id, cport1_id, intf2_id, cport2_id, ret); + } +} + +/* Creates bi-directional routes between the devices */ +int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, + u8 intf2_id, u8 dev2_id) +{ + struct gb_svc_route_create_request request; + + request.intf1_id = intf1_id; + request.dev1_id = dev1_id; + request.intf2_id = intf2_id; + request.dev2_id = dev2_id; + + return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, + &request, sizeof(request), NULL, 0); +} + +/* Destroys bi-directional routes between the devices */ +void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) +{ + struct gb_svc_route_destroy_request request; + int ret; + + request.intf1_id = intf1_id; + request.intf2_id = intf2_id; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, + &request, sizeof(request), NULL, 0); + if (ret) { + dev_err(&svc->dev, "failed to destroy route (%u %u): %d\n", + intf1_id, intf2_id, ret); + } +} + +int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, + u8 tx_mode, u8 tx_gear, u8 tx_nlanes, + u8 tx_amplitude, u8 tx_hs_equalizer, + u8 rx_mode, u8 rx_gear, u8 rx_nlanes, + u8 flags, u32 quirks, + struct gb_svc_l2_timer_cfg *local, + struct gb_svc_l2_timer_cfg *remote) +{ + struct gb_svc_intf_set_pwrm_request request; + struct gb_svc_intf_set_pwrm_response response; + int ret; + u16 result_code; + + memset(&request, 0, sizeof(request)); + + request.intf_id = intf_id; + request.hs_series = hs_series; + request.tx_mode = tx_mode; + request.tx_gear = tx_gear; + request.tx_nlanes = tx_nlanes; + request.tx_amplitude = tx_amplitude; + request.tx_hs_equalizer = tx_hs_equalizer; + request.rx_mode = rx_mode; + request.rx_gear = rx_gear; + request.rx_nlanes = rx_nlanes; + request.flags = flags; + request.quirks = cpu_to_le32(quirks); + if (local) + request.local_l2timerdata = *local; + if (remote) + request.remote_l2timerdata = *remote; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) + return ret; + + result_code = response.result_code; + if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) { + dev_err(&svc->dev, "set power mode = %d\n", result_code); + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); + +int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id) +{ + struct gb_svc_intf_set_pwrm_request request; + struct gb_svc_intf_set_pwrm_response response; + int ret; + u16 result_code; + + memset(&request, 0, sizeof(request)); + + request.intf_id = intf_id; + request.hs_series = GB_SVC_UNIPRO_HS_SERIES_A; + request.tx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; + request.rx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; + + ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, + &request, sizeof(request), + &response, sizeof(response)); + if (ret < 0) { + dev_err(&svc->dev, + "failed to send set power mode operation to interface %u: %d\n", + intf_id, ret); + return ret; + } + + result_code = response.result_code; + if (result_code != GB_SVC_SETPWRM_PWR_OK) { + dev_err(&svc->dev, + "failed to hibernate the link for interface %u: %u\n", + intf_id, result_code); + return -EIO; + } + + return 0; +} + +int gb_svc_ping(struct gb_svc *svc) +{ + return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PING, + NULL, 0, NULL, 0, + GB_OPERATION_TIMEOUT_DEFAULT * 2); +} + +static int gb_svc_version_request(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_svc_version_request *request; + struct gb_svc_version_response *response; + + if (op->request->payload_size < sizeof(*request)) { + dev_err(&svc->dev, "short version request (%zu < %zu)\n", + op->request->payload_size, + sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + if (request->major > GB_SVC_VERSION_MAJOR) { + dev_warn(&svc->dev, "unsupported major version (%u > %u)\n", + request->major, GB_SVC_VERSION_MAJOR); + return -ENOTSUPP; + } + + svc->protocol_major = request->major; + svc->protocol_minor = request->minor; + + if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) + return -ENOMEM; + + response = op->response->payload; + response->major = svc->protocol_major; + response->minor = svc->protocol_minor; + + return 0; +} + +static ssize_t pwr_debugfs_voltage_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = + file_inode(file)->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_VOL, &value); + if (ret) { + dev_err(&svc->dev, + "failed to get voltage sample %u: %d\n", + pwrmon_rails->id, ret); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static ssize_t pwr_debugfs_current_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = + file_inode(file)->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_CURR, &value); + if (ret) { + dev_err(&svc->dev, + "failed to get current sample %u: %d\n", + pwrmon_rails->id, ret); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static ssize_t pwr_debugfs_power_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + struct svc_debugfs_pwrmon_rail *pwrmon_rails = + file_inode(file)->i_private; + struct gb_svc *svc = pwrmon_rails->svc; + int ret, desc; + u32 value; + char buff[16]; + + ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, + GB_SVC_PWRMON_TYPE_PWR, &value); + if (ret) { + dev_err(&svc->dev, "failed to get power sample %u: %d\n", + pwrmon_rails->id, ret); + return ret; + } + + desc = scnprintf(buff, sizeof(buff), "%u\n", value); + + return simple_read_from_buffer(buf, len, offset, buff, desc); +} + +static const struct file_operations pwrmon_debugfs_voltage_fops = { + .read = pwr_debugfs_voltage_read, +}; + +static const struct file_operations pwrmon_debugfs_current_fops = { + .read = pwr_debugfs_current_read, +}; + +static const struct file_operations pwrmon_debugfs_power_fops = { + .read = pwr_debugfs_power_read, +}; + +static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) +{ + int i; + size_t bufsize; + struct dentry *dent; + struct gb_svc_pwrmon_rail_names_get_response *rail_names; + u8 rail_count; + + dent = debugfs_create_dir("pwrmon", svc->debugfs_dentry); + if (IS_ERR_OR_NULL(dent)) + return; + + if (gb_svc_pwrmon_rail_count_get(svc, &rail_count)) + goto err_pwrmon_debugfs; + + if (!rail_count || rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) + goto err_pwrmon_debugfs; + + bufsize = sizeof(*rail_names) + + GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count; + + rail_names = kzalloc(bufsize, GFP_KERNEL); + if (!rail_names) + goto err_pwrmon_debugfs; + + svc->pwrmon_rails = kcalloc(rail_count, sizeof(*svc->pwrmon_rails), + GFP_KERNEL); + if (!svc->pwrmon_rails) + goto err_pwrmon_debugfs_free; + + if (gb_svc_pwrmon_rail_names_get(svc, rail_names, bufsize)) + goto err_pwrmon_debugfs_free; + + for (i = 0; i < rail_count; i++) { + struct dentry *dir; + struct svc_debugfs_pwrmon_rail *rail = &svc->pwrmon_rails[i]; + char fname[GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; + + snprintf(fname, sizeof(fname), "%s", + (char *)&rail_names->name[i]); + + rail->id = i; + rail->svc = svc; + + dir = debugfs_create_dir(fname, dent); + debugfs_create_file("voltage_now", 0444, dir, rail, + &pwrmon_debugfs_voltage_fops); + debugfs_create_file("current_now", 0444, dir, rail, + &pwrmon_debugfs_current_fops); + debugfs_create_file("power_now", 0444, dir, rail, + &pwrmon_debugfs_power_fops); + } + + kfree(rail_names); + return; + +err_pwrmon_debugfs_free: + kfree(rail_names); + kfree(svc->pwrmon_rails); + svc->pwrmon_rails = NULL; + +err_pwrmon_debugfs: + debugfs_remove(dent); +} + +static void gb_svc_debugfs_init(struct gb_svc *svc) +{ + svc->debugfs_dentry = debugfs_create_dir(dev_name(&svc->dev), + gb_debugfs_get()); + gb_svc_pwrmon_debugfs_init(svc); +} + +static void gb_svc_debugfs_exit(struct gb_svc *svc) +{ + debugfs_remove_recursive(svc->debugfs_dentry); + kfree(svc->pwrmon_rails); + svc->pwrmon_rails = NULL; +} + +static int gb_svc_hello(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_svc_hello_request *hello_request; + int ret; + + if (op->request->payload_size < sizeof(*hello_request)) { + dev_warn(&svc->dev, "short hello request (%zu < %zu)\n", + op->request->payload_size, + sizeof(*hello_request)); + return -EINVAL; + } + + hello_request = op->request->payload; + svc->endo_id = le16_to_cpu(hello_request->endo_id); + svc->ap_intf_id = hello_request->interface_id; + + ret = device_add(&svc->dev); + if (ret) { + dev_err(&svc->dev, "failed to register svc device: %d\n", ret); + return ret; + } + + ret = gb_svc_watchdog_create(svc); + if (ret) { + dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); + goto err_unregister_device; + } + + gb_svc_debugfs_init(svc); + + return gb_svc_queue_deferred_request(op); + +err_unregister_device: + gb_svc_watchdog_destroy(svc); + device_del(&svc->dev); + return ret; +} + +static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc, + u8 intf_id) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + size_t num_interfaces; + u8 module_id; + + list_for_each_entry(module, &hd->modules, hd_node) { + module_id = module->module_id; + num_interfaces = module->num_interfaces; + + if (intf_id >= module_id && + intf_id < module_id + num_interfaces) { + return module->interfaces[intf_id - module_id]; + } + } + + return NULL; +} + +static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + + list_for_each_entry(module, &hd->modules, hd_node) { + if (module->module_id == module_id) + return module; + } + + return NULL; +} + +static void gb_svc_process_hello_deferred(struct gb_operation *operation) +{ + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + int ret; + + /* + * XXX This is a hack/work-around to reconfigure the APBridgeA-Switch + * link to PWM G2, 1 Lane, Slow Auto, so that it has sufficient + * bandwidth for 3 audio streams plus boot-over-UniPro of a hot-plugged + * module. + * + * The code should be removed once SW-2217, Heuristic for UniPro + * Power Mode Changes is resolved. + */ + ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, + GB_SVC_UNIPRO_HS_SERIES_A, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + GB_SVC_SMALL_AMPLITUDE, + GB_SVC_NO_DE_EMPHASIS, + GB_SVC_UNIPRO_SLOW_AUTO_MODE, + 2, 1, + 0, 0, + NULL, NULL); + + if (ret) + dev_warn(&svc->dev, + "power mode change failed on AP to switch link: %d\n", + ret); +} + +static void gb_svc_process_module_inserted(struct gb_operation *operation) +{ + struct gb_svc_module_inserted_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_host_device *hd = svc->hd; + struct gb_module *module; + size_t num_interfaces; + u8 module_id; + u16 flags; + int ret; + + /* The request message size has already been verified. */ + request = operation->request->payload; + module_id = request->primary_intf_id; + num_interfaces = request->intf_count; + flags = le16_to_cpu(request->flags); + + dev_dbg(&svc->dev, "%s - id = %u, num_interfaces = %zu, flags = 0x%04x\n", + __func__, module_id, num_interfaces, flags); + + if (flags & GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY) { + dev_warn(&svc->dev, "no primary interface detected on module %u\n", + module_id); + } + + module = gb_svc_module_lookup(svc, module_id); + if (module) { + dev_warn(&svc->dev, "unexpected module-inserted event %u\n", + module_id); + return; + } + + module = gb_module_create(hd, module_id, num_interfaces); + if (!module) { + dev_err(&svc->dev, "failed to create module\n"); + return; + } + + ret = gb_module_add(module); + if (ret) { + gb_module_put(module); + return; + } + + list_add(&module->hd_node, &hd->modules); +} + +static void gb_svc_process_module_removed(struct gb_operation *operation) +{ + struct gb_svc_module_removed_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_module *module; + u8 module_id; + + /* The request message size has already been verified. */ + request = operation->request->payload; + module_id = request->primary_intf_id; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, module_id); + + module = gb_svc_module_lookup(svc, module_id); + if (!module) { + dev_warn(&svc->dev, "unexpected module-removed event %u\n", + module_id); + return; + } + + module->disconnected = true; + + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); +} + +static void gb_svc_process_intf_oops(struct gb_operation *operation) +{ + struct gb_svc_intf_oops_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_interface *intf; + u8 intf_id; + u8 reason; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + reason = request->reason; + + intf = gb_svc_interface_lookup(svc, intf_id); + if (!intf) { + dev_warn(&svc->dev, "unexpected interface-oops event %u\n", + intf_id); + return; + } + + dev_info(&svc->dev, "Deactivating interface %u, interface oops reason = %u\n", + intf_id, reason); + + mutex_lock(&intf->mutex); + intf->disconnected = true; + gb_interface_disable(intf); + gb_interface_deactivate(intf); + mutex_unlock(&intf->mutex); +} + +static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation) +{ + struct gb_svc_intf_mailbox_event_request *request; + struct gb_connection *connection = operation->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + struct gb_interface *intf; + u8 intf_id; + u16 result_code; + u32 mailbox; + + /* The request message size has already been verified. */ + request = operation->request->payload; + intf_id = request->intf_id; + result_code = le16_to_cpu(request->result_code); + mailbox = le32_to_cpu(request->mailbox); + + dev_dbg(&svc->dev, "%s - id = %u, result = 0x%04x, mailbox = 0x%08x\n", + __func__, intf_id, result_code, mailbox); + + intf = gb_svc_interface_lookup(svc, intf_id); + if (!intf) { + dev_warn(&svc->dev, "unexpected mailbox event %u\n", intf_id); + return; + } + + gb_interface_mailbox_event(intf, result_code, mailbox); +} + +static void gb_svc_process_deferred_request(struct work_struct *work) +{ + struct gb_svc_deferred_request *dr; + struct gb_operation *operation; + struct gb_svc *svc; + u8 type; + + dr = container_of(work, struct gb_svc_deferred_request, work); + operation = dr->operation; + svc = gb_connection_get_data(operation->connection); + type = operation->request->header->type; + + switch (type) { + case GB_SVC_TYPE_SVC_HELLO: + gb_svc_process_hello_deferred(operation); + break; + case GB_SVC_TYPE_MODULE_INSERTED: + gb_svc_process_module_inserted(operation); + break; + case GB_SVC_TYPE_MODULE_REMOVED: + gb_svc_process_module_removed(operation); + break; + case GB_SVC_TYPE_INTF_MAILBOX_EVENT: + gb_svc_process_intf_mailbox_event(operation); + break; + case GB_SVC_TYPE_INTF_OOPS: + gb_svc_process_intf_oops(operation); + break; + default: + dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); + } + + gb_operation_put(operation); + kfree(dr); +} + +static int gb_svc_queue_deferred_request(struct gb_operation *operation) +{ + struct gb_svc *svc = gb_connection_get_data(operation->connection); + struct gb_svc_deferred_request *dr; + + dr = kmalloc(sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + gb_operation_get(operation); + + dr->operation = operation; + INIT_WORK(&dr->work, gb_svc_process_deferred_request); + + queue_work(svc->wq, &dr->work); + + return 0; +} + +static int gb_svc_intf_reset_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_message *request = op->request; + struct gb_svc_intf_reset_request *reset; + + if (request->payload_size < sizeof(*reset)) { + dev_warn(&svc->dev, "short reset request received (%zu < %zu)\n", + request->payload_size, sizeof(*reset)); + return -EINVAL; + } + reset = request->payload; + + /* FIXME Reset the interface here */ + + return 0; +} + +static int gb_svc_module_inserted_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_module_inserted_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short module-inserted request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, + request->primary_intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_module_removed_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_module_removed_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short module-removed request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, + request->primary_intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_intf_oops_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_intf_oops_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short intf-oops request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_intf_mailbox_event_recv(struct gb_operation *op) +{ + struct gb_svc *svc = gb_connection_get_data(op->connection); + struct gb_svc_intf_mailbox_event_request *request; + + if (op->request->payload_size < sizeof(*request)) { + dev_warn(&svc->dev, "short mailbox request received (%zu < %zu)\n", + op->request->payload_size, sizeof(*request)); + return -EINVAL; + } + + request = op->request->payload; + + dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); + + return gb_svc_queue_deferred_request(op); +} + +static int gb_svc_request_handler(struct gb_operation *op) +{ + struct gb_connection *connection = op->connection; + struct gb_svc *svc = gb_connection_get_data(connection); + u8 type = op->type; + int ret = 0; + + /* + * SVC requests need to follow a specific order (at least initially) and + * below code takes care of enforcing that. The expected order is: + * - PROTOCOL_VERSION + * - SVC_HELLO + * - Any other request, but the earlier two. + * + * Incoming requests are guaranteed to be serialized and so we don't + * need to protect 'state' for any races. + */ + switch (type) { + case GB_SVC_TYPE_PROTOCOL_VERSION: + if (svc->state != GB_SVC_STATE_RESET) + ret = -EINVAL; + break; + case GB_SVC_TYPE_SVC_HELLO: + if (svc->state != GB_SVC_STATE_PROTOCOL_VERSION) + ret = -EINVAL; + break; + default: + if (svc->state != GB_SVC_STATE_SVC_HELLO) + ret = -EINVAL; + break; + } + + if (ret) { + dev_warn(&svc->dev, "unexpected request 0x%02x received (state %u)\n", + type, svc->state); + return ret; + } + + switch (type) { + case GB_SVC_TYPE_PROTOCOL_VERSION: + ret = gb_svc_version_request(op); + if (!ret) + svc->state = GB_SVC_STATE_PROTOCOL_VERSION; + return ret; + case GB_SVC_TYPE_SVC_HELLO: + ret = gb_svc_hello(op); + if (!ret) + svc->state = GB_SVC_STATE_SVC_HELLO; + return ret; + case GB_SVC_TYPE_INTF_RESET: + return gb_svc_intf_reset_recv(op); + case GB_SVC_TYPE_MODULE_INSERTED: + return gb_svc_module_inserted_recv(op); + case GB_SVC_TYPE_MODULE_REMOVED: + return gb_svc_module_removed_recv(op); + case GB_SVC_TYPE_INTF_MAILBOX_EVENT: + return gb_svc_intf_mailbox_event_recv(op); + case GB_SVC_TYPE_INTF_OOPS: + return gb_svc_intf_oops_recv(op); + default: + dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); + return -EINVAL; + } +} + +static void gb_svc_release(struct device *dev) +{ + struct gb_svc *svc = to_gb_svc(dev); + + if (svc->connection) + gb_connection_destroy(svc->connection); + ida_destroy(&svc->device_id_map); + destroy_workqueue(svc->wq); + kfree(svc); +} + +struct device_type greybus_svc_type = { + .name = "greybus_svc", + .release = gb_svc_release, +}; + +struct gb_svc *gb_svc_create(struct gb_host_device *hd) +{ + struct gb_svc *svc; + + svc = kzalloc(sizeof(*svc), GFP_KERNEL); + if (!svc) + return NULL; + + svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); + if (!svc->wq) { + kfree(svc); + return NULL; + } + + svc->dev.parent = &hd->dev; + svc->dev.bus = &greybus_bus_type; + svc->dev.type = &greybus_svc_type; + svc->dev.groups = svc_groups; + svc->dev.dma_mask = svc->dev.parent->dma_mask; + device_initialize(&svc->dev); + + dev_set_name(&svc->dev, "%d-svc", hd->bus_id); + + ida_init(&svc->device_id_map); + svc->state = GB_SVC_STATE_RESET; + svc->hd = hd; + + svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, + gb_svc_request_handler); + if (IS_ERR(svc->connection)) { + dev_err(&svc->dev, "failed to create connection: %ld\n", + PTR_ERR(svc->connection)); + goto err_put_device; + } + + gb_connection_set_data(svc->connection, svc); + + return svc; + +err_put_device: + put_device(&svc->dev); + return NULL; +} + +int gb_svc_add(struct gb_svc *svc) +{ + int ret; + + /* + * The SVC protocol is currently driven by the SVC, so the SVC device + * is added from the connection request handler when enough + * information has been received. + */ + ret = gb_connection_enable(svc->connection); + if (ret) + return ret; + + return 0; +} + +static void gb_svc_remove_modules(struct gb_svc *svc) +{ + struct gb_host_device *hd = svc->hd; + struct gb_module *module, *tmp; + + list_for_each_entry_safe(module, tmp, &hd->modules, hd_node) { + gb_module_del(module); + list_del(&module->hd_node); + gb_module_put(module); + } +} + +void gb_svc_del(struct gb_svc *svc) +{ + gb_connection_disable_rx(svc->connection); + + /* + * The SVC device may have been registered from the request handler. + */ + if (device_is_registered(&svc->dev)) { + gb_svc_debugfs_exit(svc); + gb_svc_watchdog_destroy(svc); + device_del(&svc->dev); + } + + flush_workqueue(svc->wq); + + gb_svc_remove_modules(svc); + + gb_connection_disable(svc->connection); +} + +void gb_svc_put(struct gb_svc *svc) +{ + put_device(&svc->dev); +} diff --git a/drivers/greybus/svc_watchdog.c b/drivers/greybus/svc_watchdog.c new file mode 100644 index 000000000000..b6b1682c19c4 --- /dev/null +++ b/drivers/greybus/svc_watchdog.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SVC Greybus "watchdog" driver. + * + * Copyright 2016 Google Inc. + */ + +#include +#include +#include +#include + +#define SVC_WATCHDOG_PERIOD (2 * HZ) + +struct gb_svc_watchdog { + struct delayed_work work; + struct gb_svc *svc; + bool enabled; + struct notifier_block pm_notifier; +}; + +static struct delayed_work reset_work; + +static int svc_watchdog_pm_notifier(struct notifier_block *notifier, + unsigned long pm_event, void *unused) +{ + struct gb_svc_watchdog *watchdog = + container_of(notifier, struct gb_svc_watchdog, pm_notifier); + + switch (pm_event) { + case PM_SUSPEND_PREPARE: + gb_svc_watchdog_disable(watchdog->svc); + break; + case PM_POST_SUSPEND: + gb_svc_watchdog_enable(watchdog->svc); + break; + default: + break; + } + + return NOTIFY_DONE; +} + +static void greybus_reset(struct work_struct *work) +{ + static char const start_path[] = "/system/bin/start"; + static char *envp[] = { + "HOME=/", + "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", + NULL, + }; + static char *argv[] = { + (char *)start_path, + "unipro_reset", + NULL, + }; + + pr_err("svc_watchdog: calling \"%s %s\" to reset greybus network!\n", + argv[0], argv[1]); + call_usermodehelper(start_path, argv, envp, UMH_WAIT_EXEC); +} + +static void do_work(struct work_struct *work) +{ + struct gb_svc_watchdog *watchdog; + struct gb_svc *svc; + int retval; + + watchdog = container_of(work, struct gb_svc_watchdog, work.work); + svc = watchdog->svc; + + dev_dbg(&svc->dev, "%s: ping.\n", __func__); + retval = gb_svc_ping(svc); + if (retval) { + /* + * Something went really wrong, let's warn userspace and then + * pull the plug and reset the whole greybus network. + * We need to do this outside of this workqueue as we will be + * tearing down the svc device itself. So queue up + * yet-another-callback to do that. + */ + dev_err(&svc->dev, + "SVC ping has returned %d, something is wrong!!!\n", + retval); + + if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) { + panic("SVC is not responding\n"); + } else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) { + dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); + + INIT_DELAYED_WORK(&reset_work, greybus_reset); + schedule_delayed_work(&reset_work, HZ / 2); + + /* + * Disable ourselves, we don't want to trip again unless + * userspace wants us to. + */ + watchdog->enabled = false; + } + } + + /* resubmit our work to happen again, if we are still "alive" */ + if (watchdog->enabled) + schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); +} + +int gb_svc_watchdog_create(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + int retval; + + if (svc->watchdog) + return 0; + + watchdog = kmalloc(sizeof(*watchdog), GFP_KERNEL); + if (!watchdog) + return -ENOMEM; + + watchdog->enabled = false; + watchdog->svc = svc; + INIT_DELAYED_WORK(&watchdog->work, do_work); + svc->watchdog = watchdog; + + watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier; + retval = register_pm_notifier(&watchdog->pm_notifier); + if (retval) { + dev_err(&svc->dev, "error registering pm notifier(%d)\n", + retval); + goto svc_watchdog_create_err; + } + + retval = gb_svc_watchdog_enable(svc); + if (retval) { + dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval); + unregister_pm_notifier(&watchdog->pm_notifier); + goto svc_watchdog_create_err; + } + return retval; + +svc_watchdog_create_err: + svc->watchdog = NULL; + kfree(watchdog); + + return retval; +} + +void gb_svc_watchdog_destroy(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog = svc->watchdog; + + if (!watchdog) + return; + + unregister_pm_notifier(&watchdog->pm_notifier); + gb_svc_watchdog_disable(svc); + svc->watchdog = NULL; + kfree(watchdog); +} + +bool gb_svc_watchdog_enabled(struct gb_svc *svc) +{ + if (!svc || !svc->watchdog) + return false; + return svc->watchdog->enabled; +} + +int gb_svc_watchdog_enable(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (!svc->watchdog) + return -ENODEV; + + watchdog = svc->watchdog; + if (watchdog->enabled) + return 0; + + watchdog->enabled = true; + schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); + return 0; +} + +int gb_svc_watchdog_disable(struct gb_svc *svc) +{ + struct gb_svc_watchdog *watchdog; + + if (!svc->watchdog) + return -ENODEV; + + watchdog = svc->watchdog; + if (!watchdog->enabled) + return 0; + + watchdog->enabled = false; + cancel_delayed_work_sync(&watchdog->work); + return 0; +} diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index 4894c3514955..d03c37e1e6e8 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -1,20 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -menuconfig GREYBUS - tristate "Greybus support" - depends on SYSFS - ---help--- - This option enables the Greybus driver core. Greybus is an - hardware protocol that was designed to provide Unipro with a - sane application layer. It was originally designed for the - ARA project, a module phone system, but has shown up in other - phones, and can be tunneled over other busses in order to - control hardware devices. - - Say Y here to enable support for these types of drivers. - - To compile this code as a module, chose M here: the module - will be called greybus.ko - if GREYBUS config GREYBUS_ES2 diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index 2551ed16b742..d16853399c9a 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -1,24 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -# Greybus core -greybus-y := core.o \ - debugfs.o \ - hd.o \ - manifest.o \ - module.o \ - interface.o \ - bundle.o \ - connection.o \ - control.o \ - svc.o \ - svc_watchdog.o \ - operation.o - -obj-$(CONFIG_GREYBUS) += greybus.o - # needed for trace events ccflags-y += -I$(src) - # Greybus Host controller drivers gb-es2-y := es2.o diff --git a/drivers/staging/greybus/bundle.c b/drivers/staging/greybus/bundle.c deleted file mode 100644 index 84660729538b..000000000000 --- a/drivers/staging/greybus/bundle.c +++ /dev/null @@ -1,252 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus bundles - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#include -#include "greybus_trace.h" - -static ssize_t bundle_class_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - - return sprintf(buf, "0x%02x\n", bundle->class); -} -static DEVICE_ATTR_RO(bundle_class); - -static ssize_t bundle_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - - return sprintf(buf, "%u\n", bundle->id); -} -static DEVICE_ATTR_RO(bundle_id); - -static ssize_t state_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - - if (!bundle->state) - return sprintf(buf, "\n"); - - return sprintf(buf, "%s\n", bundle->state); -} - -static ssize_t state_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - - kfree(bundle->state); - bundle->state = kstrdup(buf, GFP_KERNEL); - if (!bundle->state) - return -ENOMEM; - - /* Tell userspace that the file contents changed */ - sysfs_notify(&bundle->dev.kobj, NULL, "state"); - - return size; -} -static DEVICE_ATTR_RW(state); - -static struct attribute *bundle_attrs[] = { - &dev_attr_bundle_class.attr, - &dev_attr_bundle_id.attr, - &dev_attr_state.attr, - NULL, -}; - -ATTRIBUTE_GROUPS(bundle); - -static struct gb_bundle *gb_bundle_find(struct gb_interface *intf, - u8 bundle_id) -{ - struct gb_bundle *bundle; - - list_for_each_entry(bundle, &intf->bundles, links) { - if (bundle->id == bundle_id) - return bundle; - } - - return NULL; -} - -static void gb_bundle_release(struct device *dev) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - - trace_gb_bundle_release(bundle); - - kfree(bundle->state); - kfree(bundle->cport_desc); - kfree(bundle); -} - -#ifdef CONFIG_PM -static void gb_bundle_disable_all_connections(struct gb_bundle *bundle) -{ - struct gb_connection *connection; - - list_for_each_entry(connection, &bundle->connections, bundle_links) - gb_connection_disable(connection); -} - -static void gb_bundle_enable_all_connections(struct gb_bundle *bundle) -{ - struct gb_connection *connection; - - list_for_each_entry(connection, &bundle->connections, bundle_links) - gb_connection_enable(connection); -} - -static int gb_bundle_suspend(struct device *dev) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - const struct dev_pm_ops *pm = dev->driver->pm; - int ret; - - if (pm && pm->runtime_suspend) { - ret = pm->runtime_suspend(&bundle->dev); - if (ret) - return ret; - } else { - gb_bundle_disable_all_connections(bundle); - } - - ret = gb_control_bundle_suspend(bundle->intf->control, bundle->id); - if (ret) { - if (pm && pm->runtime_resume) - ret = pm->runtime_resume(dev); - else - gb_bundle_enable_all_connections(bundle); - - return ret; - } - - return 0; -} - -static int gb_bundle_resume(struct device *dev) -{ - struct gb_bundle *bundle = to_gb_bundle(dev); - const struct dev_pm_ops *pm = dev->driver->pm; - int ret; - - ret = gb_control_bundle_resume(bundle->intf->control, bundle->id); - if (ret) - return ret; - - if (pm && pm->runtime_resume) { - ret = pm->runtime_resume(dev); - if (ret) - return ret; - } else { - gb_bundle_enable_all_connections(bundle); - } - - return 0; -} - -static int gb_bundle_idle(struct device *dev) -{ - pm_runtime_mark_last_busy(dev); - pm_request_autosuspend(dev); - - return 0; -} -#endif - -static const struct dev_pm_ops gb_bundle_pm_ops = { - SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle) -}; - -struct device_type greybus_bundle_type = { - .name = "greybus_bundle", - .release = gb_bundle_release, - .pm = &gb_bundle_pm_ops, -}; - -/* - * Create a gb_bundle structure to represent a discovered - * bundle. Returns a pointer to the new bundle or a null - * pointer if a failure occurs due to memory exhaustion. - */ -struct gb_bundle *gb_bundle_create(struct gb_interface *intf, u8 bundle_id, - u8 class) -{ - struct gb_bundle *bundle; - - if (bundle_id == BUNDLE_ID_NONE) { - dev_err(&intf->dev, "can't use bundle id %u\n", bundle_id); - return NULL; - } - - /* - * Reject any attempt to reuse a bundle id. We initialize - * these serially, so there's no need to worry about keeping - * the interface bundle list locked here. - */ - if (gb_bundle_find(intf, bundle_id)) { - dev_err(&intf->dev, "duplicate bundle id %u\n", bundle_id); - return NULL; - } - - bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); - if (!bundle) - return NULL; - - bundle->intf = intf; - bundle->id = bundle_id; - bundle->class = class; - INIT_LIST_HEAD(&bundle->connections); - - bundle->dev.parent = &intf->dev; - bundle->dev.bus = &greybus_bus_type; - bundle->dev.type = &greybus_bundle_type; - bundle->dev.groups = bundle_groups; - bundle->dev.dma_mask = intf->dev.dma_mask; - device_initialize(&bundle->dev); - dev_set_name(&bundle->dev, "%s.%d", dev_name(&intf->dev), bundle_id); - - list_add(&bundle->links, &intf->bundles); - - trace_gb_bundle_create(bundle); - - return bundle; -} - -int gb_bundle_add(struct gb_bundle *bundle) -{ - int ret; - - ret = device_add(&bundle->dev); - if (ret) { - dev_err(&bundle->dev, "failed to register bundle: %d\n", ret); - return ret; - } - - trace_gb_bundle_add(bundle); - - return 0; -} - -/* - * Tear down a previously set up bundle. - */ -void gb_bundle_destroy(struct gb_bundle *bundle) -{ - trace_gb_bundle_destroy(bundle); - - if (device_is_registered(&bundle->dev)) - device_del(&bundle->dev); - - list_del(&bundle->links); - - put_device(&bundle->dev); -} diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c deleted file mode 100644 index fc8f57f97ce6..000000000000 --- a/drivers/staging/greybus/connection.c +++ /dev/null @@ -1,942 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus connections - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#include -#include - -#include "greybus_trace.h" - -#define GB_CONNECTION_CPORT_QUIESCE_TIMEOUT 1000 - -static void gb_connection_kref_release(struct kref *kref); - -static DEFINE_SPINLOCK(gb_connections_lock); -static DEFINE_MUTEX(gb_connection_mutex); - -/* Caller holds gb_connection_mutex. */ -static bool gb_connection_cport_in_use(struct gb_interface *intf, u16 cport_id) -{ - struct gb_host_device *hd = intf->hd; - struct gb_connection *connection; - - list_for_each_entry(connection, &hd->connections, hd_links) { - if (connection->intf == intf && - connection->intf_cport_id == cport_id) - return true; - } - - return false; -} - -static void gb_connection_get(struct gb_connection *connection) -{ - kref_get(&connection->kref); - - trace_gb_connection_get(connection); -} - -static void gb_connection_put(struct gb_connection *connection) -{ - trace_gb_connection_put(connection); - - kref_put(&connection->kref, gb_connection_kref_release); -} - -/* - * Returns a reference-counted pointer to the connection if found. - */ -static struct gb_connection * -gb_connection_hd_find(struct gb_host_device *hd, u16 cport_id) -{ - struct gb_connection *connection; - unsigned long flags; - - spin_lock_irqsave(&gb_connections_lock, flags); - list_for_each_entry(connection, &hd->connections, hd_links) - if (connection->hd_cport_id == cport_id) { - gb_connection_get(connection); - goto found; - } - connection = NULL; -found: - spin_unlock_irqrestore(&gb_connections_lock, flags); - - return connection; -} - -/* - * Callback from the host driver to let us know that data has been - * received on the bundle. - */ -void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, - u8 *data, size_t length) -{ - struct gb_connection *connection; - - trace_gb_hd_in(hd); - - connection = gb_connection_hd_find(hd, cport_id); - if (!connection) { - dev_err(&hd->dev, - "nonexistent connection (%zu bytes dropped)\n", length); - return; - } - gb_connection_recv(connection, data, length); - gb_connection_put(connection); -} -EXPORT_SYMBOL_GPL(greybus_data_rcvd); - -static void gb_connection_kref_release(struct kref *kref) -{ - struct gb_connection *connection; - - connection = container_of(kref, struct gb_connection, kref); - - trace_gb_connection_release(connection); - - kfree(connection); -} - -static void gb_connection_init_name(struct gb_connection *connection) -{ - u16 hd_cport_id = connection->hd_cport_id; - u16 cport_id = 0; - u8 intf_id = 0; - - if (connection->intf) { - intf_id = connection->intf->interface_id; - cport_id = connection->intf_cport_id; - } - - snprintf(connection->name, sizeof(connection->name), - "%u/%u:%u", hd_cport_id, intf_id, cport_id); -} - -/* - * _gb_connection_create() - create a Greybus connection - * @hd: host device of the connection - * @hd_cport_id: host-device cport id, or -1 for dynamic allocation - * @intf: remote interface, or NULL for static connections - * @bundle: remote-interface bundle (may be NULL) - * @cport_id: remote-interface cport id, or 0 for static connections - * @handler: request handler (may be NULL) - * @flags: connection flags - * - * Create a Greybus connection, representing the bidirectional link - * between a CPort on a (local) Greybus host device and a CPort on - * another Greybus interface. - * - * A connection also maintains the state of operations sent over the - * connection. - * - * Serialised against concurrent create and destroy using the - * gb_connection_mutex. - * - * Return: A pointer to the new connection if successful, or an ERR_PTR - * otherwise. - */ -static struct gb_connection * -_gb_connection_create(struct gb_host_device *hd, int hd_cport_id, - struct gb_interface *intf, - struct gb_bundle *bundle, int cport_id, - gb_request_handler_t handler, - unsigned long flags) -{ - struct gb_connection *connection; - int ret; - - mutex_lock(&gb_connection_mutex); - - if (intf && gb_connection_cport_in_use(intf, cport_id)) { - dev_err(&intf->dev, "cport %u already in use\n", cport_id); - ret = -EBUSY; - goto err_unlock; - } - - ret = gb_hd_cport_allocate(hd, hd_cport_id, flags); - if (ret < 0) { - dev_err(&hd->dev, "failed to allocate cport: %d\n", ret); - goto err_unlock; - } - hd_cport_id = ret; - - connection = kzalloc(sizeof(*connection), GFP_KERNEL); - if (!connection) { - ret = -ENOMEM; - goto err_hd_cport_release; - } - - connection->hd_cport_id = hd_cport_id; - connection->intf_cport_id = cport_id; - connection->hd = hd; - connection->intf = intf; - connection->bundle = bundle; - connection->handler = handler; - connection->flags = flags; - if (intf && (intf->quirks & GB_INTERFACE_QUIRK_NO_CPORT_FEATURES)) - connection->flags |= GB_CONNECTION_FLAG_NO_FLOWCTRL; - connection->state = GB_CONNECTION_STATE_DISABLED; - - atomic_set(&connection->op_cycle, 0); - mutex_init(&connection->mutex); - spin_lock_init(&connection->lock); - INIT_LIST_HEAD(&connection->operations); - - connection->wq = alloc_workqueue("%s:%d", WQ_UNBOUND, 1, - dev_name(&hd->dev), hd_cport_id); - if (!connection->wq) { - ret = -ENOMEM; - goto err_free_connection; - } - - kref_init(&connection->kref); - - gb_connection_init_name(connection); - - spin_lock_irq(&gb_connections_lock); - list_add(&connection->hd_links, &hd->connections); - - if (bundle) - list_add(&connection->bundle_links, &bundle->connections); - else - INIT_LIST_HEAD(&connection->bundle_links); - - spin_unlock_irq(&gb_connections_lock); - - mutex_unlock(&gb_connection_mutex); - - trace_gb_connection_create(connection); - - return connection; - -err_free_connection: - kfree(connection); -err_hd_cport_release: - gb_hd_cport_release(hd, hd_cport_id); -err_unlock: - mutex_unlock(&gb_connection_mutex); - - return ERR_PTR(ret); -} - -struct gb_connection * -gb_connection_create_static(struct gb_host_device *hd, u16 hd_cport_id, - gb_request_handler_t handler) -{ - return _gb_connection_create(hd, hd_cport_id, NULL, NULL, 0, handler, - GB_CONNECTION_FLAG_HIGH_PRIO); -} - -struct gb_connection * -gb_connection_create_control(struct gb_interface *intf) -{ - return _gb_connection_create(intf->hd, -1, intf, NULL, 0, NULL, - GB_CONNECTION_FLAG_CONTROL | - GB_CONNECTION_FLAG_HIGH_PRIO); -} - -struct gb_connection * -gb_connection_create(struct gb_bundle *bundle, u16 cport_id, - gb_request_handler_t handler) -{ - struct gb_interface *intf = bundle->intf; - - return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, - handler, 0); -} -EXPORT_SYMBOL_GPL(gb_connection_create); - -struct gb_connection * -gb_connection_create_flags(struct gb_bundle *bundle, u16 cport_id, - gb_request_handler_t handler, - unsigned long flags) -{ - struct gb_interface *intf = bundle->intf; - - if (WARN_ON_ONCE(flags & GB_CONNECTION_FLAG_CORE_MASK)) - flags &= ~GB_CONNECTION_FLAG_CORE_MASK; - - return _gb_connection_create(intf->hd, -1, intf, bundle, cport_id, - handler, flags); -} -EXPORT_SYMBOL_GPL(gb_connection_create_flags); - -struct gb_connection * -gb_connection_create_offloaded(struct gb_bundle *bundle, u16 cport_id, - unsigned long flags) -{ - flags |= GB_CONNECTION_FLAG_OFFLOADED; - - return gb_connection_create_flags(bundle, cport_id, NULL, flags); -} -EXPORT_SYMBOL_GPL(gb_connection_create_offloaded); - -static int gb_connection_hd_cport_enable(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->cport_enable) - return 0; - - ret = hd->driver->cport_enable(hd, connection->hd_cport_id, - connection->flags); - if (ret) { - dev_err(&hd->dev, "%s: failed to enable host cport: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -static void gb_connection_hd_cport_disable(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->cport_disable) - return; - - ret = hd->driver->cport_disable(hd, connection->hd_cport_id); - if (ret) { - dev_err(&hd->dev, "%s: failed to disable host cport: %d\n", - connection->name, ret); - } -} - -static int gb_connection_hd_cport_connected(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->cport_connected) - return 0; - - ret = hd->driver->cport_connected(hd, connection->hd_cport_id); - if (ret) { - dev_err(&hd->dev, "%s: failed to set connected state: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -static int gb_connection_hd_cport_flush(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->cport_flush) - return 0; - - ret = hd->driver->cport_flush(hd, connection->hd_cport_id); - if (ret) { - dev_err(&hd->dev, "%s: failed to flush host cport: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -static int gb_connection_hd_cport_quiesce(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - size_t peer_space; - int ret; - - if (!hd->driver->cport_quiesce) - return 0; - - peer_space = sizeof(struct gb_operation_msg_hdr) + - sizeof(struct gb_cport_shutdown_request); - - if (connection->mode_switch) - peer_space += sizeof(struct gb_operation_msg_hdr); - - if (!hd->driver->cport_quiesce) - return 0; - - ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id, - peer_space, - GB_CONNECTION_CPORT_QUIESCE_TIMEOUT); - if (ret) { - dev_err(&hd->dev, "%s: failed to quiesce host cport: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -static int gb_connection_hd_cport_clear(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->cport_clear) - return 0; - - ret = hd->driver->cport_clear(hd, connection->hd_cport_id); - if (ret) { - dev_err(&hd->dev, "%s: failed to clear host cport: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -/* - * Request the SVC to create a connection from AP's cport to interface's - * cport. - */ -static int -gb_connection_svc_connection_create(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - struct gb_interface *intf; - u8 cport_flags; - int ret; - - if (gb_connection_is_static(connection)) - return 0; - - intf = connection->intf; - - /* - * Enable either E2EFC or CSD, unless no flow control is requested. - */ - cport_flags = GB_SVC_CPORT_FLAG_CSV_N; - if (gb_connection_flow_control_disabled(connection)) { - cport_flags |= GB_SVC_CPORT_FLAG_CSD_N; - } else if (gb_connection_e2efc_enabled(connection)) { - cport_flags |= GB_SVC_CPORT_FLAG_CSD_N | - GB_SVC_CPORT_FLAG_E2EFC; - } - - ret = gb_svc_connection_create(hd->svc, - hd->svc->ap_intf_id, - connection->hd_cport_id, - intf->interface_id, - connection->intf_cport_id, - cport_flags); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to create svc connection: %d\n", - connection->name, ret); - return ret; - } - - return 0; -} - -static void -gb_connection_svc_connection_destroy(struct gb_connection *connection) -{ - if (gb_connection_is_static(connection)) - return; - - gb_svc_connection_destroy(connection->hd->svc, - connection->hd->svc->ap_intf_id, - connection->hd_cport_id, - connection->intf->interface_id, - connection->intf_cport_id); -} - -/* Inform Interface about active CPorts */ -static int gb_connection_control_connected(struct gb_connection *connection) -{ - struct gb_control *control; - u16 cport_id = connection->intf_cport_id; - int ret; - - if (gb_connection_is_static(connection)) - return 0; - - if (gb_connection_is_control(connection)) - return 0; - - control = connection->intf->control; - - ret = gb_control_connected_operation(control, cport_id); - if (ret) { - dev_err(&connection->bundle->dev, - "failed to connect cport: %d\n", ret); - return ret; - } - - return 0; -} - -static void -gb_connection_control_disconnecting(struct gb_connection *connection) -{ - struct gb_control *control; - u16 cport_id = connection->intf_cport_id; - int ret; - - if (gb_connection_is_static(connection)) - return; - - control = connection->intf->control; - - ret = gb_control_disconnecting_operation(control, cport_id); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to send disconnecting: %d\n", - connection->name, ret); - } -} - -static void -gb_connection_control_disconnected(struct gb_connection *connection) -{ - struct gb_control *control; - u16 cport_id = connection->intf_cport_id; - int ret; - - if (gb_connection_is_static(connection)) - return; - - control = connection->intf->control; - - if (gb_connection_is_control(connection)) { - if (connection->mode_switch) { - ret = gb_control_mode_switch_operation(control); - if (ret) { - /* - * Allow mode switch to time out waiting for - * mailbox event. - */ - return; - } - } - - return; - } - - ret = gb_control_disconnected_operation(control, cport_id); - if (ret) { - dev_warn(&connection->bundle->dev, - "failed to disconnect cport: %d\n", ret); - } -} - -static int gb_connection_shutdown_operation(struct gb_connection *connection, - u8 phase) -{ - struct gb_cport_shutdown_request *req; - struct gb_operation *operation; - int ret; - - operation = gb_operation_create_core(connection, - GB_REQUEST_TYPE_CPORT_SHUTDOWN, - sizeof(*req), 0, 0, - GFP_KERNEL); - if (!operation) - return -ENOMEM; - - req = operation->request->payload; - req->phase = phase; - - ret = gb_operation_request_send_sync(operation); - - gb_operation_put(operation); - - return ret; -} - -static int gb_connection_cport_shutdown(struct gb_connection *connection, - u8 phase) -{ - struct gb_host_device *hd = connection->hd; - const struct gb_hd_driver *drv = hd->driver; - int ret; - - if (gb_connection_is_static(connection)) - return 0; - - if (gb_connection_is_offloaded(connection)) { - if (!drv->cport_shutdown) - return 0; - - ret = drv->cport_shutdown(hd, connection->hd_cport_id, phase, - GB_OPERATION_TIMEOUT_DEFAULT); - } else { - ret = gb_connection_shutdown_operation(connection, phase); - } - - if (ret) { - dev_err(&hd->dev, "%s: failed to send cport shutdown (phase %d): %d\n", - connection->name, phase, ret); - return ret; - } - - return 0; -} - -static int -gb_connection_cport_shutdown_phase_1(struct gb_connection *connection) -{ - return gb_connection_cport_shutdown(connection, 1); -} - -static int -gb_connection_cport_shutdown_phase_2(struct gb_connection *connection) -{ - return gb_connection_cport_shutdown(connection, 2); -} - -/* - * Cancel all active operations on a connection. - * - * Locking: Called with connection lock held and state set to DISABLED or - * DISCONNECTING. - */ -static void gb_connection_cancel_operations(struct gb_connection *connection, - int errno) - __must_hold(&connection->lock) -{ - struct gb_operation *operation; - - while (!list_empty(&connection->operations)) { - operation = list_last_entry(&connection->operations, - struct gb_operation, links); - gb_operation_get(operation); - spin_unlock_irq(&connection->lock); - - if (gb_operation_is_incoming(operation)) - gb_operation_cancel_incoming(operation, errno); - else - gb_operation_cancel(operation, errno); - - gb_operation_put(operation); - - spin_lock_irq(&connection->lock); - } -} - -/* - * Cancel all active incoming operations on a connection. - * - * Locking: Called with connection lock held and state set to ENABLED_TX. - */ -static void -gb_connection_flush_incoming_operations(struct gb_connection *connection, - int errno) - __must_hold(&connection->lock) -{ - struct gb_operation *operation; - bool incoming; - - while (!list_empty(&connection->operations)) { - incoming = false; - list_for_each_entry(operation, &connection->operations, - links) { - if (gb_operation_is_incoming(operation)) { - gb_operation_get(operation); - incoming = true; - break; - } - } - - if (!incoming) - break; - - spin_unlock_irq(&connection->lock); - - /* FIXME: flush, not cancel? */ - gb_operation_cancel_incoming(operation, errno); - gb_operation_put(operation); - - spin_lock_irq(&connection->lock); - } -} - -/* - * _gb_connection_enable() - enable a connection - * @connection: connection to enable - * @rx: whether to enable incoming requests - * - * Connection-enable helper for DISABLED->ENABLED, DISABLED->ENABLED_TX, and - * ENABLED_TX->ENABLED state transitions. - * - * Locking: Caller holds connection->mutex. - */ -static int _gb_connection_enable(struct gb_connection *connection, bool rx) -{ - int ret; - - /* Handle ENABLED_TX -> ENABLED transitions. */ - if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) { - if (!(connection->handler && rx)) - return 0; - - spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_ENABLED; - spin_unlock_irq(&connection->lock); - - return 0; - } - - ret = gb_connection_hd_cport_enable(connection); - if (ret) - return ret; - - ret = gb_connection_svc_connection_create(connection); - if (ret) - goto err_hd_cport_clear; - - ret = gb_connection_hd_cport_connected(connection); - if (ret) - goto err_svc_connection_destroy; - - spin_lock_irq(&connection->lock); - if (connection->handler && rx) - connection->state = GB_CONNECTION_STATE_ENABLED; - else - connection->state = GB_CONNECTION_STATE_ENABLED_TX; - spin_unlock_irq(&connection->lock); - - ret = gb_connection_control_connected(connection); - if (ret) - goto err_control_disconnecting; - - return 0; - -err_control_disconnecting: - spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); - - /* Transmit queue should already be empty. */ - gb_connection_hd_cport_flush(connection); - - gb_connection_control_disconnecting(connection); - gb_connection_cport_shutdown_phase_1(connection); - gb_connection_hd_cport_quiesce(connection); - gb_connection_cport_shutdown_phase_2(connection); - gb_connection_control_disconnected(connection); - connection->state = GB_CONNECTION_STATE_DISABLED; -err_svc_connection_destroy: - gb_connection_svc_connection_destroy(connection); -err_hd_cport_clear: - gb_connection_hd_cport_clear(connection); - - gb_connection_hd_cport_disable(connection); - - return ret; -} - -int gb_connection_enable(struct gb_connection *connection) -{ - int ret = 0; - - mutex_lock(&connection->mutex); - - if (connection->state == GB_CONNECTION_STATE_ENABLED) - goto out_unlock; - - ret = _gb_connection_enable(connection, true); - if (!ret) - trace_gb_connection_enable(connection); - -out_unlock: - mutex_unlock(&connection->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_connection_enable); - -int gb_connection_enable_tx(struct gb_connection *connection) -{ - int ret = 0; - - mutex_lock(&connection->mutex); - - if (connection->state == GB_CONNECTION_STATE_ENABLED) { - ret = -EINVAL; - goto out_unlock; - } - - if (connection->state == GB_CONNECTION_STATE_ENABLED_TX) - goto out_unlock; - - ret = _gb_connection_enable(connection, false); - if (!ret) - trace_gb_connection_enable(connection); - -out_unlock: - mutex_unlock(&connection->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_connection_enable_tx); - -void gb_connection_disable_rx(struct gb_connection *connection) -{ - mutex_lock(&connection->mutex); - - spin_lock_irq(&connection->lock); - if (connection->state != GB_CONNECTION_STATE_ENABLED) { - spin_unlock_irq(&connection->lock); - goto out_unlock; - } - connection->state = GB_CONNECTION_STATE_ENABLED_TX; - gb_connection_flush_incoming_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); - - trace_gb_connection_disable(connection); - -out_unlock: - mutex_unlock(&connection->mutex); -} -EXPORT_SYMBOL_GPL(gb_connection_disable_rx); - -void gb_connection_mode_switch_prepare(struct gb_connection *connection) -{ - connection->mode_switch = true; -} - -void gb_connection_mode_switch_complete(struct gb_connection *connection) -{ - gb_connection_svc_connection_destroy(connection); - gb_connection_hd_cport_clear(connection); - - gb_connection_hd_cport_disable(connection); - - connection->mode_switch = false; -} - -void gb_connection_disable(struct gb_connection *connection) -{ - mutex_lock(&connection->mutex); - - if (connection->state == GB_CONNECTION_STATE_DISABLED) - goto out_unlock; - - trace_gb_connection_disable(connection); - - spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_DISCONNECTING; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); - - gb_connection_hd_cport_flush(connection); - - gb_connection_control_disconnecting(connection); - gb_connection_cport_shutdown_phase_1(connection); - gb_connection_hd_cport_quiesce(connection); - gb_connection_cport_shutdown_phase_2(connection); - gb_connection_control_disconnected(connection); - - connection->state = GB_CONNECTION_STATE_DISABLED; - - /* control-connection tear down is deferred when mode switching */ - if (!connection->mode_switch) { - gb_connection_svc_connection_destroy(connection); - gb_connection_hd_cport_clear(connection); - - gb_connection_hd_cport_disable(connection); - } - -out_unlock: - mutex_unlock(&connection->mutex); -} -EXPORT_SYMBOL_GPL(gb_connection_disable); - -/* Disable a connection without communicating with the remote end. */ -void gb_connection_disable_forced(struct gb_connection *connection) -{ - mutex_lock(&connection->mutex); - - if (connection->state == GB_CONNECTION_STATE_DISABLED) - goto out_unlock; - - trace_gb_connection_disable(connection); - - spin_lock_irq(&connection->lock); - connection->state = GB_CONNECTION_STATE_DISABLED; - gb_connection_cancel_operations(connection, -ESHUTDOWN); - spin_unlock_irq(&connection->lock); - - gb_connection_hd_cport_flush(connection); - - gb_connection_svc_connection_destroy(connection); - gb_connection_hd_cport_clear(connection); - - gb_connection_hd_cport_disable(connection); -out_unlock: - mutex_unlock(&connection->mutex); -} -EXPORT_SYMBOL_GPL(gb_connection_disable_forced); - -/* Caller must have disabled the connection before destroying it. */ -void gb_connection_destroy(struct gb_connection *connection) -{ - if (!connection) - return; - - if (WARN_ON(connection->state != GB_CONNECTION_STATE_DISABLED)) - gb_connection_disable(connection); - - mutex_lock(&gb_connection_mutex); - - spin_lock_irq(&gb_connections_lock); - list_del(&connection->bundle_links); - list_del(&connection->hd_links); - spin_unlock_irq(&gb_connections_lock); - - destroy_workqueue(connection->wq); - - gb_hd_cport_release(connection->hd, connection->hd_cport_id); - connection->hd_cport_id = CPORT_ID_BAD; - - mutex_unlock(&gb_connection_mutex); - - gb_connection_put(connection); -} -EXPORT_SYMBOL_GPL(gb_connection_destroy); - -void gb_connection_latency_tag_enable(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->latency_tag_enable) - return; - - ret = hd->driver->latency_tag_enable(hd, connection->hd_cport_id); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to enable latency tag: %d\n", - connection->name, ret); - } -} -EXPORT_SYMBOL_GPL(gb_connection_latency_tag_enable); - -void gb_connection_latency_tag_disable(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - int ret; - - if (!hd->driver->latency_tag_disable) - return; - - ret = hd->driver->latency_tag_disable(hd, connection->hd_cport_id); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to disable latency tag: %d\n", - connection->name, ret); - } -} -EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c deleted file mode 100644 index 359a25841973..000000000000 --- a/drivers/staging/greybus/control.c +++ /dev/null @@ -1,584 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus CPort control protocol. - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - */ - -#include -#include -#include -#include - -/* Highest control-protocol version supported */ -#define GB_CONTROL_VERSION_MAJOR 0 -#define GB_CONTROL_VERSION_MINOR 1 - -static int gb_control_get_version(struct gb_control *control) -{ - struct gb_interface *intf = control->connection->intf; - struct gb_control_version_request request; - struct gb_control_version_response response; - int ret; - - request.major = GB_CONTROL_VERSION_MAJOR; - request.minor = GB_CONTROL_VERSION_MINOR; - - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_VERSION, - &request, sizeof(request), &response, - sizeof(response)); - if (ret) { - dev_err(&intf->dev, - "failed to get control-protocol version: %d\n", - ret); - return ret; - } - - if (response.major > request.major) { - dev_err(&intf->dev, - "unsupported major control-protocol version (%u > %u)\n", - response.major, request.major); - return -ENOTSUPP; - } - - control->protocol_major = response.major; - control->protocol_minor = response.minor; - - dev_dbg(&intf->dev, "%s - %u.%u\n", __func__, response.major, - response.minor); - - return 0; -} - -static int gb_control_get_bundle_version(struct gb_control *control, - struct gb_bundle *bundle) -{ - struct gb_interface *intf = control->connection->intf; - struct gb_control_bundle_version_request request; - struct gb_control_bundle_version_response response; - int ret; - - request.bundle_id = bundle->id; - - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_BUNDLE_VERSION, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) { - dev_err(&intf->dev, - "failed to get bundle %u class version: %d\n", - bundle->id, ret); - return ret; - } - - bundle->class_major = response.major; - bundle->class_minor = response.minor; - - dev_dbg(&intf->dev, "%s - %u: %u.%u\n", __func__, bundle->id, - response.major, response.minor); - - return 0; -} - -int gb_control_get_bundle_versions(struct gb_control *control) -{ - struct gb_interface *intf = control->connection->intf; - struct gb_bundle *bundle; - int ret; - - if (!control->has_bundle_version) - return 0; - - list_for_each_entry(bundle, &intf->bundles, links) { - ret = gb_control_get_bundle_version(control, bundle); - if (ret) - return ret; - } - - return 0; -} - -/* Get Manifest's size from the interface */ -int gb_control_get_manifest_size_operation(struct gb_interface *intf) -{ - struct gb_control_get_manifest_size_response response; - struct gb_connection *connection = intf->control->connection; - int ret; - - ret = gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST_SIZE, - NULL, 0, &response, sizeof(response)); - if (ret) { - dev_err(&connection->intf->dev, - "failed to get manifest size: %d\n", ret); - return ret; - } - - return le16_to_cpu(response.size); -} - -/* Reads Manifest from the interface */ -int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, - size_t size) -{ - struct gb_connection *connection = intf->control->connection; - - return gb_operation_sync(connection, GB_CONTROL_TYPE_GET_MANIFEST, - NULL, 0, manifest, size); -} - -int gb_control_connected_operation(struct gb_control *control, u16 cport_id) -{ - struct gb_control_connected_request request; - - request.cport_id = cpu_to_le16(cport_id); - return gb_operation_sync(control->connection, GB_CONTROL_TYPE_CONNECTED, - &request, sizeof(request), NULL, 0); -} - -int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) -{ - struct gb_control_disconnected_request request; - - request.cport_id = cpu_to_le16(cport_id); - return gb_operation_sync(control->connection, - GB_CONTROL_TYPE_DISCONNECTED, &request, - sizeof(request), NULL, 0); -} - -int gb_control_disconnecting_operation(struct gb_control *control, - u16 cport_id) -{ - struct gb_control_disconnecting_request *request; - struct gb_operation *operation; - int ret; - - operation = gb_operation_create_core(control->connection, - GB_CONTROL_TYPE_DISCONNECTING, - sizeof(*request), 0, 0, - GFP_KERNEL); - if (!operation) - return -ENOMEM; - - request = operation->request->payload; - request->cport_id = cpu_to_le16(cport_id); - - ret = gb_operation_request_send_sync(operation); - if (ret) { - dev_err(&control->dev, "failed to send disconnecting: %d\n", - ret); - } - - gb_operation_put(operation); - - return ret; -} - -int gb_control_mode_switch_operation(struct gb_control *control) -{ - struct gb_operation *operation; - int ret; - - operation = gb_operation_create_core(control->connection, - GB_CONTROL_TYPE_MODE_SWITCH, - 0, 0, - GB_OPERATION_FLAG_UNIDIRECTIONAL, - GFP_KERNEL); - if (!operation) - return -ENOMEM; - - ret = gb_operation_request_send_sync(operation); - if (ret) - dev_err(&control->dev, "failed to send mode switch: %d\n", ret); - - gb_operation_put(operation); - - return ret; -} - -static int gb_control_bundle_pm_status_map(u8 status) -{ - switch (status) { - case GB_CONTROL_BUNDLE_PM_INVAL: - return -EINVAL; - case GB_CONTROL_BUNDLE_PM_BUSY: - return -EBUSY; - case GB_CONTROL_BUNDLE_PM_NA: - return -ENOMSG; - case GB_CONTROL_BUNDLE_PM_FAIL: - default: - return -EREMOTEIO; - } -} - -int gb_control_bundle_suspend(struct gb_control *control, u8 bundle_id) -{ - struct gb_control_bundle_pm_request request; - struct gb_control_bundle_pm_response response; - int ret; - - request.bundle_id = bundle_id; - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_BUNDLE_SUSPEND, &request, - sizeof(request), &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, "failed to send bundle %u suspend: %d\n", - bundle_id, ret); - return ret; - } - - if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, "failed to suspend bundle %u: %d\n", - bundle_id, response.status); - return gb_control_bundle_pm_status_map(response.status); - } - - return 0; -} - -int gb_control_bundle_resume(struct gb_control *control, u8 bundle_id) -{ - struct gb_control_bundle_pm_request request; - struct gb_control_bundle_pm_response response; - int ret; - - request.bundle_id = bundle_id; - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_BUNDLE_RESUME, &request, - sizeof(request), &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, "failed to send bundle %u resume: %d\n", - bundle_id, ret); - return ret; - } - - if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, "failed to resume bundle %u: %d\n", - bundle_id, response.status); - return gb_control_bundle_pm_status_map(response.status); - } - - return 0; -} - -int gb_control_bundle_deactivate(struct gb_control *control, u8 bundle_id) -{ - struct gb_control_bundle_pm_request request; - struct gb_control_bundle_pm_response response; - int ret; - - request.bundle_id = bundle_id; - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_BUNDLE_DEACTIVATE, &request, - sizeof(request), &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, - "failed to send bundle %u deactivate: %d\n", bundle_id, - ret); - return ret; - } - - if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, "failed to deactivate bundle %u: %d\n", - bundle_id, response.status); - return gb_control_bundle_pm_status_map(response.status); - } - - return 0; -} - -int gb_control_bundle_activate(struct gb_control *control, u8 bundle_id) -{ - struct gb_control_bundle_pm_request request; - struct gb_control_bundle_pm_response response; - int ret; - - if (!control->has_bundle_activate) - return 0; - - request.bundle_id = bundle_id; - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_BUNDLE_ACTIVATE, &request, - sizeof(request), &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, - "failed to send bundle %u activate: %d\n", bundle_id, - ret); - return ret; - } - - if (response.status != GB_CONTROL_BUNDLE_PM_OK) { - dev_err(&control->dev, "failed to activate bundle %u: %d\n", - bundle_id, response.status); - return gb_control_bundle_pm_status_map(response.status); - } - - return 0; -} - -static int gb_control_interface_pm_status_map(u8 status) -{ - switch (status) { - case GB_CONTROL_INTF_PM_BUSY: - return -EBUSY; - case GB_CONTROL_INTF_PM_NA: - return -ENOMSG; - default: - return -EREMOTEIO; - } -} - -int gb_control_interface_suspend_prepare(struct gb_control *control) -{ - struct gb_control_intf_pm_response response; - int ret; - - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_INTF_SUSPEND_PREPARE, NULL, 0, - &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, - "failed to send interface suspend prepare: %d\n", ret); - return ret; - } - - if (response.status != GB_CONTROL_INTF_PM_OK) { - dev_err(&control->dev, "interface error while preparing suspend: %d\n", - response.status); - return gb_control_interface_pm_status_map(response.status); - } - - return 0; -} - -int gb_control_interface_deactivate_prepare(struct gb_control *control) -{ - struct gb_control_intf_pm_response response; - int ret; - - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_INTF_DEACTIVATE_PREPARE, NULL, - 0, &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, "failed to send interface deactivate prepare: %d\n", - ret); - return ret; - } - - if (response.status != GB_CONTROL_INTF_PM_OK) { - dev_err(&control->dev, "interface error while preparing deactivate: %d\n", - response.status); - return gb_control_interface_pm_status_map(response.status); - } - - return 0; -} - -int gb_control_interface_hibernate_abort(struct gb_control *control) -{ - struct gb_control_intf_pm_response response; - int ret; - - ret = gb_operation_sync(control->connection, - GB_CONTROL_TYPE_INTF_HIBERNATE_ABORT, NULL, 0, - &response, sizeof(response)); - if (ret) { - dev_err(&control->dev, - "failed to send interface aborting hibernate: %d\n", - ret); - return ret; - } - - if (response.status != GB_CONTROL_INTF_PM_OK) { - dev_err(&control->dev, "interface error while aborting hibernate: %d\n", - response.status); - return gb_control_interface_pm_status_map(response.status); - } - - return 0; -} - -static ssize_t vendor_string_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_control *control = to_gb_control(dev); - - return scnprintf(buf, PAGE_SIZE, "%s\n", control->vendor_string); -} -static DEVICE_ATTR_RO(vendor_string); - -static ssize_t product_string_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_control *control = to_gb_control(dev); - - return scnprintf(buf, PAGE_SIZE, "%s\n", control->product_string); -} -static DEVICE_ATTR_RO(product_string); - -static struct attribute *control_attrs[] = { - &dev_attr_vendor_string.attr, - &dev_attr_product_string.attr, - NULL, -}; -ATTRIBUTE_GROUPS(control); - -static void gb_control_release(struct device *dev) -{ - struct gb_control *control = to_gb_control(dev); - - gb_connection_destroy(control->connection); - - kfree(control->vendor_string); - kfree(control->product_string); - - kfree(control); -} - -struct device_type greybus_control_type = { - .name = "greybus_control", - .release = gb_control_release, -}; - -struct gb_control *gb_control_create(struct gb_interface *intf) -{ - struct gb_connection *connection; - struct gb_control *control; - - control = kzalloc(sizeof(*control), GFP_KERNEL); - if (!control) - return ERR_PTR(-ENOMEM); - - control->intf = intf; - - connection = gb_connection_create_control(intf); - if (IS_ERR(connection)) { - dev_err(&intf->dev, - "failed to create control connection: %ld\n", - PTR_ERR(connection)); - kfree(control); - return ERR_CAST(connection); - } - - control->connection = connection; - - control->dev.parent = &intf->dev; - control->dev.bus = &greybus_bus_type; - control->dev.type = &greybus_control_type; - control->dev.groups = control_groups; - control->dev.dma_mask = intf->dev.dma_mask; - device_initialize(&control->dev); - dev_set_name(&control->dev, "%s.ctrl", dev_name(&intf->dev)); - - gb_connection_set_data(control->connection, control); - - return control; -} - -int gb_control_enable(struct gb_control *control) -{ - int ret; - - dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - - ret = gb_connection_enable_tx(control->connection); - if (ret) { - dev_err(&control->connection->intf->dev, - "failed to enable control connection: %d\n", - ret); - return ret; - } - - ret = gb_control_get_version(control); - if (ret) - goto err_disable_connection; - - if (control->protocol_major > 0 || control->protocol_minor > 1) - control->has_bundle_version = true; - - /* FIXME: use protocol version instead */ - if (!(control->intf->quirks & GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE)) - control->has_bundle_activate = true; - - return 0; - -err_disable_connection: - gb_connection_disable(control->connection); - - return ret; -} - -void gb_control_disable(struct gb_control *control) -{ - dev_dbg(&control->connection->intf->dev, "%s\n", __func__); - - if (control->intf->disconnected) - gb_connection_disable_forced(control->connection); - else - gb_connection_disable(control->connection); -} - -int gb_control_suspend(struct gb_control *control) -{ - gb_connection_disable(control->connection); - - return 0; -} - -int gb_control_resume(struct gb_control *control) -{ - int ret; - - ret = gb_connection_enable_tx(control->connection); - if (ret) { - dev_err(&control->connection->intf->dev, - "failed to enable control connection: %d\n", ret); - return ret; - } - - return 0; -} - -int gb_control_add(struct gb_control *control) -{ - int ret; - - ret = device_add(&control->dev); - if (ret) { - dev_err(&control->dev, - "failed to register control device: %d\n", - ret); - return ret; - } - - return 0; -} - -void gb_control_del(struct gb_control *control) -{ - if (device_is_registered(&control->dev)) - device_del(&control->dev); -} - -struct gb_control *gb_control_get(struct gb_control *control) -{ - get_device(&control->dev); - - return control; -} - -void gb_control_put(struct gb_control *control) -{ - put_device(&control->dev); -} - -void gb_control_mode_switch_prepare(struct gb_control *control) -{ - gb_connection_mode_switch_prepare(control->connection); -} - -void gb_control_mode_switch_complete(struct gb_control *control) -{ - gb_connection_mode_switch_complete(control->connection); -} diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c deleted file mode 100644 index e546c6431877..000000000000 --- a/drivers/staging/greybus/core.c +++ /dev/null @@ -1,349 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus "Core" - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define CREATE_TRACE_POINTS -#include -#include "greybus_trace.h" - -#define GB_BUNDLE_AUTOSUSPEND_MS 3000 - -/* Allow greybus to be disabled at boot if needed */ -static bool nogreybus; -#ifdef MODULE -module_param(nogreybus, bool, 0444); -#else -core_param(nogreybus, nogreybus, bool, 0444); -#endif -int greybus_disabled(void) -{ - return nogreybus; -} -EXPORT_SYMBOL_GPL(greybus_disabled); - -static bool greybus_match_one_id(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != bundle->intf->vendor_id)) - return false; - - if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != bundle->intf->product_id)) - return false; - - if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && - (id->class != bundle->class)) - return false; - - return true; -} - -static const struct greybus_bundle_id * -greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) -{ - if (!id) - return NULL; - - for (; id->vendor || id->product || id->class || id->driver_info; - id++) { - if (greybus_match_one_id(bundle, id)) - return id; - } - - return NULL; -} - -static int greybus_match_device(struct device *dev, struct device_driver *drv) -{ - struct greybus_driver *driver = to_greybus_driver(drv); - struct gb_bundle *bundle; - const struct greybus_bundle_id *id; - - if (!is_gb_bundle(dev)) - return 0; - - bundle = to_gb_bundle(dev); - - id = greybus_match_id(bundle, driver->id_table); - if (id) - return 1; - /* FIXME - Dynamic ids? */ - return 0; -} - -static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct gb_host_device *hd; - struct gb_module *module = NULL; - struct gb_interface *intf = NULL; - struct gb_control *control = NULL; - struct gb_bundle *bundle = NULL; - struct gb_svc *svc = NULL; - - if (is_gb_host_device(dev)) { - hd = to_gb_host_device(dev); - } else if (is_gb_module(dev)) { - module = to_gb_module(dev); - hd = module->hd; - } else if (is_gb_interface(dev)) { - intf = to_gb_interface(dev); - module = intf->module; - hd = intf->hd; - } else if (is_gb_control(dev)) { - control = to_gb_control(dev); - intf = control->intf; - module = intf->module; - hd = intf->hd; - } else if (is_gb_bundle(dev)) { - bundle = to_gb_bundle(dev); - intf = bundle->intf; - module = intf->module; - hd = intf->hd; - } else if (is_gb_svc(dev)) { - svc = to_gb_svc(dev); - hd = svc->hd; - } else { - dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); - return -EINVAL; - } - - if (add_uevent_var(env, "BUS=%u", hd->bus_id)) - return -ENOMEM; - - if (module) { - if (add_uevent_var(env, "MODULE=%u", module->module_id)) - return -ENOMEM; - } - - if (intf) { - if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) - return -ENOMEM; - if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", - intf->vendor_id, intf->product_id)) - return -ENOMEM; - } - - if (bundle) { - // FIXME - // add a uevent that can "load" a bundle type - // This is what we need to bind a driver to so use the info - // in gmod here as well - - if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) - return -ENOMEM; - if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) - return -ENOMEM; - } - - return 0; -} - -static void greybus_shutdown(struct device *dev) -{ - if (is_gb_host_device(dev)) { - struct gb_host_device *hd; - - hd = to_gb_host_device(dev); - gb_hd_shutdown(hd); - } -} - -struct bus_type greybus_bus_type = { - .name = "greybus", - .match = greybus_match_device, - .uevent = greybus_uevent, - .shutdown = greybus_shutdown, -}; - -static int greybus_probe(struct device *dev) -{ - struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_bundle *bundle = to_gb_bundle(dev); - const struct greybus_bundle_id *id; - int retval; - - /* match id */ - id = greybus_match_id(bundle, driver->id_table); - if (!id) - return -ENODEV; - - retval = pm_runtime_get_sync(&bundle->intf->dev); - if (retval < 0) { - pm_runtime_put_noidle(&bundle->intf->dev); - return retval; - } - - retval = gb_control_bundle_activate(bundle->intf->control, bundle->id); - if (retval) { - pm_runtime_put(&bundle->intf->dev); - return retval; - } - - /* - * Unbound bundle devices are always deactivated. During probe, the - * Runtime PM is set to enabled and active and the usage count is - * incremented. If the driver supports runtime PM, it should call - * pm_runtime_put() in its probe routine and pm_runtime_get_sync() - * in remove routine. - */ - pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS); - pm_runtime_use_autosuspend(dev); - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - retval = driver->probe(bundle, id); - if (retval) { - /* - * Catch buggy drivers that fail to destroy their connections. - */ - WARN_ON(!list_empty(&bundle->connections)); - - gb_control_bundle_deactivate(bundle->intf->control, bundle->id); - - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_put(&bundle->intf->dev); - - return retval; - } - - pm_runtime_put(&bundle->intf->dev); - - return 0; -} - -static int greybus_remove(struct device *dev) -{ - struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_bundle *bundle = to_gb_bundle(dev); - struct gb_connection *connection; - int retval; - - retval = pm_runtime_get_sync(dev); - if (retval < 0) - dev_err(dev, "failed to resume bundle: %d\n", retval); - - /* - * Disable (non-offloaded) connections early in case the interface is - * already gone to avoid unceccessary operation timeouts during - * driver disconnect. Otherwise, only disable incoming requests. - */ - list_for_each_entry(connection, &bundle->connections, bundle_links) { - if (gb_connection_is_offloaded(connection)) - continue; - - if (bundle->intf->disconnected) - gb_connection_disable_forced(connection); - else - gb_connection_disable_rx(connection); - } - - driver->disconnect(bundle); - - /* Catch buggy drivers that fail to destroy their connections. */ - WARN_ON(!list_empty(&bundle->connections)); - - if (!bundle->intf->disconnected) - gb_control_bundle_deactivate(bundle->intf->control, bundle->id); - - pm_runtime_put_noidle(dev); - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_put_noidle(dev); - - return 0; -} - -int greybus_register_driver(struct greybus_driver *driver, struct module *owner, - const char *mod_name) -{ - int retval; - - if (greybus_disabled()) - return -ENODEV; - - driver->driver.bus = &greybus_bus_type; - driver->driver.name = driver->name; - driver->driver.probe = greybus_probe; - driver->driver.remove = greybus_remove; - driver->driver.owner = owner; - driver->driver.mod_name = mod_name; - - retval = driver_register(&driver->driver); - if (retval) - return retval; - - pr_info("registered new driver %s\n", driver->name); - return 0; -} -EXPORT_SYMBOL_GPL(greybus_register_driver); - -void greybus_deregister_driver(struct greybus_driver *driver) -{ - driver_unregister(&driver->driver); -} -EXPORT_SYMBOL_GPL(greybus_deregister_driver); - -static int __init gb_init(void) -{ - int retval; - - if (greybus_disabled()) - return -ENODEV; - - BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD); - - gb_debugfs_init(); - - retval = bus_register(&greybus_bus_type); - if (retval) { - pr_err("bus_register failed (%d)\n", retval); - goto error_bus; - } - - retval = gb_hd_init(); - if (retval) { - pr_err("gb_hd_init failed (%d)\n", retval); - goto error_hd; - } - - retval = gb_operation_init(); - if (retval) { - pr_err("gb_operation_init failed (%d)\n", retval); - goto error_operation; - } - return 0; /* Success */ - -error_operation: - gb_hd_exit(); -error_hd: - bus_unregister(&greybus_bus_type); -error_bus: - gb_debugfs_cleanup(); - - return retval; -} -module_init(gb_init); - -static void __exit gb_exit(void) -{ - gb_operation_exit(); - gb_hd_exit(); - bus_unregister(&greybus_bus_type); - gb_debugfs_cleanup(); - tracepoint_synchronize_unregister(); -} -module_exit(gb_exit); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/debugfs.c b/drivers/staging/greybus/debugfs.c deleted file mode 100644 index e102d7badb9d..000000000000 --- a/drivers/staging/greybus/debugfs.c +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus debugfs code - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#include -#include - -static struct dentry *gb_debug_root; - -void __init gb_debugfs_init(void) -{ - gb_debug_root = debugfs_create_dir("greybus", NULL); -} - -void gb_debugfs_cleanup(void) -{ - debugfs_remove_recursive(gb_debug_root); - gb_debug_root = NULL; -} - -struct dentry *gb_debugfs_get(void) -{ - return gb_debug_root; -} -EXPORT_SYMBOL_GPL(gb_debugfs_get); diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c index 366716f11b1a..5b755e76d8a4 100644 --- a/drivers/staging/greybus/es2.c +++ b/drivers/staging/greybus/es2.c @@ -15,7 +15,7 @@ #include #include "arpc.h" -#include "greybus_trace.h" +#include "../../greybus/greybus_trace.h" /* Default timeout for USB vendor requests. */ diff --git a/drivers/staging/greybus/greybus_trace.h b/drivers/staging/greybus/greybus_trace.h deleted file mode 100644 index 1bc9f1275c65..000000000000 --- a/drivers/staging/greybus/greybus_trace.h +++ /dev/null @@ -1,502 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Greybus driver and device API - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - */ -#undef TRACE_SYSTEM -#define TRACE_SYSTEM greybus - -#if !defined(_TRACE_GREYBUS_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_GREYBUS_H - -#include - -struct gb_message; -struct gb_operation; -struct gb_connection; -struct gb_bundle; -struct gb_host_device; - -DECLARE_EVENT_CLASS(gb_message, - - TP_PROTO(struct gb_message *message), - - TP_ARGS(message), - - TP_STRUCT__entry( - __field(u16, size) - __field(u16, operation_id) - __field(u8, type) - __field(u8, result) - ), - - TP_fast_assign( - __entry->size = le16_to_cpu(message->header->size); - __entry->operation_id = - le16_to_cpu(message->header->operation_id); - __entry->type = message->header->type; - __entry->result = message->header->result; - ), - - TP_printk("size=%hu operation_id=0x%04x type=0x%02x result=0x%02x", - __entry->size, __entry->operation_id, - __entry->type, __entry->result) -); - -#define DEFINE_MESSAGE_EVENT(name) \ - DEFINE_EVENT(gb_message, name, \ - TP_PROTO(struct gb_message *message), \ - TP_ARGS(message)) - -/* - * Occurs immediately before calling a host device's message_send() - * method. - */ -DEFINE_MESSAGE_EVENT(gb_message_send); - -/* - * Occurs after an incoming request message has been received - */ -DEFINE_MESSAGE_EVENT(gb_message_recv_request); - -/* - * Occurs after an incoming response message has been received, - * after its matching request has been found. - */ -DEFINE_MESSAGE_EVENT(gb_message_recv_response); - -/* - * Occurs after an operation has been canceled, possibly before the - * cancellation is complete. - */ -DEFINE_MESSAGE_EVENT(gb_message_cancel_outgoing); - -/* - * Occurs when an incoming request is cancelled; if the response has - * been queued for sending, this occurs after it is sent. - */ -DEFINE_MESSAGE_EVENT(gb_message_cancel_incoming); - -/* - * Occurs in the host driver message_send() function just prior to - * handing off the data to be processed by hardware. - */ -DEFINE_MESSAGE_EVENT(gb_message_submit); - -#undef DEFINE_MESSAGE_EVENT - -DECLARE_EVENT_CLASS(gb_operation, - - TP_PROTO(struct gb_operation *operation), - - TP_ARGS(operation), - - TP_STRUCT__entry( - __field(u16, cport_id) /* CPort of HD side of connection */ - __field(u16, id) /* Operation ID */ - __field(u8, type) - __field(unsigned long, flags) - __field(int, active) - __field(int, waiters) - __field(int, errno) - ), - - TP_fast_assign( - __entry->cport_id = operation->connection->hd_cport_id; - __entry->id = operation->id; - __entry->type = operation->type; - __entry->flags = operation->flags; - __entry->active = operation->active; - __entry->waiters = atomic_read(&operation->waiters); - __entry->errno = operation->errno; - ), - - TP_printk("id=%04x type=0x%02x cport_id=%04x flags=0x%lx active=%d waiters=%d errno=%d", - __entry->id, __entry->cport_id, __entry->type, __entry->flags, - __entry->active, __entry->waiters, __entry->errno) -); - -#define DEFINE_OPERATION_EVENT(name) \ - DEFINE_EVENT(gb_operation, name, \ - TP_PROTO(struct gb_operation *operation), \ - TP_ARGS(operation)) - -/* - * Occurs after a new operation is created for an outgoing request - * has been successfully created. - */ -DEFINE_OPERATION_EVENT(gb_operation_create); - -/* - * Occurs after a new core operation has been created. - */ -DEFINE_OPERATION_EVENT(gb_operation_create_core); - -/* - * Occurs after a new operation has been created for an incoming - * request has been successfully created and initialized. - */ -DEFINE_OPERATION_EVENT(gb_operation_create_incoming); - -/* - * Occurs when the last reference to an operation has been dropped, - * prior to freeing resources. - */ -DEFINE_OPERATION_EVENT(gb_operation_destroy); - -/* - * Occurs when an operation has been marked active, after updating - * its active count. - */ -DEFINE_OPERATION_EVENT(gb_operation_get_active); - -/* - * Occurs when an operation has been marked active, before updating - * its active count. - */ -DEFINE_OPERATION_EVENT(gb_operation_put_active); - -#undef DEFINE_OPERATION_EVENT - -DECLARE_EVENT_CLASS(gb_connection, - - TP_PROTO(struct gb_connection *connection), - - TP_ARGS(connection), - - TP_STRUCT__entry( - __field(int, hd_bus_id) - __field(u8, bundle_id) - /* name contains "hd_cport_id/intf_id:cport_id" */ - __dynamic_array(char, name, sizeof(connection->name)) - __field(enum gb_connection_state, state) - __field(unsigned long, flags) - ), - - TP_fast_assign( - __entry->hd_bus_id = connection->hd->bus_id; - __entry->bundle_id = connection->bundle ? - connection->bundle->id : BUNDLE_ID_NONE; - memcpy(__get_str(name), connection->name, - sizeof(connection->name)); - __entry->state = connection->state; - __entry->flags = connection->flags; - ), - - TP_printk("hd_bus_id=%d bundle_id=0x%02x name=\"%s\" state=%u flags=0x%lx", - __entry->hd_bus_id, __entry->bundle_id, __get_str(name), - (unsigned int)__entry->state, __entry->flags) -); - -#define DEFINE_CONNECTION_EVENT(name) \ - DEFINE_EVENT(gb_connection, name, \ - TP_PROTO(struct gb_connection *connection), \ - TP_ARGS(connection)) - -/* - * Occurs after a new connection is successfully created. - */ -DEFINE_CONNECTION_EVENT(gb_connection_create); - -/* - * Occurs when the last reference to a connection has been dropped, - * before its resources are freed. - */ -DEFINE_CONNECTION_EVENT(gb_connection_release); - -/* - * Occurs when a new reference to connection is added, currently - * only when a message over the connection is received. - */ -DEFINE_CONNECTION_EVENT(gb_connection_get); - -/* - * Occurs when a new reference to connection is dropped, after a - * a received message is handled, or when the connection is - * destroyed. - */ -DEFINE_CONNECTION_EVENT(gb_connection_put); - -/* - * Occurs when a request to enable a connection is made, either for - * transmit only, or for both transmit and receive. - */ -DEFINE_CONNECTION_EVENT(gb_connection_enable); - -/* - * Occurs when a request to disable a connection is made, either for - * receive only, or for both transmit and receive. Also occurs when - * a request to forcefully disable a connection is made. - */ -DEFINE_CONNECTION_EVENT(gb_connection_disable); - -#undef DEFINE_CONNECTION_EVENT - -DECLARE_EVENT_CLASS(gb_bundle, - - TP_PROTO(struct gb_bundle *bundle), - - TP_ARGS(bundle), - - TP_STRUCT__entry( - __field(u8, intf_id) - __field(u8, id) - __field(u8, class) - __field(size_t, num_cports) - ), - - TP_fast_assign( - __entry->intf_id = bundle->intf->interface_id; - __entry->id = bundle->id; - __entry->class = bundle->class; - __entry->num_cports = bundle->num_cports; - ), - - TP_printk("intf_id=0x%02x id=%02x class=0x%02x num_cports=%zu", - __entry->intf_id, __entry->id, __entry->class, - __entry->num_cports) -); - -#define DEFINE_BUNDLE_EVENT(name) \ - DEFINE_EVENT(gb_bundle, name, \ - TP_PROTO(struct gb_bundle *bundle), \ - TP_ARGS(bundle)) - -/* - * Occurs after a new bundle is successfully created. - */ -DEFINE_BUNDLE_EVENT(gb_bundle_create); - -/* - * Occurs when the last reference to a bundle has been dropped, - * before its resources are freed. - */ -DEFINE_BUNDLE_EVENT(gb_bundle_release); - -/* - * Occurs when a bundle is added to an interface when the interface - * is enabled. - */ -DEFINE_BUNDLE_EVENT(gb_bundle_add); - -/* - * Occurs when a registered bundle gets destroyed, normally at the - * time an interface is disabled. - */ -DEFINE_BUNDLE_EVENT(gb_bundle_destroy); - -#undef DEFINE_BUNDLE_EVENT - -DECLARE_EVENT_CLASS(gb_interface, - - TP_PROTO(struct gb_interface *intf), - - TP_ARGS(intf), - - TP_STRUCT__entry( - __field(u8, module_id) - __field(u8, id) /* Interface id */ - __field(u8, device_id) - __field(int, disconnected) /* bool */ - __field(int, ejected) /* bool */ - __field(int, active) /* bool */ - __field(int, enabled) /* bool */ - __field(int, mode_switch) /* bool */ - ), - - TP_fast_assign( - __entry->module_id = intf->module->module_id; - __entry->id = intf->interface_id; - __entry->device_id = intf->device_id; - __entry->disconnected = intf->disconnected; - __entry->ejected = intf->ejected; - __entry->active = intf->active; - __entry->enabled = intf->enabled; - __entry->mode_switch = intf->mode_switch; - ), - - TP_printk("intf_id=%hhu device_id=%hhu module_id=%hhu D=%d J=%d A=%d E=%d M=%d", - __entry->id, __entry->device_id, __entry->module_id, - __entry->disconnected, __entry->ejected, __entry->active, - __entry->enabled, __entry->mode_switch) -); - -#define DEFINE_INTERFACE_EVENT(name) \ - DEFINE_EVENT(gb_interface, name, \ - TP_PROTO(struct gb_interface *intf), \ - TP_ARGS(intf)) - -/* - * Occurs after a new interface is successfully created. - */ -DEFINE_INTERFACE_EVENT(gb_interface_create); - -/* - * Occurs after the last reference to an interface has been dropped. - */ -DEFINE_INTERFACE_EVENT(gb_interface_release); - -/* - * Occurs after an interface been registerd. - */ -DEFINE_INTERFACE_EVENT(gb_interface_add); - -/* - * Occurs when a registered interface gets deregisterd. - */ -DEFINE_INTERFACE_EVENT(gb_interface_del); - -/* - * Occurs when a registered interface has been successfully - * activated. - */ -DEFINE_INTERFACE_EVENT(gb_interface_activate); - -/* - * Occurs when an activated interface is being deactivated. - */ -DEFINE_INTERFACE_EVENT(gb_interface_deactivate); - -/* - * Occurs when an interface has been successfully enabled. - */ -DEFINE_INTERFACE_EVENT(gb_interface_enable); - -/* - * Occurs when an enabled interface is being disabled. - */ -DEFINE_INTERFACE_EVENT(gb_interface_disable); - -#undef DEFINE_INTERFACE_EVENT - -DECLARE_EVENT_CLASS(gb_module, - - TP_PROTO(struct gb_module *module), - - TP_ARGS(module), - - TP_STRUCT__entry( - __field(int, hd_bus_id) - __field(u8, module_id) - __field(size_t, num_interfaces) - __field(int, disconnected) /* bool */ - ), - - TP_fast_assign( - __entry->hd_bus_id = module->hd->bus_id; - __entry->module_id = module->module_id; - __entry->num_interfaces = module->num_interfaces; - __entry->disconnected = module->disconnected; - ), - - TP_printk("hd_bus_id=%d module_id=%hhu num_interfaces=%zu disconnected=%d", - __entry->hd_bus_id, __entry->module_id, - __entry->num_interfaces, __entry->disconnected) -); - -#define DEFINE_MODULE_EVENT(name) \ - DEFINE_EVENT(gb_module, name, \ - TP_PROTO(struct gb_module *module), \ - TP_ARGS(module)) - -/* - * Occurs after a new module is successfully created, before - * creating any of its interfaces. - */ -DEFINE_MODULE_EVENT(gb_module_create); - -/* - * Occurs after the last reference to a module has been dropped. - */ -DEFINE_MODULE_EVENT(gb_module_release); - -/* - * Occurs after a module is successfully created, before registering - * any of its interfaces. - */ -DEFINE_MODULE_EVENT(gb_module_add); - -/* - * Occurs when a module is deleted, before deregistering its - * interfaces. - */ -DEFINE_MODULE_EVENT(gb_module_del); - -#undef DEFINE_MODULE_EVENT - -DECLARE_EVENT_CLASS(gb_host_device, - - TP_PROTO(struct gb_host_device *hd), - - TP_ARGS(hd), - - TP_STRUCT__entry( - __field(int, bus_id) - __field(size_t, num_cports) - __field(size_t, buffer_size_max) - ), - - TP_fast_assign( - __entry->bus_id = hd->bus_id; - __entry->num_cports = hd->num_cports; - __entry->buffer_size_max = hd->buffer_size_max; - ), - - TP_printk("bus_id=%d num_cports=%zu mtu=%zu", - __entry->bus_id, __entry->num_cports, - __entry->buffer_size_max) -); - -#define DEFINE_HD_EVENT(name) \ - DEFINE_EVENT(gb_host_device, name, \ - TP_PROTO(struct gb_host_device *hd), \ - TP_ARGS(hd)) - -/* - * Occurs after a new host device is successfully created, before - * its SVC has been set up. - */ -DEFINE_HD_EVENT(gb_hd_create); - -/* - * Occurs after the last reference to a host device has been - * dropped. - */ -DEFINE_HD_EVENT(gb_hd_release); - -/* - * Occurs after a new host device has been added, after the - * connection to its SVC has been enabled. - */ -DEFINE_HD_EVENT(gb_hd_add); - -/* - * Occurs when a host device is being disconnected from the AP USB - * host controller. - */ -DEFINE_HD_EVENT(gb_hd_del); - -/* - * Occurs when a host device has passed received data to the Greybus - * core, after it has been determined it is destined for a valid - * CPort. - */ -DEFINE_HD_EVENT(gb_hd_in); - -#undef DEFINE_HD_EVENT - -#endif /* _TRACE_GREYBUS_H */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH . - -/* - * TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal - */ -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE greybus_trace -#include - diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c deleted file mode 100644 index 72b21bf2d7d3..000000000000 --- a/drivers/staging/greybus/hd.c +++ /dev/null @@ -1,256 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus Host Device - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#include -#include -#include - -#include "greybus_trace.h" - -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_create); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_release); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_add); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_del); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_hd_in); -EXPORT_TRACEPOINT_SYMBOL_GPL(gb_message_submit); - -static struct ida gb_hd_bus_id_map; - -int gb_hd_output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, - bool async) -{ - if (!hd || !hd->driver || !hd->driver->output) - return -EINVAL; - return hd->driver->output(hd, req, size, cmd, async); -} -EXPORT_SYMBOL_GPL(gb_hd_output); - -static ssize_t bus_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_host_device *hd = to_gb_host_device(dev); - - return sprintf(buf, "%d\n", hd->bus_id); -} -static DEVICE_ATTR_RO(bus_id); - -static struct attribute *bus_attrs[] = { - &dev_attr_bus_id.attr, - NULL -}; -ATTRIBUTE_GROUPS(bus); - -int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) -{ - struct ida *id_map = &hd->cport_id_map; - int ret; - - ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL); - if (ret < 0) { - dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(gb_hd_cport_reserve); - -void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id) -{ - struct ida *id_map = &hd->cport_id_map; - - ida_simple_remove(id_map, cport_id); -} -EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved); - -/* Locking: Caller guarantees serialisation */ -int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, - unsigned long flags) -{ - struct ida *id_map = &hd->cport_id_map; - int ida_start, ida_end; - - if (hd->driver->cport_allocate) - return hd->driver->cport_allocate(hd, cport_id, flags); - - if (cport_id < 0) { - ida_start = 0; - ida_end = hd->num_cports; - } else if (cport_id < hd->num_cports) { - ida_start = cport_id; - ida_end = cport_id + 1; - } else { - dev_err(&hd->dev, "cport %d not available\n", cport_id); - return -EINVAL; - } - - return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); -} - -/* Locking: Caller guarantees serialisation */ -void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) -{ - if (hd->driver->cport_release) { - hd->driver->cport_release(hd, cport_id); - return; - } - - ida_simple_remove(&hd->cport_id_map, cport_id); -} - -static void gb_hd_release(struct device *dev) -{ - struct gb_host_device *hd = to_gb_host_device(dev); - - trace_gb_hd_release(hd); - - if (hd->svc) - gb_svc_put(hd->svc); - ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id); - ida_destroy(&hd->cport_id_map); - kfree(hd); -} - -struct device_type greybus_hd_type = { - .name = "greybus_host_device", - .release = gb_hd_release, -}; - -struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, - struct device *parent, - size_t buffer_size_max, - size_t num_cports) -{ - struct gb_host_device *hd; - int ret; - - /* - * Validate that the driver implements all of the callbacks - * so that we don't have to every time we make them. - */ - if ((!driver->message_send) || (!driver->message_cancel)) { - dev_err(parent, "mandatory hd-callbacks missing\n"); - return ERR_PTR(-EINVAL); - } - - if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) { - dev_err(parent, "greybus host-device buffers too small\n"); - return ERR_PTR(-EINVAL); - } - - if (num_cports == 0 || num_cports > CPORT_ID_MAX + 1) { - dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports); - return ERR_PTR(-EINVAL); - } - - /* - * Make sure to never allocate messages larger than what the Greybus - * protocol supports. - */ - if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) { - dev_warn(parent, "limiting buffer size to %u\n", - GB_OPERATION_MESSAGE_SIZE_MAX); - buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX; - } - - hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL); - if (!hd) - return ERR_PTR(-ENOMEM); - - ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL); - if (ret < 0) { - kfree(hd); - return ERR_PTR(ret); - } - hd->bus_id = ret; - - hd->driver = driver; - INIT_LIST_HEAD(&hd->modules); - INIT_LIST_HEAD(&hd->connections); - ida_init(&hd->cport_id_map); - hd->buffer_size_max = buffer_size_max; - hd->num_cports = num_cports; - - hd->dev.parent = parent; - hd->dev.bus = &greybus_bus_type; - hd->dev.type = &greybus_hd_type; - hd->dev.groups = bus_groups; - hd->dev.dma_mask = hd->dev.parent->dma_mask; - device_initialize(&hd->dev); - dev_set_name(&hd->dev, "greybus%d", hd->bus_id); - - trace_gb_hd_create(hd); - - hd->svc = gb_svc_create(hd); - if (!hd->svc) { - dev_err(&hd->dev, "failed to create svc\n"); - put_device(&hd->dev); - return ERR_PTR(-ENOMEM); - } - - return hd; -} -EXPORT_SYMBOL_GPL(gb_hd_create); - -int gb_hd_add(struct gb_host_device *hd) -{ - int ret; - - ret = device_add(&hd->dev); - if (ret) - return ret; - - ret = gb_svc_add(hd->svc); - if (ret) { - device_del(&hd->dev); - return ret; - } - - trace_gb_hd_add(hd); - - return 0; -} -EXPORT_SYMBOL_GPL(gb_hd_add); - -void gb_hd_del(struct gb_host_device *hd) -{ - trace_gb_hd_del(hd); - - /* - * Tear down the svc and flush any on-going hotplug processing before - * removing the remaining interfaces. - */ - gb_svc_del(hd->svc); - - device_del(&hd->dev); -} -EXPORT_SYMBOL_GPL(gb_hd_del); - -void gb_hd_shutdown(struct gb_host_device *hd) -{ - gb_svc_del(hd->svc); -} -EXPORT_SYMBOL_GPL(gb_hd_shutdown); - -void gb_hd_put(struct gb_host_device *hd) -{ - put_device(&hd->dev); -} -EXPORT_SYMBOL_GPL(gb_hd_put); - -int __init gb_hd_init(void) -{ - ida_init(&gb_hd_bus_id_map); - - return 0; -} - -void gb_hd_exit(void) -{ - ida_destroy(&gb_hd_bus_id_map); -} diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c deleted file mode 100644 index 67dbe6fda9a1..000000000000 --- a/drivers/staging/greybus/interface.c +++ /dev/null @@ -1,1263 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus interface code - * - * Copyright 2014 Google Inc. - * Copyright 2014 Linaro Ltd. - */ - -#include -#include - -#include "greybus_trace.h" - -#define GB_INTERFACE_MODE_SWITCH_TIMEOUT 2000 - -#define GB_INTERFACE_DEVICE_ID_BAD 0xff - -#define GB_INTERFACE_AUTOSUSPEND_MS 3000 - -/* Time required for interface to enter standby before disabling REFCLK */ -#define GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS 20 - -/* Don't-care selector index */ -#define DME_SELECTOR_INDEX_NULL 0 - -/* DME attributes */ -/* FIXME: remove ES2 support and DME_T_TST_SRC_INCREMENT */ -#define DME_T_TST_SRC_INCREMENT 0x4083 - -#define DME_DDBL1_MANUFACTURERID 0x5003 -#define DME_DDBL1_PRODUCTID 0x5004 - -#define DME_TOSHIBA_GMP_VID 0x6000 -#define DME_TOSHIBA_GMP_PID 0x6001 -#define DME_TOSHIBA_GMP_SN0 0x6002 -#define DME_TOSHIBA_GMP_SN1 0x6003 -#define DME_TOSHIBA_GMP_INIT_STATUS 0x6101 - -/* DDBL1 Manufacturer and Product ids */ -#define TOSHIBA_DMID 0x0126 -#define TOSHIBA_ES2_BRIDGE_DPID 0x1000 -#define TOSHIBA_ES3_APBRIDGE_DPID 0x1001 -#define TOSHIBA_ES3_GBPHY_DPID 0x1002 - -static int gb_interface_hibernate_link(struct gb_interface *intf); -static int gb_interface_refclk_set(struct gb_interface *intf, bool enable); - -static int gb_interface_dme_attr_get(struct gb_interface *intf, - u16 attr, u32 *val) -{ - return gb_svc_dme_peer_get(intf->hd->svc, intf->interface_id, - attr, DME_SELECTOR_INDEX_NULL, val); -} - -static int gb_interface_read_ara_dme(struct gb_interface *intf) -{ - u32 sn0, sn1; - int ret; - - /* - * Unless this is a Toshiba bridge, bail out until we have defined - * standard GMP attributes. - */ - if (intf->ddbl1_manufacturer_id != TOSHIBA_DMID) { - dev_err(&intf->dev, "unknown manufacturer %08x\n", - intf->ddbl1_manufacturer_id); - return -ENODEV; - } - - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_VID, - &intf->vendor_id); - if (ret) - return ret; - - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_PID, - &intf->product_id); - if (ret) - return ret; - - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN0, &sn0); - if (ret) - return ret; - - ret = gb_interface_dme_attr_get(intf, DME_TOSHIBA_GMP_SN1, &sn1); - if (ret) - return ret; - - intf->serial_number = (u64)sn1 << 32 | sn0; - - return 0; -} - -static int gb_interface_read_dme(struct gb_interface *intf) -{ - int ret; - - /* DME attributes have already been read */ - if (intf->dme_read) - return 0; - - ret = gb_interface_dme_attr_get(intf, DME_DDBL1_MANUFACTURERID, - &intf->ddbl1_manufacturer_id); - if (ret) - return ret; - - ret = gb_interface_dme_attr_get(intf, DME_DDBL1_PRODUCTID, - &intf->ddbl1_product_id); - if (ret) - return ret; - - if (intf->ddbl1_manufacturer_id == TOSHIBA_DMID && - intf->ddbl1_product_id == TOSHIBA_ES2_BRIDGE_DPID) { - intf->quirks |= GB_INTERFACE_QUIRK_NO_GMP_IDS; - intf->quirks |= GB_INTERFACE_QUIRK_NO_INIT_STATUS; - } - - ret = gb_interface_read_ara_dme(intf); - if (ret) - return ret; - - intf->dme_read = true; - - return 0; -} - -static int gb_interface_route_create(struct gb_interface *intf) -{ - struct gb_svc *svc = intf->hd->svc; - u8 intf_id = intf->interface_id; - u8 device_id; - int ret; - - /* Allocate an interface device id. */ - ret = ida_simple_get(&svc->device_id_map, - GB_SVC_DEVICE_ID_MIN, GB_SVC_DEVICE_ID_MAX + 1, - GFP_KERNEL); - if (ret < 0) { - dev_err(&intf->dev, "failed to allocate device id: %d\n", ret); - return ret; - } - device_id = ret; - - ret = gb_svc_intf_device_id(svc, intf_id, device_id); - if (ret) { - dev_err(&intf->dev, "failed to set device id %u: %d\n", - device_id, ret); - goto err_ida_remove; - } - - /* FIXME: Hard-coded AP device id. */ - ret = gb_svc_route_create(svc, svc->ap_intf_id, GB_SVC_DEVICE_ID_AP, - intf_id, device_id); - if (ret) { - dev_err(&intf->dev, "failed to create route: %d\n", ret); - goto err_svc_id_free; - } - - intf->device_id = device_id; - - return 0; - -err_svc_id_free: - /* - * XXX Should we tell SVC that this id doesn't belong to interface - * XXX anymore. - */ -err_ida_remove: - ida_simple_remove(&svc->device_id_map, device_id); - - return ret; -} - -static void gb_interface_route_destroy(struct gb_interface *intf) -{ - struct gb_svc *svc = intf->hd->svc; - - if (intf->device_id == GB_INTERFACE_DEVICE_ID_BAD) - return; - - gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id); - ida_simple_remove(&svc->device_id_map, intf->device_id); - intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; -} - -/* Locking: Caller holds the interface mutex. */ -static int gb_interface_legacy_mode_switch(struct gb_interface *intf) -{ - int ret; - - dev_info(&intf->dev, "legacy mode switch detected\n"); - - /* Mark as disconnected to prevent I/O during disable. */ - intf->disconnected = true; - gb_interface_disable(intf); - intf->disconnected = false; - - ret = gb_interface_enable(intf); - if (ret) { - dev_err(&intf->dev, "failed to re-enable interface: %d\n", ret); - gb_interface_deactivate(intf); - } - - return ret; -} - -void gb_interface_mailbox_event(struct gb_interface *intf, u16 result, - u32 mailbox) -{ - mutex_lock(&intf->mutex); - - if (result) { - dev_warn(&intf->dev, - "mailbox event with UniPro error: 0x%04x\n", - result); - goto err_disable; - } - - if (mailbox != GB_SVC_INTF_MAILBOX_GREYBUS) { - dev_warn(&intf->dev, - "mailbox event with unexpected value: 0x%08x\n", - mailbox); - goto err_disable; - } - - if (intf->quirks & GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH) { - gb_interface_legacy_mode_switch(intf); - goto out_unlock; - } - - if (!intf->mode_switch) { - dev_warn(&intf->dev, "unexpected mailbox event: 0x%08x\n", - mailbox); - goto err_disable; - } - - dev_info(&intf->dev, "mode switch detected\n"); - - complete(&intf->mode_switch_completion); - -out_unlock: - mutex_unlock(&intf->mutex); - - return; - -err_disable: - gb_interface_disable(intf); - gb_interface_deactivate(intf); - mutex_unlock(&intf->mutex); -} - -static void gb_interface_mode_switch_work(struct work_struct *work) -{ - struct gb_interface *intf; - struct gb_control *control; - unsigned long timeout; - int ret; - - intf = container_of(work, struct gb_interface, mode_switch_work); - - mutex_lock(&intf->mutex); - /* Make sure interface is still enabled. */ - if (!intf->enabled) { - dev_dbg(&intf->dev, "mode switch aborted\n"); - intf->mode_switch = false; - mutex_unlock(&intf->mutex); - goto out_interface_put; - } - - /* - * Prepare the control device for mode switch and make sure to get an - * extra reference before it goes away during interface disable. - */ - control = gb_control_get(intf->control); - gb_control_mode_switch_prepare(control); - gb_interface_disable(intf); - mutex_unlock(&intf->mutex); - - timeout = msecs_to_jiffies(GB_INTERFACE_MODE_SWITCH_TIMEOUT); - ret = wait_for_completion_interruptible_timeout( - &intf->mode_switch_completion, timeout); - - /* Finalise control-connection mode switch. */ - gb_control_mode_switch_complete(control); - gb_control_put(control); - - if (ret < 0) { - dev_err(&intf->dev, "mode switch interrupted\n"); - goto err_deactivate; - } else if (ret == 0) { - dev_err(&intf->dev, "mode switch timed out\n"); - goto err_deactivate; - } - - /* Re-enable (re-enumerate) interface if still active. */ - mutex_lock(&intf->mutex); - intf->mode_switch = false; - if (intf->active) { - ret = gb_interface_enable(intf); - if (ret) { - dev_err(&intf->dev, "failed to re-enable interface: %d\n", - ret); - gb_interface_deactivate(intf); - } - } - mutex_unlock(&intf->mutex); - -out_interface_put: - gb_interface_put(intf); - - return; - -err_deactivate: - mutex_lock(&intf->mutex); - intf->mode_switch = false; - gb_interface_deactivate(intf); - mutex_unlock(&intf->mutex); - - gb_interface_put(intf); -} - -int gb_interface_request_mode_switch(struct gb_interface *intf) -{ - int ret = 0; - - mutex_lock(&intf->mutex); - if (intf->mode_switch) { - ret = -EBUSY; - goto out_unlock; - } - - intf->mode_switch = true; - reinit_completion(&intf->mode_switch_completion); - - /* - * Get a reference to the interface device, which will be put once the - * mode switch is complete. - */ - get_device(&intf->dev); - - if (!queue_work(system_long_wq, &intf->mode_switch_work)) { - put_device(&intf->dev); - ret = -EBUSY; - goto out_unlock; - } - -out_unlock: - mutex_unlock(&intf->mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_interface_request_mode_switch); - -/* - * T_TstSrcIncrement is written by the module on ES2 as a stand-in for the - * init-status attribute DME_TOSHIBA_INIT_STATUS. The AP needs to read and - * clear it after reading a non-zero value from it. - * - * FIXME: This is module-hardware dependent and needs to be extended for every - * type of module we want to support. - */ -static int gb_interface_read_and_clear_init_status(struct gb_interface *intf) -{ - struct gb_host_device *hd = intf->hd; - unsigned long bootrom_quirks; - unsigned long s2l_quirks; - int ret; - u32 value; - u16 attr; - u8 init_status; - - /* - * ES2 bridges use T_TstSrcIncrement for the init status. - * - * FIXME: Remove ES2 support - */ - if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) - attr = DME_T_TST_SRC_INCREMENT; - else - attr = DME_TOSHIBA_GMP_INIT_STATUS; - - ret = gb_svc_dme_peer_get(hd->svc, intf->interface_id, attr, - DME_SELECTOR_INDEX_NULL, &value); - if (ret) - return ret; - - /* - * A nonzero init status indicates the module has finished - * initializing. - */ - if (!value) { - dev_err(&intf->dev, "invalid init status\n"); - return -ENODEV; - } - - /* - * Extract the init status. - * - * For ES2: We need to check lowest 8 bits of 'value'. - * For ES3: We need to check highest 8 bits out of 32 of 'value'. - * - * FIXME: Remove ES2 support - */ - if (intf->quirks & GB_INTERFACE_QUIRK_NO_INIT_STATUS) - init_status = value & 0xff; - else - init_status = value >> 24; - - /* - * Check if the interface is executing the quirky ES3 bootrom that, - * for example, requires E2EFC, CSD and CSV to be disabled. - */ - bootrom_quirks = GB_INTERFACE_QUIRK_NO_CPORT_FEATURES | - GB_INTERFACE_QUIRK_FORCED_DISABLE | - GB_INTERFACE_QUIRK_LEGACY_MODE_SWITCH | - GB_INTERFACE_QUIRK_NO_BUNDLE_ACTIVATE; - - s2l_quirks = GB_INTERFACE_QUIRK_NO_PM; - - switch (init_status) { - case GB_INIT_BOOTROM_UNIPRO_BOOT_STARTED: - case GB_INIT_BOOTROM_FALLBACK_UNIPRO_BOOT_STARTED: - intf->quirks |= bootrom_quirks; - break; - case GB_INIT_S2_LOADER_BOOT_STARTED: - /* S2 Loader doesn't support runtime PM */ - intf->quirks &= ~bootrom_quirks; - intf->quirks |= s2l_quirks; - break; - default: - intf->quirks &= ~bootrom_quirks; - intf->quirks &= ~s2l_quirks; - } - - /* Clear the init status. */ - return gb_svc_dme_peer_set(hd->svc, intf->interface_id, attr, - DME_SELECTOR_INDEX_NULL, 0); -} - -/* interface sysfs attributes */ -#define gb_interface_attr(field, type) \ -static ssize_t field##_show(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct gb_interface *intf = to_gb_interface(dev); \ - return scnprintf(buf, PAGE_SIZE, type"\n", intf->field); \ -} \ -static DEVICE_ATTR_RO(field) - -gb_interface_attr(ddbl1_manufacturer_id, "0x%08x"); -gb_interface_attr(ddbl1_product_id, "0x%08x"); -gb_interface_attr(interface_id, "%u"); -gb_interface_attr(vendor_id, "0x%08x"); -gb_interface_attr(product_id, "0x%08x"); -gb_interface_attr(serial_number, "0x%016llx"); - -static ssize_t voltage_now_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - int ret; - u32 measurement; - - ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, - GB_SVC_PWRMON_TYPE_VOL, - &measurement); - if (ret) { - dev_err(&intf->dev, "failed to get voltage sample (%d)\n", ret); - return ret; - } - - return sprintf(buf, "%u\n", measurement); -} -static DEVICE_ATTR_RO(voltage_now); - -static ssize_t current_now_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - int ret; - u32 measurement; - - ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, - GB_SVC_PWRMON_TYPE_CURR, - &measurement); - if (ret) { - dev_err(&intf->dev, "failed to get current sample (%d)\n", ret); - return ret; - } - - return sprintf(buf, "%u\n", measurement); -} -static DEVICE_ATTR_RO(current_now); - -static ssize_t power_now_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - int ret; - u32 measurement; - - ret = gb_svc_pwrmon_intf_sample_get(intf->hd->svc, intf->interface_id, - GB_SVC_PWRMON_TYPE_PWR, - &measurement); - if (ret) { - dev_err(&intf->dev, "failed to get power sample (%d)\n", ret); - return ret; - } - - return sprintf(buf, "%u\n", measurement); -} -static DEVICE_ATTR_RO(power_now); - -static ssize_t power_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - - if (intf->active) - return scnprintf(buf, PAGE_SIZE, "on\n"); - else - return scnprintf(buf, PAGE_SIZE, "off\n"); -} - -static ssize_t power_state_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t len) -{ - struct gb_interface *intf = to_gb_interface(dev); - bool activate; - int ret = 0; - - if (kstrtobool(buf, &activate)) - return -EINVAL; - - mutex_lock(&intf->mutex); - - if (activate == intf->active) - goto unlock; - - if (activate) { - ret = gb_interface_activate(intf); - if (ret) { - dev_err(&intf->dev, - "failed to activate interface: %d\n", ret); - goto unlock; - } - - ret = gb_interface_enable(intf); - if (ret) { - dev_err(&intf->dev, - "failed to enable interface: %d\n", ret); - gb_interface_deactivate(intf); - goto unlock; - } - } else { - gb_interface_disable(intf); - gb_interface_deactivate(intf); - } - -unlock: - mutex_unlock(&intf->mutex); - - if (ret) - return ret; - - return len; -} -static DEVICE_ATTR_RW(power_state); - -static const char *gb_interface_type_string(struct gb_interface *intf) -{ - static const char * const types[] = { - [GB_INTERFACE_TYPE_INVALID] = "invalid", - [GB_INTERFACE_TYPE_UNKNOWN] = "unknown", - [GB_INTERFACE_TYPE_DUMMY] = "dummy", - [GB_INTERFACE_TYPE_UNIPRO] = "unipro", - [GB_INTERFACE_TYPE_GREYBUS] = "greybus", - }; - - return types[intf->type]; -} - -static ssize_t interface_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_interface *intf = to_gb_interface(dev); - - return sprintf(buf, "%s\n", gb_interface_type_string(intf)); -} -static DEVICE_ATTR_RO(interface_type); - -static struct attribute *interface_unipro_attrs[] = { - &dev_attr_ddbl1_manufacturer_id.attr, - &dev_attr_ddbl1_product_id.attr, - NULL -}; - -static struct attribute *interface_greybus_attrs[] = { - &dev_attr_vendor_id.attr, - &dev_attr_product_id.attr, - &dev_attr_serial_number.attr, - NULL -}; - -static struct attribute *interface_power_attrs[] = { - &dev_attr_voltage_now.attr, - &dev_attr_current_now.attr, - &dev_attr_power_now.attr, - &dev_attr_power_state.attr, - NULL -}; - -static struct attribute *interface_common_attrs[] = { - &dev_attr_interface_id.attr, - &dev_attr_interface_type.attr, - NULL -}; - -static umode_t interface_unipro_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct gb_interface *intf = to_gb_interface(dev); - - switch (intf->type) { - case GB_INTERFACE_TYPE_UNIPRO: - case GB_INTERFACE_TYPE_GREYBUS: - return attr->mode; - default: - return 0; - } -} - -static umode_t interface_greybus_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct gb_interface *intf = to_gb_interface(dev); - - switch (intf->type) { - case GB_INTERFACE_TYPE_GREYBUS: - return attr->mode; - default: - return 0; - } -} - -static umode_t interface_power_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct gb_interface *intf = to_gb_interface(dev); - - switch (intf->type) { - case GB_INTERFACE_TYPE_UNIPRO: - case GB_INTERFACE_TYPE_GREYBUS: - return attr->mode; - default: - return 0; - } -} - -static const struct attribute_group interface_unipro_group = { - .is_visible = interface_unipro_is_visible, - .attrs = interface_unipro_attrs, -}; - -static const struct attribute_group interface_greybus_group = { - .is_visible = interface_greybus_is_visible, - .attrs = interface_greybus_attrs, -}; - -static const struct attribute_group interface_power_group = { - .is_visible = interface_power_is_visible, - .attrs = interface_power_attrs, -}; - -static const struct attribute_group interface_common_group = { - .attrs = interface_common_attrs, -}; - -static const struct attribute_group *interface_groups[] = { - &interface_unipro_group, - &interface_greybus_group, - &interface_power_group, - &interface_common_group, - NULL -}; - -static void gb_interface_release(struct device *dev) -{ - struct gb_interface *intf = to_gb_interface(dev); - - trace_gb_interface_release(intf); - - kfree(intf); -} - -#ifdef CONFIG_PM -static int gb_interface_suspend(struct device *dev) -{ - struct gb_interface *intf = to_gb_interface(dev); - int ret; - - ret = gb_control_interface_suspend_prepare(intf->control); - if (ret) - return ret; - - ret = gb_control_suspend(intf->control); - if (ret) - goto err_hibernate_abort; - - ret = gb_interface_hibernate_link(intf); - if (ret) - return ret; - - /* Delay to allow interface to enter standby before disabling refclk */ - msleep(GB_INTERFACE_SUSPEND_HIBERNATE_DELAY_MS); - - ret = gb_interface_refclk_set(intf, false); - if (ret) - return ret; - - return 0; - -err_hibernate_abort: - gb_control_interface_hibernate_abort(intf->control); - - return ret; -} - -static int gb_interface_resume(struct device *dev) -{ - struct gb_interface *intf = to_gb_interface(dev); - struct gb_svc *svc = intf->hd->svc; - int ret; - - ret = gb_interface_refclk_set(intf, true); - if (ret) - return ret; - - ret = gb_svc_intf_resume(svc, intf->interface_id); - if (ret) - return ret; - - ret = gb_control_resume(intf->control); - if (ret) - return ret; - - return 0; -} - -static int gb_interface_runtime_idle(struct device *dev) -{ - pm_runtime_mark_last_busy(dev); - pm_request_autosuspend(dev); - - return 0; -} -#endif - -static const struct dev_pm_ops gb_interface_pm_ops = { - SET_RUNTIME_PM_OPS(gb_interface_suspend, gb_interface_resume, - gb_interface_runtime_idle) -}; - -struct device_type greybus_interface_type = { - .name = "greybus_interface", - .release = gb_interface_release, - .pm = &gb_interface_pm_ops, -}; - -/* - * A Greybus module represents a user-replaceable component on a GMP - * phone. An interface is the physical connection on that module. A - * module may have more than one interface. - * - * Create a gb_interface structure to represent a discovered interface. - * The position of interface within the Endo is encoded in "interface_id" - * argument. - * - * Returns a pointer to the new interfce or a null pointer if a - * failure occurs due to memory exhaustion. - */ -struct gb_interface *gb_interface_create(struct gb_module *module, - u8 interface_id) -{ - struct gb_host_device *hd = module->hd; - struct gb_interface *intf; - - intf = kzalloc(sizeof(*intf), GFP_KERNEL); - if (!intf) - return NULL; - - intf->hd = hd; /* XXX refcount? */ - intf->module = module; - intf->interface_id = interface_id; - INIT_LIST_HEAD(&intf->bundles); - INIT_LIST_HEAD(&intf->manifest_descs); - mutex_init(&intf->mutex); - INIT_WORK(&intf->mode_switch_work, gb_interface_mode_switch_work); - init_completion(&intf->mode_switch_completion); - - /* Invalid device id to start with */ - intf->device_id = GB_INTERFACE_DEVICE_ID_BAD; - - intf->dev.parent = &module->dev; - intf->dev.bus = &greybus_bus_type; - intf->dev.type = &greybus_interface_type; - intf->dev.groups = interface_groups; - intf->dev.dma_mask = module->dev.dma_mask; - device_initialize(&intf->dev); - dev_set_name(&intf->dev, "%s.%u", dev_name(&module->dev), - interface_id); - - pm_runtime_set_autosuspend_delay(&intf->dev, - GB_INTERFACE_AUTOSUSPEND_MS); - - trace_gb_interface_create(intf); - - return intf; -} - -static int gb_interface_vsys_set(struct gb_interface *intf, bool enable) -{ - struct gb_svc *svc = intf->hd->svc; - int ret; - - dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); - - ret = gb_svc_intf_vsys_set(svc, intf->interface_id, enable); - if (ret) { - dev_err(&intf->dev, "failed to set v_sys: %d\n", ret); - return ret; - } - - return 0; -} - -static int gb_interface_refclk_set(struct gb_interface *intf, bool enable) -{ - struct gb_svc *svc = intf->hd->svc; - int ret; - - dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); - - ret = gb_svc_intf_refclk_set(svc, intf->interface_id, enable); - if (ret) { - dev_err(&intf->dev, "failed to set refclk: %d\n", ret); - return ret; - } - - return 0; -} - -static int gb_interface_unipro_set(struct gb_interface *intf, bool enable) -{ - struct gb_svc *svc = intf->hd->svc; - int ret; - - dev_dbg(&intf->dev, "%s - %d\n", __func__, enable); - - ret = gb_svc_intf_unipro_set(svc, intf->interface_id, enable); - if (ret) { - dev_err(&intf->dev, "failed to set UniPro: %d\n", ret); - return ret; - } - - return 0; -} - -static int gb_interface_activate_operation(struct gb_interface *intf, - enum gb_interface_type *intf_type) -{ - struct gb_svc *svc = intf->hd->svc; - u8 type; - int ret; - - dev_dbg(&intf->dev, "%s\n", __func__); - - ret = gb_svc_intf_activate(svc, intf->interface_id, &type); - if (ret) { - dev_err(&intf->dev, "failed to activate: %d\n", ret); - return ret; - } - - switch (type) { - case GB_SVC_INTF_TYPE_DUMMY: - *intf_type = GB_INTERFACE_TYPE_DUMMY; - /* FIXME: handle as an error for now */ - return -ENODEV; - case GB_SVC_INTF_TYPE_UNIPRO: - *intf_type = GB_INTERFACE_TYPE_UNIPRO; - dev_err(&intf->dev, "interface type UniPro not supported\n"); - /* FIXME: handle as an error for now */ - return -ENODEV; - case GB_SVC_INTF_TYPE_GREYBUS: - *intf_type = GB_INTERFACE_TYPE_GREYBUS; - break; - default: - dev_err(&intf->dev, "unknown interface type: %u\n", type); - *intf_type = GB_INTERFACE_TYPE_UNKNOWN; - return -ENODEV; - } - - return 0; -} - -static int gb_interface_hibernate_link(struct gb_interface *intf) -{ - struct gb_svc *svc = intf->hd->svc; - - return gb_svc_intf_set_power_mode_hibernate(svc, intf->interface_id); -} - -static int _gb_interface_activate(struct gb_interface *intf, - enum gb_interface_type *type) -{ - int ret; - - *type = GB_INTERFACE_TYPE_UNKNOWN; - - if (intf->ejected || intf->removed) - return -ENODEV; - - ret = gb_interface_vsys_set(intf, true); - if (ret) - return ret; - - ret = gb_interface_refclk_set(intf, true); - if (ret) - goto err_vsys_disable; - - ret = gb_interface_unipro_set(intf, true); - if (ret) - goto err_refclk_disable; - - ret = gb_interface_activate_operation(intf, type); - if (ret) { - switch (*type) { - case GB_INTERFACE_TYPE_UNIPRO: - case GB_INTERFACE_TYPE_GREYBUS: - goto err_hibernate_link; - default: - goto err_unipro_disable; - } - } - - ret = gb_interface_read_dme(intf); - if (ret) - goto err_hibernate_link; - - ret = gb_interface_route_create(intf); - if (ret) - goto err_hibernate_link; - - intf->active = true; - - trace_gb_interface_activate(intf); - - return 0; - -err_hibernate_link: - gb_interface_hibernate_link(intf); -err_unipro_disable: - gb_interface_unipro_set(intf, false); -err_refclk_disable: - gb_interface_refclk_set(intf, false); -err_vsys_disable: - gb_interface_vsys_set(intf, false); - - return ret; -} - -/* - * At present, we assume a UniPro-only module to be a Greybus module that - * failed to send its mailbox poke. There is some reason to believe that this - * is because of a bug in the ES3 bootrom. - * - * FIXME: Check if this is a Toshiba bridge before retrying? - */ -static int _gb_interface_activate_es3_hack(struct gb_interface *intf, - enum gb_interface_type *type) -{ - int retries = 3; - int ret; - - while (retries--) { - ret = _gb_interface_activate(intf, type); - if (ret == -ENODEV && *type == GB_INTERFACE_TYPE_UNIPRO) - continue; - - break; - } - - return ret; -} - -/* - * Activate an interface. - * - * Locking: Caller holds the interface mutex. - */ -int gb_interface_activate(struct gb_interface *intf) -{ - enum gb_interface_type type; - int ret; - - switch (intf->type) { - case GB_INTERFACE_TYPE_INVALID: - case GB_INTERFACE_TYPE_GREYBUS: - ret = _gb_interface_activate_es3_hack(intf, &type); - break; - default: - ret = _gb_interface_activate(intf, &type); - } - - /* Make sure type is detected correctly during reactivation. */ - if (intf->type != GB_INTERFACE_TYPE_INVALID) { - if (type != intf->type) { - dev_err(&intf->dev, "failed to detect interface type\n"); - - if (!ret) - gb_interface_deactivate(intf); - - return -EIO; - } - } else { - intf->type = type; - } - - return ret; -} - -/* - * Deactivate an interface. - * - * Locking: Caller holds the interface mutex. - */ -void gb_interface_deactivate(struct gb_interface *intf) -{ - if (!intf->active) - return; - - trace_gb_interface_deactivate(intf); - - /* Abort any ongoing mode switch. */ - if (intf->mode_switch) - complete(&intf->mode_switch_completion); - - gb_interface_route_destroy(intf); - gb_interface_hibernate_link(intf); - gb_interface_unipro_set(intf, false); - gb_interface_refclk_set(intf, false); - gb_interface_vsys_set(intf, false); - - intf->active = false; -} - -/* - * Enable an interface by enabling its control connection, fetching the - * manifest and other information over it, and finally registering its child - * devices. - * - * Locking: Caller holds the interface mutex. - */ -int gb_interface_enable(struct gb_interface *intf) -{ - struct gb_control *control; - struct gb_bundle *bundle, *tmp; - int ret, size; - void *manifest; - - ret = gb_interface_read_and_clear_init_status(intf); - if (ret) { - dev_err(&intf->dev, "failed to clear init status: %d\n", ret); - return ret; - } - - /* Establish control connection */ - control = gb_control_create(intf); - if (IS_ERR(control)) { - dev_err(&intf->dev, "failed to create control device: %ld\n", - PTR_ERR(control)); - return PTR_ERR(control); - } - intf->control = control; - - ret = gb_control_enable(intf->control); - if (ret) - goto err_put_control; - - /* Get manifest size using control protocol on CPort */ - size = gb_control_get_manifest_size_operation(intf); - if (size <= 0) { - dev_err(&intf->dev, "failed to get manifest size: %d\n", size); - - if (size) - ret = size; - else - ret = -EINVAL; - - goto err_disable_control; - } - - manifest = kmalloc(size, GFP_KERNEL); - if (!manifest) { - ret = -ENOMEM; - goto err_disable_control; - } - - /* Get manifest using control protocol on CPort */ - ret = gb_control_get_manifest_operation(intf, manifest, size); - if (ret) { - dev_err(&intf->dev, "failed to get manifest: %d\n", ret); - goto err_free_manifest; - } - - /* - * Parse the manifest and build up our data structures representing - * what's in it. - */ - if (!gb_manifest_parse(intf, manifest, size)) { - dev_err(&intf->dev, "failed to parse manifest\n"); - ret = -EINVAL; - goto err_destroy_bundles; - } - - ret = gb_control_get_bundle_versions(intf->control); - if (ret) - goto err_destroy_bundles; - - /* Register the control device and any bundles */ - ret = gb_control_add(intf->control); - if (ret) - goto err_destroy_bundles; - - pm_runtime_use_autosuspend(&intf->dev); - pm_runtime_get_noresume(&intf->dev); - pm_runtime_set_active(&intf->dev); - pm_runtime_enable(&intf->dev); - - list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) { - ret = gb_bundle_add(bundle); - if (ret) { - gb_bundle_destroy(bundle); - continue; - } - } - - kfree(manifest); - - intf->enabled = true; - - pm_runtime_put(&intf->dev); - - trace_gb_interface_enable(intf); - - return 0; - -err_destroy_bundles: - list_for_each_entry_safe(bundle, tmp, &intf->bundles, links) - gb_bundle_destroy(bundle); -err_free_manifest: - kfree(manifest); -err_disable_control: - gb_control_disable(intf->control); -err_put_control: - gb_control_put(intf->control); - intf->control = NULL; - - return ret; -} - -/* - * Disable an interface and destroy its bundles. - * - * Locking: Caller holds the interface mutex. - */ -void gb_interface_disable(struct gb_interface *intf) -{ - struct gb_bundle *bundle; - struct gb_bundle *next; - - if (!intf->enabled) - return; - - trace_gb_interface_disable(intf); - - pm_runtime_get_sync(&intf->dev); - - /* Set disconnected flag to avoid I/O during connection tear down. */ - if (intf->quirks & GB_INTERFACE_QUIRK_FORCED_DISABLE) - intf->disconnected = true; - - list_for_each_entry_safe(bundle, next, &intf->bundles, links) - gb_bundle_destroy(bundle); - - if (!intf->mode_switch && !intf->disconnected) - gb_control_interface_deactivate_prepare(intf->control); - - gb_control_del(intf->control); - gb_control_disable(intf->control); - gb_control_put(intf->control); - intf->control = NULL; - - intf->enabled = false; - - pm_runtime_disable(&intf->dev); - pm_runtime_set_suspended(&intf->dev); - pm_runtime_dont_use_autosuspend(&intf->dev); - pm_runtime_put_noidle(&intf->dev); -} - -/* Register an interface. */ -int gb_interface_add(struct gb_interface *intf) -{ - int ret; - - ret = device_add(&intf->dev); - if (ret) { - dev_err(&intf->dev, "failed to register interface: %d\n", ret); - return ret; - } - - trace_gb_interface_add(intf); - - dev_info(&intf->dev, "Interface added (%s)\n", - gb_interface_type_string(intf)); - - switch (intf->type) { - case GB_INTERFACE_TYPE_GREYBUS: - dev_info(&intf->dev, "GMP VID=0x%08x, PID=0x%08x\n", - intf->vendor_id, intf->product_id); - /* fall-through */ - case GB_INTERFACE_TYPE_UNIPRO: - dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n", - intf->ddbl1_manufacturer_id, - intf->ddbl1_product_id); - break; - default: - break; - } - - return 0; -} - -/* Deregister an interface. */ -void gb_interface_del(struct gb_interface *intf) -{ - if (device_is_registered(&intf->dev)) { - trace_gb_interface_del(intf); - - device_del(&intf->dev); - dev_info(&intf->dev, "Interface removed\n"); - } -} - -void gb_interface_put(struct gb_interface *intf) -{ - put_device(&intf->dev); -} diff --git a/drivers/staging/greybus/manifest.c b/drivers/staging/greybus/manifest.c deleted file mode 100644 index dd7040697bde..000000000000 --- a/drivers/staging/greybus/manifest.c +++ /dev/null @@ -1,533 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus manifest parsing - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#include - -static const char *get_descriptor_type_string(u8 type) -{ - switch (type) { - case GREYBUS_TYPE_INVALID: - return "invalid"; - case GREYBUS_TYPE_STRING: - return "string"; - case GREYBUS_TYPE_INTERFACE: - return "interface"; - case GREYBUS_TYPE_CPORT: - return "cport"; - case GREYBUS_TYPE_BUNDLE: - return "bundle"; - default: - WARN_ON(1); - return "unknown"; - } -} - -/* - * We scan the manifest once to identify where all the descriptors - * are. The result is a list of these manifest_desc structures. We - * then pick through them for what we're looking for (starting with - * the interface descriptor). As each is processed we remove it from - * the list. When we're done the list should (probably) be empty. - */ -struct manifest_desc { - struct list_head links; - - size_t size; - void *data; - enum greybus_descriptor_type type; -}; - -static void release_manifest_descriptor(struct manifest_desc *descriptor) -{ - list_del(&descriptor->links); - kfree(descriptor); -} - -static void release_manifest_descriptors(struct gb_interface *intf) -{ - struct manifest_desc *descriptor; - struct manifest_desc *next; - - list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) - release_manifest_descriptor(descriptor); -} - -static void release_cport_descriptors(struct list_head *head, u8 bundle_id) -{ - struct manifest_desc *desc, *tmp; - struct greybus_descriptor_cport *desc_cport; - - list_for_each_entry_safe(desc, tmp, head, links) { - desc_cport = desc->data; - - if (desc->type != GREYBUS_TYPE_CPORT) - continue; - - if (desc_cport->bundle == bundle_id) - release_manifest_descriptor(desc); - } -} - -static struct manifest_desc *get_next_bundle_desc(struct gb_interface *intf) -{ - struct manifest_desc *descriptor; - struct manifest_desc *next; - - list_for_each_entry_safe(descriptor, next, &intf->manifest_descs, links) - if (descriptor->type == GREYBUS_TYPE_BUNDLE) - return descriptor; - - return NULL; -} - -/* - * Validate the given descriptor. Its reported size must fit within - * the number of bytes remaining, and it must have a recognized - * type. Check that the reported size is at least as big as what - * we expect to see. (It could be bigger, perhaps for a new version - * of the format.) - * - * Returns the (non-zero) number of bytes consumed by the descriptor, - * or a negative errno. - */ -static int identify_descriptor(struct gb_interface *intf, - struct greybus_descriptor *desc, size_t size) -{ - struct greybus_descriptor_header *desc_header = &desc->header; - struct manifest_desc *descriptor; - size_t desc_size; - size_t expected_size; - - if (size < sizeof(*desc_header)) { - dev_err(&intf->dev, "manifest too small (%zu < %zu)\n", size, - sizeof(*desc_header)); - return -EINVAL; /* Must at least have header */ - } - - desc_size = le16_to_cpu(desc_header->size); - if (desc_size > size) { - dev_err(&intf->dev, "descriptor too big (%zu > %zu)\n", - desc_size, size); - return -EINVAL; - } - - /* Descriptor needs to at least have a header */ - expected_size = sizeof(*desc_header); - - switch (desc_header->type) { - case GREYBUS_TYPE_STRING: - expected_size += sizeof(struct greybus_descriptor_string); - expected_size += desc->string.length; - - /* String descriptors are padded to 4 byte boundaries */ - expected_size = ALIGN(expected_size, 4); - break; - case GREYBUS_TYPE_INTERFACE: - expected_size += sizeof(struct greybus_descriptor_interface); - break; - case GREYBUS_TYPE_BUNDLE: - expected_size += sizeof(struct greybus_descriptor_bundle); - break; - case GREYBUS_TYPE_CPORT: - expected_size += sizeof(struct greybus_descriptor_cport); - break; - case GREYBUS_TYPE_INVALID: - default: - dev_err(&intf->dev, "invalid descriptor type (%u)\n", - desc_header->type); - return -EINVAL; - } - - if (desc_size < expected_size) { - dev_err(&intf->dev, "%s descriptor too small (%zu < %zu)\n", - get_descriptor_type_string(desc_header->type), - desc_size, expected_size); - return -EINVAL; - } - - /* Descriptor bigger than what we expect */ - if (desc_size > expected_size) { - dev_warn(&intf->dev, "%s descriptor size mismatch (want %zu got %zu)\n", - get_descriptor_type_string(desc_header->type), - expected_size, desc_size); - } - - descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); - if (!descriptor) - return -ENOMEM; - - descriptor->size = desc_size; - descriptor->data = (char *)desc + sizeof(*desc_header); - descriptor->type = desc_header->type; - list_add_tail(&descriptor->links, &intf->manifest_descs); - - /* desc_size is positive and is known to fit in a signed int */ - - return desc_size; -} - -/* - * Find the string descriptor having the given id, validate it, and - * allocate a duplicate copy of it. The duplicate has an extra byte - * which guarantees the returned string is NUL-terminated. - * - * String index 0 is valid (it represents "no string"), and for - * that a null pointer is returned. - * - * Otherwise returns a pointer to a newly-allocated copy of the - * descriptor string, or an error-coded pointer on failure. - */ -static char *gb_string_get(struct gb_interface *intf, u8 string_id) -{ - struct greybus_descriptor_string *desc_string; - struct manifest_desc *descriptor; - bool found = false; - char *string; - - /* A zero string id means no string (but no error) */ - if (!string_id) - return NULL; - - list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type != GREYBUS_TYPE_STRING) - continue; - - desc_string = descriptor->data; - if (desc_string->id == string_id) { - found = true; - break; - } - } - if (!found) - return ERR_PTR(-ENOENT); - - /* Allocate an extra byte so we can guarantee it's NUL-terminated */ - string = kmemdup(&desc_string->string, desc_string->length + 1, - GFP_KERNEL); - if (!string) - return ERR_PTR(-ENOMEM); - string[desc_string->length] = '\0'; - - /* Ok we've used this string, so we're done with it */ - release_manifest_descriptor(descriptor); - - return string; -} - -/* - * Find cport descriptors in the manifest associated with the given - * bundle, and set up data structures for the functions that use - * them. Returns the number of cports set up for the bundle, or 0 - * if there is an error. - */ -static u32 gb_manifest_parse_cports(struct gb_bundle *bundle) -{ - struct gb_interface *intf = bundle->intf; - struct greybus_descriptor_cport *desc_cport; - struct manifest_desc *desc, *next, *tmp; - LIST_HEAD(list); - u8 bundle_id = bundle->id; - u16 cport_id; - u32 count = 0; - int i; - - /* Set up all cport descriptors associated with this bundle */ - list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) { - if (desc->type != GREYBUS_TYPE_CPORT) - continue; - - desc_cport = desc->data; - if (desc_cport->bundle != bundle_id) - continue; - - cport_id = le16_to_cpu(desc_cport->id); - if (cport_id > CPORT_ID_MAX) - goto exit; - - /* Nothing else should have its cport_id as control cport id */ - if (cport_id == GB_CONTROL_CPORT_ID) { - dev_err(&bundle->dev, "invalid cport id found (%02u)\n", - cport_id); - goto exit; - } - - /* - * Found one, move it to our temporary list after checking for - * duplicates. - */ - list_for_each_entry(tmp, &list, links) { - desc_cport = tmp->data; - if (cport_id == le16_to_cpu(desc_cport->id)) { - dev_err(&bundle->dev, - "duplicate CPort %u found\n", cport_id); - goto exit; - } - } - list_move_tail(&desc->links, &list); - count++; - } - - if (!count) - return 0; - - bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc), - GFP_KERNEL); - if (!bundle->cport_desc) - goto exit; - - bundle->num_cports = count; - - i = 0; - list_for_each_entry_safe(desc, next, &list, links) { - desc_cport = desc->data; - memcpy(&bundle->cport_desc[i++], desc_cport, - sizeof(*desc_cport)); - - /* Release the cport descriptor */ - release_manifest_descriptor(desc); - } - - return count; -exit: - release_cport_descriptors(&list, bundle_id); - /* - * Free all cports for this bundle to avoid 'excess descriptors' - * warnings. - */ - release_cport_descriptors(&intf->manifest_descs, bundle_id); - - return 0; /* Error; count should also be 0 */ -} - -/* - * Find bundle descriptors in the manifest and set up their data - * structures. Returns the number of bundles set up for the - * given interface. - */ -static u32 gb_manifest_parse_bundles(struct gb_interface *intf) -{ - struct manifest_desc *desc; - struct gb_bundle *bundle; - struct gb_bundle *bundle_next; - u32 count = 0; - u8 bundle_id; - u8 class; - - while ((desc = get_next_bundle_desc(intf))) { - struct greybus_descriptor_bundle *desc_bundle; - - /* Found one. Set up its bundle structure*/ - desc_bundle = desc->data; - bundle_id = desc_bundle->id; - class = desc_bundle->class; - - /* Done with this bundle descriptor */ - release_manifest_descriptor(desc); - - /* Ignore any legacy control bundles */ - if (bundle_id == GB_CONTROL_BUNDLE_ID) { - dev_dbg(&intf->dev, "%s - ignoring control bundle\n", - __func__); - release_cport_descriptors(&intf->manifest_descs, - bundle_id); - continue; - } - - /* Nothing else should have its class set to control class */ - if (class == GREYBUS_CLASS_CONTROL) { - dev_err(&intf->dev, - "bundle %u cannot use control class\n", - bundle_id); - goto cleanup; - } - - bundle = gb_bundle_create(intf, bundle_id, class); - if (!bundle) - goto cleanup; - - /* - * Now go set up this bundle's functions and cports. - * - * A 'bundle' represents a device in greybus. It may require - * multiple cports for its functioning. If we fail to setup any - * cport of a bundle, we better reject the complete bundle as - * the device may not be able to function properly then. - * - * But, failing to setup a cport of bundle X doesn't mean that - * the device corresponding to bundle Y will not work properly. - * Bundles should be treated as separate independent devices. - * - * While parsing manifest for an interface, treat bundles as - * separate entities and don't reject entire interface and its - * bundles on failing to initialize a cport. But make sure the - * bundle which needs the cport, gets destroyed properly. - */ - if (!gb_manifest_parse_cports(bundle)) { - gb_bundle_destroy(bundle); - continue; - } - - count++; - } - - return count; -cleanup: - /* An error occurred; undo any changes we've made */ - list_for_each_entry_safe(bundle, bundle_next, &intf->bundles, links) { - gb_bundle_destroy(bundle); - count--; - } - return 0; /* Error; count should also be 0 */ -} - -static bool gb_manifest_parse_interface(struct gb_interface *intf, - struct manifest_desc *interface_desc) -{ - struct greybus_descriptor_interface *desc_intf = interface_desc->data; - struct gb_control *control = intf->control; - char *str; - - /* Handle the strings first--they can fail */ - str = gb_string_get(intf, desc_intf->vendor_stringid); - if (IS_ERR(str)) - return false; - control->vendor_string = str; - - str = gb_string_get(intf, desc_intf->product_stringid); - if (IS_ERR(str)) - goto out_free_vendor_string; - control->product_string = str; - - /* Assign feature flags communicated via manifest */ - intf->features = desc_intf->features; - - /* Release the interface descriptor, now that we're done with it */ - release_manifest_descriptor(interface_desc); - - /* An interface must have at least one bundle descriptor */ - if (!gb_manifest_parse_bundles(intf)) { - dev_err(&intf->dev, "manifest bundle descriptors not valid\n"); - goto out_err; - } - - return true; -out_err: - kfree(control->product_string); - control->product_string = NULL; -out_free_vendor_string: - kfree(control->vendor_string); - control->vendor_string = NULL; - - return false; -} - -/* - * Parse a buffer containing an interface manifest. - * - * If we find anything wrong with the content/format of the buffer - * we reject it. - * - * The first requirement is that the manifest's version is - * one we can parse. - * - * We make an initial pass through the buffer and identify all of - * the descriptors it contains, keeping track for each its type - * and the location size of its data in the buffer. - * - * Next we scan the descriptors, looking for an interface descriptor; - * there must be exactly one of those. When found, we record the - * information it contains, and then remove that descriptor (and any - * string descriptors it refers to) from further consideration. - * - * After that we look for the interface's bundles--there must be at - * least one of those. - * - * Returns true if parsing was successful, false otherwise. - */ -bool gb_manifest_parse(struct gb_interface *intf, void *data, size_t size) -{ - struct greybus_manifest *manifest; - struct greybus_manifest_header *header; - struct greybus_descriptor *desc; - struct manifest_desc *descriptor; - struct manifest_desc *interface_desc = NULL; - u16 manifest_size; - u32 found = 0; - bool result; - - /* Manifest descriptor list should be empty here */ - if (WARN_ON(!list_empty(&intf->manifest_descs))) - return false; - - /* we have to have at _least_ the manifest header */ - if (size < sizeof(*header)) { - dev_err(&intf->dev, "short manifest (%zu < %zu)\n", - size, sizeof(*header)); - return false; - } - - /* Make sure the size is right */ - manifest = data; - header = &manifest->header; - manifest_size = le16_to_cpu(header->size); - if (manifest_size != size) { - dev_err(&intf->dev, "manifest size mismatch (%zu != %u)\n", - size, manifest_size); - return false; - } - - /* Validate major/minor number */ - if (header->version_major > GREYBUS_VERSION_MAJOR) { - dev_err(&intf->dev, "manifest version too new (%u.%u > %u.%u)\n", - header->version_major, header->version_minor, - GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR); - return false; - } - - /* OK, find all the descriptors */ - desc = manifest->descriptors; - size -= sizeof(*header); - while (size) { - int desc_size; - - desc_size = identify_descriptor(intf, desc, size); - if (desc_size < 0) { - result = false; - goto out; - } - desc = (struct greybus_descriptor *)((char *)desc + desc_size); - size -= desc_size; - } - - /* There must be a single interface descriptor */ - list_for_each_entry(descriptor, &intf->manifest_descs, links) { - if (descriptor->type == GREYBUS_TYPE_INTERFACE) - if (!found++) - interface_desc = descriptor; - } - if (found != 1) { - dev_err(&intf->dev, "manifest must have 1 interface descriptor (%u found)\n", - found); - result = false; - goto out; - } - - /* Parse the manifest, starting with the interface descriptor */ - result = gb_manifest_parse_interface(intf, interface_desc); - - /* - * We really should have no remaining descriptors, but we - * don't know what newer format manifests might leave. - */ - if (result && !list_empty(&intf->manifest_descs)) - dev_info(&intf->dev, "excess descriptors in interface manifest\n"); -out: - release_manifest_descriptors(intf); - - return result; -} diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c deleted file mode 100644 index 36f77f9e1d74..000000000000 --- a/drivers/staging/greybus/module.c +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus Module code - * - * Copyright 2016 Google Inc. - * Copyright 2016 Linaro Ltd. - */ - -#include -#include "greybus_trace.h" - -static ssize_t eject_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct gb_module *module = to_gb_module(dev); - struct gb_interface *intf; - size_t i; - long val; - int ret; - - ret = kstrtol(buf, 0, &val); - if (ret) - return ret; - - if (!val) - return len; - - for (i = 0; i < module->num_interfaces; ++i) { - intf = module->interfaces[i]; - - mutex_lock(&intf->mutex); - /* Set flag to prevent concurrent activation. */ - intf->ejected = true; - gb_interface_disable(intf); - gb_interface_deactivate(intf); - mutex_unlock(&intf->mutex); - } - - /* Tell the SVC to eject the primary interface. */ - ret = gb_svc_intf_eject(module->hd->svc, module->module_id); - if (ret) - return ret; - - return len; -} -static DEVICE_ATTR_WO(eject); - -static ssize_t module_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_module *module = to_gb_module(dev); - - return sprintf(buf, "%u\n", module->module_id); -} -static DEVICE_ATTR_RO(module_id); - -static ssize_t num_interfaces_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_module *module = to_gb_module(dev); - - return sprintf(buf, "%zu\n", module->num_interfaces); -} -static DEVICE_ATTR_RO(num_interfaces); - -static struct attribute *module_attrs[] = { - &dev_attr_eject.attr, - &dev_attr_module_id.attr, - &dev_attr_num_interfaces.attr, - NULL, -}; -ATTRIBUTE_GROUPS(module); - -static void gb_module_release(struct device *dev) -{ - struct gb_module *module = to_gb_module(dev); - - trace_gb_module_release(module); - - kfree(module); -} - -struct device_type greybus_module_type = { - .name = "greybus_module", - .release = gb_module_release, -}; - -struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id, - size_t num_interfaces) -{ - struct gb_interface *intf; - struct gb_module *module; - int i; - - module = kzalloc(struct_size(module, interfaces, num_interfaces), - GFP_KERNEL); - if (!module) - return NULL; - - module->hd = hd; - module->module_id = module_id; - module->num_interfaces = num_interfaces; - - module->dev.parent = &hd->dev; - module->dev.bus = &greybus_bus_type; - module->dev.type = &greybus_module_type; - module->dev.groups = module_groups; - module->dev.dma_mask = hd->dev.dma_mask; - device_initialize(&module->dev); - dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id); - - trace_gb_module_create(module); - - for (i = 0; i < num_interfaces; ++i) { - intf = gb_interface_create(module, module_id + i); - if (!intf) { - dev_err(&module->dev, "failed to create interface %u\n", - module_id + i); - goto err_put_interfaces; - } - module->interfaces[i] = intf; - } - - return module; - -err_put_interfaces: - for (--i; i >= 0; --i) - gb_interface_put(module->interfaces[i]); - - put_device(&module->dev); - - return NULL; -} - -/* - * Register and enable an interface after first attempting to activate it. - */ -static void gb_module_register_interface(struct gb_interface *intf) -{ - struct gb_module *module = intf->module; - u8 intf_id = intf->interface_id; - int ret; - - mutex_lock(&intf->mutex); - - ret = gb_interface_activate(intf); - if (ret) { - if (intf->type != GB_INTERFACE_TYPE_DUMMY) { - dev_err(&module->dev, - "failed to activate interface %u: %d\n", - intf_id, ret); - } - - gb_interface_add(intf); - goto err_unlock; - } - - ret = gb_interface_add(intf); - if (ret) - goto err_interface_deactivate; - - ret = gb_interface_enable(intf); - if (ret) { - dev_err(&module->dev, "failed to enable interface %u: %d\n", - intf_id, ret); - goto err_interface_deactivate; - } - - mutex_unlock(&intf->mutex); - - return; - -err_interface_deactivate: - gb_interface_deactivate(intf); -err_unlock: - mutex_unlock(&intf->mutex); -} - -static void gb_module_deregister_interface(struct gb_interface *intf) -{ - /* Mark as disconnected to prevent I/O during disable. */ - if (intf->module->disconnected) - intf->disconnected = true; - - mutex_lock(&intf->mutex); - intf->removed = true; - gb_interface_disable(intf); - gb_interface_deactivate(intf); - mutex_unlock(&intf->mutex); - - gb_interface_del(intf); -} - -/* Register a module and its interfaces. */ -int gb_module_add(struct gb_module *module) -{ - size_t i; - int ret; - - ret = device_add(&module->dev); - if (ret) { - dev_err(&module->dev, "failed to register module: %d\n", ret); - return ret; - } - - trace_gb_module_add(module); - - for (i = 0; i < module->num_interfaces; ++i) - gb_module_register_interface(module->interfaces[i]); - - return 0; -} - -/* Deregister a module and its interfaces. */ -void gb_module_del(struct gb_module *module) -{ - size_t i; - - for (i = 0; i < module->num_interfaces; ++i) - gb_module_deregister_interface(module->interfaces[i]); - - trace_gb_module_del(module); - - device_del(&module->dev); -} - -void gb_module_put(struct gb_module *module) -{ - size_t i; - - for (i = 0; i < module->num_interfaces; ++i) - gb_interface_put(module->interfaces[i]); - - put_device(&module->dev); -} diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c deleted file mode 100644 index 8459e9bc0749..000000000000 --- a/drivers/staging/greybus/operation.c +++ /dev/null @@ -1,1264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus operations - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "greybus_trace.h" - -static struct kmem_cache *gb_operation_cache; -static struct kmem_cache *gb_message_cache; - -/* Workqueue to handle Greybus operation completions. */ -static struct workqueue_struct *gb_operation_completion_wq; - -/* Wait queue for synchronous cancellations. */ -static DECLARE_WAIT_QUEUE_HEAD(gb_operation_cancellation_queue); - -/* - * Protects updates to operation->errno. - */ -static DEFINE_SPINLOCK(gb_operations_lock); - -static int gb_operation_response_send(struct gb_operation *operation, - int errno); - -/* - * Increment operation active count and add to connection list unless the - * connection is going away. - * - * Caller holds operation reference. - */ -static int gb_operation_get_active(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - unsigned long flags; - - spin_lock_irqsave(&connection->lock, flags); - switch (connection->state) { - case GB_CONNECTION_STATE_ENABLED: - break; - case GB_CONNECTION_STATE_ENABLED_TX: - if (gb_operation_is_incoming(operation)) - goto err_unlock; - break; - case GB_CONNECTION_STATE_DISCONNECTING: - if (!gb_operation_is_core(operation)) - goto err_unlock; - break; - default: - goto err_unlock; - } - - if (operation->active++ == 0) - list_add_tail(&operation->links, &connection->operations); - - trace_gb_operation_get_active(operation); - - spin_unlock_irqrestore(&connection->lock, flags); - - return 0; - -err_unlock: - spin_unlock_irqrestore(&connection->lock, flags); - - return -ENOTCONN; -} - -/* Caller holds operation reference. */ -static void gb_operation_put_active(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - unsigned long flags; - - spin_lock_irqsave(&connection->lock, flags); - - trace_gb_operation_put_active(operation); - - if (--operation->active == 0) { - list_del(&operation->links); - if (atomic_read(&operation->waiters)) - wake_up(&gb_operation_cancellation_queue); - } - spin_unlock_irqrestore(&connection->lock, flags); -} - -static bool gb_operation_is_active(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - unsigned long flags; - bool ret; - - spin_lock_irqsave(&connection->lock, flags); - ret = operation->active; - spin_unlock_irqrestore(&connection->lock, flags); - - return ret; -} - -/* - * Set an operation's result. - * - * Initially an outgoing operation's errno value is -EBADR. - * If no error occurs before sending the request message the only - * valid value operation->errno can be set to is -EINPROGRESS, - * indicating the request has been (or rather is about to be) sent. - * At that point nobody should be looking at the result until the - * response arrives. - * - * The first time the result gets set after the request has been - * sent, that result "sticks." That is, if two concurrent threads - * race to set the result, the first one wins. The return value - * tells the caller whether its result was recorded; if not the - * caller has nothing more to do. - * - * The result value -EILSEQ is reserved to signal an implementation - * error; if it's ever observed, the code performing the request has - * done something fundamentally wrong. It is an error to try to set - * the result to -EBADR, and attempts to do so result in a warning, - * and -EILSEQ is used instead. Similarly, the only valid result - * value to set for an operation in initial state is -EINPROGRESS. - * Attempts to do otherwise will also record a (successful) -EILSEQ - * operation result. - */ -static bool gb_operation_result_set(struct gb_operation *operation, int result) -{ - unsigned long flags; - int prev; - - if (result == -EINPROGRESS) { - /* - * -EINPROGRESS is used to indicate the request is - * in flight. It should be the first result value - * set after the initial -EBADR. Issue a warning - * and record an implementation error if it's - * set at any other time. - */ - spin_lock_irqsave(&gb_operations_lock, flags); - prev = operation->errno; - if (prev == -EBADR) - operation->errno = result; - else - operation->errno = -EILSEQ; - spin_unlock_irqrestore(&gb_operations_lock, flags); - WARN_ON(prev != -EBADR); - - return true; - } - - /* - * The first result value set after a request has been sent - * will be the final result of the operation. Subsequent - * attempts to set the result are ignored. - * - * Note that -EBADR is a reserved "initial state" result - * value. Attempts to set this value result in a warning, - * and the result code is set to -EILSEQ instead. - */ - if (WARN_ON(result == -EBADR)) - result = -EILSEQ; /* Nobody should be setting -EBADR */ - - spin_lock_irqsave(&gb_operations_lock, flags); - prev = operation->errno; - if (prev == -EINPROGRESS) - operation->errno = result; /* First and final result */ - spin_unlock_irqrestore(&gb_operations_lock, flags); - - return prev == -EINPROGRESS; -} - -int gb_operation_result(struct gb_operation *operation) -{ - int result = operation->errno; - - WARN_ON(result == -EBADR); - WARN_ON(result == -EINPROGRESS); - - return result; -} -EXPORT_SYMBOL_GPL(gb_operation_result); - -/* - * Looks up an outgoing operation on a connection and returns a refcounted - * pointer if found, or NULL otherwise. - */ -static struct gb_operation * -gb_operation_find_outgoing(struct gb_connection *connection, u16 operation_id) -{ - struct gb_operation *operation; - unsigned long flags; - bool found = false; - - spin_lock_irqsave(&connection->lock, flags); - list_for_each_entry(operation, &connection->operations, links) - if (operation->id == operation_id && - !gb_operation_is_incoming(operation)) { - gb_operation_get(operation); - found = true; - break; - } - spin_unlock_irqrestore(&connection->lock, flags); - - return found ? operation : NULL; -} - -static int gb_message_send(struct gb_message *message, gfp_t gfp) -{ - struct gb_connection *connection = message->operation->connection; - - trace_gb_message_send(message); - return connection->hd->driver->message_send(connection->hd, - connection->hd_cport_id, - message, - gfp); -} - -/* - * Cancel a message we have passed to the host device layer to be sent. - */ -static void gb_message_cancel(struct gb_message *message) -{ - struct gb_host_device *hd = message->operation->connection->hd; - - hd->driver->message_cancel(message); -} - -static void gb_operation_request_handle(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - int status; - int ret; - - if (connection->handler) { - status = connection->handler(operation); - } else { - dev_err(&connection->hd->dev, - "%s: unexpected incoming request of type 0x%02x\n", - connection->name, operation->type); - - status = -EPROTONOSUPPORT; - } - - ret = gb_operation_response_send(operation, status); - if (ret) { - dev_err(&connection->hd->dev, - "%s: failed to send response %d for type 0x%02x: %d\n", - connection->name, status, operation->type, ret); - return; - } -} - -/* - * Process operation work. - * - * For incoming requests, call the protocol request handler. The operation - * result should be -EINPROGRESS at this point. - * - * For outgoing requests, the operation result value should have - * been set before queueing this. The operation callback function - * allows the original requester to know the request has completed - * and its result is available. - */ -static void gb_operation_work(struct work_struct *work) -{ - struct gb_operation *operation; - int ret; - - operation = container_of(work, struct gb_operation, work); - - if (gb_operation_is_incoming(operation)) { - gb_operation_request_handle(operation); - } else { - ret = del_timer_sync(&operation->timer); - if (!ret) { - /* Cancel request message if scheduled by timeout. */ - if (gb_operation_result(operation) == -ETIMEDOUT) - gb_message_cancel(operation->request); - } - - operation->callback(operation); - } - - gb_operation_put_active(operation); - gb_operation_put(operation); -} - -static void gb_operation_timeout(struct timer_list *t) -{ - struct gb_operation *operation = from_timer(operation, t, timer); - - if (gb_operation_result_set(operation, -ETIMEDOUT)) { - /* - * A stuck request message will be cancelled from the - * workqueue. - */ - queue_work(gb_operation_completion_wq, &operation->work); - } -} - -static void gb_operation_message_init(struct gb_host_device *hd, - struct gb_message *message, - u16 operation_id, - size_t payload_size, u8 type) -{ - struct gb_operation_msg_hdr *header; - - header = message->buffer; - - message->header = header; - message->payload = payload_size ? header + 1 : NULL; - message->payload_size = payload_size; - - /* - * The type supplied for incoming message buffers will be - * GB_REQUEST_TYPE_INVALID. Such buffers will be overwritten by - * arriving data so there's no need to initialize the message header. - */ - if (type != GB_REQUEST_TYPE_INVALID) { - u16 message_size = (u16)(sizeof(*header) + payload_size); - - /* - * For a request, the operation id gets filled in - * when the message is sent. For a response, it - * will be copied from the request by the caller. - * - * The result field in a request message must be - * zero. It will be set just prior to sending for - * a response. - */ - header->size = cpu_to_le16(message_size); - header->operation_id = 0; - header->type = type; - header->result = 0; - } -} - -/* - * Allocate a message to be used for an operation request or response. - * Both types of message contain a common header. The request message - * for an outgoing operation is outbound, as is the response message - * for an incoming operation. The message header for an outbound - * message is partially initialized here. - * - * The headers for inbound messages don't need to be initialized; - * they'll be filled in by arriving data. - * - * Our message buffers have the following layout: - * message header \_ these combined are - * message payload / the message size - */ -static struct gb_message * -gb_operation_message_alloc(struct gb_host_device *hd, u8 type, - size_t payload_size, gfp_t gfp_flags) -{ - struct gb_message *message; - struct gb_operation_msg_hdr *header; - size_t message_size = payload_size + sizeof(*header); - - if (message_size > hd->buffer_size_max) { - dev_warn(&hd->dev, "requested message size too big (%zu > %zu)\n", - message_size, hd->buffer_size_max); - return NULL; - } - - /* Allocate the message structure and buffer. */ - message = kmem_cache_zalloc(gb_message_cache, gfp_flags); - if (!message) - return NULL; - - message->buffer = kzalloc(message_size, gfp_flags); - if (!message->buffer) - goto err_free_message; - - /* Initialize the message. Operation id is filled in later. */ - gb_operation_message_init(hd, message, 0, payload_size, type); - - return message; - -err_free_message: - kmem_cache_free(gb_message_cache, message); - - return NULL; -} - -static void gb_operation_message_free(struct gb_message *message) -{ - kfree(message->buffer); - kmem_cache_free(gb_message_cache, message); -} - -/* - * Map an enum gb_operation_status value (which is represented in a - * message as a single byte) to an appropriate Linux negative errno. - */ -static int gb_operation_status_map(u8 status) -{ - switch (status) { - case GB_OP_SUCCESS: - return 0; - case GB_OP_INTERRUPTED: - return -EINTR; - case GB_OP_TIMEOUT: - return -ETIMEDOUT; - case GB_OP_NO_MEMORY: - return -ENOMEM; - case GB_OP_PROTOCOL_BAD: - return -EPROTONOSUPPORT; - case GB_OP_OVERFLOW: - return -EMSGSIZE; - case GB_OP_INVALID: - return -EINVAL; - case GB_OP_RETRY: - return -EAGAIN; - case GB_OP_NONEXISTENT: - return -ENODEV; - case GB_OP_MALFUNCTION: - return -EILSEQ; - case GB_OP_UNKNOWN_ERROR: - default: - return -EIO; - } -} - -/* - * Map a Linux errno value (from operation->errno) into the value - * that should represent it in a response message status sent - * over the wire. Returns an enum gb_operation_status value (which - * is represented in a message as a single byte). - */ -static u8 gb_operation_errno_map(int errno) -{ - switch (errno) { - case 0: - return GB_OP_SUCCESS; - case -EINTR: - return GB_OP_INTERRUPTED; - case -ETIMEDOUT: - return GB_OP_TIMEOUT; - case -ENOMEM: - return GB_OP_NO_MEMORY; - case -EPROTONOSUPPORT: - return GB_OP_PROTOCOL_BAD; - case -EMSGSIZE: - return GB_OP_OVERFLOW; /* Could be underflow too */ - case -EINVAL: - return GB_OP_INVALID; - case -EAGAIN: - return GB_OP_RETRY; - case -EILSEQ: - return GB_OP_MALFUNCTION; - case -ENODEV: - return GB_OP_NONEXISTENT; - case -EIO: - default: - return GB_OP_UNKNOWN_ERROR; - } -} - -bool gb_operation_response_alloc(struct gb_operation *operation, - size_t response_size, gfp_t gfp) -{ - struct gb_host_device *hd = operation->connection->hd; - struct gb_operation_msg_hdr *request_header; - struct gb_message *response; - u8 type; - - type = operation->type | GB_MESSAGE_TYPE_RESPONSE; - response = gb_operation_message_alloc(hd, type, response_size, gfp); - if (!response) - return false; - response->operation = operation; - - /* - * Size and type get initialized when the message is - * allocated. The errno will be set before sending. All - * that's left is the operation id, which we copy from the - * request message header (as-is, in little-endian order). - */ - request_header = operation->request->header; - response->header->operation_id = request_header->operation_id; - operation->response = response; - - return true; -} -EXPORT_SYMBOL_GPL(gb_operation_response_alloc); - -/* - * Create a Greybus operation to be sent over the given connection. - * The request buffer will be big enough for a payload of the given - * size. - * - * For outgoing requests, the request message's header will be - * initialized with the type of the request and the message size. - * Outgoing operations must also specify the response buffer size, - * which must be sufficient to hold all expected response data. The - * response message header will eventually be overwritten, so there's - * no need to initialize it here. - * - * Request messages for incoming operations can arrive in interrupt - * context, so they must be allocated with GFP_ATOMIC. In this case - * the request buffer will be immediately overwritten, so there is - * no need to initialize the message header. Responsibility for - * allocating a response buffer lies with the incoming request - * handler for a protocol. So we don't allocate that here. - * - * Returns a pointer to the new operation or a null pointer if an - * error occurs. - */ -static struct gb_operation * -gb_operation_create_common(struct gb_connection *connection, u8 type, - size_t request_size, size_t response_size, - unsigned long op_flags, gfp_t gfp_flags) -{ - struct gb_host_device *hd = connection->hd; - struct gb_operation *operation; - - operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); - if (!operation) - return NULL; - operation->connection = connection; - - operation->request = gb_operation_message_alloc(hd, type, request_size, - gfp_flags); - if (!operation->request) - goto err_cache; - operation->request->operation = operation; - - /* Allocate the response buffer for outgoing operations */ - if (!(op_flags & GB_OPERATION_FLAG_INCOMING)) { - if (!gb_operation_response_alloc(operation, response_size, - gfp_flags)) { - goto err_request; - } - - timer_setup(&operation->timer, gb_operation_timeout, 0); - } - - operation->flags = op_flags; - operation->type = type; - operation->errno = -EBADR; /* Initial value--means "never set" */ - - INIT_WORK(&operation->work, gb_operation_work); - init_completion(&operation->completion); - kref_init(&operation->kref); - atomic_set(&operation->waiters, 0); - - return operation; - -err_request: - gb_operation_message_free(operation->request); -err_cache: - kmem_cache_free(gb_operation_cache, operation); - - return NULL; -} - -/* - * Create a new operation associated with the given connection. The - * request and response sizes provided are the number of bytes - * required to hold the request/response payload only. Both of - * these are allowed to be 0. Note that 0x00 is reserved as an - * invalid operation type for all protocols, and this is enforced - * here. - */ -struct gb_operation * -gb_operation_create_flags(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, unsigned long flags, - gfp_t gfp) -{ - struct gb_operation *operation; - - if (WARN_ON_ONCE(type == GB_REQUEST_TYPE_INVALID)) - return NULL; - if (WARN_ON_ONCE(type & GB_MESSAGE_TYPE_RESPONSE)) - type &= ~GB_MESSAGE_TYPE_RESPONSE; - - if (WARN_ON_ONCE(flags & ~GB_OPERATION_FLAG_USER_MASK)) - flags &= GB_OPERATION_FLAG_USER_MASK; - - operation = gb_operation_create_common(connection, type, - request_size, response_size, - flags, gfp); - if (operation) - trace_gb_operation_create(operation); - - return operation; -} -EXPORT_SYMBOL_GPL(gb_operation_create_flags); - -struct gb_operation * -gb_operation_create_core(struct gb_connection *connection, - u8 type, size_t request_size, - size_t response_size, unsigned long flags, - gfp_t gfp) -{ - struct gb_operation *operation; - - flags |= GB_OPERATION_FLAG_CORE; - - operation = gb_operation_create_common(connection, type, - request_size, response_size, - flags, gfp); - if (operation) - trace_gb_operation_create_core(operation); - - return operation; -} - -/* Do not export this function. */ - -size_t gb_operation_get_payload_size_max(struct gb_connection *connection) -{ - struct gb_host_device *hd = connection->hd; - - return hd->buffer_size_max - sizeof(struct gb_operation_msg_hdr); -} -EXPORT_SYMBOL_GPL(gb_operation_get_payload_size_max); - -static struct gb_operation * -gb_operation_create_incoming(struct gb_connection *connection, u16 id, - u8 type, void *data, size_t size) -{ - struct gb_operation *operation; - size_t request_size; - unsigned long flags = GB_OPERATION_FLAG_INCOMING; - - /* Caller has made sure we at least have a message header. */ - request_size = size - sizeof(struct gb_operation_msg_hdr); - - if (!id) - flags |= GB_OPERATION_FLAG_UNIDIRECTIONAL; - - operation = gb_operation_create_common(connection, type, - request_size, - GB_REQUEST_TYPE_INVALID, - flags, GFP_ATOMIC); - if (!operation) - return NULL; - - operation->id = id; - memcpy(operation->request->header, data, size); - trace_gb_operation_create_incoming(operation); - - return operation; -} - -/* - * Get an additional reference on an operation. - */ -void gb_operation_get(struct gb_operation *operation) -{ - kref_get(&operation->kref); -} -EXPORT_SYMBOL_GPL(gb_operation_get); - -/* - * Destroy a previously created operation. - */ -static void _gb_operation_destroy(struct kref *kref) -{ - struct gb_operation *operation; - - operation = container_of(kref, struct gb_operation, kref); - - trace_gb_operation_destroy(operation); - - if (operation->response) - gb_operation_message_free(operation->response); - gb_operation_message_free(operation->request); - - kmem_cache_free(gb_operation_cache, operation); -} - -/* - * Drop a reference on an operation, and destroy it when the last - * one is gone. - */ -void gb_operation_put(struct gb_operation *operation) -{ - if (WARN_ON(!operation)) - return; - - kref_put(&operation->kref, _gb_operation_destroy); -} -EXPORT_SYMBOL_GPL(gb_operation_put); - -/* Tell the requester we're done */ -static void gb_operation_sync_callback(struct gb_operation *operation) -{ - complete(&operation->completion); -} - -/** - * gb_operation_request_send() - send an operation request message - * @operation: the operation to initiate - * @callback: the operation completion callback - * @timeout: operation timeout in milliseconds, or zero for no timeout - * @gfp: the memory flags to use for any allocations - * - * The caller has filled in any payload so the request message is ready to go. - * The callback function supplied will be called when the response message has - * arrived, a unidirectional request has been sent, or the operation is - * cancelled, indicating that the operation is complete. The callback function - * can fetch the result of the operation using gb_operation_result() if - * desired. - * - * Return: 0 if the request was successfully queued in the host-driver queues, - * or a negative errno. - */ -int gb_operation_request_send(struct gb_operation *operation, - gb_operation_callback callback, - unsigned int timeout, - gfp_t gfp) -{ - struct gb_connection *connection = operation->connection; - struct gb_operation_msg_hdr *header; - unsigned int cycle; - int ret; - - if (gb_connection_is_offloaded(connection)) - return -EBUSY; - - if (!callback) - return -EINVAL; - - /* - * Record the callback function, which is executed in - * non-atomic (workqueue) context when the final result - * of an operation has been set. - */ - operation->callback = callback; - - /* - * Assign the operation's id, and store it in the request header. - * Zero is a reserved operation id for unidirectional operations. - */ - if (gb_operation_is_unidirectional(operation)) { - operation->id = 0; - } else { - cycle = (unsigned int)atomic_inc_return(&connection->op_cycle); - operation->id = (u16)(cycle % U16_MAX + 1); - } - - header = operation->request->header; - header->operation_id = cpu_to_le16(operation->id); - - gb_operation_result_set(operation, -EINPROGRESS); - - /* - * Get an extra reference on the operation. It'll be dropped when the - * operation completes. - */ - gb_operation_get(operation); - ret = gb_operation_get_active(operation); - if (ret) - goto err_put; - - ret = gb_message_send(operation->request, gfp); - if (ret) - goto err_put_active; - - if (timeout) { - operation->timer.expires = jiffies + msecs_to_jiffies(timeout); - add_timer(&operation->timer); - } - - return 0; - -err_put_active: - gb_operation_put_active(operation); -err_put: - gb_operation_put(operation); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_operation_request_send); - -/* - * Send a synchronous operation. This function is expected to - * block, returning only when the response has arrived, (or when an - * error is detected. The return value is the result of the - * operation. - */ -int gb_operation_request_send_sync_timeout(struct gb_operation *operation, - unsigned int timeout) -{ - int ret; - - ret = gb_operation_request_send(operation, gb_operation_sync_callback, - timeout, GFP_KERNEL); - if (ret) - return ret; - - ret = wait_for_completion_interruptible(&operation->completion); - if (ret < 0) { - /* Cancel the operation if interrupted */ - gb_operation_cancel(operation, -ECANCELED); - } - - return gb_operation_result(operation); -} -EXPORT_SYMBOL_GPL(gb_operation_request_send_sync_timeout); - -/* - * Send a response for an incoming operation request. A non-zero - * errno indicates a failed operation. - * - * If there is any response payload, the incoming request handler is - * responsible for allocating the response message. Otherwise the - * it can simply supply the result errno; this function will - * allocate the response message if necessary. - */ -static int gb_operation_response_send(struct gb_operation *operation, - int errno) -{ - struct gb_connection *connection = operation->connection; - int ret; - - if (!operation->response && - !gb_operation_is_unidirectional(operation)) { - if (!gb_operation_response_alloc(operation, 0, GFP_KERNEL)) - return -ENOMEM; - } - - /* Record the result */ - if (!gb_operation_result_set(operation, errno)) { - dev_err(&connection->hd->dev, "request result already set\n"); - return -EIO; /* Shouldn't happen */ - } - - /* Sender of request does not care about response. */ - if (gb_operation_is_unidirectional(operation)) - return 0; - - /* Reference will be dropped when message has been sent. */ - gb_operation_get(operation); - ret = gb_operation_get_active(operation); - if (ret) - goto err_put; - - /* Fill in the response header and send it */ - operation->response->header->result = gb_operation_errno_map(errno); - - ret = gb_message_send(operation->response, GFP_KERNEL); - if (ret) - goto err_put_active; - - return 0; - -err_put_active: - gb_operation_put_active(operation); -err_put: - gb_operation_put(operation); - - return ret; -} - -/* - * This function is called when a message send request has completed. - */ -void greybus_message_sent(struct gb_host_device *hd, - struct gb_message *message, int status) -{ - struct gb_operation *operation = message->operation; - struct gb_connection *connection = operation->connection; - - /* - * If the message was a response, we just need to drop our - * reference to the operation. If an error occurred, report - * it. - * - * For requests, if there's no error and the operation in not - * unidirectional, there's nothing more to do until the response - * arrives. If an error occurred attempting to send it, or if the - * operation is unidrectional, record the result of the operation and - * schedule its completion. - */ - if (message == operation->response) { - if (status) { - dev_err(&connection->hd->dev, - "%s: error sending response 0x%02x: %d\n", - connection->name, operation->type, status); - } - - gb_operation_put_active(operation); - gb_operation_put(operation); - } else if (status || gb_operation_is_unidirectional(operation)) { - if (gb_operation_result_set(operation, status)) { - queue_work(gb_operation_completion_wq, - &operation->work); - } - } -} -EXPORT_SYMBOL_GPL(greybus_message_sent); - -/* - * We've received data on a connection, and it doesn't look like a - * response, so we assume it's a request. - * - * This is called in interrupt context, so just copy the incoming - * data into the request buffer and handle the rest via workqueue. - */ -static void gb_connection_recv_request(struct gb_connection *connection, - const struct gb_operation_msg_hdr *header, - void *data, size_t size) -{ - struct gb_operation *operation; - u16 operation_id; - u8 type; - int ret; - - operation_id = le16_to_cpu(header->operation_id); - type = header->type; - - operation = gb_operation_create_incoming(connection, operation_id, - type, data, size); - if (!operation) { - dev_err(&connection->hd->dev, - "%s: can't create incoming operation\n", - connection->name); - return; - } - - ret = gb_operation_get_active(operation); - if (ret) { - gb_operation_put(operation); - return; - } - trace_gb_message_recv_request(operation->request); - - /* - * The initial reference to the operation will be dropped when the - * request handler returns. - */ - if (gb_operation_result_set(operation, -EINPROGRESS)) - queue_work(connection->wq, &operation->work); -} - -/* - * We've received data that appears to be an operation response - * message. Look up the operation, and record that we've received - * its response. - * - * This is called in interrupt context, so just copy the incoming - * data into the response buffer and handle the rest via workqueue. - */ -static void gb_connection_recv_response(struct gb_connection *connection, - const struct gb_operation_msg_hdr *header, - void *data, size_t size) -{ - struct gb_operation *operation; - struct gb_message *message; - size_t message_size; - u16 operation_id; - int errno; - - operation_id = le16_to_cpu(header->operation_id); - - if (!operation_id) { - dev_err_ratelimited(&connection->hd->dev, - "%s: invalid response id 0 received\n", - connection->name); - return; - } - - operation = gb_operation_find_outgoing(connection, operation_id); - if (!operation) { - dev_err_ratelimited(&connection->hd->dev, - "%s: unexpected response id 0x%04x received\n", - connection->name, operation_id); - return; - } - - errno = gb_operation_status_map(header->result); - message = operation->response; - message_size = sizeof(*header) + message->payload_size; - if (!errno && size > message_size) { - dev_err_ratelimited(&connection->hd->dev, - "%s: malformed response 0x%02x received (%zu > %zu)\n", - connection->name, header->type, - size, message_size); - errno = -EMSGSIZE; - } else if (!errno && size < message_size) { - if (gb_operation_short_response_allowed(operation)) { - message->payload_size = size - sizeof(*header); - } else { - dev_err_ratelimited(&connection->hd->dev, - "%s: short response 0x%02x received (%zu < %zu)\n", - connection->name, header->type, - size, message_size); - errno = -EMSGSIZE; - } - } - - /* We must ignore the payload if a bad status is returned */ - if (errno) - size = sizeof(*header); - - /* The rest will be handled in work queue context */ - if (gb_operation_result_set(operation, errno)) { - memcpy(message->buffer, data, size); - - trace_gb_message_recv_response(message); - - queue_work(gb_operation_completion_wq, &operation->work); - } - - gb_operation_put(operation); -} - -/* - * Handle data arriving on a connection. As soon as we return the - * supplied data buffer will be reused (so unless we do something - * with, it's effectively dropped). - */ -void gb_connection_recv(struct gb_connection *connection, - void *data, size_t size) -{ - struct gb_operation_msg_hdr header; - struct device *dev = &connection->hd->dev; - size_t msg_size; - - if (connection->state == GB_CONNECTION_STATE_DISABLED || - gb_connection_is_offloaded(connection)) { - dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n", - connection->name, size); - return; - } - - if (size < sizeof(header)) { - dev_err_ratelimited(dev, "%s: short message received\n", - connection->name); - return; - } - - /* Use memcpy as data may be unaligned */ - memcpy(&header, data, sizeof(header)); - msg_size = le16_to_cpu(header.size); - if (size < msg_size) { - dev_err_ratelimited(dev, - "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n", - connection->name, - le16_to_cpu(header.operation_id), - header.type, size, msg_size); - return; /* XXX Should still complete operation */ - } - - if (header.type & GB_MESSAGE_TYPE_RESPONSE) { - gb_connection_recv_response(connection, &header, data, - msg_size); - } else { - gb_connection_recv_request(connection, &header, data, - msg_size); - } -} - -/* - * Cancel an outgoing operation synchronously, and record the given error to - * indicate why. - */ -void gb_operation_cancel(struct gb_operation *operation, int errno) -{ - if (WARN_ON(gb_operation_is_incoming(operation))) - return; - - if (gb_operation_result_set(operation, errno)) { - gb_message_cancel(operation->request); - queue_work(gb_operation_completion_wq, &operation->work); - } - trace_gb_message_cancel_outgoing(operation->request); - - atomic_inc(&operation->waiters); - wait_event(gb_operation_cancellation_queue, - !gb_operation_is_active(operation)); - atomic_dec(&operation->waiters); -} -EXPORT_SYMBOL_GPL(gb_operation_cancel); - -/* - * Cancel an incoming operation synchronously. Called during connection tear - * down. - */ -void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) -{ - if (WARN_ON(!gb_operation_is_incoming(operation))) - return; - - if (!gb_operation_is_unidirectional(operation)) { - /* - * Make sure the request handler has submitted the response - * before cancelling it. - */ - flush_work(&operation->work); - if (!gb_operation_result_set(operation, errno)) - gb_message_cancel(operation->response); - } - trace_gb_message_cancel_incoming(operation->response); - - atomic_inc(&operation->waiters); - wait_event(gb_operation_cancellation_queue, - !gb_operation_is_active(operation)); - atomic_dec(&operation->waiters); -} - -/** - * gb_operation_sync_timeout() - implement a "simple" synchronous operation - * @connection: the Greybus connection to send this to - * @type: the type of operation to send - * @request: pointer to a memory buffer to copy the request from - * @request_size: size of @request - * @response: pointer to a memory buffer to copy the response to - * @response_size: the size of @response. - * @timeout: operation timeout in milliseconds - * - * This function implements a simple synchronous Greybus operation. It sends - * the provided operation request and waits (sleeps) until the corresponding - * operation response message has been successfully received, or an error - * occurs. @request and @response are buffers to hold the request and response - * data respectively, and if they are not NULL, their size must be specified in - * @request_size and @response_size. - * - * If a response payload is to come back, and @response is not NULL, - * @response_size number of bytes will be copied into @response if the operation - * is successful. - * - * If there is an error, the response buffer is left alone. - */ -int gb_operation_sync_timeout(struct gb_connection *connection, int type, - void *request, int request_size, - void *response, int response_size, - unsigned int timeout) -{ - struct gb_operation *operation; - int ret; - - if ((response_size && !response) || - (request_size && !request)) - return -EINVAL; - - operation = gb_operation_create(connection, type, - request_size, response_size, - GFP_KERNEL); - if (!operation) - return -ENOMEM; - - if (request_size) - memcpy(operation->request->payload, request, request_size); - - ret = gb_operation_request_send_sync_timeout(operation, timeout); - if (ret) { - dev_err(&connection->hd->dev, - "%s: synchronous operation id 0x%04x of type 0x%02x failed: %d\n", - connection->name, operation->id, type, ret); - } else { - if (response_size) { - memcpy(response, operation->response->payload, - response_size); - } - } - - gb_operation_put(operation); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_operation_sync_timeout); - -/** - * gb_operation_unidirectional_timeout() - initiate a unidirectional operation - * @connection: connection to use - * @type: type of operation to send - * @request: memory buffer to copy the request from - * @request_size: size of @request - * @timeout: send timeout in milliseconds - * - * Initiate a unidirectional operation by sending a request message and - * waiting for it to be acknowledged as sent by the host device. - * - * Note that successful send of a unidirectional operation does not imply that - * the request as actually reached the remote end of the connection. - */ -int gb_operation_unidirectional_timeout(struct gb_connection *connection, - int type, void *request, - int request_size, - unsigned int timeout) -{ - struct gb_operation *operation; - int ret; - - if (request_size && !request) - return -EINVAL; - - operation = gb_operation_create_flags(connection, type, - request_size, 0, - GB_OPERATION_FLAG_UNIDIRECTIONAL, - GFP_KERNEL); - if (!operation) - return -ENOMEM; - - if (request_size) - memcpy(operation->request->payload, request, request_size); - - ret = gb_operation_request_send_sync_timeout(operation, timeout); - if (ret) { - dev_err(&connection->hd->dev, - "%s: unidirectional operation of type 0x%02x failed: %d\n", - connection->name, type, ret); - } - - gb_operation_put(operation); - - return ret; -} -EXPORT_SYMBOL_GPL(gb_operation_unidirectional_timeout); - -int __init gb_operation_init(void) -{ - gb_message_cache = kmem_cache_create("gb_message_cache", - sizeof(struct gb_message), 0, 0, - NULL); - if (!gb_message_cache) - return -ENOMEM; - - gb_operation_cache = kmem_cache_create("gb_operation_cache", - sizeof(struct gb_operation), 0, - 0, NULL); - if (!gb_operation_cache) - goto err_destroy_message_cache; - - gb_operation_completion_wq = alloc_workqueue("greybus_completion", - 0, 0); - if (!gb_operation_completion_wq) - goto err_destroy_operation_cache; - - return 0; - -err_destroy_operation_cache: - kmem_cache_destroy(gb_operation_cache); - gb_operation_cache = NULL; -err_destroy_message_cache: - kmem_cache_destroy(gb_message_cache); - gb_message_cache = NULL; - - return -ENOMEM; -} - -void gb_operation_exit(void) -{ - destroy_workqueue(gb_operation_completion_wq); - gb_operation_completion_wq = NULL; - kmem_cache_destroy(gb_operation_cache); - gb_operation_cache = NULL; - kmem_cache_destroy(gb_message_cache); - gb_message_cache = NULL; -} diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c deleted file mode 100644 index ce7740ef449b..000000000000 --- a/drivers/staging/greybus/svc.c +++ /dev/null @@ -1,1397 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SVC Greybus driver. - * - * Copyright 2015 Google Inc. - * Copyright 2015 Linaro Ltd. - */ - -#include -#include -#include - -#define SVC_INTF_EJECT_TIMEOUT 9000 -#define SVC_INTF_ACTIVATE_TIMEOUT 6000 -#define SVC_INTF_RESUME_TIMEOUT 3000 - -struct gb_svc_deferred_request { - struct work_struct work; - struct gb_operation *operation; -}; - -static int gb_svc_queue_deferred_request(struct gb_operation *operation); - -static ssize_t endo_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_svc *svc = to_gb_svc(dev); - - return sprintf(buf, "0x%04x\n", svc->endo_id); -} -static DEVICE_ATTR_RO(endo_id); - -static ssize_t ap_intf_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_svc *svc = to_gb_svc(dev); - - return sprintf(buf, "%u\n", svc->ap_intf_id); -} -static DEVICE_ATTR_RO(ap_intf_id); - -// FIXME -// This is a hack, we need to do this "right" and clean the interface up -// properly, not just forcibly yank the thing out of the system and hope for the -// best. But for now, people want their modules to come out without having to -// throw the thing to the ground or get out a screwdriver. -static ssize_t intf_eject_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t len) -{ - struct gb_svc *svc = to_gb_svc(dev); - unsigned short intf_id; - int ret; - - ret = kstrtou16(buf, 10, &intf_id); - if (ret < 0) - return ret; - - dev_warn(dev, "Forcibly trying to eject interface %d\n", intf_id); - - ret = gb_svc_intf_eject(svc, intf_id); - if (ret < 0) - return ret; - - return len; -} -static DEVICE_ATTR_WO(intf_eject); - -static ssize_t watchdog_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gb_svc *svc = to_gb_svc(dev); - - return sprintf(buf, "%s\n", - gb_svc_watchdog_enabled(svc) ? "enabled" : "disabled"); -} - -static ssize_t watchdog_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t len) -{ - struct gb_svc *svc = to_gb_svc(dev); - int retval; - bool user_request; - - retval = strtobool(buf, &user_request); - if (retval) - return retval; - - if (user_request) - retval = gb_svc_watchdog_enable(svc); - else - retval = gb_svc_watchdog_disable(svc); - if (retval) - return retval; - return len; -} -static DEVICE_ATTR_RW(watchdog); - -static ssize_t watchdog_action_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gb_svc *svc = to_gb_svc(dev); - - if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) - return sprintf(buf, "panic\n"); - else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) - return sprintf(buf, "reset\n"); - - return -EINVAL; -} - -static ssize_t watchdog_action_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - struct gb_svc *svc = to_gb_svc(dev); - - if (sysfs_streq(buf, "panic")) - svc->action = GB_SVC_WATCHDOG_BITE_PANIC_KERNEL; - else if (sysfs_streq(buf, "reset")) - svc->action = GB_SVC_WATCHDOG_BITE_RESET_UNIPRO; - else - return -EINVAL; - - return len; -} -static DEVICE_ATTR_RW(watchdog_action); - -static int gb_svc_pwrmon_rail_count_get(struct gb_svc *svc, u8 *value) -{ - struct gb_svc_pwrmon_rail_count_get_response response; - int ret; - - ret = gb_operation_sync(svc->connection, - GB_SVC_TYPE_PWRMON_RAIL_COUNT_GET, NULL, 0, - &response, sizeof(response)); - if (ret) { - dev_err(&svc->dev, "failed to get rail count: %d\n", ret); - return ret; - } - - *value = response.rail_count; - - return 0; -} - -static int gb_svc_pwrmon_rail_names_get(struct gb_svc *svc, - struct gb_svc_pwrmon_rail_names_get_response *response, - size_t bufsize) -{ - int ret; - - ret = gb_operation_sync(svc->connection, - GB_SVC_TYPE_PWRMON_RAIL_NAMES_GET, NULL, 0, - response, bufsize); - if (ret) { - dev_err(&svc->dev, "failed to get rail names: %d\n", ret); - return ret; - } - - if (response->status != GB_SVC_OP_SUCCESS) { - dev_err(&svc->dev, - "SVC error while getting rail names: %u\n", - response->status); - return -EREMOTEIO; - } - - return 0; -} - -static int gb_svc_pwrmon_sample_get(struct gb_svc *svc, u8 rail_id, - u8 measurement_type, u32 *value) -{ - struct gb_svc_pwrmon_sample_get_request request; - struct gb_svc_pwrmon_sample_get_response response; - int ret; - - request.rail_id = rail_id; - request.measurement_type = measurement_type; - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_PWRMON_SAMPLE_GET, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) { - dev_err(&svc->dev, "failed to get rail sample: %d\n", ret); - return ret; - } - - if (response.result) { - dev_err(&svc->dev, - "UniPro error while getting rail power sample (%d %d): %d\n", - rail_id, measurement_type, response.result); - switch (response.result) { - case GB_SVC_PWRMON_GET_SAMPLE_INVAL: - return -EINVAL; - case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: - return -ENOMSG; - default: - return -EREMOTEIO; - } - } - - *value = le32_to_cpu(response.measurement); - - return 0; -} - -int gb_svc_pwrmon_intf_sample_get(struct gb_svc *svc, u8 intf_id, - u8 measurement_type, u32 *value) -{ - struct gb_svc_pwrmon_intf_sample_get_request request; - struct gb_svc_pwrmon_intf_sample_get_response response; - int ret; - - request.intf_id = intf_id; - request.measurement_type = measurement_type; - - ret = gb_operation_sync(svc->connection, - GB_SVC_TYPE_PWRMON_INTF_SAMPLE_GET, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) { - dev_err(&svc->dev, "failed to get intf sample: %d\n", ret); - return ret; - } - - if (response.result) { - dev_err(&svc->dev, - "UniPro error while getting intf power sample (%d %d): %d\n", - intf_id, measurement_type, response.result); - switch (response.result) { - case GB_SVC_PWRMON_GET_SAMPLE_INVAL: - return -EINVAL; - case GB_SVC_PWRMON_GET_SAMPLE_NOSUPP: - return -ENOMSG; - default: - return -EREMOTEIO; - } - } - - *value = le32_to_cpu(response.measurement); - - return 0; -} - -static struct attribute *svc_attrs[] = { - &dev_attr_endo_id.attr, - &dev_attr_ap_intf_id.attr, - &dev_attr_intf_eject.attr, - &dev_attr_watchdog.attr, - &dev_attr_watchdog_action.attr, - NULL, -}; -ATTRIBUTE_GROUPS(svc); - -int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id) -{ - struct gb_svc_intf_device_id_request request; - - request.intf_id = intf_id; - request.device_id = device_id; - - return gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_DEVICE_ID, - &request, sizeof(request), NULL, 0); -} - -int gb_svc_intf_eject(struct gb_svc *svc, u8 intf_id) -{ - struct gb_svc_intf_eject_request request; - int ret; - - request.intf_id = intf_id; - - /* - * The pulse width for module release in svc is long so we need to - * increase the timeout so the operation will not return to soon. - */ - ret = gb_operation_sync_timeout(svc->connection, - GB_SVC_TYPE_INTF_EJECT, &request, - sizeof(request), NULL, 0, - SVC_INTF_EJECT_TIMEOUT); - if (ret) { - dev_err(&svc->dev, "failed to eject interface %u\n", intf_id); - return ret; - } - - return 0; -} - -int gb_svc_intf_vsys_set(struct gb_svc *svc, u8 intf_id, bool enable) -{ - struct gb_svc_intf_vsys_request request; - struct gb_svc_intf_vsys_response response; - int type, ret; - - request.intf_id = intf_id; - - if (enable) - type = GB_SVC_TYPE_INTF_VSYS_ENABLE; - else - type = GB_SVC_TYPE_INTF_VSYS_DISABLE; - - ret = gb_operation_sync(svc->connection, type, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) - return ret; - if (response.result_code != GB_SVC_INTF_VSYS_OK) - return -EREMOTEIO; - return 0; -} - -int gb_svc_intf_refclk_set(struct gb_svc *svc, u8 intf_id, bool enable) -{ - struct gb_svc_intf_refclk_request request; - struct gb_svc_intf_refclk_response response; - int type, ret; - - request.intf_id = intf_id; - - if (enable) - type = GB_SVC_TYPE_INTF_REFCLK_ENABLE; - else - type = GB_SVC_TYPE_INTF_REFCLK_DISABLE; - - ret = gb_operation_sync(svc->connection, type, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) - return ret; - if (response.result_code != GB_SVC_INTF_REFCLK_OK) - return -EREMOTEIO; - return 0; -} - -int gb_svc_intf_unipro_set(struct gb_svc *svc, u8 intf_id, bool enable) -{ - struct gb_svc_intf_unipro_request request; - struct gb_svc_intf_unipro_response response; - int type, ret; - - request.intf_id = intf_id; - - if (enable) - type = GB_SVC_TYPE_INTF_UNIPRO_ENABLE; - else - type = GB_SVC_TYPE_INTF_UNIPRO_DISABLE; - - ret = gb_operation_sync(svc->connection, type, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) - return ret; - if (response.result_code != GB_SVC_INTF_UNIPRO_OK) - return -EREMOTEIO; - return 0; -} - -int gb_svc_intf_activate(struct gb_svc *svc, u8 intf_id, u8 *intf_type) -{ - struct gb_svc_intf_activate_request request; - struct gb_svc_intf_activate_response response; - int ret; - - request.intf_id = intf_id; - - ret = gb_operation_sync_timeout(svc->connection, - GB_SVC_TYPE_INTF_ACTIVATE, - &request, sizeof(request), - &response, sizeof(response), - SVC_INTF_ACTIVATE_TIMEOUT); - if (ret < 0) - return ret; - if (response.status != GB_SVC_OP_SUCCESS) { - dev_err(&svc->dev, "failed to activate interface %u: %u\n", - intf_id, response.status); - return -EREMOTEIO; - } - - *intf_type = response.intf_type; - - return 0; -} - -int gb_svc_intf_resume(struct gb_svc *svc, u8 intf_id) -{ - struct gb_svc_intf_resume_request request; - struct gb_svc_intf_resume_response response; - int ret; - - request.intf_id = intf_id; - - ret = gb_operation_sync_timeout(svc->connection, - GB_SVC_TYPE_INTF_RESUME, - &request, sizeof(request), - &response, sizeof(response), - SVC_INTF_RESUME_TIMEOUT); - if (ret < 0) { - dev_err(&svc->dev, "failed to send interface resume %u: %d\n", - intf_id, ret); - return ret; - } - - if (response.status != GB_SVC_OP_SUCCESS) { - dev_err(&svc->dev, "failed to resume interface %u: %u\n", - intf_id, response.status); - return -EREMOTEIO; - } - - return 0; -} - -int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, - u32 *value) -{ - struct gb_svc_dme_peer_get_request request; - struct gb_svc_dme_peer_get_response response; - u16 result; - int ret; - - request.intf_id = intf_id; - request.attr = cpu_to_le16(attr); - request.selector = cpu_to_le16(selector); - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_GET, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) { - dev_err(&svc->dev, "failed to get DME attribute (%u 0x%04x %u): %d\n", - intf_id, attr, selector, ret); - return ret; - } - - result = le16_to_cpu(response.result_code); - if (result) { - dev_err(&svc->dev, "UniPro error while getting DME attribute (%u 0x%04x %u): %u\n", - intf_id, attr, selector, result); - return -EREMOTEIO; - } - - if (value) - *value = le32_to_cpu(response.attr_value); - - return 0; -} - -int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, - u32 value) -{ - struct gb_svc_dme_peer_set_request request; - struct gb_svc_dme_peer_set_response response; - u16 result; - int ret; - - request.intf_id = intf_id; - request.attr = cpu_to_le16(attr); - request.selector = cpu_to_le16(selector); - request.value = cpu_to_le32(value); - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_DME_PEER_SET, - &request, sizeof(request), - &response, sizeof(response)); - if (ret) { - dev_err(&svc->dev, "failed to set DME attribute (%u 0x%04x %u %u): %d\n", - intf_id, attr, selector, value, ret); - return ret; - } - - result = le16_to_cpu(response.result_code); - if (result) { - dev_err(&svc->dev, "UniPro error while setting DME attribute (%u 0x%04x %u %u): %u\n", - intf_id, attr, selector, value, result); - return -EREMOTEIO; - } - - return 0; -} - -int gb_svc_connection_create(struct gb_svc *svc, - u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id, - u8 cport_flags) -{ - struct gb_svc_conn_create_request request; - - request.intf1_id = intf1_id; - request.cport1_id = cpu_to_le16(cport1_id); - request.intf2_id = intf2_id; - request.cport2_id = cpu_to_le16(cport2_id); - request.tc = 0; /* TC0 */ - request.flags = cport_flags; - - return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, - &request, sizeof(request), NULL, 0); -} - -void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) -{ - struct gb_svc_conn_destroy_request request; - struct gb_connection *connection = svc->connection; - int ret; - - request.intf1_id = intf1_id; - request.cport1_id = cpu_to_le16(cport1_id); - request.intf2_id = intf2_id; - request.cport2_id = cpu_to_le16(cport2_id); - - ret = gb_operation_sync(connection, GB_SVC_TYPE_CONN_DESTROY, - &request, sizeof(request), NULL, 0); - if (ret) { - dev_err(&svc->dev, "failed to destroy connection (%u:%u %u:%u): %d\n", - intf1_id, cport1_id, intf2_id, cport2_id, ret); - } -} - -/* Creates bi-directional routes between the devices */ -int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id, - u8 intf2_id, u8 dev2_id) -{ - struct gb_svc_route_create_request request; - - request.intf1_id = intf1_id; - request.dev1_id = dev1_id; - request.intf2_id = intf2_id; - request.dev2_id = dev2_id; - - return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE, - &request, sizeof(request), NULL, 0); -} - -/* Destroys bi-directional routes between the devices */ -void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id) -{ - struct gb_svc_route_destroy_request request; - int ret; - - request.intf1_id = intf1_id; - request.intf2_id = intf2_id; - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_DESTROY, - &request, sizeof(request), NULL, 0); - if (ret) { - dev_err(&svc->dev, "failed to destroy route (%u %u): %d\n", - intf1_id, intf2_id, ret); - } -} - -int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series, - u8 tx_mode, u8 tx_gear, u8 tx_nlanes, - u8 tx_amplitude, u8 tx_hs_equalizer, - u8 rx_mode, u8 rx_gear, u8 rx_nlanes, - u8 flags, u32 quirks, - struct gb_svc_l2_timer_cfg *local, - struct gb_svc_l2_timer_cfg *remote) -{ - struct gb_svc_intf_set_pwrm_request request; - struct gb_svc_intf_set_pwrm_response response; - int ret; - u16 result_code; - - memset(&request, 0, sizeof(request)); - - request.intf_id = intf_id; - request.hs_series = hs_series; - request.tx_mode = tx_mode; - request.tx_gear = tx_gear; - request.tx_nlanes = tx_nlanes; - request.tx_amplitude = tx_amplitude; - request.tx_hs_equalizer = tx_hs_equalizer; - request.rx_mode = rx_mode; - request.rx_gear = rx_gear; - request.rx_nlanes = rx_nlanes; - request.flags = flags; - request.quirks = cpu_to_le32(quirks); - if (local) - request.local_l2timerdata = *local; - if (remote) - request.remote_l2timerdata = *remote; - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) - return ret; - - result_code = response.result_code; - if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) { - dev_err(&svc->dev, "set power mode = %d\n", result_code); - return -EIO; - } - - return 0; -} -EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode); - -int gb_svc_intf_set_power_mode_hibernate(struct gb_svc *svc, u8 intf_id) -{ - struct gb_svc_intf_set_pwrm_request request; - struct gb_svc_intf_set_pwrm_response response; - int ret; - u16 result_code; - - memset(&request, 0, sizeof(request)); - - request.intf_id = intf_id; - request.hs_series = GB_SVC_UNIPRO_HS_SERIES_A; - request.tx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; - request.rx_mode = GB_SVC_UNIPRO_HIBERNATE_MODE; - - ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM, - &request, sizeof(request), - &response, sizeof(response)); - if (ret < 0) { - dev_err(&svc->dev, - "failed to send set power mode operation to interface %u: %d\n", - intf_id, ret); - return ret; - } - - result_code = response.result_code; - if (result_code != GB_SVC_SETPWRM_PWR_OK) { - dev_err(&svc->dev, - "failed to hibernate the link for interface %u: %u\n", - intf_id, result_code); - return -EIO; - } - - return 0; -} - -int gb_svc_ping(struct gb_svc *svc) -{ - return gb_operation_sync_timeout(svc->connection, GB_SVC_TYPE_PING, - NULL, 0, NULL, 0, - GB_OPERATION_TIMEOUT_DEFAULT * 2); -} - -static int gb_svc_version_request(struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_svc_version_request *request; - struct gb_svc_version_response *response; - - if (op->request->payload_size < sizeof(*request)) { - dev_err(&svc->dev, "short version request (%zu < %zu)\n", - op->request->payload_size, - sizeof(*request)); - return -EINVAL; - } - - request = op->request->payload; - - if (request->major > GB_SVC_VERSION_MAJOR) { - dev_warn(&svc->dev, "unsupported major version (%u > %u)\n", - request->major, GB_SVC_VERSION_MAJOR); - return -ENOTSUPP; - } - - svc->protocol_major = request->major; - svc->protocol_minor = request->minor; - - if (!gb_operation_response_alloc(op, sizeof(*response), GFP_KERNEL)) - return -ENOMEM; - - response = op->response->payload; - response->major = svc->protocol_major; - response->minor = svc->protocol_minor; - - return 0; -} - -static ssize_t pwr_debugfs_voltage_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - struct svc_debugfs_pwrmon_rail *pwrmon_rails = - file_inode(file)->i_private; - struct gb_svc *svc = pwrmon_rails->svc; - int ret, desc; - u32 value; - char buff[16]; - - ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, - GB_SVC_PWRMON_TYPE_VOL, &value); - if (ret) { - dev_err(&svc->dev, - "failed to get voltage sample %u: %d\n", - pwrmon_rails->id, ret); - return ret; - } - - desc = scnprintf(buff, sizeof(buff), "%u\n", value); - - return simple_read_from_buffer(buf, len, offset, buff, desc); -} - -static ssize_t pwr_debugfs_current_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - struct svc_debugfs_pwrmon_rail *pwrmon_rails = - file_inode(file)->i_private; - struct gb_svc *svc = pwrmon_rails->svc; - int ret, desc; - u32 value; - char buff[16]; - - ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, - GB_SVC_PWRMON_TYPE_CURR, &value); - if (ret) { - dev_err(&svc->dev, - "failed to get current sample %u: %d\n", - pwrmon_rails->id, ret); - return ret; - } - - desc = scnprintf(buff, sizeof(buff), "%u\n", value); - - return simple_read_from_buffer(buf, len, offset, buff, desc); -} - -static ssize_t pwr_debugfs_power_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) -{ - struct svc_debugfs_pwrmon_rail *pwrmon_rails = - file_inode(file)->i_private; - struct gb_svc *svc = pwrmon_rails->svc; - int ret, desc; - u32 value; - char buff[16]; - - ret = gb_svc_pwrmon_sample_get(svc, pwrmon_rails->id, - GB_SVC_PWRMON_TYPE_PWR, &value); - if (ret) { - dev_err(&svc->dev, "failed to get power sample %u: %d\n", - pwrmon_rails->id, ret); - return ret; - } - - desc = scnprintf(buff, sizeof(buff), "%u\n", value); - - return simple_read_from_buffer(buf, len, offset, buff, desc); -} - -static const struct file_operations pwrmon_debugfs_voltage_fops = { - .read = pwr_debugfs_voltage_read, -}; - -static const struct file_operations pwrmon_debugfs_current_fops = { - .read = pwr_debugfs_current_read, -}; - -static const struct file_operations pwrmon_debugfs_power_fops = { - .read = pwr_debugfs_power_read, -}; - -static void gb_svc_pwrmon_debugfs_init(struct gb_svc *svc) -{ - int i; - size_t bufsize; - struct dentry *dent; - struct gb_svc_pwrmon_rail_names_get_response *rail_names; - u8 rail_count; - - dent = debugfs_create_dir("pwrmon", svc->debugfs_dentry); - if (IS_ERR_OR_NULL(dent)) - return; - - if (gb_svc_pwrmon_rail_count_get(svc, &rail_count)) - goto err_pwrmon_debugfs; - - if (!rail_count || rail_count > GB_SVC_PWRMON_MAX_RAIL_COUNT) - goto err_pwrmon_debugfs; - - bufsize = sizeof(*rail_names) + - GB_SVC_PWRMON_RAIL_NAME_BUFSIZE * rail_count; - - rail_names = kzalloc(bufsize, GFP_KERNEL); - if (!rail_names) - goto err_pwrmon_debugfs; - - svc->pwrmon_rails = kcalloc(rail_count, sizeof(*svc->pwrmon_rails), - GFP_KERNEL); - if (!svc->pwrmon_rails) - goto err_pwrmon_debugfs_free; - - if (gb_svc_pwrmon_rail_names_get(svc, rail_names, bufsize)) - goto err_pwrmon_debugfs_free; - - for (i = 0; i < rail_count; i++) { - struct dentry *dir; - struct svc_debugfs_pwrmon_rail *rail = &svc->pwrmon_rails[i]; - char fname[GB_SVC_PWRMON_RAIL_NAME_BUFSIZE]; - - snprintf(fname, sizeof(fname), "%s", - (char *)&rail_names->name[i]); - - rail->id = i; - rail->svc = svc; - - dir = debugfs_create_dir(fname, dent); - debugfs_create_file("voltage_now", 0444, dir, rail, - &pwrmon_debugfs_voltage_fops); - debugfs_create_file("current_now", 0444, dir, rail, - &pwrmon_debugfs_current_fops); - debugfs_create_file("power_now", 0444, dir, rail, - &pwrmon_debugfs_power_fops); - } - - kfree(rail_names); - return; - -err_pwrmon_debugfs_free: - kfree(rail_names); - kfree(svc->pwrmon_rails); - svc->pwrmon_rails = NULL; - -err_pwrmon_debugfs: - debugfs_remove(dent); -} - -static void gb_svc_debugfs_init(struct gb_svc *svc) -{ - svc->debugfs_dentry = debugfs_create_dir(dev_name(&svc->dev), - gb_debugfs_get()); - gb_svc_pwrmon_debugfs_init(svc); -} - -static void gb_svc_debugfs_exit(struct gb_svc *svc) -{ - debugfs_remove_recursive(svc->debugfs_dentry); - kfree(svc->pwrmon_rails); - svc->pwrmon_rails = NULL; -} - -static int gb_svc_hello(struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_svc_hello_request *hello_request; - int ret; - - if (op->request->payload_size < sizeof(*hello_request)) { - dev_warn(&svc->dev, "short hello request (%zu < %zu)\n", - op->request->payload_size, - sizeof(*hello_request)); - return -EINVAL; - } - - hello_request = op->request->payload; - svc->endo_id = le16_to_cpu(hello_request->endo_id); - svc->ap_intf_id = hello_request->interface_id; - - ret = device_add(&svc->dev); - if (ret) { - dev_err(&svc->dev, "failed to register svc device: %d\n", ret); - return ret; - } - - ret = gb_svc_watchdog_create(svc); - if (ret) { - dev_err(&svc->dev, "failed to create watchdog: %d\n", ret); - goto err_unregister_device; - } - - gb_svc_debugfs_init(svc); - - return gb_svc_queue_deferred_request(op); - -err_unregister_device: - gb_svc_watchdog_destroy(svc); - device_del(&svc->dev); - return ret; -} - -static struct gb_interface *gb_svc_interface_lookup(struct gb_svc *svc, - u8 intf_id) -{ - struct gb_host_device *hd = svc->hd; - struct gb_module *module; - size_t num_interfaces; - u8 module_id; - - list_for_each_entry(module, &hd->modules, hd_node) { - module_id = module->module_id; - num_interfaces = module->num_interfaces; - - if (intf_id >= module_id && - intf_id < module_id + num_interfaces) { - return module->interfaces[intf_id - module_id]; - } - } - - return NULL; -} - -static struct gb_module *gb_svc_module_lookup(struct gb_svc *svc, u8 module_id) -{ - struct gb_host_device *hd = svc->hd; - struct gb_module *module; - - list_for_each_entry(module, &hd->modules, hd_node) { - if (module->module_id == module_id) - return module; - } - - return NULL; -} - -static void gb_svc_process_hello_deferred(struct gb_operation *operation) -{ - struct gb_connection *connection = operation->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - int ret; - - /* - * XXX This is a hack/work-around to reconfigure the APBridgeA-Switch - * link to PWM G2, 1 Lane, Slow Auto, so that it has sufficient - * bandwidth for 3 audio streams plus boot-over-UniPro of a hot-plugged - * module. - * - * The code should be removed once SW-2217, Heuristic for UniPro - * Power Mode Changes is resolved. - */ - ret = gb_svc_intf_set_power_mode(svc, svc->ap_intf_id, - GB_SVC_UNIPRO_HS_SERIES_A, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 2, 1, - GB_SVC_SMALL_AMPLITUDE, - GB_SVC_NO_DE_EMPHASIS, - GB_SVC_UNIPRO_SLOW_AUTO_MODE, - 2, 1, - 0, 0, - NULL, NULL); - - if (ret) - dev_warn(&svc->dev, - "power mode change failed on AP to switch link: %d\n", - ret); -} - -static void gb_svc_process_module_inserted(struct gb_operation *operation) -{ - struct gb_svc_module_inserted_request *request; - struct gb_connection *connection = operation->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_host_device *hd = svc->hd; - struct gb_module *module; - size_t num_interfaces; - u8 module_id; - u16 flags; - int ret; - - /* The request message size has already been verified. */ - request = operation->request->payload; - module_id = request->primary_intf_id; - num_interfaces = request->intf_count; - flags = le16_to_cpu(request->flags); - - dev_dbg(&svc->dev, "%s - id = %u, num_interfaces = %zu, flags = 0x%04x\n", - __func__, module_id, num_interfaces, flags); - - if (flags & GB_SVC_MODULE_INSERTED_FLAG_NO_PRIMARY) { - dev_warn(&svc->dev, "no primary interface detected on module %u\n", - module_id); - } - - module = gb_svc_module_lookup(svc, module_id); - if (module) { - dev_warn(&svc->dev, "unexpected module-inserted event %u\n", - module_id); - return; - } - - module = gb_module_create(hd, module_id, num_interfaces); - if (!module) { - dev_err(&svc->dev, "failed to create module\n"); - return; - } - - ret = gb_module_add(module); - if (ret) { - gb_module_put(module); - return; - } - - list_add(&module->hd_node, &hd->modules); -} - -static void gb_svc_process_module_removed(struct gb_operation *operation) -{ - struct gb_svc_module_removed_request *request; - struct gb_connection *connection = operation->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_module *module; - u8 module_id; - - /* The request message size has already been verified. */ - request = operation->request->payload; - module_id = request->primary_intf_id; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, module_id); - - module = gb_svc_module_lookup(svc, module_id); - if (!module) { - dev_warn(&svc->dev, "unexpected module-removed event %u\n", - module_id); - return; - } - - module->disconnected = true; - - gb_module_del(module); - list_del(&module->hd_node); - gb_module_put(module); -} - -static void gb_svc_process_intf_oops(struct gb_operation *operation) -{ - struct gb_svc_intf_oops_request *request; - struct gb_connection *connection = operation->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_interface *intf; - u8 intf_id; - u8 reason; - - /* The request message size has already been verified. */ - request = operation->request->payload; - intf_id = request->intf_id; - reason = request->reason; - - intf = gb_svc_interface_lookup(svc, intf_id); - if (!intf) { - dev_warn(&svc->dev, "unexpected interface-oops event %u\n", - intf_id); - return; - } - - dev_info(&svc->dev, "Deactivating interface %u, interface oops reason = %u\n", - intf_id, reason); - - mutex_lock(&intf->mutex); - intf->disconnected = true; - gb_interface_disable(intf); - gb_interface_deactivate(intf); - mutex_unlock(&intf->mutex); -} - -static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation) -{ - struct gb_svc_intf_mailbox_event_request *request; - struct gb_connection *connection = operation->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - struct gb_interface *intf; - u8 intf_id; - u16 result_code; - u32 mailbox; - - /* The request message size has already been verified. */ - request = operation->request->payload; - intf_id = request->intf_id; - result_code = le16_to_cpu(request->result_code); - mailbox = le32_to_cpu(request->mailbox); - - dev_dbg(&svc->dev, "%s - id = %u, result = 0x%04x, mailbox = 0x%08x\n", - __func__, intf_id, result_code, mailbox); - - intf = gb_svc_interface_lookup(svc, intf_id); - if (!intf) { - dev_warn(&svc->dev, "unexpected mailbox event %u\n", intf_id); - return; - } - - gb_interface_mailbox_event(intf, result_code, mailbox); -} - -static void gb_svc_process_deferred_request(struct work_struct *work) -{ - struct gb_svc_deferred_request *dr; - struct gb_operation *operation; - struct gb_svc *svc; - u8 type; - - dr = container_of(work, struct gb_svc_deferred_request, work); - operation = dr->operation; - svc = gb_connection_get_data(operation->connection); - type = operation->request->header->type; - - switch (type) { - case GB_SVC_TYPE_SVC_HELLO: - gb_svc_process_hello_deferred(operation); - break; - case GB_SVC_TYPE_MODULE_INSERTED: - gb_svc_process_module_inserted(operation); - break; - case GB_SVC_TYPE_MODULE_REMOVED: - gb_svc_process_module_removed(operation); - break; - case GB_SVC_TYPE_INTF_MAILBOX_EVENT: - gb_svc_process_intf_mailbox_event(operation); - break; - case GB_SVC_TYPE_INTF_OOPS: - gb_svc_process_intf_oops(operation); - break; - default: - dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type); - } - - gb_operation_put(operation); - kfree(dr); -} - -static int gb_svc_queue_deferred_request(struct gb_operation *operation) -{ - struct gb_svc *svc = gb_connection_get_data(operation->connection); - struct gb_svc_deferred_request *dr; - - dr = kmalloc(sizeof(*dr), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - gb_operation_get(operation); - - dr->operation = operation; - INIT_WORK(&dr->work, gb_svc_process_deferred_request); - - queue_work(svc->wq, &dr->work); - - return 0; -} - -static int gb_svc_intf_reset_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_message *request = op->request; - struct gb_svc_intf_reset_request *reset; - - if (request->payload_size < sizeof(*reset)) { - dev_warn(&svc->dev, "short reset request received (%zu < %zu)\n", - request->payload_size, sizeof(*reset)); - return -EINVAL; - } - reset = request->payload; - - /* FIXME Reset the interface here */ - - return 0; -} - -static int gb_svc_module_inserted_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_svc_module_inserted_request *request; - - if (op->request->payload_size < sizeof(*request)) { - dev_warn(&svc->dev, "short module-inserted request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*request)); - return -EINVAL; - } - - request = op->request->payload; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, - request->primary_intf_id); - - return gb_svc_queue_deferred_request(op); -} - -static int gb_svc_module_removed_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_svc_module_removed_request *request; - - if (op->request->payload_size < sizeof(*request)) { - dev_warn(&svc->dev, "short module-removed request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*request)); - return -EINVAL; - } - - request = op->request->payload; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, - request->primary_intf_id); - - return gb_svc_queue_deferred_request(op); -} - -static int gb_svc_intf_oops_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_svc_intf_oops_request *request; - - if (op->request->payload_size < sizeof(*request)) { - dev_warn(&svc->dev, "short intf-oops request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*request)); - return -EINVAL; - } - - return gb_svc_queue_deferred_request(op); -} - -static int gb_svc_intf_mailbox_event_recv(struct gb_operation *op) -{ - struct gb_svc *svc = gb_connection_get_data(op->connection); - struct gb_svc_intf_mailbox_event_request *request; - - if (op->request->payload_size < sizeof(*request)) { - dev_warn(&svc->dev, "short mailbox request received (%zu < %zu)\n", - op->request->payload_size, sizeof(*request)); - return -EINVAL; - } - - request = op->request->payload; - - dev_dbg(&svc->dev, "%s - id = %u\n", __func__, request->intf_id); - - return gb_svc_queue_deferred_request(op); -} - -static int gb_svc_request_handler(struct gb_operation *op) -{ - struct gb_connection *connection = op->connection; - struct gb_svc *svc = gb_connection_get_data(connection); - u8 type = op->type; - int ret = 0; - - /* - * SVC requests need to follow a specific order (at least initially) and - * below code takes care of enforcing that. The expected order is: - * - PROTOCOL_VERSION - * - SVC_HELLO - * - Any other request, but the earlier two. - * - * Incoming requests are guaranteed to be serialized and so we don't - * need to protect 'state' for any races. - */ - switch (type) { - case GB_SVC_TYPE_PROTOCOL_VERSION: - if (svc->state != GB_SVC_STATE_RESET) - ret = -EINVAL; - break; - case GB_SVC_TYPE_SVC_HELLO: - if (svc->state != GB_SVC_STATE_PROTOCOL_VERSION) - ret = -EINVAL; - break; - default: - if (svc->state != GB_SVC_STATE_SVC_HELLO) - ret = -EINVAL; - break; - } - - if (ret) { - dev_warn(&svc->dev, "unexpected request 0x%02x received (state %u)\n", - type, svc->state); - return ret; - } - - switch (type) { - case GB_SVC_TYPE_PROTOCOL_VERSION: - ret = gb_svc_version_request(op); - if (!ret) - svc->state = GB_SVC_STATE_PROTOCOL_VERSION; - return ret; - case GB_SVC_TYPE_SVC_HELLO: - ret = gb_svc_hello(op); - if (!ret) - svc->state = GB_SVC_STATE_SVC_HELLO; - return ret; - case GB_SVC_TYPE_INTF_RESET: - return gb_svc_intf_reset_recv(op); - case GB_SVC_TYPE_MODULE_INSERTED: - return gb_svc_module_inserted_recv(op); - case GB_SVC_TYPE_MODULE_REMOVED: - return gb_svc_module_removed_recv(op); - case GB_SVC_TYPE_INTF_MAILBOX_EVENT: - return gb_svc_intf_mailbox_event_recv(op); - case GB_SVC_TYPE_INTF_OOPS: - return gb_svc_intf_oops_recv(op); - default: - dev_warn(&svc->dev, "unsupported request 0x%02x\n", type); - return -EINVAL; - } -} - -static void gb_svc_release(struct device *dev) -{ - struct gb_svc *svc = to_gb_svc(dev); - - if (svc->connection) - gb_connection_destroy(svc->connection); - ida_destroy(&svc->device_id_map); - destroy_workqueue(svc->wq); - kfree(svc); -} - -struct device_type greybus_svc_type = { - .name = "greybus_svc", - .release = gb_svc_release, -}; - -struct gb_svc *gb_svc_create(struct gb_host_device *hd) -{ - struct gb_svc *svc; - - svc = kzalloc(sizeof(*svc), GFP_KERNEL); - if (!svc) - return NULL; - - svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev)); - if (!svc->wq) { - kfree(svc); - return NULL; - } - - svc->dev.parent = &hd->dev; - svc->dev.bus = &greybus_bus_type; - svc->dev.type = &greybus_svc_type; - svc->dev.groups = svc_groups; - svc->dev.dma_mask = svc->dev.parent->dma_mask; - device_initialize(&svc->dev); - - dev_set_name(&svc->dev, "%d-svc", hd->bus_id); - - ida_init(&svc->device_id_map); - svc->state = GB_SVC_STATE_RESET; - svc->hd = hd; - - svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID, - gb_svc_request_handler); - if (IS_ERR(svc->connection)) { - dev_err(&svc->dev, "failed to create connection: %ld\n", - PTR_ERR(svc->connection)); - goto err_put_device; - } - - gb_connection_set_data(svc->connection, svc); - - return svc; - -err_put_device: - put_device(&svc->dev); - return NULL; -} - -int gb_svc_add(struct gb_svc *svc) -{ - int ret; - - /* - * The SVC protocol is currently driven by the SVC, so the SVC device - * is added from the connection request handler when enough - * information has been received. - */ - ret = gb_connection_enable(svc->connection); - if (ret) - return ret; - - return 0; -} - -static void gb_svc_remove_modules(struct gb_svc *svc) -{ - struct gb_host_device *hd = svc->hd; - struct gb_module *module, *tmp; - - list_for_each_entry_safe(module, tmp, &hd->modules, hd_node) { - gb_module_del(module); - list_del(&module->hd_node); - gb_module_put(module); - } -} - -void gb_svc_del(struct gb_svc *svc) -{ - gb_connection_disable_rx(svc->connection); - - /* - * The SVC device may have been registered from the request handler. - */ - if (device_is_registered(&svc->dev)) { - gb_svc_debugfs_exit(svc); - gb_svc_watchdog_destroy(svc); - device_del(&svc->dev); - } - - flush_workqueue(svc->wq); - - gb_svc_remove_modules(svc); - - gb_connection_disable(svc->connection); -} - -void gb_svc_put(struct gb_svc *svc) -{ - put_device(&svc->dev); -} diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c deleted file mode 100644 index b6b1682c19c4..000000000000 --- a/drivers/staging/greybus/svc_watchdog.c +++ /dev/null @@ -1,197 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * SVC Greybus "watchdog" driver. - * - * Copyright 2016 Google Inc. - */ - -#include -#include -#include -#include - -#define SVC_WATCHDOG_PERIOD (2 * HZ) - -struct gb_svc_watchdog { - struct delayed_work work; - struct gb_svc *svc; - bool enabled; - struct notifier_block pm_notifier; -}; - -static struct delayed_work reset_work; - -static int svc_watchdog_pm_notifier(struct notifier_block *notifier, - unsigned long pm_event, void *unused) -{ - struct gb_svc_watchdog *watchdog = - container_of(notifier, struct gb_svc_watchdog, pm_notifier); - - switch (pm_event) { - case PM_SUSPEND_PREPARE: - gb_svc_watchdog_disable(watchdog->svc); - break; - case PM_POST_SUSPEND: - gb_svc_watchdog_enable(watchdog->svc); - break; - default: - break; - } - - return NOTIFY_DONE; -} - -static void greybus_reset(struct work_struct *work) -{ - static char const start_path[] = "/system/bin/start"; - static char *envp[] = { - "HOME=/", - "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", - NULL, - }; - static char *argv[] = { - (char *)start_path, - "unipro_reset", - NULL, - }; - - pr_err("svc_watchdog: calling \"%s %s\" to reset greybus network!\n", - argv[0], argv[1]); - call_usermodehelper(start_path, argv, envp, UMH_WAIT_EXEC); -} - -static void do_work(struct work_struct *work) -{ - struct gb_svc_watchdog *watchdog; - struct gb_svc *svc; - int retval; - - watchdog = container_of(work, struct gb_svc_watchdog, work.work); - svc = watchdog->svc; - - dev_dbg(&svc->dev, "%s: ping.\n", __func__); - retval = gb_svc_ping(svc); - if (retval) { - /* - * Something went really wrong, let's warn userspace and then - * pull the plug and reset the whole greybus network. - * We need to do this outside of this workqueue as we will be - * tearing down the svc device itself. So queue up - * yet-another-callback to do that. - */ - dev_err(&svc->dev, - "SVC ping has returned %d, something is wrong!!!\n", - retval); - - if (svc->action == GB_SVC_WATCHDOG_BITE_PANIC_KERNEL) { - panic("SVC is not responding\n"); - } else if (svc->action == GB_SVC_WATCHDOG_BITE_RESET_UNIPRO) { - dev_err(&svc->dev, "Resetting the greybus network, watch out!!!\n"); - - INIT_DELAYED_WORK(&reset_work, greybus_reset); - schedule_delayed_work(&reset_work, HZ / 2); - - /* - * Disable ourselves, we don't want to trip again unless - * userspace wants us to. - */ - watchdog->enabled = false; - } - } - - /* resubmit our work to happen again, if we are still "alive" */ - if (watchdog->enabled) - schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); -} - -int gb_svc_watchdog_create(struct gb_svc *svc) -{ - struct gb_svc_watchdog *watchdog; - int retval; - - if (svc->watchdog) - return 0; - - watchdog = kmalloc(sizeof(*watchdog), GFP_KERNEL); - if (!watchdog) - return -ENOMEM; - - watchdog->enabled = false; - watchdog->svc = svc; - INIT_DELAYED_WORK(&watchdog->work, do_work); - svc->watchdog = watchdog; - - watchdog->pm_notifier.notifier_call = svc_watchdog_pm_notifier; - retval = register_pm_notifier(&watchdog->pm_notifier); - if (retval) { - dev_err(&svc->dev, "error registering pm notifier(%d)\n", - retval); - goto svc_watchdog_create_err; - } - - retval = gb_svc_watchdog_enable(svc); - if (retval) { - dev_err(&svc->dev, "error enabling watchdog (%d)\n", retval); - unregister_pm_notifier(&watchdog->pm_notifier); - goto svc_watchdog_create_err; - } - return retval; - -svc_watchdog_create_err: - svc->watchdog = NULL; - kfree(watchdog); - - return retval; -} - -void gb_svc_watchdog_destroy(struct gb_svc *svc) -{ - struct gb_svc_watchdog *watchdog = svc->watchdog; - - if (!watchdog) - return; - - unregister_pm_notifier(&watchdog->pm_notifier); - gb_svc_watchdog_disable(svc); - svc->watchdog = NULL; - kfree(watchdog); -} - -bool gb_svc_watchdog_enabled(struct gb_svc *svc) -{ - if (!svc || !svc->watchdog) - return false; - return svc->watchdog->enabled; -} - -int gb_svc_watchdog_enable(struct gb_svc *svc) -{ - struct gb_svc_watchdog *watchdog; - - if (!svc->watchdog) - return -ENODEV; - - watchdog = svc->watchdog; - if (watchdog->enabled) - return 0; - - watchdog->enabled = true; - schedule_delayed_work(&watchdog->work, SVC_WATCHDOG_PERIOD); - return 0; -} - -int gb_svc_watchdog_disable(struct gb_svc *svc) -{ - struct gb_svc_watchdog *watchdog; - - if (!svc->watchdog) - return -ENODEV; - - watchdog = svc->watchdog; - if (!watchdog->enabled) - return 0; - - watchdog->enabled = false; - cancel_delayed_work_sync(&watchdog->work); - return 0; -} -- cgit v1.2.3-59-g8ed1b From b81beec9cb2d586412c7166c893894930f19965e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 25 Aug 2019 07:54:29 +0200 Subject: staging: greybus: move es2 to drivers/greybus/ The es2 Greybus host controller has long been stable, so move it out of drivers/staging/ to drivers/greybus/ Cc: Johan Hovold Cc: greybus-dev@lists.linaro.org Cc: linux-kernel@vger.kernel.org Acked-by: Viresh Kumar Acked-by: Alex Elder Link: https://lore.kernel.org/r/20190825055429.18547-10-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/greybus/Kconfig | 16 + drivers/greybus/Makefile | 7 + drivers/greybus/arpc.h | 63 ++ drivers/greybus/es2.c | 1465 ++++++++++++++++++++++++++++++++++++++ drivers/staging/greybus/Kconfig | 11 - drivers/staging/greybus/Makefile | 5 - drivers/staging/greybus/arpc.h | 63 -- drivers/staging/greybus/es2.c | 1465 -------------------------------------- 8 files changed, 1551 insertions(+), 1544 deletions(-) create mode 100644 drivers/greybus/arpc.h create mode 100644 drivers/greybus/es2.c delete mode 100644 drivers/staging/greybus/arpc.h delete mode 100644 drivers/staging/greybus/es2.c (limited to 'drivers/staging') diff --git a/drivers/greybus/Kconfig b/drivers/greybus/Kconfig index 158d8893114c..b84fcaf8b105 100644 --- a/drivers/greybus/Kconfig +++ b/drivers/greybus/Kconfig @@ -14,3 +14,19 @@ menuconfig GREYBUS To compile this code as a module, chose M here: the module will be called greybus.ko + +if GREYBUS + +config GREYBUS_ES2 + tristate "Greybus ES3 USB host controller" + depends on USB + ---help--- + Select this option if you have a Toshiba ES3 USB device that + acts as a Greybus "host controller". This device is a bridge + from a USB device to a Unipro network. + + To compile this code as a module, chose M here: the module + will be called gb-es2.ko + +endif # GREYBUS + diff --git a/drivers/greybus/Makefile b/drivers/greybus/Makefile index 03b22616ec7d..9bccdd229aa2 100644 --- a/drivers/greybus/Makefile +++ b/drivers/greybus/Makefile @@ -17,3 +17,10 @@ obj-$(CONFIG_GREYBUS) += greybus.o # needed for trace events ccflags-y += -I$(src) + +# Greybus Host controller drivers +gb-es2-y := es2.o + +obj-$(CONFIG_GREYBUS_ES2) += gb-es2.o + + diff --git a/drivers/greybus/arpc.h b/drivers/greybus/arpc.h new file mode 100644 index 000000000000..c8b83c5cfa79 --- /dev/null +++ b/drivers/greybus/arpc.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright(c) 2016 Google Inc. All rights reserved. + * Copyright(c) 2016 Linaro Ltd. All rights reserved. + */ + +#ifndef __ARPC_H +#define __ARPC_H + +/* APBridgeA RPC (ARPC) */ + +enum arpc_result { + ARPC_SUCCESS = 0x00, + ARPC_NO_MEMORY = 0x01, + ARPC_INVALID = 0x02, + ARPC_TIMEOUT = 0x03, + ARPC_UNKNOWN_ERROR = 0xff, +}; + +struct arpc_request_message { + __le16 id; /* RPC unique id */ + __le16 size; /* Size in bytes of header + payload */ + __u8 type; /* RPC type */ + __u8 data[0]; /* ARPC data */ +} __packed; + +struct arpc_response_message { + __le16 id; /* RPC unique id */ + __u8 result; /* Result of RPC */ +} __packed; + +/* ARPC requests */ +#define ARPC_TYPE_CPORT_CONNECTED 0x01 +#define ARPC_TYPE_CPORT_QUIESCE 0x02 +#define ARPC_TYPE_CPORT_CLEAR 0x03 +#define ARPC_TYPE_CPORT_FLUSH 0x04 +#define ARPC_TYPE_CPORT_SHUTDOWN 0x05 + +struct arpc_cport_connected_req { + __le16 cport_id; +} __packed; + +struct arpc_cport_quiesce_req { + __le16 cport_id; + __le16 peer_space; + __le16 timeout; +} __packed; + +struct arpc_cport_clear_req { + __le16 cport_id; +} __packed; + +struct arpc_cport_flush_req { + __le16 cport_id; +} __packed; + +struct arpc_cport_shutdown_req { + __le16 cport_id; + __le16 timeout; + __u8 phase; +} __packed; + +#endif /* __ARPC_H */ diff --git a/drivers/greybus/es2.c b/drivers/greybus/es2.c new file mode 100644 index 000000000000..366716f11b1a --- /dev/null +++ b/drivers/greybus/es2.c @@ -0,0 +1,1465 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Greybus "AP" USB driver for "ES2" controller chips + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arpc.h" +#include "greybus_trace.h" + + +/* Default timeout for USB vendor requests. */ +#define ES2_USB_CTRL_TIMEOUT 500 + +/* Default timeout for ARPC CPort requests */ +#define ES2_ARPC_CPORT_TIMEOUT 500 + +/* Fixed CPort numbers */ +#define ES2_CPORT_CDSI0 16 +#define ES2_CPORT_CDSI1 17 + +/* Memory sizes for the buffers sent to/from the ES2 controller */ +#define ES2_GBUF_MSG_SIZE_MAX 2048 + +/* Memory sizes for the ARPC buffers */ +#define ARPC_OUT_SIZE_MAX U16_MAX +#define ARPC_IN_SIZE_MAX 128 + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x18d1, 0x1eaf) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +#define APB1_LOG_SIZE SZ_16K + +/* + * Number of CPort IN urbs in flight at any point in time. + * Adjust if we are having stalls in the USB buffer due to not enough urbs in + * flight. + */ +#define NUM_CPORT_IN_URB 4 + +/* Number of CPort OUT urbs in flight at any point in time. + * Adjust if we get messages saying we are out of urbs in the system log. + */ +#define NUM_CPORT_OUT_URB 8 + +/* + * Number of ARPC in urbs in flight at any point in time. + */ +#define NUM_ARPC_IN_URB 2 + +/* + * @endpoint: bulk in endpoint for CPort data + * @urb: array of urbs for the CPort in messages + * @buffer: array of buffers for the @cport_in_urb urbs + */ +struct es2_cport_in { + __u8 endpoint; + struct urb *urb[NUM_CPORT_IN_URB]; + u8 *buffer[NUM_CPORT_IN_URB]; +}; + +/** + * es2_ap_dev - ES2 USB Bridge to AP structure + * @usb_dev: pointer to the USB device we are. + * @usb_intf: pointer to the USB interface we are bound to. + * @hd: pointer to our gb_host_device structure + + * @cport_in: endpoint, urbs and buffer for cport in messages + * @cport_out_endpoint: endpoint for for cport out messages + * @cport_out_urb: array of urbs for the CPort out messages + * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or + * not. + * @cport_out_urb_cancelled: array of flags indicating whether the + * corresponding @cport_out_urb is being cancelled + * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" + * + * @apb_log_task: task pointer for logging thread + * @apb_log_dentry: file system entry for the log file interface + * @apb_log_enable_dentry: file system entry for enabling logging + * @apb_log_fifo: kernel FIFO to carry logged data + * @arpc_urb: array of urbs for the ARPC in messages + * @arpc_buffer: array of buffers for the @arpc_urb urbs + * @arpc_endpoint_in: bulk in endpoint for APBridgeA RPC + * @arpc_id_cycle: gives an unique id to ARPC + * @arpc_lock: locks ARPC list + * @arpcs: list of in progress ARPCs + */ +struct es2_ap_dev { + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + struct gb_host_device *hd; + + struct es2_cport_in cport_in; + __u8 cport_out_endpoint; + struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; + bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; + bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; + spinlock_t cport_out_urb_lock; + + bool cdsi1_in_use; + + struct task_struct *apb_log_task; + struct dentry *apb_log_dentry; + struct dentry *apb_log_enable_dentry; + DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE); + + __u8 arpc_endpoint_in; + struct urb *arpc_urb[NUM_ARPC_IN_URB]; + u8 *arpc_buffer[NUM_ARPC_IN_URB]; + + int arpc_id_cycle; + spinlock_t arpc_lock; + struct list_head arpcs; +}; + +struct arpc { + struct list_head list; + struct arpc_request_message *req; + struct arpc_response_message *resp; + struct completion response_received; + bool active; +}; + +static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) +{ + return (struct es2_ap_dev *)&hd->hd_priv; +} + +static void cport_out_callback(struct urb *urb); +static void usb_log_enable(struct es2_ap_dev *es2); +static void usb_log_disable(struct es2_ap_dev *es2); +static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, + size_t size, int *result, unsigned int timeout); + +static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) +{ + struct usb_device *udev = es2->usb_dev; + u8 *data; + int retval; + + data = kmemdup(req, size, GFP_KERNEL); + if (!data) + return -ENOMEM; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + cmd, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0, 0, data, size, ES2_USB_CTRL_TIMEOUT); + if (retval < 0) + dev_err(&udev->dev, "%s: return error %d\n", __func__, retval); + else + retval = 0; + + kfree(data); + return retval; +} + +static void ap_urb_complete(struct urb *urb) +{ + struct usb_ctrlrequest *dr = urb->context; + + kfree(dr); + usb_free_urb(urb); +} + +static int output_async(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) +{ + struct usb_device *udev = es2->usb_dev; + struct urb *urb; + struct usb_ctrlrequest *dr; + u8 *buf; + int retval; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + dr = kmalloc(sizeof(*dr) + size, GFP_ATOMIC); + if (!dr) { + usb_free_urb(urb); + return -ENOMEM; + } + + buf = (u8 *)dr + sizeof(*dr); + memcpy(buf, req, size); + + dr->bRequest = cmd; + dr->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + dr->wValue = 0; + dr->wIndex = 0; + dr->wLength = cpu_to_le16(size); + + usb_fill_control_urb(urb, udev, usb_sndctrlpipe(udev, 0), + (unsigned char *)dr, buf, size, + ap_urb_complete, dr); + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) { + usb_free_urb(urb); + kfree(dr); + } + return retval; +} + +static int output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, + bool async) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + + if (async) + return output_async(es2, req, size, cmd); + + return output_sync(es2, req, size, cmd); +} + +static int es2_cport_in_enable(struct es2_ap_dev *es2, + struct es2_cport_in *cport_in) +{ + struct urb *urb; + int ret; + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + urb = cport_in->urb[i]; + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(&es2->usb_dev->dev, + "failed to submit in-urb: %d\n", ret); + goto err_kill_urbs; + } + } + + return 0; + +err_kill_urbs: + for (--i; i >= 0; --i) { + urb = cport_in->urb[i]; + usb_kill_urb(urb); + } + + return ret; +} + +static void es2_cport_in_disable(struct es2_ap_dev *es2, + struct es2_cport_in *cport_in) +{ + struct urb *urb; + int i; + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + urb = cport_in->urb[i]; + usb_kill_urb(urb); + } +} + +static int es2_arpc_in_enable(struct es2_ap_dev *es2) +{ + struct urb *urb; + int ret; + int i; + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + urb = es2->arpc_urb[i]; + + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + dev_err(&es2->usb_dev->dev, + "failed to submit arpc in-urb: %d\n", ret); + goto err_kill_urbs; + } + } + + return 0; + +err_kill_urbs: + for (--i; i >= 0; --i) { + urb = es2->arpc_urb[i]; + usb_kill_urb(urb); + } + + return ret; +} + +static void es2_arpc_in_disable(struct es2_ap_dev *es2) +{ + struct urb *urb; + int i; + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + urb = es2->arpc_urb[i]; + usb_kill_urb(urb); + } +} + +static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) +{ + struct urb *urb = NULL; + unsigned long flags; + int i; + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + + /* Look in our pool of allocated urbs first, as that's the "fastest" */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (!es2->cport_out_urb_busy[i] && + !es2->cport_out_urb_cancelled[i]) { + es2->cport_out_urb_busy[i] = true; + urb = es2->cport_out_urb[i]; + break; + } + } + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + if (urb) + return urb; + + /* + * Crap, pool is empty, complain to the syslog and go allocate one + * dynamically as we have to succeed. + */ + dev_dbg(&es2->usb_dev->dev, + "No free CPort OUT urbs, having to dynamically allocate one!\n"); + return usb_alloc_urb(0, gfp_mask); +} + +static void free_urb(struct es2_ap_dev *es2, struct urb *urb) +{ + unsigned long flags; + int i; + /* + * See if this was an urb in our pool, if so mark it "free", otherwise + * we need to free it ourselves. + */ + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es2->cport_out_urb[i]) { + es2->cport_out_urb_busy[i] = false; + urb = NULL; + break; + } + } + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + /* If urb is not NULL, then we need to free this urb */ + usb_free_urb(urb); +} + +/* + * We (ab)use the operation-message header pad bytes to transfer the + * cport id in order to minimise overhead. + */ +static void +gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) +{ + header->pad[0] = cport_id; +} + +/* Clear the pad bytes used for the CPort id */ +static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) +{ + header->pad[0] = 0; +} + +/* Extract the CPort id packed into the header, and clear it */ +static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) +{ + u16 cport_id = header->pad[0]; + + gb_message_cport_clear(header); + + return cport_id; +} + +/* + * Returns zero if the message was successfully queued, or a negative errno + * otherwise. + */ +static int message_send(struct gb_host_device *hd, u16 cport_id, + struct gb_message *message, gfp_t gfp_mask) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + size_t buffer_size; + int retval; + struct urb *urb; + unsigned long flags; + + /* + * The data actually transferred will include an indication + * of where the data should be sent. Do one last check of + * the target CPort id before filling it in. + */ + if (!cport_id_valid(hd, cport_id)) { + dev_err(&udev->dev, "invalid cport %u\n", cport_id); + return -EINVAL; + } + + /* Find a free urb */ + urb = next_free_urb(es2, gfp_mask); + if (!urb) + return -ENOMEM; + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + message->hcpriv = urb; + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + /* Pack the cport id into the message header */ + gb_message_cport_pack(message->header, cport_id); + + buffer_size = sizeof(*message->header) + message->payload_size; + + usb_fill_bulk_urb(urb, udev, + usb_sndbulkpipe(udev, + es2->cport_out_endpoint), + message->buffer, buffer_size, + cport_out_callback, message); + urb->transfer_flags |= URB_ZERO_PACKET; + + trace_gb_message_submit(message); + + retval = usb_submit_urb(urb, gfp_mask); + if (retval) { + dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + free_urb(es2, urb); + gb_message_cport_clear(message->header); + + return retval; + } + + return 0; +} + +/* + * Can not be called in atomic context. + */ +static void message_cancel(struct gb_message *message) +{ + struct gb_host_device *hd = message->operation->connection->hd; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct urb *urb; + int i; + + might_sleep(); + + spin_lock_irq(&es2->cport_out_urb_lock); + urb = message->hcpriv; + + /* Prevent dynamically allocated urb from being deallocated. */ + usb_get_urb(urb); + + /* Prevent pre-allocated urb from being reused. */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + if (urb == es2->cport_out_urb[i]) { + es2->cport_out_urb_cancelled[i] = true; + break; + } + } + spin_unlock_irq(&es2->cport_out_urb_lock); + + usb_kill_urb(urb); + + if (i < NUM_CPORT_OUT_URB) { + spin_lock_irq(&es2->cport_out_urb_lock); + es2->cport_out_urb_cancelled[i] = false; + spin_unlock_irq(&es2->cport_out_urb_lock); + } + + usb_free_urb(urb); +} + +static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, + unsigned long flags) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + switch (cport_id) { + case ES2_CPORT_CDSI0: + case ES2_CPORT_CDSI1: + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EBUSY; + } + + if (flags & GB_CONNECTION_FLAG_OFFLOADED && + flags & GB_CONNECTION_FLAG_CDSI1) { + if (es2->cdsi1_in_use) { + dev_err(&hd->dev, "CDSI1 already in use\n"); + return -EBUSY; + } + + es2->cdsi1_in_use = true; + + return ES2_CPORT_CDSI1; + } + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + + switch (cport_id) { + case ES2_CPORT_CDSI1: + es2->cdsi1_in_use = false; + return; + } + + ida_simple_remove(&hd->cport_id_map, cport_id); +} + +static int cport_enable(struct gb_host_device *hd, u16 cport_id, + unsigned long flags) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + struct gb_apb_request_cport_flags *req; + u32 connection_flags; + int ret; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + connection_flags = 0; + if (flags & GB_CONNECTION_FLAG_CONTROL) + connection_flags |= GB_APB_CPORT_FLAG_CONTROL; + if (flags & GB_CONNECTION_FLAG_HIGH_PRIO) + connection_flags |= GB_APB_CPORT_FLAG_HIGH_PRIO; + + req->flags = cpu_to_le32(connection_flags); + + dev_dbg(&hd->dev, "%s - cport = %u, flags = %02x\n", __func__, + cport_id, connection_flags); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_CPORT_FLAGS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, + req, sizeof(*req), ES2_USB_CTRL_TIMEOUT); + if (ret != sizeof(*req)) { + dev_err(&udev->dev, "failed to set cport flags for port %d\n", + cport_id); + if (ret >= 0) + ret = -EIO; + + goto out; + } + + ret = 0; +out: + kfree(req); + + return ret; +} + +static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_connected_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_CONNECTED, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to set connected state for cport %u: %d\n", + cport_id, ret); + return ret; + } + + return 0; +} + +static int es2_cport_flush(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_flush_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_FLUSH, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to flush cport %u: %d\n", cport_id, ret); + return ret; + } + + return 0; +} + +static int es2_cport_shutdown(struct gb_host_device *hd, u16 cport_id, + u8 phase, unsigned int timeout) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_shutdown_req req; + int result; + int ret; + + if (timeout > U16_MAX) + return -EINVAL; + + req.cport_id = cpu_to_le16(cport_id); + req.timeout = cpu_to_le16(timeout); + req.phase = phase; + ret = arpc_sync(es2, ARPC_TYPE_CPORT_SHUTDOWN, &req, sizeof(req), + &result, ES2_ARPC_CPORT_TIMEOUT + timeout); + if (ret) { + dev_err(dev, "failed to send shutdown over cport %u: %d (%d)\n", + cport_id, ret, result); + return ret; + } + + return 0; +} + +static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, + size_t peer_space, unsigned int timeout) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_quiesce_req req; + int result; + int ret; + + if (peer_space > U16_MAX) + return -EINVAL; + + if (timeout > U16_MAX) + return -EINVAL; + + req.cport_id = cpu_to_le16(cport_id); + req.peer_space = cpu_to_le16(peer_space); + req.timeout = cpu_to_le16(timeout); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_QUIESCE, &req, sizeof(req), + &result, ES2_ARPC_CPORT_TIMEOUT + timeout); + if (ret) { + dev_err(dev, "failed to quiesce cport %u: %d (%d)\n", + cport_id, ret, result); + return ret; + } + + return 0; +} + +static int es2_cport_clear(struct gb_host_device *hd, u16 cport_id) +{ + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct device *dev = &es2->usb_dev->dev; + struct arpc_cport_clear_req req; + int ret; + + req.cport_id = cpu_to_le16(cport_id); + ret = arpc_sync(es2, ARPC_TYPE_CPORT_CLEAR, &req, sizeof(req), + NULL, ES2_ARPC_CPORT_TIMEOUT); + if (ret) { + dev_err(dev, "failed to clear cport %u: %d\n", cport_id, ret); + return ret; + } + + return 0; +} + +static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_LATENCY_TAG_EN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES2_USB_CTRL_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", + cport_id); + return retval; +} + +static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) +{ + int retval; + struct es2_ap_dev *es2 = hd_to_es2(hd); + struct usb_device *udev = es2->usb_dev; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_LATENCY_TAG_DIS, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, cport_id, 0, NULL, + 0, ES2_USB_CTRL_TIMEOUT); + + if (retval < 0) + dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", + cport_id); + return retval; +} + +static struct gb_hd_driver es2_driver = { + .hd_priv_size = sizeof(struct es2_ap_dev), + .message_send = message_send, + .message_cancel = message_cancel, + .cport_allocate = es2_cport_allocate, + .cport_release = es2_cport_release, + .cport_enable = cport_enable, + .cport_connected = es2_cport_connected, + .cport_flush = es2_cport_flush, + .cport_shutdown = es2_cport_shutdown, + .cport_quiesce = es2_cport_quiesce, + .cport_clear = es2_cport_clear, + .latency_tag_enable = latency_tag_enable, + .latency_tag_disable = latency_tag_disable, + .output = output, +}; + +/* Common function to report consistent warnings based on URB status */ +static int check_urb_status(struct urb *urb) +{ + struct device *dev = &urb->dev->dev; + int status = urb->status; + + switch (status) { + case 0: + return 0; + + case -EOVERFLOW: + dev_err(dev, "%s: overflow actual length is %d\n", + __func__, urb->actual_length); + /* fall through */ + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -EPROTO: + /* device is gone, stop sending */ + return status; + } + dev_err(dev, "%s: unknown status %d\n", __func__, status); + + return -EAGAIN; +} + +static void es2_destroy(struct es2_ap_dev *es2) +{ + struct usb_device *udev; + struct urb *urb; + int i; + + debugfs_remove(es2->apb_log_enable_dentry); + usb_log_disable(es2); + + /* Tear down everything! */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + urb = es2->cport_out_urb[i]; + usb_kill_urb(urb); + usb_free_urb(urb); + es2->cport_out_urb[i] = NULL; + es2->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + usb_free_urb(es2->arpc_urb[i]); + kfree(es2->arpc_buffer[i]); + es2->arpc_buffer[i] = NULL; + } + + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + usb_free_urb(es2->cport_in.urb[i]); + kfree(es2->cport_in.buffer[i]); + es2->cport_in.buffer[i] = NULL; + } + + /* release reserved CDSI0 and CDSI1 cports */ + gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1); + gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0); + + udev = es2->usb_dev; + gb_hd_put(es2->hd); + + usb_put_dev(udev); +} + +static void cport_in_callback(struct urb *urb) +{ + struct gb_host_device *hd = urb->context; + struct device *dev = &urb->dev->dev; + struct gb_operation_msg_hdr *header; + int status = check_urb_status(urb); + int retval; + u16 cport_id; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + + /* The urb is being unlinked */ + if (status == -ENOENT || status == -ESHUTDOWN) + return; + + dev_err(dev, "urb cport in error %d (dropped)\n", status); + return; + } + + if (urb->actual_length < sizeof(*header)) { + dev_err(dev, "short message received\n"); + goto exit; + } + + /* Extract the CPort id, which is packed in the message header */ + header = urb->transfer_buffer; + cport_id = gb_message_cport_unpack(header); + + if (cport_id_valid(hd, cport_id)) { + greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, + urb->actual_length); + } else { + dev_err(dev, "invalid cport id %u received\n", cport_id); + } +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "failed to resubmit in-urb: %d\n", retval); +} + +static void cport_out_callback(struct urb *urb) +{ + struct gb_message *message = urb->context; + struct gb_host_device *hd = message->operation->connection->hd; + struct es2_ap_dev *es2 = hd_to_es2(hd); + int status = check_urb_status(urb); + unsigned long flags; + + gb_message_cport_clear(message->header); + + spin_lock_irqsave(&es2->cport_out_urb_lock, flags); + message->hcpriv = NULL; + spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); + + /* + * Tell the submitter that the message send (attempt) is + * complete, and report the status. + */ + greybus_message_sent(hd, message, status); + + free_urb(es2, urb); +} + +static struct arpc *arpc_alloc(void *payload, u16 size, u8 type) +{ + struct arpc *rpc; + + if (size + sizeof(*rpc->req) > ARPC_OUT_SIZE_MAX) + return NULL; + + rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return NULL; + + INIT_LIST_HEAD(&rpc->list); + rpc->req = kzalloc(sizeof(*rpc->req) + size, GFP_KERNEL); + if (!rpc->req) + goto err_free_rpc; + + rpc->resp = kzalloc(sizeof(*rpc->resp), GFP_KERNEL); + if (!rpc->resp) + goto err_free_req; + + rpc->req->type = type; + rpc->req->size = cpu_to_le16(sizeof(*rpc->req) + size); + memcpy(rpc->req->data, payload, size); + + init_completion(&rpc->response_received); + + return rpc; + +err_free_req: + kfree(rpc->req); +err_free_rpc: + kfree(rpc); + + return NULL; +} + +static void arpc_free(struct arpc *rpc) +{ + kfree(rpc->req); + kfree(rpc->resp); + kfree(rpc); +} + +static struct arpc *arpc_find(struct es2_ap_dev *es2, __le16 id) +{ + struct arpc *rpc; + + list_for_each_entry(rpc, &es2->arpcs, list) { + if (rpc->req->id == id) + return rpc; + } + + return NULL; +} + +static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc) +{ + rpc->active = true; + rpc->req->id = cpu_to_le16(es2->arpc_id_cycle++); + list_add_tail(&rpc->list, &es2->arpcs); +} + +static void arpc_del(struct es2_ap_dev *es2, struct arpc *rpc) +{ + if (rpc->active) { + rpc->active = false; + list_del(&rpc->list); + } +} + +static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) +{ + struct usb_device *udev = es2->usb_dev; + int retval; + + retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + GB_APB_REQUEST_ARPC_RUN, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0, 0, + rpc->req, le16_to_cpu(rpc->req->size), + ES2_USB_CTRL_TIMEOUT); + if (retval != le16_to_cpu(rpc->req->size)) { + dev_err(&udev->dev, + "failed to send ARPC request %d: %d\n", + rpc->req->type, retval); + if (retval > 0) + retval = -EIO; + return retval; + } + + return 0; +} + +static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, + size_t size, int *result, unsigned int timeout) +{ + struct arpc *rpc; + unsigned long flags; + int retval; + + if (result) + *result = 0; + + rpc = arpc_alloc(payload, size, type); + if (!rpc) + return -ENOMEM; + + spin_lock_irqsave(&es2->arpc_lock, flags); + arpc_add(es2, rpc); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + + retval = arpc_send(es2, rpc, timeout); + if (retval) + goto out_arpc_del; + + retval = wait_for_completion_interruptible_timeout( + &rpc->response_received, + msecs_to_jiffies(timeout)); + if (retval <= 0) { + if (!retval) + retval = -ETIMEDOUT; + goto out_arpc_del; + } + + if (rpc->resp->result) { + retval = -EREMOTEIO; + if (result) + *result = rpc->resp->result; + } else { + retval = 0; + } + +out_arpc_del: + spin_lock_irqsave(&es2->arpc_lock, flags); + arpc_del(es2, rpc); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + arpc_free(rpc); + + if (retval < 0 && retval != -EREMOTEIO) { + dev_err(&es2->usb_dev->dev, + "failed to execute ARPC: %d\n", retval); + } + + return retval; +} + +static void arpc_in_callback(struct urb *urb) +{ + struct es2_ap_dev *es2 = urb->context; + struct device *dev = &urb->dev->dev; + int status = check_urb_status(urb); + struct arpc *rpc; + struct arpc_response_message *resp; + unsigned long flags; + int retval; + + if (status) { + if ((status == -EAGAIN) || (status == -EPROTO)) + goto exit; + + /* The urb is being unlinked */ + if (status == -ENOENT || status == -ESHUTDOWN) + return; + + dev_err(dev, "arpc in-urb error %d (dropped)\n", status); + return; + } + + if (urb->actual_length < sizeof(*resp)) { + dev_err(dev, "short aprc response received\n"); + goto exit; + } + + resp = urb->transfer_buffer; + spin_lock_irqsave(&es2->arpc_lock, flags); + rpc = arpc_find(es2, resp->id); + if (!rpc) { + dev_err(dev, "invalid arpc response id received: %u\n", + le16_to_cpu(resp->id)); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + goto exit; + } + + arpc_del(es2, rpc); + memcpy(rpc->resp, resp, sizeof(*resp)); + complete(&rpc->response_received); + spin_unlock_irqrestore(&es2->arpc_lock, flags); + +exit: + /* put our urb back in the request pool */ + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + dev_err(dev, "failed to resubmit arpc in-urb: %d\n", retval); +} + +#define APB1_LOG_MSG_SIZE 64 +static void apb_log_get(struct es2_ap_dev *es2, char *buf) +{ + int retval; + + do { + retval = usb_control_msg(es2->usb_dev, + usb_rcvctrlpipe(es2->usb_dev, 0), + GB_APB_REQUEST_LOG, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, + 0x00, 0x00, + buf, + APB1_LOG_MSG_SIZE, + ES2_USB_CTRL_TIMEOUT); + if (retval > 0) + kfifo_in(&es2->apb_log_fifo, buf, retval); + } while (retval > 0); +} + +static int apb_log_poll(void *data) +{ + struct es2_ap_dev *es2 = data; + char *buf; + + buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + while (!kthread_should_stop()) { + msleep(1000); + apb_log_get(es2, buf); + } + + kfree(buf); + + return 0; +} + +static ssize_t apb_log_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + struct es2_ap_dev *es2 = file_inode(f)->i_private; + ssize_t ret; + size_t copied; + char *tmp_buf; + + if (count > APB1_LOG_SIZE) + count = APB1_LOG_SIZE; + + tmp_buf = kmalloc(count, GFP_KERNEL); + if (!tmp_buf) + return -ENOMEM; + + copied = kfifo_out(&es2->apb_log_fifo, tmp_buf, count); + ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); + + kfree(tmp_buf); + + return ret; +} + +static const struct file_operations apb_log_fops = { + .read = apb_log_read, +}; + +static void usb_log_enable(struct es2_ap_dev *es2) +{ + if (!IS_ERR_OR_NULL(es2->apb_log_task)) + return; + + /* get log from APB1 */ + es2->apb_log_task = kthread_run(apb_log_poll, es2, "apb_log"); + if (IS_ERR(es2->apb_log_task)) + return; + /* XXX We will need to rename this per APB */ + es2->apb_log_dentry = debugfs_create_file("apb_log", 0444, + gb_debugfs_get(), es2, + &apb_log_fops); +} + +static void usb_log_disable(struct es2_ap_dev *es2) +{ + if (IS_ERR_OR_NULL(es2->apb_log_task)) + return; + + debugfs_remove(es2->apb_log_dentry); + es2->apb_log_dentry = NULL; + + kthread_stop(es2->apb_log_task); + es2->apb_log_task = NULL; +} + +static ssize_t apb_log_enable_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + struct es2_ap_dev *es2 = file_inode(f)->i_private; + int enable = !IS_ERR_OR_NULL(es2->apb_log_task); + char tmp_buf[3]; + + sprintf(tmp_buf, "%d\n", enable); + return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); +} + +static ssize_t apb_log_enable_write(struct file *f, const char __user *buf, + size_t count, loff_t *ppos) +{ + int enable; + ssize_t retval; + struct es2_ap_dev *es2 = file_inode(f)->i_private; + + retval = kstrtoint_from_user(buf, count, 10, &enable); + if (retval) + return retval; + + if (enable) + usb_log_enable(es2); + else + usb_log_disable(es2); + + return count; +} + +static const struct file_operations apb_log_enable_fops = { + .read = apb_log_enable_read, + .write = apb_log_enable_write, +}; + +static int apb_get_cport_count(struct usb_device *udev) +{ + int retval; + __le16 *cport_count; + + cport_count = kzalloc(sizeof(*cport_count), GFP_KERNEL); + if (!cport_count) + return -ENOMEM; + + retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + GB_APB_REQUEST_CPORT_COUNT, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE, 0, 0, cport_count, + sizeof(*cport_count), ES2_USB_CTRL_TIMEOUT); + if (retval != sizeof(*cport_count)) { + dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", + retval); + + if (retval >= 0) + retval = -EIO; + + goto out; + } + + retval = le16_to_cpu(*cport_count); + + /* We need to fit a CPort ID in one byte of a message header */ + if (retval > U8_MAX) { + retval = U8_MAX; + dev_warn(&udev->dev, "Limiting number of CPorts to U8_MAX\n"); + } + +out: + kfree(cport_count); + return retval; +} + +/* + * The ES2 USB Bridge device has 15 endpoints + * 1 Control - usual USB stuff + AP -> APBridgeA messages + * 7 Bulk IN - CPort data in + * 7 Bulk OUT - CPort data out + */ +static int ap_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct es2_ap_dev *es2; + struct gb_host_device *hd; + struct usb_device *udev; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + __u8 ep_addr; + int retval; + int i; + int num_cports; + bool bulk_out_found = false; + bool bulk_in_found = false; + bool arpc_in_found = false; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + num_cports = apb_get_cport_count(udev); + if (num_cports < 0) { + usb_put_dev(udev); + dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", + num_cports); + return num_cports; + } + + hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, + num_cports); + if (IS_ERR(hd)) { + usb_put_dev(udev); + return PTR_ERR(hd); + } + + es2 = hd_to_es2(hd); + es2->hd = hd; + es2->usb_intf = interface; + es2->usb_dev = udev; + spin_lock_init(&es2->cport_out_urb_lock); + INIT_KFIFO(es2->apb_log_fifo); + usb_set_intfdata(interface, es2); + + /* + * Reserve the CDSI0 and CDSI1 CPorts so they won't be allocated + * dynamically. + */ + retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI0); + if (retval) + goto error; + retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI1); + if (retval) + goto error; + + /* find all bulk endpoints */ + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + ep_addr = endpoint->bEndpointAddress; + + if (usb_endpoint_is_bulk_in(endpoint)) { + if (!bulk_in_found) { + es2->cport_in.endpoint = ep_addr; + bulk_in_found = true; + } else if (!arpc_in_found) { + es2->arpc_endpoint_in = ep_addr; + arpc_in_found = true; + } else { + dev_warn(&udev->dev, + "Unused bulk IN endpoint found: 0x%02x\n", + ep_addr); + } + continue; + } + if (usb_endpoint_is_bulk_out(endpoint)) { + if (!bulk_out_found) { + es2->cport_out_endpoint = ep_addr; + bulk_out_found = true; + } else { + dev_warn(&udev->dev, + "Unused bulk OUT endpoint found: 0x%02x\n", + ep_addr); + } + continue; + } + dev_warn(&udev->dev, + "Unknown endpoint type found, address 0x%02x\n", + ep_addr); + } + if (!bulk_in_found || !arpc_in_found || !bulk_out_found) { + dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); + retval = -ENODEV; + goto error; + } + + /* Allocate buffers for our cport in messages */ + for (i = 0; i < NUM_CPORT_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + es2->cport_in.urb[i] = urb; + + buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); + if (!buffer) { + retval = -ENOMEM; + goto error; + } + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, es2->cport_in.endpoint), + buffer, ES2_GBUF_MSG_SIZE_MAX, + cport_in_callback, hd); + + es2->cport_in.buffer[i] = buffer; + } + + /* Allocate buffers for ARPC in messages */ + for (i = 0; i < NUM_ARPC_IN_URB; ++i) { + struct urb *urb; + u8 *buffer; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + es2->arpc_urb[i] = urb; + + buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL); + if (!buffer) { + retval = -ENOMEM; + goto error; + } + + usb_fill_bulk_urb(urb, udev, + usb_rcvbulkpipe(udev, + es2->arpc_endpoint_in), + buffer, ARPC_IN_SIZE_MAX, + arpc_in_callback, es2); + + es2->arpc_buffer[i] = buffer; + } + + /* Allocate urbs for our CPort OUT messages */ + for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + retval = -ENOMEM; + goto error; + } + + es2->cport_out_urb[i] = urb; + es2->cport_out_urb_busy[i] = false; /* just to be anal */ + } + + /* XXX We will need to rename this per APB */ + es2->apb_log_enable_dentry = debugfs_create_file("apb_log_enable", + 0644, + gb_debugfs_get(), es2, + &apb_log_enable_fops); + + INIT_LIST_HEAD(&es2->arpcs); + spin_lock_init(&es2->arpc_lock); + + retval = es2_arpc_in_enable(es2); + if (retval) + goto error; + + retval = gb_hd_add(hd); + if (retval) + goto err_disable_arpc_in; + + retval = es2_cport_in_enable(es2, &es2->cport_in); + if (retval) + goto err_hd_del; + + return 0; + +err_hd_del: + gb_hd_del(hd); +err_disable_arpc_in: + es2_arpc_in_disable(es2); +error: + es2_destroy(es2); + + return retval; +} + +static void ap_disconnect(struct usb_interface *interface) +{ + struct es2_ap_dev *es2 = usb_get_intfdata(interface); + + gb_hd_del(es2->hd); + + es2_cport_in_disable(es2, &es2->cport_in); + es2_arpc_in_disable(es2); + + es2_destroy(es2); +} + +static struct usb_driver es2_ap_driver = { + .name = "es2_ap_driver", + .probe = ap_probe, + .disconnect = ap_disconnect, + .id_table = id_table, + .soft_unbind = 1, +}; + +module_usb_driver(es2_ap_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Greg Kroah-Hartman "); diff --git a/drivers/staging/greybus/Kconfig b/drivers/staging/greybus/Kconfig index d03c37e1e6e8..d4777f5a8b90 100644 --- a/drivers/staging/greybus/Kconfig +++ b/drivers/staging/greybus/Kconfig @@ -1,17 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 if GREYBUS -config GREYBUS_ES2 - tristate "Greybus ES3 USB host controller" - depends on USB - ---help--- - Select this option if you have a Toshiba ES3 USB device that - acts as a Greybus "host controller". This device is a bridge - from a USB device to a Unipro network. - - To compile this code as a module, chose M here: the module - will be called gb-es2.ko - config GREYBUS_AUDIO tristate "Greybus Audio Class driver" depends on SOUND diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile index d16853399c9a..627e44f2a983 100644 --- a/drivers/staging/greybus/Makefile +++ b/drivers/staging/greybus/Makefile @@ -2,11 +2,6 @@ # needed for trace events ccflags-y += -I$(src) -# Greybus Host controller drivers -gb-es2-y := es2.o - -obj-$(CONFIG_GREYBUS_ES2) += gb-es2.o - # Greybus class drivers gb-bootrom-y := bootrom.o gb-camera-y := camera.o diff --git a/drivers/staging/greybus/arpc.h b/drivers/staging/greybus/arpc.h deleted file mode 100644 index c8b83c5cfa79..000000000000 --- a/drivers/staging/greybus/arpc.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ -/* - * Copyright(c) 2016 Google Inc. All rights reserved. - * Copyright(c) 2016 Linaro Ltd. All rights reserved. - */ - -#ifndef __ARPC_H -#define __ARPC_H - -/* APBridgeA RPC (ARPC) */ - -enum arpc_result { - ARPC_SUCCESS = 0x00, - ARPC_NO_MEMORY = 0x01, - ARPC_INVALID = 0x02, - ARPC_TIMEOUT = 0x03, - ARPC_UNKNOWN_ERROR = 0xff, -}; - -struct arpc_request_message { - __le16 id; /* RPC unique id */ - __le16 size; /* Size in bytes of header + payload */ - __u8 type; /* RPC type */ - __u8 data[0]; /* ARPC data */ -} __packed; - -struct arpc_response_message { - __le16 id; /* RPC unique id */ - __u8 result; /* Result of RPC */ -} __packed; - -/* ARPC requests */ -#define ARPC_TYPE_CPORT_CONNECTED 0x01 -#define ARPC_TYPE_CPORT_QUIESCE 0x02 -#define ARPC_TYPE_CPORT_CLEAR 0x03 -#define ARPC_TYPE_CPORT_FLUSH 0x04 -#define ARPC_TYPE_CPORT_SHUTDOWN 0x05 - -struct arpc_cport_connected_req { - __le16 cport_id; -} __packed; - -struct arpc_cport_quiesce_req { - __le16 cport_id; - __le16 peer_space; - __le16 timeout; -} __packed; - -struct arpc_cport_clear_req { - __le16 cport_id; -} __packed; - -struct arpc_cport_flush_req { - __le16 cport_id; -} __packed; - -struct arpc_cport_shutdown_req { - __le16 cport_id; - __le16 timeout; - __u8 phase; -} __packed; - -#endif /* __ARPC_H */ diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c deleted file mode 100644 index 5b755e76d8a4..000000000000 --- a/drivers/staging/greybus/es2.c +++ /dev/null @@ -1,1465 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus "AP" USB driver for "ES2" controller chips - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "arpc.h" -#include "../../greybus/greybus_trace.h" - - -/* Default timeout for USB vendor requests. */ -#define ES2_USB_CTRL_TIMEOUT 500 - -/* Default timeout for ARPC CPort requests */ -#define ES2_ARPC_CPORT_TIMEOUT 500 - -/* Fixed CPort numbers */ -#define ES2_CPORT_CDSI0 16 -#define ES2_CPORT_CDSI1 17 - -/* Memory sizes for the buffers sent to/from the ES2 controller */ -#define ES2_GBUF_MSG_SIZE_MAX 2048 - -/* Memory sizes for the ARPC buffers */ -#define ARPC_OUT_SIZE_MAX U16_MAX -#define ARPC_IN_SIZE_MAX 128 - -static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x18d1, 0x1eaf) }, - { }, -}; -MODULE_DEVICE_TABLE(usb, id_table); - -#define APB1_LOG_SIZE SZ_16K - -/* - * Number of CPort IN urbs in flight at any point in time. - * Adjust if we are having stalls in the USB buffer due to not enough urbs in - * flight. - */ -#define NUM_CPORT_IN_URB 4 - -/* Number of CPort OUT urbs in flight at any point in time. - * Adjust if we get messages saying we are out of urbs in the system log. - */ -#define NUM_CPORT_OUT_URB 8 - -/* - * Number of ARPC in urbs in flight at any point in time. - */ -#define NUM_ARPC_IN_URB 2 - -/* - * @endpoint: bulk in endpoint for CPort data - * @urb: array of urbs for the CPort in messages - * @buffer: array of buffers for the @cport_in_urb urbs - */ -struct es2_cport_in { - __u8 endpoint; - struct urb *urb[NUM_CPORT_IN_URB]; - u8 *buffer[NUM_CPORT_IN_URB]; -}; - -/** - * es2_ap_dev - ES2 USB Bridge to AP structure - * @usb_dev: pointer to the USB device we are. - * @usb_intf: pointer to the USB interface we are bound to. - * @hd: pointer to our gb_host_device structure - - * @cport_in: endpoint, urbs and buffer for cport in messages - * @cport_out_endpoint: endpoint for for cport out messages - * @cport_out_urb: array of urbs for the CPort out messages - * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or - * not. - * @cport_out_urb_cancelled: array of flags indicating whether the - * corresponding @cport_out_urb is being cancelled - * @cport_out_urb_lock: locks the @cport_out_urb_busy "list" - * - * @apb_log_task: task pointer for logging thread - * @apb_log_dentry: file system entry for the log file interface - * @apb_log_enable_dentry: file system entry for enabling logging - * @apb_log_fifo: kernel FIFO to carry logged data - * @arpc_urb: array of urbs for the ARPC in messages - * @arpc_buffer: array of buffers for the @arpc_urb urbs - * @arpc_endpoint_in: bulk in endpoint for APBridgeA RPC - * @arpc_id_cycle: gives an unique id to ARPC - * @arpc_lock: locks ARPC list - * @arpcs: list of in progress ARPCs - */ -struct es2_ap_dev { - struct usb_device *usb_dev; - struct usb_interface *usb_intf; - struct gb_host_device *hd; - - struct es2_cport_in cport_in; - __u8 cport_out_endpoint; - struct urb *cport_out_urb[NUM_CPORT_OUT_URB]; - bool cport_out_urb_busy[NUM_CPORT_OUT_URB]; - bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB]; - spinlock_t cport_out_urb_lock; - - bool cdsi1_in_use; - - struct task_struct *apb_log_task; - struct dentry *apb_log_dentry; - struct dentry *apb_log_enable_dentry; - DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE); - - __u8 arpc_endpoint_in; - struct urb *arpc_urb[NUM_ARPC_IN_URB]; - u8 *arpc_buffer[NUM_ARPC_IN_URB]; - - int arpc_id_cycle; - spinlock_t arpc_lock; - struct list_head arpcs; -}; - -struct arpc { - struct list_head list; - struct arpc_request_message *req; - struct arpc_response_message *resp; - struct completion response_received; - bool active; -}; - -static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd) -{ - return (struct es2_ap_dev *)&hd->hd_priv; -} - -static void cport_out_callback(struct urb *urb); -static void usb_log_enable(struct es2_ap_dev *es2); -static void usb_log_disable(struct es2_ap_dev *es2); -static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, - size_t size, int *result, unsigned int timeout); - -static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) -{ - struct usb_device *udev = es2->usb_dev; - u8 *data; - int retval; - - data = kmemdup(req, size, GFP_KERNEL); - if (!data) - return -ENOMEM; - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - cmd, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - 0, 0, data, size, ES2_USB_CTRL_TIMEOUT); - if (retval < 0) - dev_err(&udev->dev, "%s: return error %d\n", __func__, retval); - else - retval = 0; - - kfree(data); - return retval; -} - -static void ap_urb_complete(struct urb *urb) -{ - struct usb_ctrlrequest *dr = urb->context; - - kfree(dr); - usb_free_urb(urb); -} - -static int output_async(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd) -{ - struct usb_device *udev = es2->usb_dev; - struct urb *urb; - struct usb_ctrlrequest *dr; - u8 *buf; - int retval; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) - return -ENOMEM; - - dr = kmalloc(sizeof(*dr) + size, GFP_ATOMIC); - if (!dr) { - usb_free_urb(urb); - return -ENOMEM; - } - - buf = (u8 *)dr + sizeof(*dr); - memcpy(buf, req, size); - - dr->bRequest = cmd; - dr->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; - dr->wValue = 0; - dr->wIndex = 0; - dr->wLength = cpu_to_le16(size); - - usb_fill_control_urb(urb, udev, usb_sndctrlpipe(udev, 0), - (unsigned char *)dr, buf, size, - ap_urb_complete, dr); - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) { - usb_free_urb(urb); - kfree(dr); - } - return retval; -} - -static int output(struct gb_host_device *hd, void *req, u16 size, u8 cmd, - bool async) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - - if (async) - return output_async(es2, req, size, cmd); - - return output_sync(es2, req, size, cmd); -} - -static int es2_cport_in_enable(struct es2_ap_dev *es2, - struct es2_cport_in *cport_in) -{ - struct urb *urb; - int ret; - int i; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - urb = cport_in->urb[i]; - - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret) { - dev_err(&es2->usb_dev->dev, - "failed to submit in-urb: %d\n", ret); - goto err_kill_urbs; - } - } - - return 0; - -err_kill_urbs: - for (--i; i >= 0; --i) { - urb = cport_in->urb[i]; - usb_kill_urb(urb); - } - - return ret; -} - -static void es2_cport_in_disable(struct es2_ap_dev *es2, - struct es2_cport_in *cport_in) -{ - struct urb *urb; - int i; - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - urb = cport_in->urb[i]; - usb_kill_urb(urb); - } -} - -static int es2_arpc_in_enable(struct es2_ap_dev *es2) -{ - struct urb *urb; - int ret; - int i; - - for (i = 0; i < NUM_ARPC_IN_URB; ++i) { - urb = es2->arpc_urb[i]; - - ret = usb_submit_urb(urb, GFP_KERNEL); - if (ret) { - dev_err(&es2->usb_dev->dev, - "failed to submit arpc in-urb: %d\n", ret); - goto err_kill_urbs; - } - } - - return 0; - -err_kill_urbs: - for (--i; i >= 0; --i) { - urb = es2->arpc_urb[i]; - usb_kill_urb(urb); - } - - return ret; -} - -static void es2_arpc_in_disable(struct es2_ap_dev *es2) -{ - struct urb *urb; - int i; - - for (i = 0; i < NUM_ARPC_IN_URB; ++i) { - urb = es2->arpc_urb[i]; - usb_kill_urb(urb); - } -} - -static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) -{ - struct urb *urb = NULL; - unsigned long flags; - int i; - - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); - - /* Look in our pool of allocated urbs first, as that's the "fastest" */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (!es2->cport_out_urb_busy[i] && - !es2->cport_out_urb_cancelled[i]) { - es2->cport_out_urb_busy[i] = true; - urb = es2->cport_out_urb[i]; - break; - } - } - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); - if (urb) - return urb; - - /* - * Crap, pool is empty, complain to the syslog and go allocate one - * dynamically as we have to succeed. - */ - dev_dbg(&es2->usb_dev->dev, - "No free CPort OUT urbs, having to dynamically allocate one!\n"); - return usb_alloc_urb(0, gfp_mask); -} - -static void free_urb(struct es2_ap_dev *es2, struct urb *urb) -{ - unsigned long flags; - int i; - /* - * See if this was an urb in our pool, if so mark it "free", otherwise - * we need to free it ourselves. - */ - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es2->cport_out_urb[i]) { - es2->cport_out_urb_busy[i] = false; - urb = NULL; - break; - } - } - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); - - /* If urb is not NULL, then we need to free this urb */ - usb_free_urb(urb); -} - -/* - * We (ab)use the operation-message header pad bytes to transfer the - * cport id in order to minimise overhead. - */ -static void -gb_message_cport_pack(struct gb_operation_msg_hdr *header, u16 cport_id) -{ - header->pad[0] = cport_id; -} - -/* Clear the pad bytes used for the CPort id */ -static void gb_message_cport_clear(struct gb_operation_msg_hdr *header) -{ - header->pad[0] = 0; -} - -/* Extract the CPort id packed into the header, and clear it */ -static u16 gb_message_cport_unpack(struct gb_operation_msg_hdr *header) -{ - u16 cport_id = header->pad[0]; - - gb_message_cport_clear(header); - - return cport_id; -} - -/* - * Returns zero if the message was successfully queued, or a negative errno - * otherwise. - */ -static int message_send(struct gb_host_device *hd, u16 cport_id, - struct gb_message *message, gfp_t gfp_mask) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - size_t buffer_size; - int retval; - struct urb *urb; - unsigned long flags; - - /* - * The data actually transferred will include an indication - * of where the data should be sent. Do one last check of - * the target CPort id before filling it in. - */ - if (!cport_id_valid(hd, cport_id)) { - dev_err(&udev->dev, "invalid cport %u\n", cport_id); - return -EINVAL; - } - - /* Find a free urb */ - urb = next_free_urb(es2, gfp_mask); - if (!urb) - return -ENOMEM; - - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); - message->hcpriv = urb; - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); - - /* Pack the cport id into the message header */ - gb_message_cport_pack(message->header, cport_id); - - buffer_size = sizeof(*message->header) + message->payload_size; - - usb_fill_bulk_urb(urb, udev, - usb_sndbulkpipe(udev, - es2->cport_out_endpoint), - message->buffer, buffer_size, - cport_out_callback, message); - urb->transfer_flags |= URB_ZERO_PACKET; - - trace_gb_message_submit(message); - - retval = usb_submit_urb(urb, gfp_mask); - if (retval) { - dev_err(&udev->dev, "failed to submit out-urb: %d\n", retval); - - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); - message->hcpriv = NULL; - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); - - free_urb(es2, urb); - gb_message_cport_clear(message->header); - - return retval; - } - - return 0; -} - -/* - * Can not be called in atomic context. - */ -static void message_cancel(struct gb_message *message) -{ - struct gb_host_device *hd = message->operation->connection->hd; - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct urb *urb; - int i; - - might_sleep(); - - spin_lock_irq(&es2->cport_out_urb_lock); - urb = message->hcpriv; - - /* Prevent dynamically allocated urb from being deallocated. */ - usb_get_urb(urb); - - /* Prevent pre-allocated urb from being reused. */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - if (urb == es2->cport_out_urb[i]) { - es2->cport_out_urb_cancelled[i] = true; - break; - } - } - spin_unlock_irq(&es2->cport_out_urb_lock); - - usb_kill_urb(urb); - - if (i < NUM_CPORT_OUT_URB) { - spin_lock_irq(&es2->cport_out_urb_lock); - es2->cport_out_urb_cancelled[i] = false; - spin_unlock_irq(&es2->cport_out_urb_lock); - } - - usb_free_urb(urb); -} - -static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, - unsigned long flags) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct ida *id_map = &hd->cport_id_map; - int ida_start, ida_end; - - switch (cport_id) { - case ES2_CPORT_CDSI0: - case ES2_CPORT_CDSI1: - dev_err(&hd->dev, "cport %d not available\n", cport_id); - return -EBUSY; - } - - if (flags & GB_CONNECTION_FLAG_OFFLOADED && - flags & GB_CONNECTION_FLAG_CDSI1) { - if (es2->cdsi1_in_use) { - dev_err(&hd->dev, "CDSI1 already in use\n"); - return -EBUSY; - } - - es2->cdsi1_in_use = true; - - return ES2_CPORT_CDSI1; - } - - if (cport_id < 0) { - ida_start = 0; - ida_end = hd->num_cports; - } else if (cport_id < hd->num_cports) { - ida_start = cport_id; - ida_end = cport_id + 1; - } else { - dev_err(&hd->dev, "cport %d not available\n", cport_id); - return -EINVAL; - } - - return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); -} - -static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - - switch (cport_id) { - case ES2_CPORT_CDSI1: - es2->cdsi1_in_use = false; - return; - } - - ida_simple_remove(&hd->cport_id_map, cport_id); -} - -static int cport_enable(struct gb_host_device *hd, u16 cport_id, - unsigned long flags) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - struct gb_apb_request_cport_flags *req; - u32 connection_flags; - int ret; - - req = kzalloc(sizeof(*req), GFP_KERNEL); - if (!req) - return -ENOMEM; - - connection_flags = 0; - if (flags & GB_CONNECTION_FLAG_CONTROL) - connection_flags |= GB_APB_CPORT_FLAG_CONTROL; - if (flags & GB_CONNECTION_FLAG_HIGH_PRIO) - connection_flags |= GB_APB_CPORT_FLAG_HIGH_PRIO; - - req->flags = cpu_to_le32(connection_flags); - - dev_dbg(&hd->dev, "%s - cport = %u, flags = %02x\n", __func__, - cport_id, connection_flags); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_CPORT_FLAGS, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, - req, sizeof(*req), ES2_USB_CTRL_TIMEOUT); - if (ret != sizeof(*req)) { - dev_err(&udev->dev, "failed to set cport flags for port %d\n", - cport_id); - if (ret >= 0) - ret = -EIO; - - goto out; - } - - ret = 0; -out: - kfree(req); - - return ret; -} - -static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct device *dev = &es2->usb_dev->dev; - struct arpc_cport_connected_req req; - int ret; - - req.cport_id = cpu_to_le16(cport_id); - ret = arpc_sync(es2, ARPC_TYPE_CPORT_CONNECTED, &req, sizeof(req), - NULL, ES2_ARPC_CPORT_TIMEOUT); - if (ret) { - dev_err(dev, "failed to set connected state for cport %u: %d\n", - cport_id, ret); - return ret; - } - - return 0; -} - -static int es2_cport_flush(struct gb_host_device *hd, u16 cport_id) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct device *dev = &es2->usb_dev->dev; - struct arpc_cport_flush_req req; - int ret; - - req.cport_id = cpu_to_le16(cport_id); - ret = arpc_sync(es2, ARPC_TYPE_CPORT_FLUSH, &req, sizeof(req), - NULL, ES2_ARPC_CPORT_TIMEOUT); - if (ret) { - dev_err(dev, "failed to flush cport %u: %d\n", cport_id, ret); - return ret; - } - - return 0; -} - -static int es2_cport_shutdown(struct gb_host_device *hd, u16 cport_id, - u8 phase, unsigned int timeout) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct device *dev = &es2->usb_dev->dev; - struct arpc_cport_shutdown_req req; - int result; - int ret; - - if (timeout > U16_MAX) - return -EINVAL; - - req.cport_id = cpu_to_le16(cport_id); - req.timeout = cpu_to_le16(timeout); - req.phase = phase; - ret = arpc_sync(es2, ARPC_TYPE_CPORT_SHUTDOWN, &req, sizeof(req), - &result, ES2_ARPC_CPORT_TIMEOUT + timeout); - if (ret) { - dev_err(dev, "failed to send shutdown over cport %u: %d (%d)\n", - cport_id, ret, result); - return ret; - } - - return 0; -} - -static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id, - size_t peer_space, unsigned int timeout) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct device *dev = &es2->usb_dev->dev; - struct arpc_cport_quiesce_req req; - int result; - int ret; - - if (peer_space > U16_MAX) - return -EINVAL; - - if (timeout > U16_MAX) - return -EINVAL; - - req.cport_id = cpu_to_le16(cport_id); - req.peer_space = cpu_to_le16(peer_space); - req.timeout = cpu_to_le16(timeout); - ret = arpc_sync(es2, ARPC_TYPE_CPORT_QUIESCE, &req, sizeof(req), - &result, ES2_ARPC_CPORT_TIMEOUT + timeout); - if (ret) { - dev_err(dev, "failed to quiesce cport %u: %d (%d)\n", - cport_id, ret, result); - return ret; - } - - return 0; -} - -static int es2_cport_clear(struct gb_host_device *hd, u16 cport_id) -{ - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct device *dev = &es2->usb_dev->dev; - struct arpc_cport_clear_req req; - int ret; - - req.cport_id = cpu_to_le16(cport_id); - ret = arpc_sync(es2, ARPC_TYPE_CPORT_CLEAR, &req, sizeof(req), - NULL, ES2_ARPC_CPORT_TIMEOUT); - if (ret) { - dev_err(dev, "failed to clear cport %u: %d\n", cport_id, ret); - return ret; - } - - return 0; -} - -static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_LATENCY_TAG_EN, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_USB_CTRL_TIMEOUT); - - if (retval < 0) - dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n", - cport_id); - return retval; -} - -static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id) -{ - int retval; - struct es2_ap_dev *es2 = hd_to_es2(hd); - struct usb_device *udev = es2->usb_dev; - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_LATENCY_TAG_DIS, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, cport_id, 0, NULL, - 0, ES2_USB_CTRL_TIMEOUT); - - if (retval < 0) - dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n", - cport_id); - return retval; -} - -static struct gb_hd_driver es2_driver = { - .hd_priv_size = sizeof(struct es2_ap_dev), - .message_send = message_send, - .message_cancel = message_cancel, - .cport_allocate = es2_cport_allocate, - .cport_release = es2_cport_release, - .cport_enable = cport_enable, - .cport_connected = es2_cport_connected, - .cport_flush = es2_cport_flush, - .cport_shutdown = es2_cport_shutdown, - .cport_quiesce = es2_cport_quiesce, - .cport_clear = es2_cport_clear, - .latency_tag_enable = latency_tag_enable, - .latency_tag_disable = latency_tag_disable, - .output = output, -}; - -/* Common function to report consistent warnings based on URB status */ -static int check_urb_status(struct urb *urb) -{ - struct device *dev = &urb->dev->dev; - int status = urb->status; - - switch (status) { - case 0: - return 0; - - case -EOVERFLOW: - dev_err(dev, "%s: overflow actual length is %d\n", - __func__, urb->actual_length); - /* fall through */ - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - case -EILSEQ: - case -EPROTO: - /* device is gone, stop sending */ - return status; - } - dev_err(dev, "%s: unknown status %d\n", __func__, status); - - return -EAGAIN; -} - -static void es2_destroy(struct es2_ap_dev *es2) -{ - struct usb_device *udev; - struct urb *urb; - int i; - - debugfs_remove(es2->apb_log_enable_dentry); - usb_log_disable(es2); - - /* Tear down everything! */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - urb = es2->cport_out_urb[i]; - usb_kill_urb(urb); - usb_free_urb(urb); - es2->cport_out_urb[i] = NULL; - es2->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - for (i = 0; i < NUM_ARPC_IN_URB; ++i) { - usb_free_urb(es2->arpc_urb[i]); - kfree(es2->arpc_buffer[i]); - es2->arpc_buffer[i] = NULL; - } - - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - usb_free_urb(es2->cport_in.urb[i]); - kfree(es2->cport_in.buffer[i]); - es2->cport_in.buffer[i] = NULL; - } - - /* release reserved CDSI0 and CDSI1 cports */ - gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1); - gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0); - - udev = es2->usb_dev; - gb_hd_put(es2->hd); - - usb_put_dev(udev); -} - -static void cport_in_callback(struct urb *urb) -{ - struct gb_host_device *hd = urb->context; - struct device *dev = &urb->dev->dev; - struct gb_operation_msg_hdr *header; - int status = check_urb_status(urb); - int retval; - u16 cport_id; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - - /* The urb is being unlinked */ - if (status == -ENOENT || status == -ESHUTDOWN) - return; - - dev_err(dev, "urb cport in error %d (dropped)\n", status); - return; - } - - if (urb->actual_length < sizeof(*header)) { - dev_err(dev, "short message received\n"); - goto exit; - } - - /* Extract the CPort id, which is packed in the message header */ - header = urb->transfer_buffer; - cport_id = gb_message_cport_unpack(header); - - if (cport_id_valid(hd, cport_id)) { - greybus_data_rcvd(hd, cport_id, urb->transfer_buffer, - urb->actual_length); - } else { - dev_err(dev, "invalid cport id %u received\n", cport_id); - } -exit: - /* put our urb back in the request pool */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "failed to resubmit in-urb: %d\n", retval); -} - -static void cport_out_callback(struct urb *urb) -{ - struct gb_message *message = urb->context; - struct gb_host_device *hd = message->operation->connection->hd; - struct es2_ap_dev *es2 = hd_to_es2(hd); - int status = check_urb_status(urb); - unsigned long flags; - - gb_message_cport_clear(message->header); - - spin_lock_irqsave(&es2->cport_out_urb_lock, flags); - message->hcpriv = NULL; - spin_unlock_irqrestore(&es2->cport_out_urb_lock, flags); - - /* - * Tell the submitter that the message send (attempt) is - * complete, and report the status. - */ - greybus_message_sent(hd, message, status); - - free_urb(es2, urb); -} - -static struct arpc *arpc_alloc(void *payload, u16 size, u8 type) -{ - struct arpc *rpc; - - if (size + sizeof(*rpc->req) > ARPC_OUT_SIZE_MAX) - return NULL; - - rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); - if (!rpc) - return NULL; - - INIT_LIST_HEAD(&rpc->list); - rpc->req = kzalloc(sizeof(*rpc->req) + size, GFP_KERNEL); - if (!rpc->req) - goto err_free_rpc; - - rpc->resp = kzalloc(sizeof(*rpc->resp), GFP_KERNEL); - if (!rpc->resp) - goto err_free_req; - - rpc->req->type = type; - rpc->req->size = cpu_to_le16(sizeof(*rpc->req) + size); - memcpy(rpc->req->data, payload, size); - - init_completion(&rpc->response_received); - - return rpc; - -err_free_req: - kfree(rpc->req); -err_free_rpc: - kfree(rpc); - - return NULL; -} - -static void arpc_free(struct arpc *rpc) -{ - kfree(rpc->req); - kfree(rpc->resp); - kfree(rpc); -} - -static struct arpc *arpc_find(struct es2_ap_dev *es2, __le16 id) -{ - struct arpc *rpc; - - list_for_each_entry(rpc, &es2->arpcs, list) { - if (rpc->req->id == id) - return rpc; - } - - return NULL; -} - -static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc) -{ - rpc->active = true; - rpc->req->id = cpu_to_le16(es2->arpc_id_cycle++); - list_add_tail(&rpc->list, &es2->arpcs); -} - -static void arpc_del(struct es2_ap_dev *es2, struct arpc *rpc) -{ - if (rpc->active) { - rpc->active = false; - list_del(&rpc->list); - } -} - -static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout) -{ - struct usb_device *udev = es2->usb_dev; - int retval; - - retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - GB_APB_REQUEST_ARPC_RUN, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - 0, 0, - rpc->req, le16_to_cpu(rpc->req->size), - ES2_USB_CTRL_TIMEOUT); - if (retval != le16_to_cpu(rpc->req->size)) { - dev_err(&udev->dev, - "failed to send ARPC request %d: %d\n", - rpc->req->type, retval); - if (retval > 0) - retval = -EIO; - return retval; - } - - return 0; -} - -static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload, - size_t size, int *result, unsigned int timeout) -{ - struct arpc *rpc; - unsigned long flags; - int retval; - - if (result) - *result = 0; - - rpc = arpc_alloc(payload, size, type); - if (!rpc) - return -ENOMEM; - - spin_lock_irqsave(&es2->arpc_lock, flags); - arpc_add(es2, rpc); - spin_unlock_irqrestore(&es2->arpc_lock, flags); - - retval = arpc_send(es2, rpc, timeout); - if (retval) - goto out_arpc_del; - - retval = wait_for_completion_interruptible_timeout( - &rpc->response_received, - msecs_to_jiffies(timeout)); - if (retval <= 0) { - if (!retval) - retval = -ETIMEDOUT; - goto out_arpc_del; - } - - if (rpc->resp->result) { - retval = -EREMOTEIO; - if (result) - *result = rpc->resp->result; - } else { - retval = 0; - } - -out_arpc_del: - spin_lock_irqsave(&es2->arpc_lock, flags); - arpc_del(es2, rpc); - spin_unlock_irqrestore(&es2->arpc_lock, flags); - arpc_free(rpc); - - if (retval < 0 && retval != -EREMOTEIO) { - dev_err(&es2->usb_dev->dev, - "failed to execute ARPC: %d\n", retval); - } - - return retval; -} - -static void arpc_in_callback(struct urb *urb) -{ - struct es2_ap_dev *es2 = urb->context; - struct device *dev = &urb->dev->dev; - int status = check_urb_status(urb); - struct arpc *rpc; - struct arpc_response_message *resp; - unsigned long flags; - int retval; - - if (status) { - if ((status == -EAGAIN) || (status == -EPROTO)) - goto exit; - - /* The urb is being unlinked */ - if (status == -ENOENT || status == -ESHUTDOWN) - return; - - dev_err(dev, "arpc in-urb error %d (dropped)\n", status); - return; - } - - if (urb->actual_length < sizeof(*resp)) { - dev_err(dev, "short aprc response received\n"); - goto exit; - } - - resp = urb->transfer_buffer; - spin_lock_irqsave(&es2->arpc_lock, flags); - rpc = arpc_find(es2, resp->id); - if (!rpc) { - dev_err(dev, "invalid arpc response id received: %u\n", - le16_to_cpu(resp->id)); - spin_unlock_irqrestore(&es2->arpc_lock, flags); - goto exit; - } - - arpc_del(es2, rpc); - memcpy(rpc->resp, resp, sizeof(*resp)); - complete(&rpc->response_received); - spin_unlock_irqrestore(&es2->arpc_lock, flags); - -exit: - /* put our urb back in the request pool */ - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(dev, "failed to resubmit arpc in-urb: %d\n", retval); -} - -#define APB1_LOG_MSG_SIZE 64 -static void apb_log_get(struct es2_ap_dev *es2, char *buf) -{ - int retval; - - do { - retval = usb_control_msg(es2->usb_dev, - usb_rcvctrlpipe(es2->usb_dev, 0), - GB_APB_REQUEST_LOG, - USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - 0x00, 0x00, - buf, - APB1_LOG_MSG_SIZE, - ES2_USB_CTRL_TIMEOUT); - if (retval > 0) - kfifo_in(&es2->apb_log_fifo, buf, retval); - } while (retval > 0); -} - -static int apb_log_poll(void *data) -{ - struct es2_ap_dev *es2 = data; - char *buf; - - buf = kmalloc(APB1_LOG_MSG_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - while (!kthread_should_stop()) { - msleep(1000); - apb_log_get(es2, buf); - } - - kfree(buf); - - return 0; -} - -static ssize_t apb_log_read(struct file *f, char __user *buf, - size_t count, loff_t *ppos) -{ - struct es2_ap_dev *es2 = file_inode(f)->i_private; - ssize_t ret; - size_t copied; - char *tmp_buf; - - if (count > APB1_LOG_SIZE) - count = APB1_LOG_SIZE; - - tmp_buf = kmalloc(count, GFP_KERNEL); - if (!tmp_buf) - return -ENOMEM; - - copied = kfifo_out(&es2->apb_log_fifo, tmp_buf, count); - ret = simple_read_from_buffer(buf, count, ppos, tmp_buf, copied); - - kfree(tmp_buf); - - return ret; -} - -static const struct file_operations apb_log_fops = { - .read = apb_log_read, -}; - -static void usb_log_enable(struct es2_ap_dev *es2) -{ - if (!IS_ERR_OR_NULL(es2->apb_log_task)) - return; - - /* get log from APB1 */ - es2->apb_log_task = kthread_run(apb_log_poll, es2, "apb_log"); - if (IS_ERR(es2->apb_log_task)) - return; - /* XXX We will need to rename this per APB */ - es2->apb_log_dentry = debugfs_create_file("apb_log", 0444, - gb_debugfs_get(), es2, - &apb_log_fops); -} - -static void usb_log_disable(struct es2_ap_dev *es2) -{ - if (IS_ERR_OR_NULL(es2->apb_log_task)) - return; - - debugfs_remove(es2->apb_log_dentry); - es2->apb_log_dentry = NULL; - - kthread_stop(es2->apb_log_task); - es2->apb_log_task = NULL; -} - -static ssize_t apb_log_enable_read(struct file *f, char __user *buf, - size_t count, loff_t *ppos) -{ - struct es2_ap_dev *es2 = file_inode(f)->i_private; - int enable = !IS_ERR_OR_NULL(es2->apb_log_task); - char tmp_buf[3]; - - sprintf(tmp_buf, "%d\n", enable); - return simple_read_from_buffer(buf, count, ppos, tmp_buf, 3); -} - -static ssize_t apb_log_enable_write(struct file *f, const char __user *buf, - size_t count, loff_t *ppos) -{ - int enable; - ssize_t retval; - struct es2_ap_dev *es2 = file_inode(f)->i_private; - - retval = kstrtoint_from_user(buf, count, 10, &enable); - if (retval) - return retval; - - if (enable) - usb_log_enable(es2); - else - usb_log_disable(es2); - - return count; -} - -static const struct file_operations apb_log_enable_fops = { - .read = apb_log_enable_read, - .write = apb_log_enable_write, -}; - -static int apb_get_cport_count(struct usb_device *udev) -{ - int retval; - __le16 *cport_count; - - cport_count = kzalloc(sizeof(*cport_count), GFP_KERNEL); - if (!cport_count) - return -ENOMEM; - - retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - GB_APB_REQUEST_CPORT_COUNT, - USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, 0, 0, cport_count, - sizeof(*cport_count), ES2_USB_CTRL_TIMEOUT); - if (retval != sizeof(*cport_count)) { - dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", - retval); - - if (retval >= 0) - retval = -EIO; - - goto out; - } - - retval = le16_to_cpu(*cport_count); - - /* We need to fit a CPort ID in one byte of a message header */ - if (retval > U8_MAX) { - retval = U8_MAX; - dev_warn(&udev->dev, "Limiting number of CPorts to U8_MAX\n"); - } - -out: - kfree(cport_count); - return retval; -} - -/* - * The ES2 USB Bridge device has 15 endpoints - * 1 Control - usual USB stuff + AP -> APBridgeA messages - * 7 Bulk IN - CPort data in - * 7 Bulk OUT - CPort data out - */ -static int ap_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct es2_ap_dev *es2; - struct gb_host_device *hd; - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - __u8 ep_addr; - int retval; - int i; - int num_cports; - bool bulk_out_found = false; - bool bulk_in_found = false; - bool arpc_in_found = false; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - num_cports = apb_get_cport_count(udev); - if (num_cports < 0) { - usb_put_dev(udev); - dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", - num_cports); - return num_cports; - } - - hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, - num_cports); - if (IS_ERR(hd)) { - usb_put_dev(udev); - return PTR_ERR(hd); - } - - es2 = hd_to_es2(hd); - es2->hd = hd; - es2->usb_intf = interface; - es2->usb_dev = udev; - spin_lock_init(&es2->cport_out_urb_lock); - INIT_KFIFO(es2->apb_log_fifo); - usb_set_intfdata(interface, es2); - - /* - * Reserve the CDSI0 and CDSI1 CPorts so they won't be allocated - * dynamically. - */ - retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI0); - if (retval) - goto error; - retval = gb_hd_cport_reserve(hd, ES2_CPORT_CDSI1); - if (retval) - goto error; - - /* find all bulk endpoints */ - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - ep_addr = endpoint->bEndpointAddress; - - if (usb_endpoint_is_bulk_in(endpoint)) { - if (!bulk_in_found) { - es2->cport_in.endpoint = ep_addr; - bulk_in_found = true; - } else if (!arpc_in_found) { - es2->arpc_endpoint_in = ep_addr; - arpc_in_found = true; - } else { - dev_warn(&udev->dev, - "Unused bulk IN endpoint found: 0x%02x\n", - ep_addr); - } - continue; - } - if (usb_endpoint_is_bulk_out(endpoint)) { - if (!bulk_out_found) { - es2->cport_out_endpoint = ep_addr; - bulk_out_found = true; - } else { - dev_warn(&udev->dev, - "Unused bulk OUT endpoint found: 0x%02x\n", - ep_addr); - } - continue; - } - dev_warn(&udev->dev, - "Unknown endpoint type found, address 0x%02x\n", - ep_addr); - } - if (!bulk_in_found || !arpc_in_found || !bulk_out_found) { - dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); - retval = -ENODEV; - goto error; - } - - /* Allocate buffers for our cport in messages */ - for (i = 0; i < NUM_CPORT_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - retval = -ENOMEM; - goto error; - } - es2->cport_in.urb[i] = urb; - - buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); - if (!buffer) { - retval = -ENOMEM; - goto error; - } - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, es2->cport_in.endpoint), - buffer, ES2_GBUF_MSG_SIZE_MAX, - cport_in_callback, hd); - - es2->cport_in.buffer[i] = buffer; - } - - /* Allocate buffers for ARPC in messages */ - for (i = 0; i < NUM_ARPC_IN_URB; ++i) { - struct urb *urb; - u8 *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - retval = -ENOMEM; - goto error; - } - es2->arpc_urb[i] = urb; - - buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL); - if (!buffer) { - retval = -ENOMEM; - goto error; - } - - usb_fill_bulk_urb(urb, udev, - usb_rcvbulkpipe(udev, - es2->arpc_endpoint_in), - buffer, ARPC_IN_SIZE_MAX, - arpc_in_callback, es2); - - es2->arpc_buffer[i] = buffer; - } - - /* Allocate urbs for our CPort OUT messages */ - for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { - struct urb *urb; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - retval = -ENOMEM; - goto error; - } - - es2->cport_out_urb[i] = urb; - es2->cport_out_urb_busy[i] = false; /* just to be anal */ - } - - /* XXX We will need to rename this per APB */ - es2->apb_log_enable_dentry = debugfs_create_file("apb_log_enable", - 0644, - gb_debugfs_get(), es2, - &apb_log_enable_fops); - - INIT_LIST_HEAD(&es2->arpcs); - spin_lock_init(&es2->arpc_lock); - - retval = es2_arpc_in_enable(es2); - if (retval) - goto error; - - retval = gb_hd_add(hd); - if (retval) - goto err_disable_arpc_in; - - retval = es2_cport_in_enable(es2, &es2->cport_in); - if (retval) - goto err_hd_del; - - return 0; - -err_hd_del: - gb_hd_del(hd); -err_disable_arpc_in: - es2_arpc_in_disable(es2); -error: - es2_destroy(es2); - - return retval; -} - -static void ap_disconnect(struct usb_interface *interface) -{ - struct es2_ap_dev *es2 = usb_get_intfdata(interface); - - gb_hd_del(es2->hd); - - es2_cport_in_disable(es2, &es2->cport_in); - es2_arpc_in_disable(es2); - - es2_destroy(es2); -} - -static struct usb_driver es2_ap_driver = { - .name = "es2_ap_driver", - .probe = ap_probe, - .disconnect = ap_disconnect, - .id_table = id_table, - .soft_unbind = 1, -}; - -module_usb_driver(es2_ap_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Greg Kroah-Hartman "); -- cgit v1.2.3-59-g8ed1b From a1617c8c3d39b1348e72d04548229e2ed9bf8121 Mon Sep 17 00:00:00 2001 From: Stephen Brennan Date: Tue, 27 Aug 2019 21:35:42 -0700 Subject: staging: rtl8192u: Fix indentation Checkpatch reports WARNING:SUSPECT_CODE_INDENT in several places. Fix this by aligning code properly with tabs. Signed-off-by: Stephen Brennan Link: https://lore.kernel.org/r/20190828043542.3753-1-stephen@brennan.io Signed-off-by: Greg Kroah-Hartman --- .../rtl8192u/ieee80211/ieee80211_crypt_ccmp.c | 2 +- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 112 ++++++++++----------- drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c | 8 +- drivers/staging/rtl8192u/r819xU_firmware.c | 2 +- 5 files changed, 63 insertions(+), 63 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c index a43a5d617bd9..c241cf484023 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c @@ -345,7 +345,7 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) } if (crypto_aead_setauthsize(tfm, CCMP_MIC_LEN) || crypto_aead_setkey(tfm, data->key, CCMP_TK_LEN)) - return -1; + return -1; } else if (len == 0) { data->key_set = 0; } else { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index a1462ec55767..5c33bcb0db2e 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -103,17 +103,17 @@ ieee80211_frag_cache_get(struct ieee80211_device *ieee, u8 tid; if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else { - tid = 0; + tid = 0; } if (frag == 0) { @@ -170,17 +170,17 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, u8 tid; if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else { - tid = 0; + tid = 0; } entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2, @@ -425,17 +425,17 @@ static int is_duplicate_packet(struct ieee80211_device *ieee, //TO2DS and QoS if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_4addrqos = (struct rtl_80211_hdr_4addrqos *)header; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS - hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; - tid = UP2AC(tid); - tid++; + hdr_3addrqos = (struct rtl_80211_hdr_3addrqos *)header; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID; + tid = UP2AC(tid); + tid++; } else { // no QoS - tid = 0; + tid = 0; } switch (ieee->iw_mode) { @@ -993,7 +993,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, // if QoS enabled, should check the sequence for each of the AC if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active || !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) { if (is_duplicate_packet(ieee, hdr)) - goto rx_dropped; + goto rx_dropped; } else { struct rx_ts_record *pRxTS = NULL; @@ -1211,10 +1211,10 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, #ifdef CONFIG_IEEE80211_DEBUG if (crypt && !(fc & IEEE80211_FCTL_WEP) && ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - struct eapol *eap = (struct eapol *)(skb->data + - 24); - IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); + struct eapol *eap = (struct eapol *)(skb->data + + 24); + IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); } #endif @@ -1770,13 +1770,13 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[2] == 0x4c && info_element->data[3] == 0x033){ - tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); - if (tmp_htcap_len != 0) { - network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ - sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; - memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); - } + tmp_htcap_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htcap_len != 0) { + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ? \ + sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen); + } } if (tmp_htcap_len != 0) network->bssht.bdSupportHT = true; @@ -1792,17 +1792,17 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[2] == 0x4c && info_element->data[3] == 0x034){ - tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); - if (tmp_htinfo_len != 0) { - network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; - if (tmp_htinfo_len) { - network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ - sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; - memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); - } - + tmp_htinfo_len = min(info_element->len, (u8)MAX_IE_LEN); + if (tmp_htinfo_len != 0) { + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + if (tmp_htinfo_len) { + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ? \ + sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen); } + } + } } @@ -1822,7 +1822,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, network->bssht.bdRT2RTAggregation = true; if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) - network->bssht.bdRT2RTLongSlotTime = true; + network->bssht.bdRT2RTLongSlotTime = true; } } @@ -1843,7 +1843,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee, info_element->data[1] == 0x10 && info_element->data[2] == 0x18)){ - network->broadcom_cap_exist = true; + network->broadcom_cap_exist = true; } } @@ -2262,7 +2262,7 @@ static inline void update_network(struct ieee80211_network *dst, src->wmm_param[1].aci_aifsn || \ src->wmm_param[2].aci_aifsn || \ src->wmm_param[3].aci_aifsn) { - memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); + memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); } //dst->QoS_Enable = src->QoS_Enable; #ifdef THOMAS_TURBO @@ -2401,11 +2401,11 @@ static inline void ieee80211_process_probe_response( if (is_same_network(&ieee->current_network, network, ieee)) { update_network(&ieee->current_network, network); if ((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) - && ieee->current_network.berp_info_valid){ - if (ieee->current_network.erp_value & ERP_UseProtection) - ieee->current_network.buseprotection = true; - else - ieee->current_network.buseprotection = false; + && ieee->current_network.berp_info_valid){ + if (ieee->current_network.erp_value & ERP_UseProtection) + ieee->current_network.buseprotection = true; + else + ieee->current_network.buseprotection = false; } if (is_beacon(beacon->header.frame_ctl)) { if (ieee->state == IEEE80211_LINKED) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index 140e3cb66a2e..f0b6b8372f91 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -488,7 +488,7 @@ static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) tcb_desc->bUseShortPreamble = true; if (ieee->mode == IW_MODE_MASTER) - goto NO_PROTECTION; + goto NO_PROTECTION; return; NO_PROTECTION: tcb_desc->bRTSEnable = false; diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index 8ca7a7fd74f9..9dd5c04181ea 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -177,7 +177,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(info, start, stop, &iwe, custom); if (ieee->wpa_enabled && network->wpa_ie_len) { char buf[MAX_WPA_IE_LEN * 2 + 30]; @@ -218,7 +218,7 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee, " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(info, start, stop, &iwe, custom); return start; } @@ -785,8 +785,8 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) u8 *buf; if (len > MAX_WPA_IE_LEN || (len && !ie)) { - // printk("return error out, len:%d\n", len); - return -EINVAL; + //printk("return error out, len:%d\n", len); + return -EINVAL; } diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c index 153d4ee0ec07..dd81d210bd49 100644 --- a/drivers/staging/rtl8192u/r819xU_firmware.c +++ b/drivers/staging/rtl8192u/r819xU_firmware.c @@ -231,7 +231,7 @@ bool init_firmware(struct net_device *dev) rst_opt = OPT_FIRMWARE_RESET; starting_state = FW_INIT_STEP2_DATA; } else { - RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n"); + RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n"); } /* -- cgit v1.2.3-59-g8ed1b From 3982f1df00df57768f0782bc702fc4fbea347ca2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 27 Aug 2019 21:13:46 +0800 Subject: staging: most: sound: Fix error path of audio_init If most_register_configfs_subsys() fails, we should call most_deregister_component() do cleanup. Reported-by: Hulk Robot Fixes: 919c03ae11b9 ("staging: most: enable configfs support") Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190827131346.12704-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/sound/sound.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 342f390d68b3..79817061fcfa 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -802,8 +802,11 @@ static int __init audio_init(void) if (ret) pr_err("Failed to register %s\n", comp.name); ret = most_register_configfs_subsys(&comp); - if (ret) + if (ret) { pr_err("Failed to register %s configfs subsys\n", comp.name); + most_deregister_component(&comp); + } + return ret; } -- cgit v1.2.3-59-g8ed1b From c48c9f7ff32b8b3965a08e40eb6763682d905b5d Mon Sep 17 00:00:00 2001 From: Valdis Klētnieks Date: Wed, 28 Aug 2019 18:08:17 +0200 Subject: staging: exfat: add exfat filesystem code to staging The exfat code needs a lot of work to get it into "real" shape for the fs/ part of the kernel, so put it into drivers/staging/ for now so that it can be worked on by everyone in the community. The full specification of the filesystem can be found at: https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification Signed-off-by: Valdis Kletnieks Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190828160817.6250-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 5 + drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/exfat/Kconfig | 39 + drivers/staging/exfat/Makefile | 10 + drivers/staging/exfat/TODO | 12 + drivers/staging/exfat/exfat.h | 973 ++++++++ drivers/staging/exfat/exfat_blkdev.c | 136 ++ drivers/staging/exfat/exfat_cache.c | 722 ++++++ drivers/staging/exfat/exfat_core.c | 3704 ++++++++++++++++++++++++++++++ drivers/staging/exfat/exfat_nls.c | 404 ++++ drivers/staging/exfat/exfat_super.c | 4137 ++++++++++++++++++++++++++++++++++ drivers/staging/exfat/exfat_upcase.c | 740 ++++++ 13 files changed, 10885 insertions(+) create mode 100644 drivers/staging/exfat/Kconfig create mode 100644 drivers/staging/exfat/Makefile create mode 100644 drivers/staging/exfat/TODO create mode 100644 drivers/staging/exfat/exfat.h create mode 100644 drivers/staging/exfat/exfat_blkdev.c create mode 100644 drivers/staging/exfat/exfat_cache.c create mode 100644 drivers/staging/exfat/exfat_core.c create mode 100644 drivers/staging/exfat/exfat_nls.c create mode 100644 drivers/staging/exfat/exfat_super.c create mode 100644 drivers/staging/exfat/exfat_upcase.c (limited to 'drivers/staging') diff --git a/MAINTAINERS b/MAINTAINERS index e3242687cd19..a484b36e5117 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6097,6 +6097,11 @@ F: include/trace/events/mdio.h F: include/uapi/linux/mdio.h F: include/uapi/linux/mii.h +EXFAT FILE SYSTEM +M: Valdis Kletnieks +S: Maintained +F: fs/exfat/ + EXT2 FILE SYSTEM M: Jan Kara L: linux-ext4@vger.kernel.org diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d972ec8e71fb..fbdc33874780 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -118,4 +118,6 @@ source "drivers/staging/kpc2000/Kconfig" source "drivers/staging/isdn/Kconfig" +source "drivers/staging/exfat/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6018b9a4a077..ca13f87b1e1b 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -49,3 +49,4 @@ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_ISDN_CAPI) += isdn/ +obj-$(CONFIG_EXFAT_FS) += exfat/ diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig new file mode 100644 index 000000000000..78b32aa2ca19 --- /dev/null +++ b/drivers/staging/exfat/Kconfig @@ -0,0 +1,39 @@ +config EXFAT_FS + tristate "exFAT fs support" + select NLS + help + This adds support for the exFAT file system. + +config EXFAT_DISCARD + bool "enable discard support" + depends on EXFAT_FS + default y + +config EXFAT_DELAYED_SYNC + bool "enable delayed sync" + depends on EXFAT_FS + default n + +config EXFAT_KERNEL_DEBUG + bool "enable kernel debug features via ioctl" + depends on EXFAT_FS + default n + +config EXFAT_DEBUG_MSG + bool "print debug messages" + depends on EXFAT_FS + default n + +config EXFAT_DEFAULT_CODEPAGE + int "Default codepage for exFAT" + default 437 + depends on EXFAT_FS + help + This option should be set to the codepage of your exFAT filesystems. + +config EXFAT_DEFAULT_IOCHARSET + string "Default iocharset for exFAT" + default "utf8" + depends on EXFAT_FS + help + Set this to the default input/output character set you'd like exFAT to use. diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile new file mode 100644 index 000000000000..84944dfbae28 --- /dev/null +++ b/drivers/staging/exfat/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_EXFAT_FS) += exfat.o + +exfat-y := exfat_core.o \ + exfat_super.o \ + exfat_blkdev.o \ + exfat_cache.o \ + exfat_nls.o \ + exfat_upcase.o diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO new file mode 100644 index 000000000000..a3eb282f9efc --- /dev/null +++ b/drivers/staging/exfat/TODO @@ -0,0 +1,12 @@ +exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse(). +same for ffsWriteFile. + +exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell. +There's only one place that calls it with a non-zero argument. + +ffsTruncateFile - if (old_size <= new_size) { +That doesn't look right. How did it ever work? Are they relying on lazy +block allocation when actual writes happen? If nothing else, it never +does the 'fid->size = new_size' and do the inode update.... + +ffsSetAttr() is just dangling in the breeze, not wired up at all... diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h new file mode 100644 index 000000000000..bae180e10609 --- /dev/null +++ b/drivers/staging/exfat/exfat.h @@ -0,0 +1,973 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#ifndef _EXFAT_H +#define _EXFAT_H + +#include +#include + +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + /* For Debugging Purpose */ + /* IOCTL code 'f' used by + * - file systems typically #0~0x1F + * - embedded terminal devices #128~ + * - exts for debugging purpose #99 + * number 100 and 101 is available now but has possible conflicts + */ +#define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) +#define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) + +#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 +#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + +#ifdef CONFIG_EXFAT_DEBUG_MSG +#define DEBUG 1 +#else +#undef DEBUG +#endif + +#define DENTRY_SIZE 32 /* dir entry size */ +#define DENTRY_SIZE_BITS 5 + +/* PBR entries */ +#define PBR_SIGNATURE 0xAA55 +#define EXT_SIGNATURE 0xAA550000 +#define VOL_LABEL "NO NAME " /* size should be 11 */ +#define OEM_NAME "MSWIN4.1" /* size should be 8 */ +#define STR_FAT12 "FAT12 " /* size should be 8 */ +#define STR_FAT16 "FAT16 " /* size should be 8 */ +#define STR_FAT32 "FAT32 " /* size should be 8 */ +#define STR_EXFAT "EXFAT " /* size should be 8 */ +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + +/* max number of clusters */ +#define FAT12_THRESHOLD 4087 /* 2^12 - 1 + 2 (clu 0 & 1) */ +#define FAT16_THRESHOLD 65527 /* 2^16 - 1 + 2 */ +#define FAT32_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ +#define EXFAT_THRESHOLD 268435457 /* 2^28 - 1 + 2 */ + +/* file types */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_SYMLINK 0x015F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + +/* time modes */ +#define TM_CREATE 0 +#define TM_MODIFY 1 +#define TM_ACCESS 2 + +/* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +#define CLUSTER_16(x) ((u16)(x)) +#define CLUSTER_32(x) ((u32)(x)) + +#define FALSE 0 +#define TRUE 1 + +#define START_SECTOR(x) \ + ((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + \ + p_fs->data_start_sector) + +#define IS_LAST_SECTOR_IN_CLUSTER(sec) \ + ((((sec) - p_fs->data_start_sector + 1) & \ + ((1 << p_fs->sectors_per_clu_bits) - 1)) == 0) + +#define GET_CLUSTER_FROM_SECTOR(sec) \ + ((u32)((((sec) - p_fs->data_start_sector) >> \ + p_fs->sectors_per_clu_bits) + 2)) + +#define GET16(p_src) \ + (((u16)(p_src)[0]) | (((u16)(p_src)[1]) << 8)) +#define GET32(p_src) \ + (((u32)(p_src)[0]) | (((u32)(p_src)[1]) << 8) | \ + (((u32)(p_src)[2]) << 16) | (((u32)(p_src)[3]) << 24)) +#define GET64(p_src) \ + (((u64)(p_src)[0]) | (((u64)(p_src)[1]) << 8) | \ + (((u64)(p_src)[2]) << 16) | (((u64)(p_src)[3]) << 24) | \ + (((u64)(p_src)[4]) << 32) | (((u64)(p_src)[5]) << 40) | \ + (((u64)(p_src)[6]) << 48) | (((u64)(p_src)[7]) << 56)) + +#define SET16(p_dst, src) \ + do { \ + (p_dst)[0] = (u8)(src); \ + (p_dst)[1] = (u8)(((u16)(src)) >> 8); \ + } while (0) +#define SET32(p_dst, src) \ + do { \ + (p_dst)[0] = (u8)(src); \ + (p_dst)[1] = (u8)(((u32)(src)) >> 8); \ + (p_dst)[2] = (u8)(((u32)(src)) >> 16); \ + (p_dst)[3] = (u8)(((u32)(src)) >> 24); \ + } while (0) +#define SET64(p_dst, src) \ + do { \ + (p_dst)[0] = (u8)(src); \ + (p_dst)[1] = (u8)(((u64)(src)) >> 8); \ + (p_dst)[2] = (u8)(((u64)(src)) >> 16); \ + (p_dst)[3] = (u8)(((u64)(src)) >> 24); \ + (p_dst)[4] = (u8)(((u64)(src)) >> 32); \ + (p_dst)[5] = (u8)(((u64)(src)) >> 40); \ + (p_dst)[6] = (u8)(((u64)(src)) >> 48); \ + (p_dst)[7] = (u8)(((u64)(src)) >> 56); \ + } while (0) + +#ifdef __LITTLE_ENDIAN +#define GET16_A(p_src) (*((u16 *)(p_src))) +#define GET32_A(p_src) (*((u32 *)(p_src))) +#define GET64_A(p_src) (*((u64 *)(p_src))) +#define SET16_A(p_dst, src) (*((u16 *)(p_dst)) = (u16)(src)) +#define SET32_A(p_dst, src) (*((u32 *)(p_dst)) = (u32)(src)) +#define SET64_A(p_dst, src) (*((u64 *)(p_dst)) = (u64)(src)) +#else /* BIG_ENDIAN */ +#define GET16_A(p_src) GET16(p_src) +#define GET32_A(p_src) GET32(p_src) +#define GET64_A(p_src) GET64(p_src) +#define SET16_A(p_dst, src) SET16(p_dst, src) +#define SET32_A(p_dst, src) SET32(p_dst, src) +#define SET64_A(p_dst, src) SET64(p_dst, src) +#endif + +/* cache size (in number of sectors) */ +/* (should be an exponential value of 2) */ +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +/* Upcase table macro */ +#define HIGH_INDEX_BIT (8) +#define HIGH_INDEX_MASK (0xFF00) +#define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) +#define UTBL_ROW_COUNT (1<> LOW_INDEX_BIT; +} +static inline u16 get_row_index(u16 i) +{ + return i & ~HIGH_INDEX_MASK; +} + +#define EXFAT_SUPER_MAGIC (0x2011BAB0L) +#define EXFAT_ROOT_INO 1 + +/* FAT types */ +#define FAT12 0x01 /* FAT12 */ +#define FAT16 0x0E /* Win95 FAT16 (LBA) */ +#define FAT32 0x0C /* Win95 FAT32 (LBA) */ +#define EXFAT 0x07 /* exFAT */ + +/* file name lengths */ +#define MAX_CHARSET_SIZE 3 /* max size of multi-byte character */ +#define MAX_PATH_DEPTH 15 /* max depth of path name */ +#define MAX_NAME_LENGTH 256 /* max len of filename including NULL */ +#define MAX_PATH_LENGTH 260 /* max len of pathname including NULL */ +#define DOS_NAME_LENGTH 11 /* DOS filename length excluding NULL */ +#define DOS_PATH_LENGTH 80 /* DOS pathname length excluding NULL */ + +/* file attributes */ +#define ATTR_NORMAL 0x0000 +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 +#define ATTR_SYMLINK 0x0040 +#define ATTR_EXTEND 0x000F +#define ATTR_RWMASK 0x007E + +/* file creation modes */ +#define FM_REGULAR 0x00 +#define FM_SYMLINK 0x40 + +/* return values */ +#define FFS_SUCCESS 0 +#define FFS_MEDIAERR 1 +#define FFS_FORMATERR 2 +#define FFS_MOUNTED 3 +#define FFS_NOTMOUNTED 4 +#define FFS_ALIGNMENTERR 5 +#define FFS_SEMAPHOREERR 6 +#define FFS_INVALIDPATH 7 +#define FFS_INVALIDFID 8 +#define FFS_NOTFOUND 9 +#define FFS_FILEEXIST 10 +#define FFS_PERMISSIONERR 11 +#define FFS_NOTOPENED 12 +#define FFS_MAXOPENED 13 +#define FFS_FULL 14 +#define FFS_EOF 15 +#define FFS_DIRBUSY 16 +#define FFS_MEMORYERR 17 +#define FFS_NAMETOOLONG 18 +#define FFS_ERROR 19 + +#define NUM_UPCASE 2918 + +#define DOS_CUR_DIR_NAME ". " +#define DOS_PAR_DIR_NAME ".. " + +#ifdef __LITTLE_ENDIAN +#define UNI_CUR_DIR_NAME ".\0" +#define UNI_PAR_DIR_NAME ".\0.\0" +#else +#define UNI_CUR_DIR_NAME "\0." +#define UNI_PAR_DIR_NAME "\0.\0." +#endif + +struct date_time_t { + u16 Year; + u16 Month; + u16 Day; + u16 Hour; + u16 Minute; + u16 Second; + u16 MilliSecond; +}; + +struct part_info_t { + u32 Offset; /* start sector number of the partition */ + u32 Size; /* in sectors */ +}; + +struct dev_info_t { + u32 SecSize; /* sector size in bytes */ + u32 DevSize; /* block device size in sectors */ +}; + +struct vol_info_t { + u32 FatType; + u32 ClusterSize; + u32 NumClusters; + u32 FreeClusters; + u32 UsedClusters; +}; + +/* directory structure */ +struct chain_t { + u32 dir; + s32 size; + u8 flags; +}; + +struct file_id_t { + struct chain_t dir; + s32 entry; + u32 type; + u32 attr; + u32 start_clu; + u64 size; + u8 flags; + s64 rwoffset; + s32 hint_last_off; + u32 hint_last_clu; +}; + +struct dir_entry_t { + char Name[MAX_NAME_LENGTH * MAX_CHARSET_SIZE]; + + /* used only for FAT12/16/32, not used for exFAT */ + char ShortName[DOS_NAME_LENGTH + 2]; + + u32 Attr; + u64 Size; + u32 NumSubdirs; + struct date_time_t CreateTimestamp; + struct date_time_t ModifyTimestamp; + struct date_time_t AccessTimestamp; +}; + +struct timestamp_t { + u16 sec; /* 0 ~ 59 */ + u16 min; /* 0 ~ 59 */ + u16 hour; /* 0 ~ 23 */ + u16 day; /* 1 ~ 31 */ + u16 mon; /* 1 ~ 12 */ + u16 year; /* 0 ~ 127 (since 1980) */ +}; + +/* MS_DOS FAT partition boot record (512 bytes) */ +struct pbr_sector_t { + u8 jmp_boot[3]; + u8 oem_name[8]; + u8 bpb[109]; + u8 boot_code[390]; + u8 signature[2]; +}; + +/* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */ +struct bpb16_t { + u8 sector_size[2]; + u8 sectors_per_clu; + u8 num_reserved[2]; + u8 num_fats; + u8 num_root_entries[2]; + u8 num_sectors[2]; + u8 media_type; + u8 num_fat_sectors[2]; + u8 sectors_in_track[2]; + u8 num_heads[2]; + u8 num_hid_sectors[4]; + u8 num_huge_sectors[4]; + + u8 phy_drv_no; + u8 reserved; + u8 ext_signature; + u8 vol_serial[4]; + u8 vol_label[11]; + u8 vol_type[8]; +}; + +/* MS-DOS FAT32 BIOS parameter block (79 bytes) */ +struct bpb32_t { + u8 sector_size[2]; + u8 sectors_per_clu; + u8 num_reserved[2]; + u8 num_fats; + u8 num_root_entries[2]; + u8 num_sectors[2]; + u8 media_type; + u8 num_fat_sectors[2]; + u8 sectors_in_track[2]; + u8 num_heads[2]; + u8 num_hid_sectors[4]; + u8 num_huge_sectors[4]; + u8 num_fat32_sectors[4]; + u8 ext_flags[2]; + u8 fs_version[2]; + u8 root_cluster[4]; + u8 fsinfo_sector[2]; + u8 backup_sector[2]; + u8 reserved[12]; + + u8 phy_drv_no; + u8 ext_reserved; + u8 ext_signature; + u8 vol_serial[4]; + u8 vol_label[11]; + u8 vol_type[8]; +}; + +/* MS-DOS EXFAT BIOS parameter block (109 bytes) */ +struct bpbex_t { + u8 reserved1[53]; + u8 vol_offset[8]; + u8 vol_length[8]; + u8 fat_offset[4]; + u8 fat_length[4]; + u8 clu_offset[4]; + u8 clu_count[4]; + u8 root_cluster[4]; + u8 vol_serial[4]; + u8 fs_version[2]; + u8 vol_flags[2]; + u8 sector_size_bits; + u8 sectors_per_clu_bits; + u8 num_fats; + u8 phy_drv_no; + u8 perc_in_use; + u8 reserved2[7]; +}; + +/* MS-DOS FAT file system information sector (512 bytes) */ +struct fsi_sector_t { + u8 signature1[4]; + u8 reserved1[480]; + u8 signature2[4]; + u8 free_cluster[4]; + u8 next_cluster[4]; + u8 reserved2[14]; + u8 signature3[2]; +}; + +/* MS-DOS FAT directory entry (32 bytes) */ +struct dentry_t { + u8 dummy[32]; +}; + +struct dos_dentry_t { + u8 name[DOS_NAME_LENGTH]; + u8 attr; + u8 lcase; + u8 create_time_ms; + u8 create_time[2]; + u8 create_date[2]; + u8 access_date[2]; + u8 start_clu_hi[2]; + u8 modify_time[2]; + u8 modify_date[2]; + u8 start_clu_lo[2]; + u8 size[4]; +}; + +/* MS-DOS FAT extended directory entry (32 bytes) */ +struct ext_dentry_t { + u8 order; + u8 unicode_0_4[10]; + u8 attr; + u8 sysid; + u8 checksum; + u8 unicode_5_10[12]; + u8 start_clu[2]; + u8 unicode_11_12[4]; +}; + +/* MS-DOS EXFAT file directory entry (32 bytes) */ +struct file_dentry_t { + u8 type; + u8 num_ext; + u8 checksum[2]; + u8 attr[2]; + u8 reserved1[2]; + u8 create_time[2]; + u8 create_date[2]; + u8 modify_time[2]; + u8 modify_date[2]; + u8 access_time[2]; + u8 access_date[2]; + u8 create_time_ms; + u8 modify_time_ms; + u8 access_time_ms; + u8 reserved2[9]; +}; + +/* MS-DOS EXFAT stream extension directory entry (32 bytes) */ +struct strm_dentry_t { + u8 type; + u8 flags; + u8 reserved1; + u8 name_len; + u8 name_hash[2]; + u8 reserved2[2]; + u8 valid_size[8]; + u8 reserved3[4]; + u8 start_clu[4]; + u8 size[8]; +}; + +/* MS-DOS EXFAT file name directory entry (32 bytes) */ +struct name_dentry_t { + u8 type; + u8 flags; + u8 unicode_0_14[30]; +}; + +/* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */ +struct bmap_dentry_t { + u8 type; + u8 flags; + u8 reserved[18]; + u8 start_clu[4]; + u8 size[8]; +}; + +/* MS-DOS EXFAT up-case table directory entry (32 bytes) */ +struct case_dentry_t { + u8 type; + u8 reserved1[3]; + u8 checksum[4]; + u8 reserved2[12]; + u8 start_clu[4]; + u8 size[8]; +}; + +/* MS-DOS EXFAT volume label directory entry (32 bytes) */ +struct volm_dentry_t { + u8 type; + u8 label_len; + u8 unicode_0_10[22]; + u8 reserved[8]; +}; + +/* unused entry hint information */ +struct uentry_t { + u32 dir; + s32 entry; + struct chain_t clu; +}; + +/* DOS name structure */ +struct dos_name_t { + u8 name[DOS_NAME_LENGTH]; + u8 name_case; +}; + +/* unicode name structure */ +struct uni_name_t { + u16 name[MAX_NAME_LENGTH]; + u16 name_hash; + u8 name_len; +}; + +struct buf_cache_t { + struct buf_cache_t *next; + struct buf_cache_t *prev; + struct buf_cache_t *hash_next; + struct buf_cache_t *hash_prev; + s32 drv; + sector_t sec; + u32 flag; + struct buffer_head *buf_bh; +}; + +struct fs_func { + s32 (*alloc_cluster)(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); + void (*free_cluster)(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); + s32 (*count_used_clusters)(struct super_block *sb); + + s32 (*init_dir_entry)(struct super_block *sb, struct chain_t *p_dir, + s32 entry, u32 type, u32 start_clu, u64 size); + s32 (*init_ext_entry)(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); + s32 (*find_dir_entry)(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); + void (*delete_dir_entry)(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + s32 offset, s32 num_entries); + void (*get_uni_name_from_ext_entry)(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); + s32 (*count_ext_entries)(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + struct dentry_t *p_entry); + s32 (*calc_num_entries)(struct uni_name_t *p_uniname); + + u32 (*get_entry_type)(struct dentry_t *p_entry); + void (*set_entry_type)(struct dentry_t *p_entry, u32 type); + u32 (*get_entry_attr)(struct dentry_t *p_entry); + void (*set_entry_attr)(struct dentry_t *p_entry, u32 attr); + u8 (*get_entry_flag)(struct dentry_t *p_entry); + void (*set_entry_flag)(struct dentry_t *p_entry, u8 flag); + u32 (*get_entry_clu0)(struct dentry_t *p_entry); + void (*set_entry_clu0)(struct dentry_t *p_entry, u32 clu0); + u64 (*get_entry_size)(struct dentry_t *p_entry); + void (*set_entry_size)(struct dentry_t *p_entry, u64 size); + void (*get_entry_time)(struct dentry_t *p_entry, + struct timestamp_t *tp, u8 mode); + void (*set_entry_time)(struct dentry_t *p_entry, + struct timestamp_t *tp, u8 mode); +}; + +struct fs_info_t { + u32 drv; /* drive ID */ + u32 vol_type; /* volume FAT type */ + u32 vol_id; /* volume serial number */ + + u64 num_sectors; /* num of sectors in volume */ + u32 num_clusters; /* num of clusters in volume */ + u32 cluster_size; /* cluster size in bytes */ + u32 cluster_size_bits; + u32 sectors_per_clu; /* cluster size in sectors */ + u32 sectors_per_clu_bits; + + u32 PBR_sector; /* PBR sector */ + u32 FAT1_start_sector; /* FAT1 start sector */ + u32 FAT2_start_sector; /* FAT2 start sector */ + u32 root_start_sector; /* root dir start sector */ + u32 data_start_sector; /* data area start sector */ + u32 num_FAT_sectors; /* num of FAT sectors */ + + u32 root_dir; /* root dir cluster */ + u32 dentries_in_root; /* num of dentries in root dir */ + u32 dentries_per_clu; /* num of dentries per cluster */ + + u32 vol_flag; /* volume dirty flag */ + struct buffer_head *pbr_bh; /* PBR sector */ + + u32 map_clu; /* allocation bitmap start cluster */ + u32 map_sectors; /* num of allocation bitmap sectors */ + struct buffer_head **vol_amap; /* allocation bitmap */ + + u16 **vol_utbl; /* upcase table */ + + u32 clu_srch_ptr; /* cluster search pointer */ + u32 used_clusters; /* number of used clusters */ + struct uentry_t hint_uentry; /* unused entry hint information */ + + u32 dev_ejected; /* block device operation error flag */ + + struct fs_func *fs_func; + struct semaphore v_sem; + + /* FAT cache */ + struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE]; + struct buf_cache_t FAT_cache_lru_list; + struct buf_cache_t FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; + + /* buf cache */ + struct buf_cache_t buf_cache_array[BUF_CACHE_SIZE]; + struct buf_cache_t buf_cache_lru_list; + struct buf_cache_t buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; +}; + +#define ES_2_ENTRIES 2 +#define ES_3_ENTRIES 3 +#define ES_ALL_ENTRIES 0 + +struct entry_set_cache_t { + /* sector number that contains file_entry */ + sector_t sector; + + /* byte offset in the sector */ + s32 offset; + + /* + * flag in stream entry. + * 01 for cluster chain, + * 03 for contig. clusteres. + */ + s32 alloc_flag; + + u32 num_entries; + + /* __buf should be the last member */ + void *__buf; +}; + +#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */ +#define EXFAT_ERRORS_PANIC 2 /* panic on error */ +#define EXFAT_ERRORS_RO 3 /* remount r/o on error */ + +/* ioctl command */ +#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) + +struct exfat_mount_options { + kuid_t fs_uid; + kgid_t fs_gid; + unsigned short fs_fmask; + unsigned short fs_dmask; + + /* permission for setting the [am]time */ + unsigned short allow_utime; + + /* codepage for shortname conversions */ + unsigned short codepage; + + /* charset for filename input/display */ + char *iocharset; + + unsigned char casesensitive; + + /* on error: continue, panic, remount-ro */ + unsigned char errors; +#ifdef CONFIG_EXFAT_DISCARD + /* flag on if -o dicard specified and device support discard() */ + unsigned char discard; +#endif /* CONFIG_EXFAT_DISCARD */ +}; + +#define EXFAT_HASH_BITS 8 +#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS) + +/* + * EXFAT file system in-core superblock data + */ +struct bd_info_t { + s32 sector_size; /* in bytes */ + s32 sector_size_bits; + s32 sector_size_mask; + + /* total number of sectors in this block device */ + s32 num_sectors; + + /* opened or not */ + bool opened; +}; + +struct exfat_sb_info { + struct fs_info_t fs_info; + struct bd_info_t bd_info; + + struct exfat_mount_options options; + + int s_dirt; + struct mutex s_lock; + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ + + struct inode *fat_inode; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + long debug_flags; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ +}; + +/* + * EXFAT file system inode data in memory + */ +struct exfat_inode_info { + struct file_id_t fid; + char *target; + /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ + loff_t mmu_private; /* physically allocated size */ + loff_t i_pos; /* on-disk position of directory entry or 0 */ + struct hlist_node i_hash_fat; /* hash by i_location */ + struct rw_semaphore truncate_lock; + struct inode vfs_inode; + struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */ +}; + +#define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) + +static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) +{ + return container_of(inode, struct exfat_inode_info, vfs_inode); +} + +/* NLS management function */ +u16 nls_upper(struct super_block *sb, u16 a); +int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b); +int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b); +void nls_uniname_to_dosname(struct super_block *sb, + struct dos_name_t *p_dosname, + struct uni_name_t *p_uniname, bool *p_lossy); +void nls_dosname_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); +void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, + struct uni_name_t *p_uniname); +void nls_cstring_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, u8 *p_cstring, + bool *p_lossy); + +/* buffer cache management */ +void buf_init(struct super_block *sb); +void buf_shutdown(struct super_block *sb); +int FAT_read(struct super_block *sb, u32 loc, u32 *content); +s32 FAT_write(struct super_block *sb, u32 loc, u32 content); +u8 *FAT_getblk(struct super_block *sb, sector_t sec); +void FAT_modify(struct super_block *sb, sector_t sec); +void FAT_release_all(struct super_block *sb); +void FAT_sync(struct super_block *sb); +u8 *buf_getblk(struct super_block *sb, sector_t sec); +void buf_modify(struct super_block *sb, sector_t sec); +void buf_lock(struct super_block *sb, sector_t sec); +void buf_unlock(struct super_block *sb, sector_t sec); +void buf_release(struct super_block *sb, sector_t sec); +void buf_release_all(struct super_block *sb); +void buf_sync(struct super_block *sb); + +/* fs management functions */ +void fs_set_vol_flags(struct super_block *sb, u32 new_flag); +void fs_error(struct super_block *sb); + +/* cluster management functions */ +s32 clear_cluster(struct super_block *sb, u32 clu); +s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); +s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain); +void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); +void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse); +u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain); +s32 count_num_clusters(struct super_block *sb, struct chain_t *dir); +s32 fat_count_used_clusters(struct super_block *sb); +s32 exfat_count_used_clusters(struct super_block *sb); +void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len); + +/* allocation bitmap management functions */ +s32 load_alloc_bitmap(struct super_block *sb); +void free_alloc_bitmap(struct super_block *sb); +s32 set_alloc_bitmap(struct super_block *sb, u32 clu); +s32 clr_alloc_bitmap(struct super_block *sb, u32 clu); +u32 test_alloc_bitmap(struct super_block *sb, u32 clu); +void sync_alloc_bitmap(struct super_block *sb); + +/* upcase table management functions */ +s32 load_upcase_table(struct super_block *sb); +void free_upcase_table(struct super_block *sb); + +/* dir entry management functions */ +u32 fat_get_entry_type(struct dentry_t *p_entry); +u32 exfat_get_entry_type(struct dentry_t *p_entry); +void fat_set_entry_type(struct dentry_t *p_entry, u32 type); +void exfat_set_entry_type(struct dentry_t *p_entry, u32 type); +u32 fat_get_entry_attr(struct dentry_t *p_entry); +u32 exfat_get_entry_attr(struct dentry_t *p_entry); +void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr); +void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr); +u8 fat_get_entry_flag(struct dentry_t *p_entry); +u8 exfat_get_entry_flag(struct dentry_t *p_entry); +void fat_set_entry_flag(struct dentry_t *p_entry, u8 flag); +void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag); +u32 fat_get_entry_clu0(struct dentry_t *p_entry); +u32 exfat_get_entry_clu0(struct dentry_t *p_entry); +void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); +void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu); +u64 fat_get_entry_size(struct dentry_t *p_entry); +u64 exfat_get_entry_size(struct dentry_t *p_entry); +void fat_set_entry_size(struct dentry_t *p_entry, u64 size); +void exfat_set_entry_size(struct dentry_t *p_entry, u64 size); +struct timestamp_t *tm_current(struct timestamp_t *tm); +void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode); +s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry, + u32 type, u32 start_clu, u64 size); +s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, u32 type, u32 start_clu, u64 size); +s32 fat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); +s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname); +void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu); +void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, + u16 *uniname); +void init_file_entry(struct file_dentry_t *ep, u32 type); +void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, + u64 size); +void init_name_entry(struct name_dentry_t *ep, u16 *uniname); +void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries); +void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries); + +s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry, + sector_t *sector, s32 *offset); +struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector, + s32 offset); +struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, + s32 entry, sector_t *sector); +struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u32 type, + struct dentry_t **file_ep); +void release_entry_set(struct entry_set_cache_t *es); +s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es); +s32 write_partial_entries_in_entry_set(struct super_block *sb, + struct entry_set_cache_t *es, + struct dentry_t *ep, u32 count); +s32 search_deleted_or_unused_entry(struct super_block *sb, + struct chain_t *p_dir, s32 num_entries); +s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, + s32 num_entries); +s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); +s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type); +s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry); +s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry); +s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir, + u32 type); +void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, + s32 entry); +void update_dir_checksum_with_entry_set(struct super_block *sb, + struct entry_set_cache_t *es); +bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir); + +/* name conversion functions */ +s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 *entries, + struct dos_name_t *p_dosname); +void get_uni_name_from_dos_entry(struct super_block *sb, + struct dos_dentry_t *ep, + struct uni_name_t *p_uniname, u8 mode); +void fat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname); +s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, + u16 *uniname, s32 order); +s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, + u16 *uniname, s32 order); +s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct dos_name_t *p_dosname); +void fat_attach_count_to_dos_name(u8 *dosname, s32 count); +s32 fat_calc_num_entries(struct uni_name_t *p_uniname); +s32 exfat_calc_num_entries(struct uni_name_t *p_uniname); +u8 calc_checksum_1byte(void *data, s32 len, u8 chksum); +u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type); +u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type); + +/* name resolution functions */ +s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, + struct uni_name_t *p_uniname); +s32 resolve_name(u8 *name, u8 **arg); + +/* file operation functions */ +s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); +s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); +s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr); +s32 create_dir(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, struct file_id_t *fid); +s32 create_file(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid); +void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry); +s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry, + struct uni_name_t *p_uniname, struct file_id_t *fid); +s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, + struct chain_t *p_newdir, struct uni_name_t *p_uniname, + struct file_id_t *fid); + +/* sector read/write functions */ +int sector_read(struct super_block *sb, sector_t sec, + struct buffer_head **bh, bool read); +int sector_write(struct super_block *sb, sector_t sec, + struct buffer_head *bh, bool sync); +int multi_sector_read(struct super_block *sb, sector_t sec, + struct buffer_head **bh, s32 num_secs, bool read); +int multi_sector_write(struct super_block *sb, sector_t sec, + struct buffer_head *bh, s32 num_secs, bool sync); + +void bdev_open(struct super_block *sb); +void bdev_close(struct super_block *sb); +int bdev_read(struct super_block *sb, sector_t secno, + struct buffer_head **bh, u32 num_secs, bool read); +int bdev_write(struct super_block *sb, sector_t secno, + struct buffer_head *bh, u32 num_secs, bool sync); +int bdev_sync(struct super_block *sb); + +extern const u8 uni_upcase[]; +#endif /* _EXFAT_H */ diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c new file mode 100644 index 000000000000..f086c75e7076 --- /dev/null +++ b/drivers/staging/exfat/exfat_blkdev.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include "exfat.h" + +void bdev_open(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bd->opened) + return; + + p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); + p_bd->sector_size_bits = ilog2(p_bd->sector_size); + p_bd->sector_size_mask = p_bd->sector_size - 1; + p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> + p_bd->sector_size_bits; + p_bd->opened = true; +} + +void bdev_close(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + p_bd->opened = false; +} + +int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh, + u32 num_secs, bool read) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) + return FFS_MEDIAERR; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + if (!p_bd->opened) + return FFS_MEDIAERR; + + if (*bh) + __brelse(*bh); + + if (read) + *bh = __bread(sb->s_bdev, secno, + num_secs << p_bd->sector_size_bits); + else + *bh = __getblk(sb->s_bdev, secno, + num_secs << p_bd->sector_size_bits); + + if (*bh) + return 0; + + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return FFS_MEDIAERR; +} + +int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh, + u32 num_secs, bool sync) +{ + s32 count; + struct buffer_head *bh2; + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) + return FFS_MEDIAERR; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + if (!p_bd->opened) + return FFS_MEDIAERR; + + if (secno == bh->b_blocknr) { + lock_buffer(bh); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + unlock_buffer(bh); + if (sync && (sync_dirty_buffer(bh) != 0)) + return FFS_MEDIAERR; + } else { + count = num_secs << p_bd->sector_size_bits; + + bh2 = __getblk(sb->s_bdev, secno, count); + if (!bh2) + goto no_bh; + + lock_buffer(bh2); + memcpy(bh2->b_data, bh->b_data, count); + set_buffer_uptodate(bh2); + mark_buffer_dirty(bh2); + unlock_buffer(bh2); + if (sync && (sync_dirty_buffer(bh2) != 0)) { + __brelse(bh2); + goto no_bh; + } + __brelse(bh2); + } + + return 0; + +no_bh: + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return FFS_MEDIAERR; +} + +int bdev_sync(struct super_block *sb) +{ + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) + return FFS_MEDIAERR; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + if (!p_bd->opened) + return FFS_MEDIAERR; + + return sync_blockdev(sb->s_bdev); +} diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c new file mode 100644 index 000000000000..f05d692c2b1e --- /dev/null +++ b/drivers/staging/exfat/exfat_cache.c @@ -0,0 +1,722 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include "exfat.h" + +#define LOCKBIT 0x01 +#define DIRTYBIT 0x02 + +/* Local variables */ +static DEFINE_SEMAPHORE(f_sem); +static DEFINE_SEMAPHORE(b_sem); + +static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec) +{ + s32 off; + struct buf_cache_t *bp, *hp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + + (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1); + + hp = &p_fs->FAT_cache_hash_list[off]; + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + WARN(!bp->buf_bh, + "[EXFAT] FAT_cache has no bh. It will make system panic.\n"); + + touch_buffer(bp->buf_bh); + return bp; + } + } + return NULL; +} + +static void push_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->next = list->next; + bp->prev = list; + list->next->prev = bp; + list->next = bp; +} + +static void push_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->prev = list->prev; + bp->next = list; + list->prev->next = bp; + list->prev = bp; +} + +static void move_to_mru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_mru(bp, list); +} + +static void move_to_lru(struct buf_cache_t *bp, struct buf_cache_t *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_lru(bp, list); +} + +static struct buf_cache_t *FAT_cache_get(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->FAT_cache_lru_list.prev; + + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return bp; +} + +static void FAT_cache_insert_hash(struct super_block *sb, + struct buf_cache_t *bp) +{ + s32 off; + struct buf_cache_t *hp; + struct fs_info_t *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + + (bp->sec >> p_fs->sectors_per_clu_bits)) & + (FAT_CACHE_HASH_SIZE - 1); + + hp = &p_fs->FAT_cache_hash_list[off]; + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} + +static void FAT_cache_remove_hash(struct buf_cache_t *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} + +static void buf_cache_insert_hash(struct super_block *sb, + struct buf_cache_t *bp) +{ + s32 off; + struct buf_cache_t *hp; + struct fs_info_t *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + + (bp->sec >> p_fs->sectors_per_clu_bits)) & + (BUF_CACHE_HASH_SIZE - 1); + + hp = &p_fs->buf_cache_hash_list[off]; + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} + +static void buf_cache_remove_hash(struct buf_cache_t *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} + +void buf_init(struct super_block *sb) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + int i; + + /* LRU list */ + p_fs->FAT_cache_lru_list.next = &p_fs->FAT_cache_lru_list; + p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list; + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + p_fs->FAT_cache_array[i].drv = -1; + p_fs->FAT_cache_array[i].sec = ~0; + p_fs->FAT_cache_array[i].flag = 0; + p_fs->FAT_cache_array[i].buf_bh = NULL; + p_fs->FAT_cache_array[i].prev = NULL; + p_fs->FAT_cache_array[i].next = NULL; + push_to_mru(&p_fs->FAT_cache_array[i], + &p_fs->FAT_cache_lru_list); + } + + p_fs->buf_cache_lru_list.next = &p_fs->buf_cache_lru_list; + p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list; + + for (i = 0; i < BUF_CACHE_SIZE; i++) { + p_fs->buf_cache_array[i].drv = -1; + p_fs->buf_cache_array[i].sec = ~0; + p_fs->buf_cache_array[i].flag = 0; + p_fs->buf_cache_array[i].buf_bh = NULL; + p_fs->buf_cache_array[i].prev = NULL; + p_fs->buf_cache_array[i].next = NULL; + push_to_mru(&p_fs->buf_cache_array[i], + &p_fs->buf_cache_lru_list); + } + + /* HASH list */ + for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { + p_fs->FAT_cache_hash_list[i].drv = -1; + p_fs->FAT_cache_hash_list[i].sec = ~0; + p_fs->FAT_cache_hash_list[i].hash_next = + &p_fs->FAT_cache_hash_list[i]; + p_fs->FAT_cache_hash_list[i].hash_prev = + &p_fs->FAT_cache_hash_list[i]; + } + + for (i = 0; i < FAT_CACHE_SIZE; i++) + FAT_cache_insert_hash(sb, &p_fs->FAT_cache_array[i]); + + for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { + p_fs->buf_cache_hash_list[i].drv = -1; + p_fs->buf_cache_hash_list[i].sec = ~0; + p_fs->buf_cache_hash_list[i].hash_next = + &p_fs->buf_cache_hash_list[i]; + p_fs->buf_cache_hash_list[i].hash_prev = + &p_fs->buf_cache_hash_list[i]; + } + + for (i = 0; i < BUF_CACHE_SIZE; i++) + buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]); +} + +void buf_shutdown(struct super_block *sb) +{ +} + +static int __FAT_read(struct super_block *sb, u32 loc, u32 *content) +{ + s32 off; + u32 _content; + sector_t sec; + u8 *fat_sector, *fat_entry; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + sec = p_fs->FAT1_start_sector + + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + if (off == (p_bd->sector_size - 1)) { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + _content = (u32)fat_sector[off]; + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + _content |= (u32)fat_sector[0] << 8; + } else { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + _content = GET16(fat_entry); + } + + if (loc & 1) + _content >>= 4; + + _content &= 0x00000FFF; + + if (_content >= CLUSTER_16(0x0FF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } else if (p_fs->vol_type == FAT16) { + sec = p_fs->FAT1_start_sector + + (loc >> (p_bd->sector_size_bits - 1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + _content = GET16_A(fat_entry); + + _content &= 0x0000FFFF; + + if (_content >= CLUSTER_16(0xFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } else if (p_fs->vol_type == FAT32) { + sec = p_fs->FAT1_start_sector + + (loc >> (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + _content = GET32_A(fat_entry); + + _content &= 0x0FFFFFFF; + + if (_content >= CLUSTER_32(0x0FFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } else if (p_fs->vol_type == EXFAT) { + sec = p_fs->FAT1_start_sector + + (loc >> (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + _content = GET32_A(fat_entry); + + if (_content >= CLUSTER_32(0xFFFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } + *content = CLUSTER_32(_content); + return 0; + } + + /* Unknown volume type, throw in the towel and go home */ + *content = CLUSTER_32(~0); + return 0; +} + +/* in : sb, loc + * out: content + * returns 0 on success + * -1 on error + */ +int FAT_read(struct super_block *sb, u32 loc, u32 *content) +{ + s32 ret; + + down(&f_sem); + ret = __FAT_read(sb, loc, content); + up(&f_sem); + + return ret; +} + +static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content) +{ + s32 off; + sector_t sec; + u8 *fat_sector, *fat_entry; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + content &= 0x00000FFF; + + sec = p_fs->FAT1_start_sector + + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + if (loc & 1) { /* odd */ + content <<= 4; + + if (off == (p_bd->sector_size - 1)) { + fat_sector[off] = (u8)(content | + (fat_sector[off] & + 0x0F)); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + fat_sector[0] = (u8)(content >> 8); + } else { + fat_entry = &fat_sector[off]; + content |= GET16(fat_entry) & 0x000F; + + SET16(fat_entry, content); + } + } else { /* even */ + fat_sector[off] = (u8)(content); + + if (off == (p_bd->sector_size - 1)) { + fat_sector[off] = (u8)(content); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + fat_sector[0] = (u8)((fat_sector[0] & 0xF0) | + (content >> 8)); + } else { + fat_entry = &fat_sector[off]; + content |= GET16(fat_entry) & 0xF000; + + SET16(fat_entry, content); + } + } + } + + else if (p_fs->vol_type == FAT16) { + content &= 0x0000FFFF; + + sec = p_fs->FAT1_start_sector + (loc >> + (p_bd->sector_size_bits - 1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + SET16_A(fat_entry, content); + } else if (p_fs->vol_type == FAT32) { + content &= 0x0FFFFFFF; + + sec = p_fs->FAT1_start_sector + (loc >> + (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + content |= GET32_A(fat_entry) & 0xF0000000; + + SET32_A(fat_entry, content); + } else { /* p_fs->vol_type == EXFAT */ + sec = p_fs->FAT1_start_sector + (loc >> + (p_bd->sector_size_bits - 2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &fat_sector[off]; + + SET32_A(fat_entry, content); + } + + FAT_modify(sb, sec); + return 0; +} + +int FAT_write(struct super_block *sb, u32 loc, u32 content) +{ + s32 ret; + + down(&f_sem); + ret = __FAT_write(sb, loc, content); + up(&f_sem); + + return ret; +} + +u8 *FAT_getblk(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = FAT_cache_find(sb, sec); + if (bp) { + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return bp->buf_bh->b_data; + } + + bp = FAT_cache_get(sb, sec); + + FAT_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + FAT_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) { + FAT_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->FAT_cache_lru_list); + return NULL; + } + + return bp->buf_bh->b_data; +} + +void FAT_modify(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + bp = FAT_cache_find(sb, sec); + if (bp) + sector_write(sb, sec, bp->buf_bh, 0); +} + +void FAT_release_all(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if (bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + up(&f_sem); +} + +void FAT_sync(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + up(&f_sem); +} + +static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec) +{ + s32 off; + struct buf_cache_t *bp, *hp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & + (BUF_CACHE_HASH_SIZE - 1); + + hp = &p_fs->buf_cache_hash_list[off]; + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + touch_buffer(bp->buf_bh); + return bp; + } + } + return NULL; +} + +static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->buf_cache_lru_list.prev; + while (bp->flag & LOCKBIT) + bp = bp->prev; + + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return bp; +} + +static u8 *__buf_getblk(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = buf_cache_find(sb, sec); + if (bp) { + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return bp->buf_bh->b_data; + } + + bp = buf_cache_get(sb, sec); + + buf_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + buf_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) { + buf_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + return NULL; + } + + return bp->buf_bh->b_data; +} + +u8 *buf_getblk(struct super_block *sb, sector_t sec) +{ + u8 *buf; + + down(&b_sem); + buf = __buf_getblk(sb, sec); + up(&b_sem); + + return buf; +} + +void buf_modify(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) + sector_write(sb, sec, bp->buf_bh, 0); + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", + (unsigned long long)sec); + + up(&b_sem); +} + +void buf_lock(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) + bp->flag |= LOCKBIT; + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", + (unsigned long long)sec); + + up(&b_sem); +} + +void buf_unlock(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) + bp->flag &= ~(LOCKBIT); + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n", + (unsigned long long)sec); + + up(&b_sem); +} + +void buf_release(struct super_block *sb, sector_t sec) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp)) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if (bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + } + + up(&b_sem); +} + +void buf_release_all(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if (bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + up(&b_sem); +} + +void buf_sync(struct super_block *sb) +{ + struct buf_cache_t *bp; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + down(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + up(&b_sem); +} diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c new file mode 100644 index 000000000000..9f76ca175c80 --- /dev/null +++ b/drivers/staging/exfat/exfat_core.c @@ -0,0 +1,3704 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include "exfat.h" + + +static void __set_sb_dirty(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + sbi->s_dirt = 1; +} + +static u8 name_buf[MAX_PATH_LENGTH * MAX_CHARSET_SIZE]; + +static char *reserved_names[] = { + "AUX ", "CON ", "NUL ", "PRN ", + "COM1 ", "COM2 ", "COM3 ", "COM4 ", + "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ", + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ", + "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ", + NULL +}; + +static u8 free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 40 ~ 59 */ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 ~ 79 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /* 80 ~ 99 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 240 ~ 254 */ +}; + +static u8 used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /* 0 ~ 19 */ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /* 20 ~ 39 */ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /* 40 ~ 59 */ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 60 ~ 79 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /* 80 ~ 99 */ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 ~ 255 */ +}; + +#define BITMAP_LOC(v) ((v) >> 3) +#define BITMAP_SHIFT(v) ((v) & 0x07) + +static inline s32 exfat_bitmap_test(u8 *bitmap, int i) +{ + u8 data; + + data = bitmap[BITMAP_LOC(i)]; + if ((data >> BITMAP_SHIFT(i)) & 0x01) + return 1; + return 0; +} + +static inline void exfat_bitmap_set(u8 *bitmap, int i) +{ + bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i)); +} + +static inline void exfat_bitmap_clear(u8 *bitmap, int i) +{ + bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i)); +} + +/* + * File System Management Functions + */ + +void fs_set_vol_flags(struct super_block *sb, u32 new_flag) +{ + struct pbr_sector_t *p_pbr; + struct bpbex_t *p_bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_flag == new_flag) + return; + + p_fs->vol_flag = new_flag; + + if (p_fs->vol_type == EXFAT) { + if (p_fs->pbr_bh == NULL) { + if (sector_read(sb, p_fs->PBR_sector, + &p_fs->pbr_bh, 1) != FFS_SUCCESS) + return; + } + + p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data; + p_bpb = (struct bpbex_t *)p_pbr->bpb; + SET16(p_bpb->vol_flags, (u16)new_flag); + + /* XXX duyoung + * what can we do here? (cuz fs_set_vol_flags() is void) + */ + if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh))) + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1); + else + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0); + } +} + +void fs_error(struct super_block *sb) +{ + struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; + + if (opts->errors == EXFAT_ERRORS_PANIC) { + panic("[EXFAT] Filesystem panic from previous error\n"); + } else if ((opts->errors == EXFAT_ERRORS_RO) && !sb_rdonly(sb)) { + sb->s_flags |= SB_RDONLY; + pr_err("[EXFAT] Filesystem has been set read-only\n"); + } +} + +/* + * Cluster Management Functions + */ + +s32 clear_cluster(struct super_block *sb, u32 clu) +{ + sector_t s, n; + s32 ret = FFS_SUCCESS; + struct buffer_head *tmp_bh = NULL; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (clu == CLUSTER_32(0)) { /* FAT16 root_dir */ + s = p_fs->root_start_sector; + n = p_fs->data_start_sector; + } else { + s = START_SECTOR(clu); + n = s + p_fs->sectors_per_clu; + } + + for (; s < n; s++) { + ret = sector_read(sb, s, &tmp_bh, 0); + if (ret != FFS_SUCCESS) + return ret; + + memset((char *)tmp_bh->b_data, 0x0, p_bd->sector_size); + ret = sector_write(sb, s, tmp_bh, 0); + if (ret != FFS_SUCCESS) + break; + } + + brelse(tmp_bh); + return ret; +} + +s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain) +{ + int i, num_clusters = 0; + u32 new_clu, last_clu = CLUSTER_32(~0), read_clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + new_clu = p_chain->dir; + if (new_clu == CLUSTER_32(~0)) + new_clu = p_fs->clu_srch_ptr; + else if (new_clu >= p_fs->num_clusters) + new_clu = 2; + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, new_clu, &read_clu) != 0) + return -1; + + if (read_clu == CLUSTER_32(0)) { + if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0) + return -1; + num_clusters++; + + if (p_chain->dir == CLUSTER_32(~0)) { + p_chain->dir = new_clu; + } else { + if (FAT_write(sb, last_clu, new_clu) < 0) + return -1; + } + + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != (u32) ~0) + p_fs->used_clusters += num_clusters; + + return num_clusters; + } + } + if ((++new_clu) >= p_fs->num_clusters) + new_clu = 2; + } + + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != (u32) ~0) + p_fs->used_clusters += num_clusters; + + return num_clusters; +} + +s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, + struct chain_t *p_chain) +{ + s32 num_clusters = 0; + u32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + hint_clu = p_chain->dir; + if (hint_clu == CLUSTER_32(~0)) { + hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2); + if (hint_clu == CLUSTER_32(~0)) + return 0; + } else if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + p_chain->flags = 0x01; + } + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) { + if (new_clu != hint_clu) { + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters); + p_chain->flags = 0x01; + } + } + + if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS) + return -1; + + num_clusters++; + + if (p_chain->flags == 0x01) { + if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0) + return -1; + } + + if (p_chain->dir == CLUSTER_32(~0)) { + p_chain->dir = new_clu; + } else { + if (p_chain->flags == 0x01) { + if (FAT_write(sb, last_clu, new_clu) < 0) + return -1; + } + } + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != (u32) ~0) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return num_clusters; + } + + hint_clu = new_clu + 1; + if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, + num_clusters); + p_chain->flags = 0x01; + } + } + } + + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != (u32) ~0) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return num_clusters; +} + +void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse) +{ + s32 num_clusters = 0; + u32 clu, prev; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int i; + sector_t sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->size <= 0) + return; + + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) + buf_release(sb, sector+i); + } + + prev = clu; + if (FAT_read(sb, clu, &clu) == -1) + break; + + if (FAT_write(sb, prev, CLUSTER_32(0)) < 0) + break; + num_clusters++; + + } while (clu != CLUSTER_32(~0)); + + if (p_fs->used_clusters != (u32) ~0) + p_fs->used_clusters -= num_clusters; +} + +void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, + s32 do_relse) +{ + s32 num_clusters = 0; + u32 clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int i; + sector_t sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + + if (p_chain->size <= 0) { + pr_err("[EXFAT] free_cluster : skip free-req clu:%u, because of zero-size truncation\n", + p_chain->dir); + return; + } + + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + do { + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) + buf_release(sb, sector+i); + } + + if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + break; + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) + buf_release(sb, sector+i); + } + + if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + break; + + if (FAT_read(sb, clu, &clu) == -1) + break; + num_clusters++; + } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); + } + + if (p_fs->used_clusters != (u32) ~0) + p_fs->used_clusters -= num_clusters; +} + +u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain) +{ + u32 clu, next; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + clu += p_chain->size - 1; + } else { + while ((FAT_read(sb, clu, &next) == 0) && + (next != CLUSTER_32(~0))) { + if (p_fs->dev_ejected) + break; + clu = next; + } + } + + return clu; +} + +s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain) +{ + int i, count = 0; + u32 clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return 0; + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + count = p_chain->size; + } else { + for (i = 2; i < p_fs->num_clusters; i++) { + count++; + if (FAT_read(sb, clu, &clu) != 0) + return 0; + if (clu == CLUSTER_32(~0)) + break; + } + } + + return count; +} + +s32 fat_count_used_clusters(struct super_block *sb) +{ + int i, count = 0; + u32 clu; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, i, &clu) != 0) + break; + if (clu != CLUSTER_32(0)) + count++; + } + + return count; +} + +s32 exfat_count_used_clusters(struct super_block *sb) +{ + int i, map_i, map_b, count = 0; + u8 k; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + map_i = map_b = 0; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((u8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + count += used_bit[k]; + + if ((++map_b) >= p_bd->sector_size) { + map_i++; + map_b = 0; + } + } + + return count; +} + +void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) +{ + if (len == 0) + return; + + while (len > 1) { + if (FAT_write(sb, chain, chain+1) < 0) + break; + chain++; + len--; + } + FAT_write(sb, chain, CLUSTER_32(~0)); +} + +/* + * Allocation Bitmap Management Functions + */ + +s32 load_alloc_bitmap(struct super_block *sb) +{ + int i, j, ret; + u32 map_size; + u32 type; + sector_t sector; + struct chain_t clu; + struct bmap_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (struct bmap_dentry_t *)get_entry_in_dir(sb, &clu, + i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + + if (ep->flags == 0x0) { + p_fs->map_clu = GET32_A(ep->start_clu); + map_size = (u32) GET64_A(ep->size); + + p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1; + + p_fs->vol_amap = kmalloc_array(p_fs->map_sectors, + sizeof(struct buffer_head *), + GFP_KERNEL); + if (p_fs->vol_amap == NULL) + return FFS_MEMORYERR; + + sector = START_SECTOR(p_fs->map_clu); + + for (j = 0; j < p_fs->map_sectors; j++) { + p_fs->vol_amap[j] = NULL; + ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1); + if (ret != FFS_SUCCESS) { + /* release all buffers and free vol_amap */ + i = 0; + while (i < j) + brelse(p_fs->vol_amap[i++]); + + kfree(p_fs->vol_amap); + p_fs->vol_amap = NULL; + return ret; + } + } + + p_fs->pbr_bh = NULL; + return FFS_SUCCESS; + } + } + + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return FFS_MEDIAERR; + } + + return FFS_FORMATERR; +} + +void free_alloc_bitmap(struct super_block *sb) +{ + int i; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + brelse(p_fs->pbr_bh); + + for (i = 0; i < p_fs->map_sectors; i++) + __brelse(p_fs->vol_amap[i]); + + kfree(p_fs->vol_amap); + p_fs->vol_amap = NULL; +} + +s32 set_alloc_bitmap(struct super_block *sb, u32 clu) +{ + int i, b; + sector_t sector; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + exfat_bitmap_set((u8 *) p_fs->vol_amap[i]->b_data, b); + + return sector_write(sb, sector, p_fs->vol_amap[i], 0); +} + +s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) +{ + int i, b; + sector_t sector; +#ifdef CONFIG_EXFAT_DISCARD + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + int ret; +#endif /* CONFIG_EXFAT_DISCARD */ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + exfat_bitmap_clear((u8 *) p_fs->vol_amap[i]->b_data, b); + + return sector_write(sb, sector, p_fs->vol_amap[i], 0); + +#ifdef CONFIG_EXFAT_DISCARD + if (opts->discard) { + ret = sb_issue_discard(sb, START_SECTOR(clu), + (1 << p_fs->sectors_per_clu_bits), + GFP_NOFS, 0); + if (ret == -EOPNOTSUPP) { + pr_warn("discard not supported by device, disabling"); + opts->discard = 0; + } + } +#endif /* CONFIG_EXFAT_DISCARD */ +} + +u32 test_alloc_bitmap(struct super_block *sb, u32 clu) +{ + int i, map_i, map_b; + u32 clu_base, clu_free; + u8 k, clu_mask; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu_base = (clu & ~(0x7)) + 2; + clu_mask = (1 << (clu - clu_base + 2)) - 1; + + map_i = clu >> (p_bd->sector_size_bits + 3); + map_b = (clu >> 3) & p_bd->sector_size_mask; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((u8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < p_fs->num_clusters) + return clu_free; + } + clu_base += 8; + + if (((++map_b) >= p_bd->sector_size) || + (clu_base >= p_fs->num_clusters)) { + if ((++map_i) >= p_fs->map_sectors) { + clu_base = 2; + map_i = 0; + } + map_b = 0; + } + } + + return CLUSTER_32(~0); +} + +void sync_alloc_bitmap(struct super_block *sb) +{ + int i; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_amap == NULL) + return; + + for (i = 0; i < p_fs->map_sectors; i++) + sync_dirty_buffer(p_fs->vol_amap[i]); +} + +/* + * Upcase table Management Functions + */ +static s32 __load_upcase_table(struct super_block *sb, sector_t sector, + u32 num_sectors, u32 utbl_checksum) +{ + int i, ret = FFS_ERROR; + u32 j; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct buffer_head *tmp_bh = NULL; + sector_t end_sector = num_sectors + sector; + + u8 skip = FALSE; + u32 index = 0; + u16 uni = 0; + u16 **upcase_table; + + u32 checksum = 0; + + upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *), + GFP_KERNEL); + if (upcase_table == NULL) + return FFS_MEMORYERR; + memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); + + while (sector < end_sector) { + ret = sector_read(sb, sector, &tmp_bh, 1); + if (ret != FFS_SUCCESS) { + pr_debug("sector read (0x%llX)fail\n", + (unsigned long long)sector); + goto error; + } + sector++; + + for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { + uni = GET16(((u8 *) tmp_bh->b_data)+i); + + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + + i); + checksum = ((checksum & 1) ? 0x80000000 : 0) + + (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + + (i + 1)); + + if (skip) { + pr_debug("skip from 0x%X ", index); + index += uni; + pr_debug("to 0x%X (amount of 0x%X)\n", + index, uni); + skip = FALSE; + } else if (uni == index) + index++; + else if (uni == 0xFFFF) + skip = TRUE; + else { /* uni != index , uni != 0xFFFF */ + u16 col_index = get_col_index(index); + + if (upcase_table[col_index] == NULL) { + pr_debug("alloc = 0x%X\n", col_index); + upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, + sizeof(u16), GFP_KERNEL); + if (upcase_table[col_index] == NULL) { + ret = FFS_MEMORYERR; + goto error; + } + + for (j = 0; j < UTBL_ROW_COUNT; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + } + if (index >= 0xFFFF && utbl_checksum == checksum) { + if (tmp_bh) + brelse(tmp_bh); + return FFS_SUCCESS; + } + ret = FFS_ERROR; +error: + if (tmp_bh) + brelse(tmp_bh); + free_upcase_table(sb); + return ret; +} + +static s32 __load_default_upcase_table(struct super_block *sb) +{ + int i, ret = FFS_ERROR; + u32 j; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + u8 skip = FALSE; + u32 index = 0; + u16 uni = 0; + u16 **upcase_table; + + upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *), + GFP_KERNEL); + if (upcase_table == NULL) + return FFS_MEMORYERR; + memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); + + for (i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) { + uni = GET16(uni_upcase + i); + if (skip) { + pr_debug("skip from 0x%X ", index); + index += uni; + pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); + skip = FALSE; + } else if (uni == index) + index++; + else if (uni == 0xFFFF) + skip = TRUE; + else { /* uni != index , uni != 0xFFFF */ + u16 col_index = get_col_index(index); + + if (upcase_table[col_index] == NULL) { + pr_debug("alloc = 0x%X\n", col_index); + upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, + sizeof(u16), + GFP_KERNEL); + if (upcase_table[col_index] == NULL) { + ret = FFS_MEMORYERR; + goto error; + } + + for (j = 0; j < UTBL_ROW_COUNT; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + + if (index >= 0xFFFF) + return FFS_SUCCESS; + +error: + /* FATAL error: default upcase table has error */ + free_upcase_table(sb); + return ret; +} + +s32 load_upcase_table(struct super_block *sb) +{ + int i; + u32 tbl_clu, tbl_size; + sector_t sector; + u32 type, num_sectors; + struct chain_t clu; + struct case_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + while (clu.dir != CLUSTER_32(~0)) { + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (struct case_dentry_t *)get_entry_in_dir(sb, &clu, + i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_UPCASE) + continue; + + tbl_clu = GET32_A(ep->start_clu); + tbl_size = (u32) GET64_A(ep->size); + + sector = START_SECTOR(tbl_clu); + num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1; + if (__load_upcase_table(sb, sector, num_sectors, + GET32_A(ep->checksum)) != FFS_SUCCESS) + break; + return FFS_SUCCESS; + } + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return FFS_MEDIAERR; + } + /* load default upcase table */ + return __load_default_upcase_table(sb); +} + +void free_upcase_table(struct super_block *sb) +{ + u32 i; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + u16 **upcase_table; + + upcase_table = p_fs->vol_utbl; + for (i = 0; i < UTBL_COL_COUNT; i++) + kfree(upcase_table[i]); + + kfree(p_fs->vol_utbl); + p_fs->vol_utbl = NULL; +} + +/* + * Directory Entry Management Functions + */ + +u32 fat_get_entry_type(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + + if (*(ep->name) == 0x0) + return TYPE_UNUSED; + + else if (*(ep->name) == 0xE5) + return TYPE_DELETED; + + else if (ep->attr == ATTR_EXTEND) + return TYPE_EXTEND; + + else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME) + return TYPE_VOLUME; + + else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR) + return TYPE_DIR; + + return TYPE_FILE; +} + +u32 exfat_get_entry_type(struct dentry_t *p_entry) +{ + struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + + if (ep->type == 0x0) { + return TYPE_UNUSED; + } else if (ep->type < 0x80) { + return TYPE_DELETED; + } else if (ep->type == 0x80) { + return TYPE_INVALID; + } else if (ep->type < 0xA0) { + if (ep->type == 0x81) { + return TYPE_BITMAP; + } else if (ep->type == 0x82) { + return TYPE_UPCASE; + } else if (ep->type == 0x83) { + return TYPE_VOLUME; + } else if (ep->type == 0x85) { + if (GET16_A(ep->attr) & ATTR_SUBDIR) + return TYPE_DIR; + else + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } else if (ep->type < 0xC0) { + if (ep->type == 0xA0) + return TYPE_GUID; + else if (ep->type == 0xA1) + return TYPE_PADDING; + else if (ep->type == 0xA2) + return TYPE_ACLTAB; + return TYPE_BENIGN_PRI; + } else if (ep->type < 0xE0) { + if (ep->type == 0xC0) + return TYPE_STREAM; + else if (ep->type == 0xC1) + return TYPE_EXTEND; + else if (ep->type == 0xC2) + return TYPE_ACL; + return TYPE_CRITICAL_SEC; + } + + return TYPE_BENIGN_SEC; +} + +void fat_set_entry_type(struct dentry_t *p_entry, u32 type) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + + if (type == TYPE_UNUSED) + *(ep->name) = 0x0; + + else if (type == TYPE_DELETED) + *(ep->name) = 0xE5; + + else if (type == TYPE_EXTEND) + ep->attr = ATTR_EXTEND; + + else if (type == TYPE_DIR) + ep->attr = ATTR_SUBDIR; + + else if (type == TYPE_FILE) + ep->attr = ATTR_ARCHIVE; + + else if (type == TYPE_SYMLINK) + ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK; +} + +void exfat_set_entry_type(struct dentry_t *p_entry, u32 type) +{ + struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + + if (type == TYPE_UNUSED) { + ep->type = 0x0; + } else if (type == TYPE_DELETED) { + ep->type &= ~0x80; + } else if (type == TYPE_STREAM) { + ep->type = 0xC0; + } else if (type == TYPE_EXTEND) { + ep->type = 0xC1; + } else if (type == TYPE_BITMAP) { + ep->type = 0x81; + } else if (type == TYPE_UPCASE) { + ep->type = 0x82; + } else if (type == TYPE_VOLUME) { + ep->type = 0x83; + } else if (type == TYPE_DIR) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE); + } else if (type == TYPE_SYMLINK) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK); + } +} + +u32 fat_get_entry_attr(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + + return (u32) ep->attr; +} + +u32 exfat_get_entry_attr(struct dentry_t *p_entry) +{ + struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + + return (u32) GET16_A(ep->attr); +} + +void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + + ep->attr = (u8) attr; +} + +void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr) +{ + struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + + SET16_A(ep->attr, (u16) attr); +} + +u8 fat_get_entry_flag(struct dentry_t *p_entry) +{ + return 0x01; +} + +u8 exfat_get_entry_flag(struct dentry_t *p_entry) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry; + + return ep->flags; +} + +void fat_set_entry_flag(struct dentry_t *p_entry, u8 flags) +{ +} + +void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry; + + ep->flags = flags; +} + +u32 fat_get_entry_clu0(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + + return ((u32)GET16_A(ep->start_clu_hi) << 16) | + GET16_A(ep->start_clu_lo); +} + +u32 exfat_get_entry_clu0(struct dentry_t *p_entry) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry; + + return GET32_A(ep->start_clu); +} + +void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); +} + +void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + SET32_A(ep->start_clu, start_clu); +} + +u64 fat_get_entry_size(struct dentry_t *p_entry) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + return (u64) GET32_A(ep->size); +} + +u64 exfat_get_entry_size(struct dentry_t *p_entry) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + return GET64_A(ep->valid_size); +} + +void fat_set_entry_size(struct dentry_t *p_entry, u64 size) +{ + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + SET32_A(ep->size, (u32) size); +} + +void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) +{ + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; + + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} + +void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t = 0x00, d = 0x21; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} + +void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t = 0x00, d = 0x21; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + case TM_ACCESS: + t = GET16_A(ep->access_time); + d = GET16_A(ep->access_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} + +void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t, d; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + } +} + +void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp, + u8 mode) +{ + u16 t, d; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + case TM_ACCESS: + SET16_A(ep->access_time, t); + SET16_A(ep->access_date, d); + break; + } +} + +s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry, + u32 type, u32 start_clu, u64 size) +{ + sector_t sector; + struct dos_dentry_t *dos_ep; + + dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!dos_ep) + return FFS_MEDIAERR; + + init_dos_entry(dos_ep, type, start_clu); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} + +s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, u32 type, u32 start_clu, u64 size) +{ + sector_t sector; + u8 flags; + struct file_dentry_t *file_ep; + struct strm_dentry_t *strm_ep; + + flags = (type == TYPE_FILE) ? 0x01 : 0x03; + + /* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */ + file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!file_ep) + return FFS_MEDIAERR; + + strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry+1, + §or); + if (!strm_ep) + return FFS_MEDIAERR; + + init_file_entry(file_ep, type); + buf_modify(sb, sector); + + init_strm_entry(strm_ep, flags, start_clu, size); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} + +static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname) +{ + int i; + sector_t sector; + u8 chksum; + u16 *uniname = p_uniname->name; + struct dos_dentry_t *dos_ep; + struct ext_dentry_t *ext_ep; + + dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!dos_ep) + return FFS_MEDIAERR; + + dos_ep->lcase = p_dosname->name_case; + memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH); + buf_modify(sb, sector); + + if ((--num_entries) > 0) { + chksum = calc_checksum_1byte((void *)dos_ep->name, + DOS_NAME_LENGTH, 0); + + for (i = 1; i < num_entries; i++) { + ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, + p_dir, + entry - i, + §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i, chksum, uniname); + buf_modify(sb, sector); + uniname += 13; + } + + ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, + entry - i, + §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i+0x40, chksum, uniname); + buf_modify(sb, sector); + } + + return FFS_SUCCESS; +} + +static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 num_entries, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname) +{ + int i; + sector_t sector; + u16 *uniname = p_uniname->name; + struct file_dentry_t *file_ep; + struct strm_dentry_t *strm_ep; + struct name_dentry_t *name_ep; + + file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!file_ep) + return FFS_MEDIAERR; + + file_ep->num_ext = (u8)(num_entries - 1); + buf_modify(sb, sector); + + strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry+1, + §or); + if (!strm_ep) + return FFS_MEDIAERR; + + strm_ep->name_len = p_uniname->name_len; + SET16_A(strm_ep->name_hash, p_uniname->name_hash); + buf_modify(sb, sector); + + for (i = 2; i < num_entries; i++) { + name_ep = (struct name_dentry_t *)get_entry_in_dir(sb, p_dir, + entry + i, + §or); + if (!name_ep) + return FFS_MEDIAERR; + + init_name_entry(name_ep, uniname); + buf_modify(sb, sector); + uniname += 15; + } + + update_dir_checksum(sb, p_dir, entry); + + return FFS_SUCCESS; +} + +void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu) +{ + struct timestamp_t tm, *tp; + + fat_set_entry_type((struct dentry_t *) ep, type); + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); + SET32_A(ep->size, 0); + + tp = tm_current(&tm); + fat_set_entry_time((struct dentry_t *) ep, tp, TM_CREATE); + fat_set_entry_time((struct dentry_t *) ep, tp, TM_MODIFY); + SET16_A(ep->access_date, 0); + ep->create_time_ms = 0; +} + +void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) +{ + int i; + u8 end = FALSE; + + fat_set_entry_type((struct dentry_t *) ep, TYPE_EXTEND); + ep->order = (u8) order; + ep->sysid = 0; + ep->checksum = chksum; + SET16_A(ep->start_clu, 0); + + for (i = 0; i < 10; i += 2) { + if (!end) { + SET16(ep->unicode_0_4+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16(ep->unicode_0_4+i, 0xFFFF); + } + } + + for (i = 0; i < 12; i += 2) { + if (!end) { + SET16_A(ep->unicode_5_10 + i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16_A(ep->unicode_5_10 + i, 0xFFFF); + } + } + + for (i = 0; i < 4; i += 2) { + if (!end) { + SET16_A(ep->unicode_11_12 + i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16_A(ep->unicode_11_12 + i, 0xFFFF); + } + } +} + +void init_file_entry(struct file_dentry_t *ep, u32 type) +{ + struct timestamp_t tm, *tp; + + exfat_set_entry_type((struct dentry_t *)ep, type); + + tp = tm_current(&tm); + exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE); + exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY); + exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS); + ep->create_time_ms = 0; + ep->modify_time_ms = 0; + ep->access_time_ms = 0; +} + +void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size) +{ + exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM); + ep->flags = flags; + SET32_A(ep->start_clu, start_clu); + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} + +void init_name_entry(struct name_dentry_t *ep, u16 *uniname) +{ + int i; + + exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND); + ep->flags = 0x0; + + for (i = 0; i < 30; i++, i++) { + SET16_A(ep->unicode_0_14+i, *uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} + +void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries) +{ + int i; + sector_t sector; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = num_entries-1; i >= order; i--) { + ep = get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} + +void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, + s32 entry, s32 order, s32 num_entries) +{ + int i; + sector_t sector; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = order; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry+i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} + +void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, + s32 entry) +{ + int i, num_entries; + sector_t sector; + u16 chksum; + struct file_dentry_t *file_ep; + struct dentry_t *ep; + + file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + §or); + if (!file_ep) + return; + + buf_lock(sb, sector); + + num_entries = (s32) file_ep->num_ext + 1; + chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0, + CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry+i, NULL); + if (!ep) { + buf_unlock(sb, sector); + return; + } + + chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum, + CS_DEFAULT); + } + + SET16_A(file_ep->checksum, chksum); + buf_modify(sb, sector); + buf_unlock(sb, sector); +} + +void update_dir_checksum_with_entry_set(struct super_block *sb, + struct entry_set_cache_t *es) +{ + struct dentry_t *ep; + u16 chksum = 0; + s32 chksum_type = CS_DIR_ENTRY, i; + + ep = (struct dentry_t *)&(es->__buf); + for (i = 0; i < es->num_entries; i++) { + pr_debug("%s ep %p\n", __func__, ep); + chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum, + chksum_type); + ep++; + chksum_type = CS_DEFAULT; + } + + ep = (struct dentry_t *)&(es->__buf); + SET16_A(((struct file_dentry_t *)ep)->checksum, chksum); + write_whole_entry_set(sb, es); +} + +static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir, + s32 byte_offset, u32 *clu) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + s32 clu_offset; + u32 cur_clu; + + clu_offset = byte_offset >> p_fs->cluster_size_bits; + cur_clu = p_dir->dir; + + if (p_dir->flags == 0x03) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (FAT_read(sb, cur_clu, &cur_clu) == -1) + return FFS_MEDIAERR; + clu_offset--; + } + } + + if (clu) + *clu = cur_clu; + return FFS_SUCCESS; +} + +s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry, + sector_t *sector, s32 *offset) +{ + s32 off, ret; + u32 clu = 0; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + off = entry << DENTRY_SIZE_BITS; + + if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + *offset = off & p_bd->sector_size_mask; + *sector = off >> p_bd->sector_size_bits; + *sector += p_fs->root_start_sector; + } else { + ret = _walk_fat_chain(sb, p_dir, off, &clu); + if (ret != FFS_SUCCESS) + return ret; + + /* byte offset in cluster */ + off &= p_fs->cluster_size - 1; + + /* byte offset in sector */ + *offset = off & p_bd->sector_size_mask; + + /* sector offset in cluster */ + *sector = off >> p_bd->sector_size_bits; + *sector += START_SECTOR(clu); + } + return FFS_SUCCESS; +} + +struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector, + s32 offset) +{ + u8 *buf; + + buf = buf_getblk(sb, sector); + + if (buf == NULL) + return NULL; + + return (struct dentry_t *)(buf + offset); +} + +struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, + s32 entry, sector_t *sector) +{ + s32 off; + sector_t sec; + u8 *buf; + + if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS) + return NULL; + + buf = buf_getblk(sb, sec); + + if (buf == NULL) + return NULL; + + if (sector != NULL) + *sector = sec; + return (struct dentry_t *)(buf + off); +} + +/* returns a set of dentries for a file or dir. + * Note that this is a copy (dump) of dentries so that user should call write_entry_set() + * to apply changes made in this entry set to the real device. + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ + +#define ES_MODE_STARTED 0 +#define ES_MODE_GET_FILE_ENTRY 1 +#define ES_MODE_GET_STRM_ENTRY 2 +#define ES_MODE_GET_NAME_ENTRY 3 +#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4 +struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u32 type, + struct dentry_t **file_ep) +{ + s32 off, ret, byte_offset; + u32 clu = 0; + sector_t sec; + u32 entry_type; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct entry_set_cache_t *es = NULL; + struct dentry_t *ep, *pos; + u8 *buf; + u8 num_entries; + s32 mode = ES_MODE_STARTED; + size_t bufsize; + + pr_debug("%s entered p_dir dir %u flags %x size %d\n", + __func__, p_dir->dir, p_dir->flags, p_dir->size); + + byte_offset = entry << DENTRY_SIZE_BITS; + ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return NULL; + + + /* byte offset in cluster */ + byte_offset &= p_fs->cluster_size - 1; + + /* byte offset in sector */ + off = byte_offset & p_bd->sector_size_mask; + + /* sector offset in cluster */ + sec = byte_offset >> p_bd->sector_size_bits; + sec += START_SECTOR(clu); + + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + + + ep = (struct dentry_t *)(buf + off); + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type != TYPE_FILE) + && (entry_type != TYPE_DIR)) + goto err_out; + + if (type == ES_ALL_ENTRIES) + num_entries = ((struct file_dentry_t *)ep)->num_ext+1; + else + num_entries = type; + + bufsize = offsetof(struct entry_set_cache_t, __buf) + (num_entries) * + sizeof(struct dentry_t); + pr_debug("%s: trying to kmalloc %zx bytes for %d entries\n", __func__, + bufsize, num_entries); + es = kmalloc(bufsize, GFP_KERNEL); + if (es == NULL) + goto err_out; + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = (struct dentry_t *) &(es->__buf); + + while (num_entries) { + /* + * instead of copying whole sector, we will check every entry. + * this will provide minimum stablity and consistancy. + */ + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) + goto err_out; + + switch (mode) { + case ES_MODE_STARTED: + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) + mode = ES_MODE_GET_FILE_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_FILE_ENTRY: + if (entry_type == TYPE_STREAM) + mode = ES_MODE_GET_STRM_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_STRM_ENTRY: + if (entry_type == TYPE_EXTEND) + mode = ES_MODE_GET_NAME_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_NAME_ENTRY: + if (entry_type == TYPE_EXTEND) + break; + else if (entry_type == TYPE_STREAM) + goto err_out; + else if (entry_type & TYPE_CRITICAL_SEC) + mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if ((entry_type == TYPE_EXTEND) || + (entry_type == TYPE_STREAM)) + goto err_out; + else if ((entry_type & TYPE_CRITICAL_SEC) != + TYPE_CRITICAL_SEC) + goto err_out; + break; + } + + memcpy(pos, ep, sizeof(struct dentry_t)); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & p_bd->sector_size_mask) < + (off & p_bd->sector_size_mask)) { + /* get the next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + off = 0; + ep = (struct dentry_t *)(buf); + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = (struct dentry_t *)&(es->__buf); + + pr_debug("%s exiting es %p sec %llu offset %d flags %d, num_entries %u buf ptr %p\n", + __func__, es, (unsigned long long)es->sector, es->offset, + es->alloc_flag, es->num_entries, &es->__buf); + return es; +err_out: + pr_debug("%s exited NULL (es %p)\n", __func__, es); + kfree(es); + return NULL; +} + +void release_entry_set(struct entry_set_cache_t *es) +{ + pr_debug("%s es=%p\n", __func__, es); + kfree(es); +} + + +static s32 __write_partial_entries_in_entry_set(struct super_block *sb, + struct entry_set_cache_t *es, + sector_t sec, s32 off, u32 count) +{ + s32 num_entries, buf_off = (off - es->offset); + u32 remaining_byte_in_sector, copy_entries; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + u32 clu; + u8 *buf, *esbuf = (u8 *)&(es->__buf); + + pr_debug("%s entered es %p sec %llu off %d count %d\n", + __func__, es, (unsigned long long)sec, off, count); + num_entries = count; + + while (num_entries) { + /* white per sector base */ + remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off; + copy_entries = min_t(s32, + remaining_byte_in_sector >> DENTRY_SIZE_BITS, + num_entries); + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off); + pr_debug("copying %d entries from %p to sector %llu\n", + copy_entries, (esbuf + buf_off), + (unsigned long long)sec); + memcpy(buf + off, esbuf + buf_off, + copy_entries << DENTRY_SIZE_BITS); + buf_modify(sb, sec); + num_entries -= copy_entries; + + if (num_entries) { + /* get next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + clu = GET_CLUSTER_FROM_SECTOR(sec); + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + off = 0; + buf_off += copy_entries << DENTRY_SIZE_BITS; + } + } + + pr_debug("%s exited successfully\n", __func__); + return FFS_SUCCESS; +err_out: + pr_debug("%s failed\n", __func__); + return FFS_ERROR; +} + +/* write back all entries in entry set */ +s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es) +{ + return __write_partial_entries_in_entry_set(sb, es, es->sector, + es->offset, + es->num_entries); +} + +/* write back some entries in entry set */ +s32 write_partial_entries_in_entry_set(struct super_block *sb, + struct entry_set_cache_t *es, struct dentry_t *ep, u32 count) +{ + s32 ret, byte_offset, off; + u32 clu = 0; + sector_t sec; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct chain_t dir; + + /* vaidity check */ + if (ep + count > ((struct dentry_t *)&(es->__buf)) + es->num_entries) + return FFS_ERROR; + + dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector); + dir.flags = es->alloc_flag; + dir.size = 0xffffffff; /* XXX */ + + byte_offset = (es->sector - START_SECTOR(dir.dir)) << + p_bd->sector_size_bits; + byte_offset += ((void **)ep - &(es->__buf)) + es->offset; + + ret = _walk_fat_chain(sb, &dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return ret; + + /* byte offset in cluster */ + byte_offset &= p_fs->cluster_size - 1; + + /* byte offset in sector */ + off = byte_offset & p_bd->sector_size_mask; + + /* sector offset in cluster */ + sec = byte_offset >> p_bd->sector_size_bits; + sec += START_SECTOR(clu); + return __write_partial_entries_in_entry_set(sb, es, sec, off, count); +} + +/* search EMPTY CONTINUOUS "num_entries" entries */ +s32 search_deleted_or_unused_entry(struct super_block *sb, + struct chain_t *p_dir, s32 num_entries) +{ + int i, dentry, num_empty = 0; + s32 dentries_per_clu; + u32 type; + struct chain_t clu; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + if (p_fs->hint_uentry.dir == p_dir->dir) { + if (p_fs->hint_uentry.entry == -1) + return -1; + + clu.dir = p_fs->hint_uentry.clu.dir; + clu.size = p_fs->hint_uentry.clu.size; + clu.flags = p_fs->hint_uentry.clu.flags; + + dentry = p_fs->hint_uentry.entry; + } else { + p_fs->hint_uentry.entry = -1; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + dentry = 0; + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for (; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) { + num_empty++; + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = dentry; + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + } else if (type == TYPE_DELETED) { + num_empty++; + } else { + num_empty = 0; + } + + if (num_empty >= num_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + + if (p_fs->vol_type == EXFAT) + return dentry - (num_entries-1); + else + return dentry; + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -1; + } + } + + return -1; +} + +s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries) +{ + s32 ret, dentry; + u32 last_clu; + sector_t sector; + u64 size = 0; + struct chain_t clu; + struct dentry_t *ep = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + return search_deleted_or_unused_entry(sb, p_dir, num_entries); + + while ((dentry = search_deleted_or_unused_entry(sb, p_dir, num_entries)) < 0) { + if (p_fs->dev_ejected) + break; + + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) + size = i_size_read(inode); + } + + last_clu = find_last_cluster(sb, p_dir); + clu.dir = last_clu + 1; + clu.size = 0; + clu.flags = p_dir->flags; + + /* (1) allocate a cluster */ + ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 1) + return -1; + + if (clear_cluster(sb, clu.dir) != FFS_SUCCESS) + return -1; + + /* (2) append to the FAT chain */ + if (clu.flags != p_dir->flags) { + exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = 0x01; + p_fs->hint_uentry.clu.flags = 0x01; + } + if (clu.flags == 0x01) + if (FAT_write(sb, last_clu, clu.dir) < 0) + return -1; + + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = p_dir->size << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = 0; + p_fs->hint_uentry.clu.flags = clu.flags; + } + p_fs->hint_uentry.clu.size++; + p_dir->size++; + + /* (3) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) { + size += p_fs->cluster_size; + + ep = get_entry_in_dir(sb, &fid->dir, + fid->entry + 1, §or); + if (!ep) + return -1; + p_fs->fs_func->set_entry_size(ep, size); + p_fs->fs_func->set_entry_flag(ep, p_dir->flags); + buf_modify(sb, sector); + + update_dir_checksum(sb, &(fid->dir), + fid->entry); + } + } + + i_size_write(inode, i_size_read(inode)+p_fs->cluster_size); + EXFAT_I(inode)->mmu_private += p_fs->cluster_size; + EXFAT_I(inode)->fid.size += p_fs->cluster_size; + EXFAT_I(inode)->fid.flags = p_dir->flags; + inode->i_blocks += 1 << (p_fs->cluster_size_bits - 9); + } + + return dentry; +} + +/* return values of fat_find_dir_entry() + * >= 0 : return dir entiry position with the name in dir + * -1 : (root dir, ".") it is the root dir itself + * -2 : entry with the name does not exist + */ +s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type) +{ + int i, dentry = 0, lossy = FALSE, len; + s32 order = 0, is_feasible_entry = TRUE, has_ext_entry = FALSE; + s32 dentries_per_clu; + u32 entry_type; + u16 entry_uniname[14], *uniname = NULL, unichar; + struct chain_t clu; + struct dentry_t *ep; + struct dos_dentry_t *dos_ep; + struct ext_dentry_t *ext_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + if ((type == TYPE_ALL) || (type == entry_type)) { + if (is_feasible_entry && has_ext_entry) + return dentry; + + dos_ep = (struct dos_dentry_t *) ep; + if ((!lossy) && (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name))) + return dentry; + } + is_feasible_entry = TRUE; + has_ext_entry = FALSE; + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + ext_ep = (struct ext_dentry_t *) ep; + if (ext_ep->order > 0x40) { + order = (s32)(ext_ep->order - 0x40); + uniname = p_uniname->name + 13 * (order-1); + } else { + order = (s32) ext_ep->order; + uniname -= 13; + } + + len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order); + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) + is_feasible_entry = FALSE; + + *(uniname+len) = unichar; + } + has_ext_entry = TRUE; + } else if (entry_type == TYPE_UNUSED) { + return -2; + } + is_feasible_entry = TRUE; + has_ext_entry = FALSE; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -2; + } + + return -2; +} + +/* return values of exfat_find_dir_entry() + * >= 0 : return dir entiry position with the name in dir + * -1 : (root dir, ".") it is the root dir itself + * -2 : entry with the name does not exist + */ +s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 num_entries, + struct dos_name_t *p_dosname, u32 type) +{ + int i = 0, dentry = 0, num_ext_entries = 0, len, step; + s32 order = 0, is_feasible_entry = FALSE; + s32 dentries_per_clu, num_empty = 0; + u32 entry_type; + u16 entry_uniname[16], *uniname = NULL, unichar; + struct chain_t clu; + struct dentry_t *ep; + struct file_dentry_t *file_ep; + struct strm_dentry_t *strm_ep; + struct name_dentry_t *name_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, + (u16 *)UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = -1; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + while (i < dentries_per_clu) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + step = 1; + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { + is_feasible_entry = FALSE; + + if (p_fs->hint_uentry.entry == -1) { + num_empty++; + + if (num_empty == 1) { + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED)) + p_fs->hint_uentry.entry = dentry - (num_empty-1); + } + + if (entry_type == TYPE_UNUSED) + return -2; + } else { + num_empty = 0; + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + file_ep = (struct file_dentry_t *) ep; + if ((type == TYPE_ALL) || (type == entry_type)) { + num_ext_entries = file_ep->num_ext; + is_feasible_entry = TRUE; + } else { + is_feasible_entry = FALSE; + step = file_ep->num_ext + 1; + } + } else if (entry_type == TYPE_STREAM) { + if (is_feasible_entry) { + strm_ep = (struct strm_dentry_t *)ep; + if (p_uniname->name_hash == GET16_A(strm_ep->name_hash) && + p_uniname->name_len == strm_ep->name_len) { + order = 1; + } else { + is_feasible_entry = FALSE; + step = num_ext_entries; + } + } + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + name_ep = (struct name_dentry_t *)ep; + + if ((++order) == 2) + uniname = p_uniname->name; + else + uniname += 15; + + len = extract_uni_name_from_name_entry(name_ep, + entry_uniname, order); + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) { + is_feasible_entry = FALSE; + step = num_ext_entries - order + 1; + } else if (order == num_ext_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + return dentry - (num_ext_entries); + } + + *(uniname+len) = unichar; + } + } else { + is_feasible_entry = FALSE; + } + } + + i += step; + dentry += step; + } + + i -= dentries_per_clu; + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -2; + } + } + + return -2; +} + +s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry) +{ + s32 count = 0; + u8 chksum; + struct dos_dentry_t *dos_ep = (struct dos_dentry_t *) p_entry; + struct ext_dentry_t *ext_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (entry--; entry >= 0; entry--) { + ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, + entry, NULL); + if (!ext_ep) + return -1; + + if ((p_fs->fs_func->get_entry_type((struct dentry_t *)ext_ep) == + TYPE_EXTEND) && (ext_ep->checksum == chksum)) { + count++; + if (ext_ep->order > 0x40) + return count; + } else { + return count; + } + } + + return count; +} + +s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, + s32 entry, struct dentry_t *p_entry) +{ + int i, count = 0; + u32 type; + struct file_dentry_t *file_ep = (struct file_dentry_t *)p_entry; + struct dentry_t *ext_ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { + ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ext_ep); + if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) + count++; + else + return count; + } + + return count; +} + +s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir, + u32 type) +{ + int i, count = 0; + s32 dentries_per_clu; + u32 entry_type; + struct chain_t clu; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_UNUSED) + return count; + if (!(type & TYPE_CRITICAL_PRI) && + !(type & TYPE_BENIGN_PRI)) + continue; + + if ((type == TYPE_ALL) || (type == entry_type)) + count++; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return -1; + } + } + + return count; +} + +bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir) +{ + int i, count = 0; + s32 dentries_per_clu; + u32 type; + struct chain_t clu; + struct dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + break; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + return TRUE; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + return FALSE; + + if (p_fs->vol_type == EXFAT) + return FALSE; + if ((p_dir->dir == p_fs->root_dir) || ((++count) > 2)) + return FALSE; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + break; + } + + return TRUE; +} + +/* + * Name Conversion Functions + */ + +/* input : dir, uni_name + * output : num_of_entry, dos_name(format : aaaaaa~1.bbb) + */ +s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct uni_name_t *p_uniname, s32 *entries, + struct dos_name_t *p_dosname) +{ + s32 ret, num_entries; + bool lossy = false; + char **r; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + num_entries = p_fs->fs_func->calc_num_entries(p_uniname); + if (num_entries == 0) + return FFS_INVALIDPATH; + + if (p_fs->vol_type != EXFAT) { + nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy); + + if (lossy) { + ret = fat_generate_dos_name(sb, p_dir, p_dosname); + if (ret) + return ret; + } else { + for (r = reserved_names; *r; r++) { + if (!strncmp((void *)p_dosname->name, *r, 8)) + return FFS_INVALIDPATH; + } + + if (p_dosname->name_case != 0xFF) + num_entries = 1; + } + + if (num_entries > 1) + p_dosname->name_case = 0x0; + } + + *entries = num_entries; + + return FFS_SUCCESS; +} + +void get_uni_name_from_dos_entry(struct super_block *sb, + struct dos_dentry_t *ep, + struct uni_name_t *p_uniname, u8 mode) +{ + struct dos_name_t dos_name; + + if (mode == 0x0) + dos_name.name_case = 0x0; + else + dos_name.name_case = ep->lcase; + + memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH); + nls_dosname_to_uniname(sb, p_uniname, &dos_name); +} + +void fat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname) +{ + int i; + struct ext_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (entry--, i = 1; entry >= 0; entry--, i++) { + ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, entry, + NULL); + if (!ep) + return; + + if (p_fs->fs_func->get_entry_type((struct dentry_t *)ep) == + TYPE_EXTEND) { + extract_uni_name_from_ext_entry(ep, uniname, i); + if (ep->order > 0x40) + return; + } else { + return; + } + + uniname += 13; + } +} + +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, + struct chain_t *p_dir, s32 entry, + u16 *uniname) +{ + int i; + struct dentry_t *ep; + struct entry_set_cache_t *es; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (es == NULL || es->num_entries < 3) { + if (es) + release_entry_set(es); + return; + } + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND) + extract_uni_name_from_name_entry((struct name_dentry_t *) + ep, uniname, i); + else + goto out; + uniname += 15; + } + +out: + release_entry_set(es); +} + +s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, u16 *uniname, + s32 order) +{ + int i, len = 0; + + for (i = 0; i < 10; i += 2) { + *uniname = GET16(ep->unicode_0_4 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + if (order < 20) { + for (i = 0; i < 12; i += 2) { + *uniname = GET16_A(ep->unicode_5_10 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + } else { + for (i = 0; i < 8; i += 2) { + *uniname = GET16_A(ep->unicode_5_10 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + *uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */ + return len; + } + + for (i = 0; i < 4; i += 2) { + *uniname = GET16_A(ep->unicode_11_12 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; +} + +s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname, + s32 order) +{ + int i, len = 0; + + for (i = 0; i < 30; i += 2) { + *uniname = GET16_A(ep->unicode_0_14 + i); + if (*uniname == 0x0) + return len; + uniname++; + len++; + } + + *uniname = 0x0; + return len; +} + +s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, + struct dos_name_t *p_dosname) +{ + int i, j, count = 0, count_begin = FALSE; + s32 dentries_per_clu; + u32 type; + u8 bmap[128/* 1 ~ 1023 */]; + struct chain_t clu; + struct dos_dentry_t *ep; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + memset(bmap, 0, sizeof(bmap)); + exfat_bitmap_set(bmap, 0); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = (struct dos_dentry_t *)get_entry_in_dir(sb, &clu, + i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((struct dentry_t *) + ep); + + if (type == TYPE_UNUSED) + break; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + count = 0; + count_begin = FALSE; + + for (j = 0; j < 8; j++) { + if (ep->name[j] == ' ') + break; + + if (ep->name[j] == '~') { + count_begin = TRUE; + } else if (count_begin) { + if ((ep->name[j] >= '0') && + (ep->name[j] <= '9')) { + count = count * 10 + + (ep->name[j] - '0'); + } else { + count = 0; + count_begin = FALSE; + } + } + } + + if ((count > 0) && (count < 1024)) + exfat_bitmap_set(bmap, count); + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &clu.dir) != 0) + return FFS_MEDIAERR; + } + + count = 0; + for (i = 0; i < 128; i++) { + if (bmap[i] != 0xFF) { + for (j = 0; j < 8; j++) { + if (exfat_bitmap_test(&bmap[i], j) == 0) { + count = (i << 3) + j; + break; + } + } + if (count != 0) + break; + } + } + + if ((count == 0) || (count >= 1024)) + return FFS_FILEEXIST; + fat_attach_count_to_dos_name(p_dosname->name, count); + + /* Now dos_name has DOS~????.EXT */ + return FFS_SUCCESS; +} + +void fat_attach_count_to_dos_name(u8 *dosname, s32 count) +{ + int i, j, length; + char str_count[6]; + + snprintf(str_count, sizeof(str_count), "~%d", count); + length = strlen(str_count); + + i = 0; + j = 0; + while (j <= (8 - length)) { + i = j; + if (dosname[j] == ' ') + break; + if (dosname[j] & 0x80) + j += 2; + else + j++; + } + + for (j = 0; j < length; i++, j++) + dosname[i] = (u8)str_count[j]; + + if (i == 7) + dosname[7] = ' '; +} + +s32 fat_calc_num_entries(struct uni_name_t *p_uniname) +{ + s32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 dos name entry + extended entries */ + return (len - 1) / 13 + 2; +} + +s32 exfat_calc_num_entries(struct uni_name_t *p_uniname) +{ + s32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 file entry + 1 stream entry + name entries */ + return (len - 1) / 15 + 3; +} + +u8 calc_checksum_1byte(void *data, s32 len, u8 chksum) +{ + int i; + u8 *c = (u8 *)data; + + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c; + + return chksum; +} + +u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type) +{ + int i; + u8 *c = (u8 *)data; + + switch (type) { + case CS_DIR_ENTRY: + for (i = 0; i < len; i++, c++) { + if ((i == 2) || (i == 3)) + continue; + chksum = (((chksum & 1) << 15) | + ((chksum & 0xFFFE) >> 1)) + (u16)*c; + } + break; + default + : + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 15) | + ((chksum & 0xFFFE) >> 1)) + (u16)*c; + } + + return chksum; +} + +u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type) +{ + int i; + u8 *c = (u8 *)data; + + switch (type) { + case CS_PBR_SECTOR: + for (i = 0; i < len; i++, c++) { + if ((i == 106) || (i == 107) || (i == 112)) + continue; + chksum = (((chksum & 1) << 31) | + ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c; + } + break; + default + : + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 31) | + ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c; + } + + return chksum; +} + +/* + * Name Resolution Functions + */ + +/* return values of resolve_path() + * > 0 : return the length of the path + * < 0 : return error + */ +s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, + struct uni_name_t *p_uniname) +{ + bool lossy = false; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + if (strlen(path) >= (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + return FFS_INVALIDPATH; + + strcpy(name_buf, path); + + nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy); + if (lossy) + return FFS_INVALIDPATH; + + fid->size = i_size_read(inode); + + p_dir->dir = fid->start_clu; + p_dir->size = (s32)(fid->size >> p_fs->cluster_size_bits); + p_dir->flags = fid->flags; + + return FFS_SUCCESS; +} + +/* + * File Operation Functions + */ +static struct fs_func fat_fs_func = { + .alloc_cluster = fat_alloc_cluster, + .free_cluster = fat_free_cluster, + .count_used_clusters = fat_count_used_clusters, + + .init_dir_entry = fat_init_dir_entry, + .init_ext_entry = fat_init_ext_entry, + .find_dir_entry = fat_find_dir_entry, + .delete_dir_entry = fat_delete_dir_entry, + .get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry, + .count_ext_entries = fat_count_ext_entries, + .calc_num_entries = fat_calc_num_entries, + + .get_entry_type = fat_get_entry_type, + .set_entry_type = fat_set_entry_type, + .get_entry_attr = fat_get_entry_attr, + .set_entry_attr = fat_set_entry_attr, + .get_entry_flag = fat_get_entry_flag, + .set_entry_flag = fat_set_entry_flag, + .get_entry_clu0 = fat_get_entry_clu0, + .set_entry_clu0 = fat_set_entry_clu0, + .get_entry_size = fat_get_entry_size, + .set_entry_size = fat_set_entry_size, + .get_entry_time = fat_get_entry_time, + .set_entry_time = fat_set_entry_time, +}; + +s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) +{ + s32 num_reserved, num_root_sectors; + struct bpb16_t *p_bpb = (struct bpb16_t *)p_pbr->bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS; + num_root_sectors = ((num_root_sectors - 1) >> + p_bd->sector_size_bits) + 1; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors; + + p_fs->num_sectors = GET16(p_bpb->num_sectors); + if (p_fs->num_sectors == 0) + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >> + p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + if (p_fs->num_clusters < FAT12_THRESHOLD) + p_fs->vol_type = FAT12; + else + p_fs->vol_type = FAT16; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = 0; + p_fs->dentries_in_root = GET16(p_bpb->num_root_entries); + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - + DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (u32)~0; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} + +s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) +{ + s32 num_reserved; + struct bpb32_t *p_bpb = (struct bpb32_t *)p_pbr->bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + + p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >> + p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = FAT32; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - + DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (u32)~0; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} + +static struct fs_func exfat_fs_func = { + .alloc_cluster = exfat_alloc_cluster, + .free_cluster = exfat_free_cluster, + .count_used_clusters = exfat_count_used_clusters, + + .init_dir_entry = exfat_init_dir_entry, + .init_ext_entry = exfat_init_ext_entry, + .find_dir_entry = exfat_find_dir_entry, + .delete_dir_entry = exfat_delete_dir_entry, + .get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry, + .count_ext_entries = exfat_count_ext_entries, + .calc_num_entries = exfat_calc_num_entries, + + .get_entry_type = exfat_get_entry_type, + .set_entry_type = exfat_set_entry_type, + .get_entry_attr = exfat_get_entry_attr, + .set_entry_attr = exfat_set_entry_attr, + .get_entry_flag = exfat_get_entry_flag, + .set_entry_flag = exfat_set_entry_flag, + .get_entry_clu0 = exfat_get_entry_clu0, + .set_entry_clu0 = exfat_set_entry_clu0, + .get_entry_size = exfat_get_entry_size, + .set_entry_size = exfat_set_entry_size, + .get_entry_time = exfat_get_entry_time, + .set_entry_time = exfat_set_entry_time, +}; + +s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) +{ + struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits; + p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits; + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->fat_length); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset); + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET64(p_bpb->vol_length); + p_fs->num_clusters = GET32(p_bpb->clu_count) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = EXFAT; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - + DENTRY_SIZE_BITS); + + p_fs->vol_flag = (u32)GET16(p_bpb->vol_flags); + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (u32)~0; + + p_fs->fs_func = &exfat_fs_func; + + return FFS_SUCCESS; +} + +s32 create_dir(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, struct file_id_t *fid) +{ + s32 ret, dentry, num_entries; + u64 size; + struct chain_t clu; + struct dos_name_t dos_name, dot_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, + &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + clu.dir = CLUSTER_32(~0); + clu.size = 0; + clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + + /* (1) allocate a cluster */ + ret = fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 0) + return FFS_MEDIAERR; + else if (ret == 0) + return FFS_FULL; + + ret = clear_cluster(sb, clu.dir); + if (ret != FFS_SUCCESS) + return ret; + + if (p_fs->vol_type == EXFAT) { + size = p_fs->cluster_size; + } else { + size = 0; + + /* initialize the . and .. entry + * Information for . points to itself + * Information for .. points to parent dir + */ + + dot_name.name_case = 0x0; + memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH); + + ret = fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir, + 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name); + if (ret != FFS_SUCCESS) + return ret; + + memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH); + + if (p_dir->dir == p_fs->root_dir) + ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, + CLUSTER_32(0), 0); + else + ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, + p_dir->dir, 0); + + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL, + &dot_name); + if (ret != FFS_SUCCESS) + return ret; + } + + /* (2) update the directory entry */ + /* make sub-dir entry in parent directory */ + ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, + size); + if (ret != FFS_SUCCESS) + return ret; + + ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_SUBDIR; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = size; + fid->start_clu = clu.dir; + + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} + +s32 create_file(struct inode *inode, struct chain_t *p_dir, + struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid) +{ + s32 ret, dentry, num_entries; + struct dos_name_t dos_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, + &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster() */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + /* (1) update the directory entry */ + /* fill the dos name directory entry information of the created file. + * the first cluster is not determined yet. (0) + */ + ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, + CLUSTER_32(0), 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_ARCHIVE | mode; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + + fid->type = TYPE_FILE; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} + +void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry) +{ + s32 num_entries; + sector_t sector; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + ep = get_entry_in_dir(sb, p_dir, entry, §or); + if (!ep) + return; + + buf_lock(sb, sector); + + /* buf_lock() before call count_ext_entries() */ + num_entries = fs_func->count_ext_entries(sb, p_dir, entry, ep); + if (num_entries < 0) { + buf_unlock(sb, sector); + return; + } + num_entries++; + + buf_unlock(sb, sector); + + /* (1) update the directory entry */ + fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries); +} + +s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry, + struct uni_name_t *p_uniname, struct file_id_t *fid) +{ + s32 ret, newentry = -1, num_old_entries, num_new_entries; + sector_t sector_old, sector_new; + struct dos_name_t dos_name; + struct dentry_t *epold, *epnew; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old); + if (!epold) + return FFS_MEDIAERR; + + buf_lock(sb, sector_old); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = fs_func->count_ext_entries(sb, p_dir, oldentry, + epold); + if (num_old_entries < 0) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, + &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_old); + return ret; + } + + if (num_old_entries < num_new_entries) { + newentry = find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_old); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epold, DENTRY_SIZE); + if (fs_func->get_entry_type(epnew) == TYPE_FILE) { + fs_func->set_entry_attr(epnew, + fs_func->get_entry_attr(epnew) | + ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + + if (p_fs->vol_type == EXFAT) { + epold = get_entry_in_dir(sb, p_dir, oldentry + 1, + §or_old); + buf_lock(sb, sector_old); + epnew = get_entry_in_dir(sb, p_dir, newentry + 1, + §or_new); + + if (!epold || !epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epold, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + } + + ret = fs_func->init_ext_entry(sb, p_dir, newentry, + num_new_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, + num_old_entries); + fid->entry = newentry; + } else { + if (fs_func->get_entry_type(epold) == TYPE_FILE) { + fs_func->set_entry_attr(epold, + fs_func->get_entry_attr(epold) | + ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_old); + buf_unlock(sb, sector_old); + + ret = fs_func->init_ext_entry(sb, p_dir, oldentry, + num_new_entries, p_uniname, + &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, + num_old_entries); + } + + return FFS_SUCCESS; +} + +s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry, + struct chain_t *p_newdir, struct uni_name_t *p_uniname, + struct file_id_t *fid) +{ + s32 ret, newentry, num_new_entries, num_old_entries; + sector_t sector_mov, sector_new; + struct chain_t clu; + struct dos_name_t dos_name; + struct dentry_t *epmov, *epnew; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + + epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov); + if (!epmov) + return FFS_MEDIAERR; + + /* check if the source and target directory is the same */ + if (fs_func->get_entry_type(epmov) == TYPE_DIR && + fs_func->get_entry_clu0(epmov) == p_newdir->dir) + return FFS_INVALIDPATH; + + buf_lock(sb, sector_mov); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = fs_func->count_ext_entries(sb, p_olddir, oldentry, + epmov); + if (num_old_entries < 0) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname, + &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_mov); + return ret; + } + + newentry = find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_mov); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE); + if (fs_func->get_entry_type(epnew) == TYPE_FILE) { + fs_func->set_entry_attr(epnew, fs_func->get_entry_attr(epnew) | + ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + + if (p_fs->vol_type == EXFAT) { + epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1, + §or_mov); + buf_lock(sb, sector_mov); + epnew = get_entry_in_dir(sb, p_newdir, newentry + 1, + §or_new); + if (!epmov || !epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + } else if (fs_func->get_entry_type(epnew) == TYPE_DIR) { + /* change ".." pointer to new parent dir */ + clu.dir = fs_func->get_entry_clu0(epnew); + clu.flags = 0x01; + + epnew = get_entry_in_dir(sb, &clu, 1, §or_new); + if (!epnew) + return FFS_MEDIAERR; + + if (p_newdir->dir == p_fs->root_dir) + fs_func->set_entry_clu0(epnew, CLUSTER_32(0)); + else + fs_func->set_entry_clu0(epnew, p_newdir->dir); + buf_modify(sb, sector_new); + } + + ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, + p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); + + fid->dir.dir = p_newdir->dir; + fid->dir.size = p_newdir->size; + fid->dir.flags = p_newdir->flags; + + fid->entry = newentry; + + return FFS_SUCCESS; +} + +/* + * Sector Read/Write Functions + */ + +int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, + bool read) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n", + __func__, (unsigned long long)sec); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, 1, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} + +int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, + bool sync) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu)\n", + __func__, (unsigned long long)sec); + fs_error(sb); + return ret; + } + + if (!bh) { + pr_err("[EXFAT] %s: bh is NULL!\n", __func__); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, 1, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} + +int multi_sector_read(struct super_block *sb, sector_t sec, + struct buffer_head **bh, s32 num_secs, bool read) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n", + __func__, (unsigned long long)sec, num_secs); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, num_secs, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} + +int multi_sector_write(struct super_block *sb, sector_t sec, + struct buffer_head *bh, s32 num_secs, bool sync) +{ + s32 ret = FFS_MEDIAERR; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) && + (p_fs->num_sectors > 0)) { + pr_err("[EXFAT] %s: out of range error! (sec = %llu, num_secs = %d)\n", + __func__, (unsigned long long)sec, num_secs); + fs_error(sb); + return ret; + } + if (!bh) { + pr_err("[EXFAT] %s: bh is NULL!\n", __func__); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, num_secs, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c new file mode 100644 index 000000000000..2ca58616159b --- /dev/null +++ b/drivers/staging/exfat/exfat_nls.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include "exfat.h" + +static u16 bad_dos_chars[] = { + /* + , ; = [ ] */ + 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D, + 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D, + 0 +}; + +static u16 bad_uni_chars[] = { + /* " * / : < > ? \ | */ + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, + 0 +}; + +static int convert_ch_to_uni(struct nls_table *nls, u16 *uni, u8 *ch, + bool *lossy) +{ + int len; + + *uni = 0x0; + + if (ch[0] < 0x80) { + *uni = (u16)ch[0]; + return 1; + } + + len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni); + if (len < 0) { + /* conversion failed */ + pr_info("%s: fail to use nls\n", __func__); + if (lossy) + *lossy = true; + *uni = (u16)'_'; + if (!strcmp(nls->charset, "utf8")) + return 1; + else + return 2; + } + + return len; +} + +static int convert_uni_to_ch(struct nls_table *nls, u8 *ch, u16 uni, + bool *lossy) +{ + int len; + + ch[0] = 0x0; + + if (uni < 0x0080) { + ch[0] = (u8)uni; + return 1; + } + + len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE); + if (len < 0) { + /* conversion failed */ + pr_info("%s: fail to use nls\n", __func__); + if (lossy) + *lossy = true; + ch[0] = '_'; + return 1; + } + + return len; +} + +u16 nls_upper(struct super_block *sb, u16 a) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (EXFAT_SB(sb)->options.casesensitive) + return a; + if (p_fs->vol_utbl && p_fs->vol_utbl[get_col_index(a)]) + return p_fs->vol_utbl[get_col_index(a)][get_row_index(a)]; + else + return a; +} + +static u16 *nls_wstrchr(u16 *str, u16 wchar) +{ + while (*str) { + if (*(str++) == wchar) + return str; + } + + return NULL; +} + +int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b) +{ + return strncmp(a, b, DOS_NAME_LENGTH); +} + +int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b) +{ + int i; + + for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { + if (nls_upper(sb, *a) != nls_upper(sb, *b)) + return 1; + if (*a == 0x0) + return 0; + } + return 0; +} + +void nls_uniname_to_dosname(struct super_block *sb, + struct dos_name_t *p_dosname, + struct uni_name_t *p_uniname, bool *p_lossy) +{ + int i, j, len; + bool lossy = false; + u8 buf[MAX_CHARSET_SIZE]; + u8 lower = 0, upper = 0; + u8 *dosname = p_dosname->name; + u16 *uniname = p_uniname->name; + u16 *p, *last_period; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + for (i = 0; i < DOS_NAME_LENGTH; i++) + *(dosname + i) = ' '; + + if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_CUR_DIR_NAME)) { + *(dosname) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy) + *p_lossy = false; + return; + } + + if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_PAR_DIR_NAME)) { + *(dosname) = '.'; + *(dosname + 1) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy) + *p_lossy = false; + return; + } + + /* search for the last embedded period */ + last_period = NULL; + for (p = uniname; *p; p++) { + if (*p == (u16)'.') + last_period = p; + } + + i = 0; + while (i < DOS_NAME_LENGTH) { + if (i == 8) { + if (!last_period) + break; + + if (uniname <= last_period) { + if (uniname < last_period) + lossy = true; + uniname = last_period + 1; + } + } + + if (*uniname == (u16)'\0') { + break; + } else if (*uniname == (u16)' ') { + lossy = true; + } else if (*uniname == (u16)'.') { + if (uniname < last_period) + lossy = true; + else + i = 8; + } else if (nls_wstrchr(bad_dos_chars, *uniname)) { + lossy = true; + *(dosname + i) = '_'; + i++; + } else { + len = convert_uni_to_ch(nls, buf, *uniname, &lossy); + + if (len > 1) { + if ((i >= 8) && ((i + len) > DOS_NAME_LENGTH)) + break; + + if ((i < 8) && ((i + len) > 8)) { + i = 8; + continue; + } + + lower = 0xFF; + + for (j = 0; j < len; j++, i++) + *(dosname + i) = *(buf + j); + } else { /* len == 1 */ + if ((*buf >= 'a') && (*buf <= 'z')) { + *(dosname + i) = *buf - ('a' - 'A'); + + if (i < 8) + lower |= 0x08; + else + lower |= 0x10; + } else if ((*buf >= 'A') && (*buf <= 'Z')) { + *(dosname + i) = *buf; + + if (i < 8) + upper |= 0x08; + else + upper |= 0x10; + } else { + *(dosname + i) = *buf; + } + i++; + } + } + + uniname++; + } + + if (*dosname == 0xE5) + *dosname = 0x05; + + if (*uniname != 0x0) + lossy = TRUE; + + if (upper & lower) + p_dosname->name_case = 0xFF; + else + p_dosname->name_case = lower; + + if (p_lossy) + *p_lossy = lossy; +} + +void nls_dosname_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, + struct dos_name_t *p_dosname) +{ + int i = 0, j, n = 0; + u8 buf[DOS_NAME_LENGTH + 2]; + u8 *dosname = p_dosname->name; + u16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + if (*dosname == 0x05) { + *buf = 0xE5; + i++; + n++; + } + + for (; i < 8; i++, n++) { + if (*(dosname + i) == ' ') + break; + + if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') && + (p_dosname->name_case & 0x08)) + *(buf + n) = *(dosname + i) + ('a' - 'A'); + else + *(buf + n) = *(dosname + i); + } + if (*(dosname + 8) != ' ') { + *(buf + n) = '.'; + n++; + } + + for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { + if (*(dosname + i) == ' ') + break; + + if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') && + (p_dosname->name_case & 0x10)) + *(buf + n) = *(dosname + i) + ('a' - 'A'); + else + *(buf + n) = *(dosname + i); + } + *(buf + n) = '\0'; + + i = 0; + j = 0; + while (j < (MAX_NAME_LENGTH - 1)) { + if (*(buf + i) == '\0') + break; + + i += convert_ch_to_uni(nls, uniname, (buf + i), NULL); + + uniname++; + j++; + } + + *uniname = (u16)'\0'; +} + +void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, + struct uni_name_t *p_uniname) +{ + int i, j, len; + u8 buf[MAX_CHARSET_SIZE]; + u16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + if (!nls) { + len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, + UTF16_HOST_ENDIAN, p_cstring, + MAX_NAME_LENGTH); + p_cstring[len] = 0; + return; + } + + i = 0; + while (i < (MAX_NAME_LENGTH - 1)) { + if (*uniname == (u16)'\0') + break; + + len = convert_uni_to_ch(nls, buf, *uniname, NULL); + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = (char)*(buf + j); + } else { /* len == 1 */ + *p_cstring++ = (char)*buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; +} + +void nls_cstring_to_uniname(struct super_block *sb, + struct uni_name_t *p_uniname, u8 *p_cstring, + bool *p_lossy) +{ + int i, j; + bool lossy = false; + u8 *end_of_name; + u8 upname[MAX_NAME_LENGTH * 2]; + u16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + /* strip all trailing spaces */ + end_of_name = p_cstring + strlen(p_cstring); + + while (*(--end_of_name) == ' ') { + if (end_of_name < p_cstring) + break; + } + *(++end_of_name) = '\0'; + + if (strcmp(p_cstring, ".") && strcmp(p_cstring, "..")) { + /* strip all trailing periods */ + while (*(--end_of_name) == '.') { + if (end_of_name < p_cstring) + break; + } + *(++end_of_name) = '\0'; + } + + if (*p_cstring == '\0') + lossy = true; + + if (!nls) { + i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH, + UTF16_HOST_ENDIAN, uniname, + MAX_NAME_LENGTH); + for (j = 0; j < i; j++) + SET16_A(upname + j * 2, nls_upper(sb, uniname[j])); + uniname[i] = '\0'; + } else { + i = 0; + j = 0; + while (j < (MAX_NAME_LENGTH - 1)) { + if (*(p_cstring + i) == '\0') + break; + + i += convert_ch_to_uni(nls, uniname, + (u8 *)(p_cstring + i), &lossy); + + if ((*uniname < 0x0020) || + nls_wstrchr(bad_uni_chars, *uniname)) + lossy = true; + + SET16_A(upname + j * 2, nls_upper(sb, *uniname)); + + uniname++; + j++; + } + + if (*(p_cstring + i) != '\0') + lossy = true; + *uniname = (u16)'\0'; + } + + p_uniname->name_len = j; + p_uniname->name_hash = calc_checksum_2byte(upname, j << 1, 0, + CS_DEFAULT); + + if (p_lossy) + *p_lossy = lossy; +} diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c new file mode 100644 index 000000000000..5b5c2ca8c9aa --- /dev/null +++ b/drivers/staging/exfat/exfat_super.c @@ -0,0 +1,4137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define EXFAT_VERSION "1.3.0" + +#include "exfat.h" + +static struct kmem_cache *exfat_inode_cachep; + +// FIXME use commented lines +// static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; +// static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; +static int exfat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; +static char exfat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; + +#define INC_IVERSION(x) (inode_inc_iversion(x)) +#define GET_IVERSION(x) (inode_peek_iversion_raw(x)) +#define SET_IVERSION(x, y) (inode_set_iversion(x, y)) + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); +static int exfat_sync_inode(struct inode *inode); +static struct inode *exfat_build_inode(struct super_block *sb, + struct file_id_t *fid, loff_t i_pos); +static int exfat_write_inode(struct inode *inode, + struct writeback_control *wbc); +static void exfat_write_super(struct super_block *sb); + +#define UNIX_SECS_1980 315532800L + +#if BITS_PER_LONG == 64 +#define UNIX_SECS_2108 4354819200L +#endif + +/* days between 1.1.70 and 1.1.80 (2 leap days) */ +#define DAYS_DELTA_DECADE (365 * 10 + 2) +/* 120 (2100 - 1980) isn't leap year */ +#define NO_LEAP_YEAR_2100 (120) +#define IS_LEAP_YEAR(y) (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +#define MAKE_LEAP_YEAR(leap_year, year) \ + do { \ + if (unlikely(year > NO_LEAP_YEAR_2100)) \ + leap_year = ((year + 3) / 4) - 1; \ + else \ + leap_year = ((year + 3) / 4); \ + } while (0) + +/* Linear day numbers of the respective 1sts in non-leap years. */ +static time_t accum_days_in_year[] = { + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, +}; + +/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ +static void exfat_time_fat2unix(struct exfat_sb_info *sbi, + struct timespec64 *ts, struct date_time_t *tp) +{ + time_t year = tp->Year; + time_t ld; + + MAKE_LEAP_YEAR(ld, year); + + if (IS_LEAP_YEAR(year) && (tp->Month) > 2) + ld++; + + ts->tv_sec = tp->Second + + tp->Minute * SECS_PER_MIN + + tp->Hour * SECS_PER_HOUR + + (ld + accum_days_in_year[(tp->Month)] + + (tp->Day - 1)) * SECS_PER_DAY + + (year * 365 + DAYS_DELTA_DECADE) * SECS_PER_DAY + + sys_tz.tz_minuteswest * SECS_PER_MIN; + + ts->tv_nsec = 0; +} + +/* Convert linear UNIX date to a FAT time/date pair. */ +static void exfat_time_unix2fat(struct exfat_sb_info *sbi, + struct timespec64 *ts, struct date_time_t *tp) +{ + time_t second = ts->tv_sec; + time_t day, month, year; + time_t ld; + + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->Second = 0; + tp->Minute = 0; + tp->Hour = 0; + tp->Day = 1; + tp->Month = 1; + tp->Year = 0; + return; + } +#if (BITS_PER_LONG == 64) + if (second >= UNIX_SECS_2108) { + tp->Second = 59; + tp->Minute = 59; + tp->Hour = 23; + tp->Day = 31; + tp->Month = 12; + tp->Year = 127; + return; + } +#endif + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + MAKE_LEAP_YEAR(ld, year); + if (year * 365 + ld > day) + year--; + + MAKE_LEAP_YEAR(ld, year); + day -= year * 365 + ld; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->Second = second % SECS_PER_MIN; + tp->Minute = (second / SECS_PER_MIN) % 60; + tp->Hour = (second / SECS_PER_HOUR) % 24; + tp->Day = day + 1; + tp->Month = month; + tp->Year = year; +} + +struct timestamp_t *tm_current(struct timestamp_t *tp) +{ + struct timespec64 ts; + time_t second, day, leap_day, month, year; + + ktime_get_real_ts64(&ts); + + second = ts.tv_sec; + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->sec = 0; + tp->min = 0; + tp->hour = 0; + tp->day = 1; + tp->mon = 1; + tp->year = 0; + return tp; + } +#if BITS_PER_LONG == 64 + if (second >= UNIX_SECS_2108) { + tp->sec = 59; + tp->min = 59; + tp->hour = 23; + tp->day = 31; + tp->mon = 12; + tp->year = 127; + return tp; + } +#endif + + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + + MAKE_LEAP_YEAR(leap_day, year); + if (year * 365 + leap_day > day) + year--; + + MAKE_LEAP_YEAR(leap_day, year); + + day -= year * 365 + leap_day; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->sec = second % SECS_PER_MIN; + tp->min = (second / SECS_PER_MIN) % 60; + tp->hour = (second / SECS_PER_HOUR) % 24; + tp->day = day + 1; + tp->mon = month; + tp->year = year; + + return tp; +} + +static void __lock_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + mutex_lock(&sbi->s_lock); +} + +static void __unlock_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + mutex_unlock(&sbi->s_lock); +} + +static int __is_sb_dirty(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + return sbi->s_dirt; +} + +static void __set_sb_clean(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + sbi->s_dirt = 0; +} + +static int __exfat_revalidate(struct dentry *dentry) +{ + return 0; +} + +static int exfat_revalidate(struct dentry *dentry, unsigned int flags) +{ + if (flags & LOOKUP_RCU) + return -ECHILD; + + if (dentry->d_inode) + return 1; + return __exfat_revalidate(dentry); +} + +static int exfat_revalidate_ci(struct dentry *dentry, unsigned int flags) +{ + if (flags & LOOKUP_RCU) + return -ECHILD; + + if (dentry->d_inode) + return 1; + + if (!flags) + return 0; + + if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) + return 0; + + return __exfat_revalidate(dentry); +} + +static unsigned int __exfat_striptail_len(unsigned int len, const char *name) +{ + while (len && name[len - 1] == '.') + len--; + return len; +} + +static unsigned int exfat_striptail_len(const struct qstr *qstr) +{ + return __exfat_striptail_len(qstr->len, qstr->name); +} + +static int exfat_d_hash(const struct dentry *dentry, struct qstr *qstr) +{ + qstr->hash = full_name_hash(dentry, qstr->name, + exfat_striptail_len(qstr)); + return 0; +} + +static int exfat_d_hashi(const struct dentry *dentry, struct qstr *qstr) +{ + struct super_block *sb = dentry->d_sb; + const unsigned char *name; + unsigned int len; + unsigned long hash; + + name = qstr->name; + len = exfat_striptail_len(qstr); + + hash = init_name_hash(dentry); + while (len--) + hash = partial_name_hash(nls_upper(sb, *name++), hash); + qstr->hash = end_name_hash(hash); + + return 0; +} + +static int exfat_cmpi(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + struct nls_table *t = EXFAT_SB(dentry->d_sb)->nls_io; + unsigned int alen, blen; + + alen = exfat_striptail_len(name); + blen = __exfat_striptail_len(len, str); + if (alen == blen) { + if (t == NULL) { + if (strncasecmp(name->name, str, alen) == 0) + return 0; + } else if (nls_strnicmp(t, name->name, str, alen) == 0) + return 0; + } + return 1; +} + +static int exfat_cmp(const struct dentry *dentry, unsigned int len, + const char *str, const struct qstr *name) +{ + unsigned int alen, blen; + + alen = exfat_striptail_len(name); + blen = __exfat_striptail_len(len, str); + if (alen == blen) { + if (strncmp(name->name, str, alen) == 0) + return 0; + } + return 1; +} + +static const struct dentry_operations exfat_ci_dentry_ops = { + .d_revalidate = exfat_revalidate_ci, + .d_hash = exfat_d_hashi, + .d_compare = exfat_cmpi, +}; + +static const struct dentry_operations exfat_dentry_ops = { + .d_revalidate = exfat_revalidate, + .d_hash = exfat_d_hash, + .d_compare = exfat_cmp, +}; + +static DEFINE_SEMAPHORE(z_sem); + +static inline void fs_sync(struct super_block *sb, bool do_sync) +{ + if (do_sync) + bdev_sync(sb); +} + +/* + * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int exfat_mode_can_hold_ro(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & 0222) + return 1; + return 0; +} + +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, u32 attr, + mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~0222; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + else if (attr & ATTR_SYMLINK) + return (mode & ~sbi->options.fs_dmask) | S_IFLNK; + else + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline u32 exfat_make_attr(struct inode *inode) +{ + if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & 0222)) + return (EXFAT_I(inode)->fid.attr) | ATTR_READONLY; + else + return EXFAT_I(inode)->fid.attr; +} + +static inline void exfat_save_attr(struct inode *inode, u32 attr) +{ + if (exfat_mode_can_hold_ro(inode)) + EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; + else + EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); +} + +static int ffsMountVol(struct super_block *sb) +{ + int i, ret; + struct pbr_sector_t *p_pbr; + struct buffer_head *tmp_bh = NULL; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + pr_info("[EXFAT] trying to mount...\n"); + + down(&z_sem); + + buf_init(sb); + + sema_init(&p_fs->v_sem, 1); + p_fs->dev_ejected = FALSE; + + /* open the block device */ + bdev_open(sb); + + if (p_bd->sector_size < sb->s_blocksize) { + ret = FFS_MEDIAERR; + goto out; + } + if (p_bd->sector_size > sb->s_blocksize) + sb_set_blocksize(sb, p_bd->sector_size); + + /* read Sector 0 */ + if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) { + ret = FFS_MEDIAERR; + goto out; + } + + p_fs->PBR_sector = 0; + + p_pbr = (struct pbr_sector_t *) tmp_bh->b_data; + + /* check the validity of PBR */ + if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { + brelse(tmp_bh); + bdev_close(sb); + ret = FFS_FORMATERR; + goto out; + } + + /* fill fs_stuct */ + for (i = 0; i < 53; i++) + if (p_pbr->bpb[i]) + break; + + if (i < 53) { + if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */ + ret = fat16_mount(sb, p_pbr); + else + ret = fat32_mount(sb, p_pbr); + } else { + ret = exfat_mount(sb, p_pbr); + } + + brelse(tmp_bh); + + if (ret) { + bdev_close(sb); + goto out; + } + + if (p_fs->vol_type == EXFAT) { + ret = load_alloc_bitmap(sb); + if (ret) { + bdev_close(sb); + goto out; + } + ret = load_upcase_table(sb); + if (ret) { + free_alloc_bitmap(sb); + bdev_close(sb); + goto out; + } + } + + if (p_fs->dev_ejected) { + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + bdev_close(sb); + ret = FFS_MEDIAERR; + goto out; + } + + pr_info("[EXFAT] mounted successfully\n"); + +out: + up(&z_sem); + + return ret; +} + +static int ffsUmountVol(struct super_block *sb) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int err = FFS_SUCCESS; + + pr_info("[EXFAT] trying to unmount...\n"); + + down(&z_sem); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + + FAT_release_all(sb); + buf_release_all(sb); + + /* close the block device */ + bdev_close(sb); + + if (p_fs->dev_ejected) { + pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n"); + err = FFS_MEDIAERR; + } + + buf_shutdown(sb); + + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + up(&z_sem); + + pr_info("[EXFAT] unmounted successfully\n"); + + return err; +} + +static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) +{ + int err = FFS_SUCCESS; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (info == NULL) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (p_fs->used_clusters == (u32) ~0) + p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); + + info->FatType = p_fs->vol_type; + info->ClusterSize = p_fs->cluster_size; + info->NumClusters = p_fs->num_clusters - 2; /* clu 0 & 1 */ + info->UsedClusters = p_fs->used_clusters; + info->FreeClusters = info->NumClusters - info->UsedClusters; + + if (p_fs->dev_ejected) + err = FFS_MEDIAERR; + + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return err; +} + +static int ffsSyncVol(struct super_block *sb, bool do_sync) +{ + int err = FFS_SUCCESS; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* synchronize the file system */ + fs_sync(sb, do_sync); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->dev_ejected) + err = FFS_MEDIAERR; + + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return err; +} + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) +{ + int ret, dentry, num_entries; + struct chain_t dir; + struct uni_name_t uni_name; + struct dos_name_t dos_name; + struct dentry_t *ep, *ep2; + struct entry_set_cache_t *es = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + pr_debug("%s entered\n", __func__); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, + &dos_name); + if (ret) + goto out; + + /* search the file name for directories */ + dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, + &dos_name, TYPE_ALL); + if (dentry < -1) { + return FFS_NOTFOUND; + goto out; + } + + fid->dir.dir = dir.dir; + fid->dir.size = dir.size; + fid->dir.flags = dir.flags; + fid->entry = dentry; + + if (dentry == -1) { + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + fid->attr = ATTR_SUBDIR; + fid->flags = 0x01; + fid->size = 0; + fid->start_clu = p_fs->root_dir; + } else { + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &dir, dentry, + ES_2_ENTRIES, &ep); + if (!es) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + } + + fid->type = p_fs->fs_func->get_entry_type(ep); + fid->rwoffset = 0; + fid->hint_last_off = -1; + fid->attr = p_fs->fs_func->get_entry_attr(ep); + + fid->size = p_fs->fs_func->get_entry_size(ep2); + if ((fid->type == TYPE_FILE) && (fid->size == 0)) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } else { + fid->flags = p_fs->fs_func->get_entry_flag(ep2); + fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2); + } + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + } + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsCreateFile(struct inode *inode, char *path, u8 mode, + struct file_id_t *fid) +{ + struct chain_t dir; + struct uni_name_t uni_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + int ret; + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* create a new file */ + ret = create_file(inode, &dir, &uni_name, mode, fid); + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, + u64 count, u64 *rcount) +{ + s32 offset, sec_offset, clu_offset; + u32 clu; + int ret; + sector_t LogSector; + u64 oneblkread, read_bytes; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check the validity of the given file id */ + if (fid == NULL) + return FFS_INVALIDFID; + + /* check the validity of pointer parameters */ + if (buffer == NULL) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) { + ret = FFS_PERMISSIONERR; + goto out; + } + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count > (fid->size - fid->rwoffset)) + count = fid->size - fid->rwoffset; + + if (count == 0) { + if (rcount != NULL) + *rcount = 0; + ret = FFS_EOF; + goto out; + } + + read_bytes = 0; + + while (count > 0) { + clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = fid->start_clu; + + if (fid->flags == 0x03) { + clu += clu_offset; + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + + /* hint information */ + fid->hint_last_off = (s32)(fid->rwoffset >> + p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + /* byte offset in cluster */ + offset = (s32)(fid->rwoffset & (p_fs->cluster_size-1)); + + /* sector offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; + + /* byte offset in sector */ + offset &= p_bd->sector_size_mask; + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkread = (u64)(p_bd->sector_size - offset); + if (oneblkread > count) + oneblkread = count; + + if ((offset == 0) && (oneblkread == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != + FFS_SUCCESS) + goto err_out; + memcpy((char *)buffer + read_bytes, + (char *)tmp_bh->b_data, (s32)oneblkread); + } else { + if (sector_read(sb, LogSector, &tmp_bh, 1) != + FFS_SUCCESS) + goto err_out; + memcpy((char *)buffer + read_bytes, + (char *)tmp_bh->b_data + offset, + (s32)oneblkread); + } + count -= oneblkread; + read_bytes += oneblkread; + fid->rwoffset += oneblkread; + } + brelse(tmp_bh); + +/* How did this ever work and not leak a brlse()?? */ +err_out: + /* set the size of read bytes */ + if (rcount != NULL) + *rcount = read_bytes; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, + void *buffer, u64 count, u64 *wcount) +{ + s32 modified = FALSE, offset, sec_offset, clu_offset; + s32 num_clusters, num_alloc, num_alloced = (s32) ~0; + int ret = 0; + u32 clu, last_clu; + sector_t LogSector, sector = 0; + u64 oneblkwrite, write_bytes; + struct chain_t new_clu; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct entry_set_cache_t *es = NULL; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check the validity of the given file id */ + if (fid == NULL) + return FFS_INVALIDFID; + + /* check the validity of pointer parameters */ + if (buffer == NULL) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) { + ret = FFS_PERMISSIONERR; + goto out; + } + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count == 0) { + if (wcount != NULL) + *wcount = 0; + ret = FFS_SUCCESS; + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (fid->size == 0) + num_clusters = 0; + else + num_clusters = (s32)((fid->size-1) >> + p_fs->cluster_size_bits) + 1; + + write_bytes = 0; + + while (count > 0) { + clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + clu = CLUSTER_32(~0); + else + clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu = clu; + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + clu_offset--; + } + } + + if (clu == CLUSTER_32(~0)) { + num_alloc = (s32)((count - 1) >> + p_fs->cluster_size_bits) + 1; + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? + CLUSTER_32(~0) : last_clu+1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a chain of clusters */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, + num_alloc, + &new_clu); + if (num_alloced == 0) + break; + else if (num_alloced < 0) { + ret = FFS_MEDIAERR; + goto out; + } + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = TRUE; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, + fid->start_clu, + num_clusters); + fid->flags = 0x01; + modified = TRUE; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + num_clusters += num_alloced; + clu = new_clu.dir; + } + + /* hint information */ + fid->hint_last_off = (s32)(fid->rwoffset >> + p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + /* byte offset in cluster */ + offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1)); + + /* sector offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; + + /* byte offset in sector */ + offset &= p_bd->sector_size_mask; + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkwrite = (u64)(p_bd->sector_size - offset); + if (oneblkwrite > count) + oneblkwrite = count; + + if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 0) != + FFS_SUCCESS) + goto err_out; + memcpy((char *)tmp_bh->b_data, + (char *)buffer + write_bytes, (s32)oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != + FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } else { + if ((offset > 0) || + ((fid->rwoffset+oneblkwrite) < fid->size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != + FFS_SUCCESS) + goto err_out; + } else { + if (sector_read(sb, LogSector, &tmp_bh, 0) != + FFS_SUCCESS) + goto err_out; + } + + memcpy((char *)tmp_bh->b_data + offset, + (char *)buffer + write_bytes, (s32)oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != + FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } + + count -= oneblkwrite; + write_bytes += oneblkwrite; + fid->rwoffset += oneblkwrite; + + fid->attr |= ATTR_ARCHIVE; + + if (fid->size < fid->rwoffset) { + fid->size = fid->rwoffset; + modified = TRUE; + } + } + + brelse(tmp_bh); + + /* (3) update the direcoty entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_ALL_ENTRIES, &ep); + if (es == NULL) + goto err_out; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + goto err_out; + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + + if (modified) { + if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags) + p_fs->fs_func->set_entry_flag(ep2, fid->flags); + + if (p_fs->fs_func->get_entry_size(ep2) != fid->size) + p_fs->fs_func->set_entry_size(ep2, fid->size); + + if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + +err_out: + /* set the size of written bytes */ + if (wcount != NULL) + *wcount = write_bytes; + + if (num_alloced == 0) + ret = FFS_FULL; + + else if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) +{ + s32 num_clusters; + u32 last_clu = CLUSTER_32(0); + int ret = 0; + sector_t sector = 0; + struct chain_t clu; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + struct entry_set_cache_t *es = NULL; + + pr_debug("%s entered (inode %p size %llu)\n", __func__, inode, + new_size); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) { + ret = FFS_PERMISSIONERR; + goto out; + } + + if (fid->size != old_size) { + pr_err("[EXFAT] truncate : can't skip it because of size-mismatch(old:%lld->fid:%lld).\n", + old_size, fid->size); + } + + if (old_size <= new_size) { + ret = FFS_SUCCESS; + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + clu.dir = fid->start_clu; + clu.size = (s32)((old_size-1) >> p_fs->cluster_size_bits) + 1; + clu.flags = fid->flags; + + if (new_size > 0) { + num_clusters = (s32)((new_size-1) >> + p_fs->cluster_size_bits) + 1; + + if (clu.flags == 0x03) { + clu.dir += num_clusters; + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (FAT_read(sb, clu.dir, &clu.dir) == -1) + return FFS_MEDIAERR; + num_clusters--; + } + } + + clu.size -= num_clusters; + } + + fid->size = new_size; + fid->attr |= ATTR_ARCHIVE; + if (new_size == 0) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } + + /* (1) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (es == NULL) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + p_fs->fs_func->set_entry_size(ep2, new_size); + if (new_size == 0) { + p_fs->fs_func->set_entry_flag(ep2, 0x01); + p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); + } + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* (2) cut off from the FAT chain */ + if (last_clu != CLUSTER_32(0)) { + if (fid->flags == 0x01) + FAT_write(sb, last_clu, CLUSTER_32(~0)); + } + + /* (3) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu, 0); + + /* hint information */ + fid->hint_last_off = -1; + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + pr_debug("%s exited (%d)\n", __func__, ret); + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static void update_parent_info(struct file_id_t *fid, + struct inode *parent_inode) +{ + struct fs_info_t *p_fs = &(EXFAT_SB(parent_inode->i_sb)->fs_info); + struct file_id_t *parent_fid = &(EXFAT_I(parent_inode)->fid); + + if (unlikely((parent_fid->flags != fid->dir.flags) || + (parent_fid->size != + (fid->dir.size << p_fs->cluster_size_bits)) || + (parent_fid->start_clu != fid->dir.dir))) { + fid->dir.dir = parent_fid->start_clu; + fid->dir.flags = parent_fid->flags; + fid->dir.size = ((parent_fid->size + (p_fs->cluster_size-1)) + >> p_fs->cluster_size_bits); + } +} + +static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, + struct inode *new_parent_inode, struct dentry *new_dentry) +{ + s32 ret; + s32 dentry; + struct chain_t olddir, newdir; + struct chain_t *p_dir = NULL; + struct uni_name_t uni_name; + struct dentry_t *ep; + struct super_block *sb = old_parent_inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + u8 *new_path = (u8 *) new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + struct file_id_t *new_fid = NULL; + s32 new_entry = 0; + + /* check the validity of the given file id */ + if (fid == NULL) + return FFS_INVALIDFID; + + /* check the validity of pointer parameters */ + if ((new_path == NULL) || (*new_path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + update_parent_info(fid, old_parent_inode); + + olddir.dir = fid->dir.dir; + olddir.size = fid->dir.size; + olddir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the old file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) { + ret = FFS_PERMISSIONERR; + goto out2; + } + } + + ep = get_entry_in_dir(sb, &olddir, dentry, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out2; + } + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { + ret = FFS_PERMISSIONERR; + goto out2; + } + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + u32 entry_type; + + ret = FFS_MEDIAERR; + new_fid = &EXFAT_I(new_inode)->fid; + + update_parent_info(new_fid, new_parent_inode); + + p_dir = &(new_fid->dir); + new_entry = new_fid->entry; + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_DIR) { + struct chain_t new_clu; + + new_clu.dir = new_fid->start_clu; + new_clu.size = (s32)((new_fid->size - 1) >> + p_fs->cluster_size_bits) + 1; + new_clu.flags = new_fid->flags; + + if (!is_dir_empty(sb, &new_clu)) { + ret = FFS_FILEEXIST; + goto out; + } + } + } + + /* check the validity of directory name in the given new pathname */ + ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name); + if (ret) + goto out2; + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, + fid); + else + ret = move_file(new_parent_inode, &olddir, dentry, &newdir, + &uni_name, fid); + + if ((ret == FFS_SUCCESS) && new_inode) { + /* delete entries of new_dir */ + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, + new_entry, ep); + if (num_entries < 0) + goto out; + p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, + num_entries+1); + } +out: +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out2: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) +{ + s32 dentry; + int ret = FFS_SUCCESS; + struct chain_t dir, clu_to_free; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) + return FFS_INVALIDFID; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { + ret = FFS_PERMISSIONERR; + goto out; + } + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 0); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +#if 0 +/* Not currently wired up */ +static int ffsSetAttr(struct inode *inode, u32 attr) +{ + u32 type; + int ret = FFS_SUCCESS; + sector_t sector = 0; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + struct entry_set_cache_t *es = NULL; + + if (fid->attr == attr) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* get the directory entry of given file */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_ALL_ENTRIES, &ep); + if (es == NULL) { + ret = FFS_MEDIAERR; + goto out; + } + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + } + + type = p_fs->fs_func->get_entry_type(ep); + + if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) || + ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) { + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + else + ret = FFS_ERROR; + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* set the file attribute */ + fid->attr = attr; + p_fs->fs_func->set_entry_attr(ep, attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} +#endif + +static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) +{ + sector_t sector = 0; + s32 count; + int ret = FFS_SUCCESS; + struct chain_t dir; + struct uni_name_t uni_name; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + struct entry_set_cache_t *es = NULL; + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + pr_debug("%s entered\n", __func__); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + info->Attr = ATTR_SUBDIR; + memset((char *)&info->CreateTimestamp, 0, + sizeof(struct date_time_t)); + memset((char *)&info->ModifyTimestamp, 0, + sizeof(struct date_time_t)); + memset((char *)&info->AccessTimestamp, 0, + sizeof(struct date_time_t)); + strcpy(info->ShortName, "."); + strcpy(info->Name, "."); + + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + + if (p_fs->root_dir == CLUSTER_32(0)) { + /* FAT16 root_dir */ + info->Size = p_fs->dentries_in_root << + DENTRY_SIZE_BITS; + } else { + info->Size = count_num_clusters(sb, &dir) << + p_fs->cluster_size_bits; + } + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) { + ret = FFS_MEDIAERR; + goto out; + } + info->NumSubdirs = count; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + goto out; + } + } + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_2_ENTRIES, &ep); + if (es == NULL) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + buf_lock(sb, sector); + } + + /* set FILE_INFO structure using the acquired struct dentry_t */ + info->Attr = p_fs->fs_func->get_entry_attr(ep); + + p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + info->CreateTimestamp.Year = tm.year; + info->CreateTimestamp.Month = tm.mon; + info->CreateTimestamp.Day = tm.day; + info->CreateTimestamp.Hour = tm.hour; + info->CreateTimestamp.Minute = tm.min; + info->CreateTimestamp.Second = tm.sec; + info->CreateTimestamp.MilliSecond = 0; + + p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + info->ModifyTimestamp.Year = tm.year; + info->ModifyTimestamp.Month = tm.mon; + info->ModifyTimestamp.Day = tm.day; + info->ModifyTimestamp.Hour = tm.hour; + info->ModifyTimestamp.Minute = tm.min; + info->ModifyTimestamp.Second = tm.sec; + info->ModifyTimestamp.MilliSecond = 0; + + memset((char *) &info->AccessTimestamp, 0, sizeof(struct date_time_t)); + + *(uni_name.name) = 0x0; + /* XXX this is very bad for exfat cuz name is already included in es. + * API should be revised + */ + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, + uni_name.name); + if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT) + get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep, + &uni_name, 0x1); + nls_uniname_to_cstring(sb, info->Name, &uni_name); + + if (p_fs->vol_type == EXFAT) { + info->NumSubdirs = 2; + } else { + buf_unlock(sb, sector); + get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep, + &uni_name, 0x0); + nls_uniname_to_cstring(sb, info->ShortName, &uni_name); + info->NumSubdirs = 0; + } + + info->Size = p_fs->fs_func->get_entry_size(ep2); + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + + if (is_dir) { + dir.dir = fid->start_clu; + dir.flags = 0x01; + + if (info->Size == 0) + info->Size = (u64)count_num_clusters(sb, &dir) << + p_fs->cluster_size_bits; + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) { + ret = FFS_MEDIAERR; + goto out; + } + info->NumSubdirs += count; + } + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + pr_debug("%s exited successfully\n", __func__); + return ret; +} + +static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) +{ + sector_t sector = 0; + int ret = FFS_SUCCESS; + struct timestamp_t tm; + struct dentry_t *ep, *ep2; + struct entry_set_cache_t *es = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + pr_debug("%s entered (inode %p info %p\n", __func__, inode, info); + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + ret = FFS_SUCCESS; + goto out; + } + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, + ES_ALL_ENTRIES, &ep); + if (es == NULL) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep+1; + } else { + /* for other than exfat */ + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + ep2 = ep; + } + + p_fs->fs_func->set_entry_attr(ep, info->Attr); + + /* set FILE_INFO structure using the acquired struct dentry_t */ + tm.sec = info->CreateTimestamp.Second; + tm.min = info->CreateTimestamp.Minute; + tm.hour = info->CreateTimestamp.Hour; + tm.day = info->CreateTimestamp.Day; + tm.mon = info->CreateTimestamp.Month; + tm.year = info->CreateTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE); + + tm.sec = info->ModifyTimestamp.Second; + tm.min = info->ModifyTimestamp.Minute; + tm.hour = info->ModifyTimestamp.Hour; + tm.day = info->ModifyTimestamp.Day; + tm.mon = info->ModifyTimestamp.Month; + tm.year = info->ModifyTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY); + + p_fs->fs_func->set_entry_size(ep2, info->Size); + + if (p_fs->vol_type != EXFAT) { + buf_modify(sb, sector); + } else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + pr_debug("%s exited (%d)\n", __func__, ret); + + return ret; +} + +static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) +{ + s32 num_clusters, num_alloced, modified = FALSE; + u32 last_clu; + int ret = FFS_SUCCESS; + sector_t sector = 0; + struct chain_t new_clu; + struct dentry_t *ep; + struct entry_set_cache_t *es = NULL; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + /* check the validity of pointer parameters */ + if (clu == NULL) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits; + + if (EXFAT_I(inode)->mmu_private == 0) + num_clusters = 0; + else + num_clusters = (s32)((EXFAT_I(inode)->mmu_private - 1) >> + p_fs->cluster_size_bits) + 1; + + *clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = CLUSTER_32(~0); + else + *clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + *clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu = *clu; + if (FAT_read(sb, *clu, clu) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + clu_offset--; + } + } + + if (*clu == CLUSTER_32(~0)) { + fs_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : + last_clu + 1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a cluster */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu); + if (num_alloced < 0) { + ret = FFS_MEDIAERR; + goto out; + } else if (num_alloced == 0) { + ret = FFS_FULL; + goto out; + } + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = TRUE; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, fid->start_clu, + num_clusters); + fid->flags = 0x01; + modified = TRUE; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + num_clusters += num_alloced; + *clu = new_clu.dir; + + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (es == NULL) { + ret = FFS_MEDIAERR; + goto out; + } + /* get stream entry */ + ep++; + } + + /* (3) update directory entry */ + if (modified) { + if (p_fs->vol_type != EXFAT) { + ep = get_entry_in_dir(sb, &(fid->dir), + fid->entry, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + } + + if (p_fs->fs_func->get_entry_flag(ep) != fid->flags) + p_fs->fs_func->set_entry_flag(ep, fid->flags); + + if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep, + fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* add number of new blocks to inode */ + inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9); + } + + /* hint information */ + fid->hint_last_off = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = *clu; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) +{ + int ret = FFS_SUCCESS; + struct chain_t dir; + struct uni_name_t uni_name; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + pr_debug("%s entered\n", __func__); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return FFS_ERROR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + /* check the validity of directory name in the given old pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + goto out; + + fs_set_vol_flags(sb, VOL_DIRTY); + + ret = create_dir(inode, &dir, &uni_name, fid); + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) +{ + int i, dentry, clu_offset; + int ret = FFS_SUCCESS; + s32 dentries_per_clu, dentries_per_clu_bits = 0; + u32 type; + sector_t sector; + struct chain_t dir, clu; + struct uni_name_t uni_name; + struct timestamp_t tm; + struct dentry_t *ep; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct fs_func *fs_func = p_fs->fs_func; + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + + /* check the validity of pointer parameters */ + if (dir_entry == NULL) + return FFS_ERROR; + + /* check if the given file ID is opened */ + if (fid->type != TYPE_DIR) + return FFS_PERMISSIONERR; + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + if (fid->entry == -1) { + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + } else { + dir.dir = fid->start_clu; + dir.size = (s32)(fid->size >> p_fs->cluster_size_bits); + dir.flags = fid->flags; + } + + dentry = (s32)fid->rwoffset; + + if (dir.dir == CLUSTER_32(0)) { + /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + + if (dentry == dentries_per_clu) { + clu.dir = CLUSTER_32(~0); + } else { + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + } + } else { + dentries_per_clu = p_fs->dentries_per_clu; + dentries_per_clu_bits = ilog2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + + if (clu.flags == 0x03) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu.dir = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &clu.dir) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + clu_offset--; + } + } + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, §or); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + type = fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + break; + + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + buf_lock(sb, sector); + dir_entry->Attr = fs_func->get_entry_attr(ep); + + fs_func->get_entry_time(ep, &tm, TM_CREATE); + dir_entry->CreateTimestamp.Year = tm.year; + dir_entry->CreateTimestamp.Month = tm.mon; + dir_entry->CreateTimestamp.Day = tm.day; + dir_entry->CreateTimestamp.Hour = tm.hour; + dir_entry->CreateTimestamp.Minute = tm.min; + dir_entry->CreateTimestamp.Second = tm.sec; + dir_entry->CreateTimestamp.MilliSecond = 0; + + fs_func->get_entry_time(ep, &tm, TM_MODIFY); + dir_entry->ModifyTimestamp.Year = tm.year; + dir_entry->ModifyTimestamp.Month = tm.mon; + dir_entry->ModifyTimestamp.Day = tm.day; + dir_entry->ModifyTimestamp.Hour = tm.hour; + dir_entry->ModifyTimestamp.Minute = tm.min; + dir_entry->ModifyTimestamp.Second = tm.sec; + dir_entry->ModifyTimestamp.MilliSecond = 0; + + memset((char *)&dir_entry->AccessTimestamp, 0, + sizeof(struct date_time_t)); + + *(uni_name.name) = 0x0; + fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, + uni_name.name); + if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT) + get_uni_name_from_dos_entry(sb, + (struct dos_dentry_t *)ep, + &uni_name, 0x1); + nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name); + buf_unlock(sb, sector); + + if (p_fs->vol_type == EXFAT) { + ep = get_entry_in_dir(sb, &clu, i+1, NULL); + if (!ep) { + ret = FFS_MEDIAERR; + goto out; + } + } else { + get_uni_name_from_dos_entry(sb, + (struct dos_dentry_t *)ep, + &uni_name, 0x0); + nls_uniname_to_cstring(sb, dir_entry->ShortName, + &uni_name); + } + + dir_entry->Size = fs_func->get_entry_size(ep); + + /* hint information */ + if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + } else { + fid->hint_last_off = dentry >> + dentries_per_clu_bits; + fid->hint_last_clu = clu.dir; + } + + fid->rwoffset = (s64) ++dentry; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + goto out; + } + + if (dir.dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &clu.dir) == -1) { + ret = FFS_MEDIAERR; + goto out; + } + } + } + + *(dir_entry->Name) = '\0'; + + fid->rwoffset = (s64) ++dentry; + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) +{ + s32 dentry; + int ret = FFS_SUCCESS; + struct chain_t dir, clu_to_free; + struct super_block *sb = inode->i_sb; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) + return FFS_INVALIDFID; + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((dir.dir != p_fs->root_dir) && (dentry < 2)) + return FFS_PERMISSIONERR; + } + + /* acquire the lock for file system critical section */ + down(&p_fs->v_sem); + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + if (!is_dir_empty(sb, &clu_to_free)) { + ret = FFS_FILEEXIST; + goto out; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 1); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + +#ifdef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, false); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + ret = FFS_MEDIAERR; + +out: + /* release the lock for file system critical section */ + up(&p_fs->v_sem); + + return ret; +} + +/*======================================================================*/ +/* Directory Entry Operations */ +/*======================================================================*/ + +static int exfat_readdir(struct file *filp, struct dir_context *ctx) +{ + struct inode *inode = file_inode(filp); + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); + struct dir_entry_t de; + unsigned long inum; + loff_t cpos; + int err = 0; + + __lock_super(sb); + + cpos = ctx->pos; + /* Fake . and .. for the root directory. */ + if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) { + while (cpos < 2) { + if (inode->i_ino == EXFAT_ROOT_INO) + inum = EXFAT_ROOT_INO; + else if (cpos == 0) + inum = inode->i_ino; + else /* (cpos == 1) */ + inum = parent_ino(filp->f_path.dentry); + + if (!dir_emit_dots(filp, ctx)) + goto out; + cpos++; + ctx->pos++; + } + if (cpos == 2) + cpos = 0; + } + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto out; + } + +get_new: + EXFAT_I(inode)->fid.size = i_size_read(inode); + EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; + + err = ffsReadDir(inode, &de); + if (err) { + /* at least we tried to read a sector + * move cpos to next sector position (should be aligned) + */ + if (err == FFS_MEDIAERR) { + cpos += 1 << p_bd->sector_size_bits; + cpos &= ~((1 << p_bd->sector_size_bits)-1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; + + if (!de.Name[0]) + goto end_of_dir; + + if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = inode->i_ino; + } else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = parent_ino(filp->f_path.dentry); + } else { + loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) | + ((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); + struct inode *tmp = exfat_iget(sb, i_pos); + + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, EXFAT_ROOT_INO); + } + } + + if (!dir_emit(ctx, de.Name, strlen(de.Name), inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) + goto out; + + ctx->pos = cpos; + goto get_new; + +end_of_dir: + ctx->pos = cpos; +out: + __unlock_super(sb); + return err; +} + +static int exfat_ioctl_volume_id(struct inode *dir) +{ + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + + return p_fs->vol_id; +} + +static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ +struct inode *inode = filp->f_path.dentry->d_inode; +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + unsigned int flags; +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + + switch (cmd) { + case EXFAT_IOCTL_GET_VOLUME_ID: + return exfat_ioctl_volume_id(inode); +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + case EXFAT_IOC_GET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + flags = sbi->debug_flags; + return put_user(flags, (int __user *)arg); + } + case EXFAT_IOC_SET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(flags, (int __user *) arg)) + return -EFAULT; + + __lock_super(sb); + sbi->debug_flags = flags; + __unlock_super(sb); + + return 0; + } +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + default: + return -ENOTTY; /* Inappropriate ioctl for device */ + } +} + +static const struct file_operations exfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .iterate = exfat_readdir, + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, +}; + +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct file_id_t fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + err = ffsCreateFile(dir, (u8 *) dentry->d_name.name, FM_REGULAR, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + INC_IVERSION(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + /* + * timestamp is already written, so mark_inode_dirty() is unnecessary. + */ + + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_find(struct inode *dir, struct qstr *qname, + struct file_id_t *fid) +{ + int err; + + if (qname->len == 0) + return -ENOENT; + + err = ffsLookupFile(dir, (u8 *) qname->name, fid); + if (err) + return -ENOENT; + + return 0; +} + +static int exfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + int err; + struct file_id_t fid; + loff_t i_pos; + u64 ret; + mode_t i_mode; + + __lock_super(sb); + pr_debug("%s entered\n", __func__); + err = exfat_find(dir, &dentry->d_name, &fid); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto error; + } + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto error; + } + + i_mode = inode->i_mode; + if (S_ISLNK(i_mode) && !EXFAT_I(inode)->target) { + EXFAT_I(inode)->target = kmalloc(i_size_read(inode) + 1, + GFP_KERNEL); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto error; + } + ffsReadFile(dir, &fid, EXFAT_I(inode)->target, + i_size_read(inode), &ret); + *(EXFAT_I(inode)->target + i_size_read(inode)) = '\0'; + } + + alias = d_find_alias(inode); + if (alias && !exfat_d_anon_disconn(alias)) { + BUG_ON(d_unhashed(alias)); + if (!S_ISDIR(i_mode)) + d_move(alias, dentry); + iput(inode); + __unlock_super(sb); + pr_debug("%s exited 1\n", __func__); + return alias; + } + dput(alias); +out: + __unlock_super(sb); + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + dentry = d_splice_alias(inode, dentry); + if (dentry) + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + pr_debug("%s exited 2\n", __func__); + return dentry; + +error: + __unlock_super(sb); + pr_debug("%s exited 3\n", __func__); + return ERR_PTR(err); +} + +static inline unsigned long exfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, EXFAT_HASH_BITS); +} + +static void exfat_attach(struct inode *inode, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + EXFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +static void exfat_detach(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&EXFAT_I(inode)->i_hash_fat); + EXFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + +static int exfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_symlink(struct inode *dir, struct dentry *dentry, + const char *target) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct file_id_t fid; + loff_t i_pos; + int err; + u64 len = (u64) strlen(target); + u64 ret; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + err = ffsCreateFile(dir, (u8 *) dentry->d_name.name, FM_SYMLINK, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + err = ffsWriteFile(dir, &fid, (char *) target, len, &ret); + + if (err) { + ffsRemoveFile(dir, &fid); + + if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + INC_IVERSION(dir); + dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + INC_IVERSION(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + EXFAT_I(inode)->target = kmalloc(len+1, GFP_KERNEL); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto out; + } + memcpy(EXFAT_I(inode)->target, target, len+1); + + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct file_id_t fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + err = ffsCreateDir(dir, (u8 *) dentry->d_name.name, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + INC_IVERSION(inode); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + int err; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -ENOTEMPTY; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_DIRBUSY) + err = -EBUSY; + else + err = -EIO; + goto out; + } + INC_IVERSION(dir); + dir->i_mtime = dir->i_atime = current_time(dir); + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = current_time(inode); + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + loff_t i_pos; + int err; + + if (flags) + return -EINVAL; + + __lock_super(sb); + + pr_debug("%s entered\n", __func__); + + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + EXFAT_I(old_inode)->fid.size = i_size_read(old_inode); + + err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, + new_dentry); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + INC_IVERSION(new_dir); + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = + current_time(new_dir); + if (IS_DIRSYNC(new_dir)) + (void) exfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = ((loff_t) EXFAT_I(old_inode)->fid.dir.dir << 32) | + (EXFAT_I(old_inode)->fid.entry & 0xffffffff); + + exfat_detach(old_inode); + exfat_attach(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + (void) exfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { + drop_nlink(old_dir); + if (!new_inode) + inc_nlink(new_dir); + } + INC_IVERSION(old_dir); + old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); + if (IS_DIRSYNC(old_dir)) + (void) exfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + exfat_detach(new_inode); + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + new_inode->i_ctime = current_time(new_inode); + } + +out: + __unlock_super(sb); + pr_debug("%s exited\n", __func__); + return err; +} + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + err = generic_cont_expand_simple(inode, size); + if (err != 0) + return err; + + inode->i_ctime = inode->i_mtime = current_time(inode); + mark_inode_dirty(inode); + + if (IS_SYNC(inode)) { + err = filemap_fdatawrite_range(mapping, start, + start + count - 1); + err2 = sync_mapping_buffers(mapping); + err = (err) ? (err) : (err2); + err2 = write_inode_now(inode, 1); + err = (err) ? (err) : (err2); + if (!err) + err = filemap_fdatawait_range(mapping, start, + start + count - 1); + } + return err; +} + +static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + + if (!uid_eq(current_fsuid(), inode->i_uid)) { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return 1; + } + + /* use a default check */ + return 0; +} + +static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + if (S_ISREG(i_mode) || S_ISLNK(i_mode)) + mask = sbi->options.fs_fmask; + else + mask = sbi->options.fs_dmask; + + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & 0555) != (i_mode & 0555)) + return -EPERM; + + if (exfat_mode_can_hold_ro(inode)) { + /* + * Of the w bits, either all (subject to umask) or none must be + * present. + */ + if ((perm & 0222) && ((perm & 0222) != (0222 & ~mask))) + return -EPERM; + } else { + /* + * If exfat_mode_can_hold_ro(inode) is false, can't change w + * bits. + */ + if ((perm & 0222) != (0222 & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +static void exfat_truncate(struct inode *inode, loff_t old_size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + int err; + + __lock_super(sb); + + /* + * This protects against truncating a file bigger than it was then + * trying to write into the hole. + */ + if (EXFAT_I(inode)->mmu_private > i_size_read(inode)) + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + if (EXFAT_I(inode)->fid.start_clu == 0) + goto out; + + err = ffsTruncateFile(inode, old_size, i_size_read(inode)); + if (err) + goto out; + + inode->i_ctime = inode->i_mtime = current_time(inode); + if (IS_DIRSYNC(inode)) + (void) exfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) & + ~((loff_t)p_fs->cluster_size - 1)) >> 9; +out: + __unlock_super(sb); +} + +static int exfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + + struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + loff_t old_size; + + pr_debug("%s entered\n", __func__); + + if ((attr->ia_valid & ATTR_SIZE) + && (attr->ia_size > i_size_read(inode))) { + error = exfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + ia_valid = attr->ia_valid; + + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) + && exfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | + ATTR_ATIME_SET | + ATTR_TIMES_SET); + } + + error = setattr_prepare(dentry, attr); + attr->ia_valid = ia_valid; + if (error) + return error; + + if (((attr->ia_valid & ATTR_UID) && + (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) || + ((attr->ia_valid & ATTR_GID) && + (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) || + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | 0777)))) { + return -EPERM; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + if (attr->ia_valid & ATTR_SIZE) { + old_size = i_size_read(inode); + down_write(&EXFAT_I(inode)->truncate_lock); + truncate_setsize(inode, attr->ia_size); + exfat_truncate(inode, old_size); + up_write(&EXFAT_I(inode)->truncate_lock); + } + setattr_copy(inode, attr); + mark_inode_dirty(inode); + + pr_debug("%s exited\n", __func__); + return error; +} + +static int exfat_getattr(const struct path *path, struct kstat *stat, + u32 request_mask, unsigned int flags) +{ + struct inode *inode = path->dentry->d_inode; + + pr_debug("%s entered\n", __func__); + + generic_fillattr(inode, stat); + stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size; + + pr_debug("%s exited\n", __func__); + return 0; +} + +static const struct inode_operations exfat_dir_inode_operations = { + .create = exfat_create, + .lookup = exfat_lookup, + .unlink = exfat_unlink, + .symlink = exfat_symlink, + .mkdir = exfat_mkdir, + .rmdir = exfat_rmdir, + .rename = exfat_rename, + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* File Operations */ +/*======================================================================*/ +static const char *exfat_get_link(struct dentry *dentry, struct inode *inode, + struct delayed_call *done) +{ + struct exfat_inode_info *ei = EXFAT_I(inode); + + if (ei->target != NULL) { + char *cookie = ei->target; + + if (cookie != NULL) + return (char *)(ei->target); + } + return NULL; +} + +static const struct inode_operations exfat_symlink_inode_operations = { + .get_link = exfat_get_link, +}; + +static int exfat_file_release(struct inode *inode, struct file *filp) +{ + struct super_block *sb = inode->i_sb; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + ffsSyncVol(sb, false); + return 0; +} + +static const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, + .read_iter = generic_file_read_iter, + .write_iter = generic_file_write_iter, + .mmap = generic_file_mmap, + .release = exfat_file_release, + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, + .splice_read = generic_file_splice_read, +}; + +static const struct inode_operations exfat_file_inode_operations = { + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* Address Space Operations */ +/*======================================================================*/ + +static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, + unsigned long *mapped_blocks, int *create) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct bd_info_t *p_bd = &(sbi->bd_info); + const unsigned long blocksize = sb->s_blocksize; + const unsigned char blocksize_bits = sb->s_blocksize_bits; + sector_t last_block; + int err, clu_offset, sec_offset; + unsigned int cluster; + + *phys = 0; + *mapped_blocks = 0; + + if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) { + if (inode->i_ino == EXFAT_ROOT_INO) { + if (sector < + (p_fs->dentries_in_root >> + (p_bd->sector_size_bits-DENTRY_SIZE_BITS))) { + *phys = sector + p_fs->root_start_sector; + *mapped_blocks = 1; + } + return 0; + } + } + + last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; + if (sector >= last_block) { + if (*create == 0) + return 0; + } else { + *create = 0; + } + + /* cluster offset */ + clu_offset = sector >> p_fs->sectors_per_clu_bits; + + /* sector offset in cluster */ + sec_offset = sector & (p_fs->sectors_per_clu - 1); + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = ffsMapCluster(inode, clu_offset, &cluster); + + if (err) { + if (err == FFS_FULL) + return -ENOSPC; + else + return -EIO; + } else if (cluster != CLUSTER_32(~0)) { + *phys = START_SECTOR(cluster) + sec_offset; + *mapped_blocks = p_fs->sectors_per_clu - sec_offset; + } + + return 0; +} + +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err; + unsigned long mapped_blocks; + sector_t phys; + + __lock_super(sb); + + err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create); + if (err) { + __unlock_super(sb); + return err; + } + + if (phys) { + max_blocks = min(mapped_blocks, max_blocks); + if (create) { + EXFAT_I(inode)->mmu_private += max_blocks << + sb->s_blocksize_bits; + set_buffer_new(bh_result); + } + map_bh(bh_result, sb, phys); + } + + bh_result->b_size = max_blocks << sb->s_blocksize_bits; + __unlock_super(sb); + + return 0; +} + +static int exfat_readpage(struct file *file, struct page *page) +{ + return mpage_readpage(page, exfat_get_block); +} + +static int exfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned int nr_pages) +{ + return mpage_readpages(mapping, pages, nr_pages, exfat_get_block); +} + +static int exfat_writepage(struct page *page, struct writeback_control *wbc) +{ + return block_write_full_page(page, exfat_get_block, wbc); +} + +static int exfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + return mpage_writepages(mapping, wbc, exfat_get_block); +} + +static void exfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > i_size_read(inode)) { + truncate_pagecache(inode, i_size_read(inode)); + EXFAT_I(inode)->fid.size = i_size_read(inode); + exfat_truncate(inode, i_size_read(inode)); + } +} + +static int exfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int flags, + struct page **pagep, void **fsdata) +{ + int ret; + + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + exfat_get_block, + &EXFAT_I(mapping->host)->mmu_private); + + if (ret < 0) + exfat_write_failed(mapping, pos+len); + return ret; +} + +static int exfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned int len, unsigned int copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + struct file_id_t *fid = &(EXFAT_I(inode)->fid); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + + if (err < len) + exfat_write_failed(mapping, pos+len); + + if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = current_time(inode); + fid->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + return err; +} + +static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; + struct address_space *mapping = iocb->ki_filp->f_mapping; + ssize_t ret; + int rw; + + rw = iov_iter_rw(iter); + + if (rw == WRITE) { + if (EXFAT_I(inode)->mmu_private < iov_iter_count(iter)) + return 0; + } + ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); + + if ((ret < 0) && (rw & WRITE)) + exfat_write_failed(mapping, iov_iter_count(iter)); + return ret; +} + +static sector_t _exfat_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ + down_read(&EXFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->truncate_lock); + + return blocknr; +} + +static const struct address_space_operations exfat_aops = { + .readpage = exfat_readpage, + .readpages = exfat_readpages, + .writepage = exfat_writepage, + .writepages = exfat_writepages, + .write_begin = exfat_write_begin, + .write_end = exfat_write_end, + .direct_IO = exfat_direct_IO, + .bmap = _exfat_bmap +}; + +/*======================================================================*/ +/* Super Operations */ +/*======================================================================*/ + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + struct inode *inode = NULL; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { + BUG_ON(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} + +/* doesn't deal with root inode */ +static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct dir_entry_t info; + + memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t)); + + ffsReadStat(inode, &info); + + EXFAT_I(inode)->i_pos = 0; + EXFAT_I(inode)->target = NULL; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + INC_IVERSION(inode); + inode->i_generation = get_seconds(); + + if (info.Attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + set_nlink(inode, info.NumSubdirs); + } else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777); + inode->i_op = &exfat_symlink_inode_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, 0777); + inode->i_op = &exfat_file_inode_operations; + inode->i_fop = &exfat_file_operations; + inode->i_mapping->a_ops = &exfat_aops; + inode->i_mapping->nrpages = 0; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } + exfat_save_attr(inode, info.Attr); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + + exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp); + exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp); + exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp); + + return 0; +} + +static struct inode *exfat_build_inode(struct super_block *sb, + struct file_id_t *fid, loff_t i_pos) +{ + struct inode *inode; + int err; + + inode = exfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, EXFAT_ROOT_INO); + SET_IVERSION(inode, 1); + err = exfat_fill_inode(inode, fid); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + exfat_attach(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +static int exfat_sync_inode(struct inode *inode) +{ + return exfat_write_inode(inode, NULL); +} + +static struct inode *exfat_alloc_inode(struct super_block *sb) +{ + struct exfat_inode_info *ei; + + ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; + + init_rwsem(&ei->truncate_lock); + + return &ei->vfs_inode; +} + +static void exfat_destroy_inode(struct inode *inode) +{ + if (EXFAT_I(inode)->target) + kfree(EXFAT_I(inode)->target); + EXFAT_I(inode)->target = NULL; + + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct dir_entry_t info; + + if (inode->i_ino == EXFAT_ROOT_INO) + return 0; + + info.Attr = exfat_make_attr(inode); + info.Size = i_size_read(inode); + + exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp); + exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp); + exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp); + + ffsWriteStat(inode, &info); + + return 0; +} + +static void exfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) + i_size_write(inode, 0); + invalidate_inode_buffers(inode); + clear_inode(inode); + exfat_detach(inode); + + remove_inode_hash(inode); +} + +static void exfat_free_super(struct exfat_sb_info *sbi) +{ + if (sbi->nls_disk) + unload_nls(sbi->nls_disk); + if (sbi->nls_io) + unload_nls(sbi->nls_io); + if (sbi->options.iocharset != exfat_default_iocharset) + kfree(sbi->options.iocharset); + /* mutex_init is in exfat_fill_super function. only for 3.7+ */ + mutex_destroy(&sbi->s_lock); + kfree(sbi); +} + +static void exfat_put_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (__is_sb_dirty(sb)) + exfat_write_super(sb); + + ffsUmountVol(sb); + + sb->s_fs_info = NULL; + exfat_free_super(sbi); +} + +static void exfat_write_super(struct super_block *sb) +{ + __lock_super(sb); + + __set_sb_clean(sb); + + if (!sb_rdonly(sb)) + ffsSyncVol(sb, true); + + __unlock_super(sb); +} + +static int exfat_sync_fs(struct super_block *sb, int wait) +{ + int err = 0; + + if (__is_sb_dirty(sb)) { + __lock_super(sb); + __set_sb_clean(sb); + err = ffsSyncVol(sb, true); + __unlock_super(sb); + } + + return err; +} + +static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + struct vol_info_t info; + + if (p_fs->used_clusters == (u32) ~0) { + if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR) + return -EIO; + + } else { + info.FatType = p_fs->vol_type; + info.ClusterSize = p_fs->cluster_size; + info.NumClusters = p_fs->num_clusters - 2; + info.UsedClusters = p_fs->used_clusters; + info.FreeClusters = info.NumClusters - info.UsedClusters; + + if (p_fs->dev_ejected) + pr_info("[EXFAT] statfs on device that is ejected\n"); + } + + buf->f_type = sb->s_magic; + buf->f_bsize = info.ClusterSize; + buf->f_blocks = info.NumClusters; + buf->f_bfree = info.FreeClusters; + buf->f_bavail = info.FreeClusters; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_namelen = 260; + + return 0; +} + +static int exfat_remount(struct super_block *sb, int *flags, char *data) +{ + *flags |= SB_NODIRATIME; + return 0; +} + +static int exfat_show_options(struct seq_file *m, struct dentry *root) +{ + struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb); + struct exfat_mount_options *opts = &sbi->options; + + if (__kuid_val(opts->fs_uid)) + seq_printf(m, ",uid=%u", __kuid_val(opts->fs_uid)); + if (__kgid_val(opts->fs_gid)) + seq_printf(m, ",gid=%u", __kgid_val(opts->fs_gid)); + seq_printf(m, ",fmask=%04o", opts->fs_fmask); + seq_printf(m, ",dmask=%04o", opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (sbi->nls_disk) + seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); + if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + seq_printf(m, ",namecase=%u", opts->casesensitive); + if (opts->errors == EXFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == EXFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); +#ifdef CONFIG_EXFAT_DISCARD + if (opts->discard) + seq_puts(m, ",discard"); +#endif + return 0; +} + +static const struct super_operations exfat_sops = { + .alloc_inode = exfat_alloc_inode, + .destroy_inode = exfat_destroy_inode, + .write_inode = exfat_write_inode, + .evict_inode = exfat_evict_inode, + .put_super = exfat_put_super, + .sync_fs = exfat_sync_fs, + .statfs = exfat_statfs, + .remount_fs = exfat_remount, + .show_options = exfat_show_options, +}; + +/*======================================================================*/ +/* Export Operations */ +/*======================================================================*/ + +static struct inode *exfat_nfs_get_inode(struct super_block *sb, u64 ino, + u32 generation) +{ + struct inode *inode = NULL; + + if (ino < EXFAT_ROOT_INO) + return inode; + inode = ilookup(sb, ino); + + if (inode && generation && (inode->i_generation != generation)) { + iput(inode); + inode = NULL; + } + + return inode; +} + +static struct dentry *exfat_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, + int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + exfat_nfs_get_inode); +} + +static struct dentry *exfat_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, + int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + exfat_nfs_get_inode); +} + +static const struct export_operations exfat_export_ops = { + .fh_to_dentry = exfat_fh_to_dentry, + .fh_to_parent = exfat_fh_to_parent, +}; + +/*======================================================================*/ +/* Super Block Read Operations */ +/*======================================================================*/ + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_codepage, + Opt_charset, + Opt_namecase, + Opt_debug, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, + Opt_utf8_hack, + Opt_err, +#ifdef CONFIG_EXFAT_DISCARD + Opt_discard, +#endif /* EXFAT_CONFIG_DISCARD */ +}; + +static const match_table_t exfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_codepage, "codepage=%u"}, + {Opt_charset, "iocharset=%s"}, + {Opt_namecase, "namecase=%u"}, + {Opt_debug, "debug"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, + {Opt_utf8_hack, "utf8"}, +#ifdef CONFIG_EXFAT_DISCARD + {Opt_discard, "discard"}, +#endif /* CONFIG_EXFAT_DISCARD */ + {Opt_err, NULL} +}; + +static int parse_options(char *options, int silent, int *debug, + struct exfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + char *iocharset; + + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = (unsigned short) -1; + opts->codepage = exfat_default_codepage; + opts->iocharset = exfat_default_iocharset; + opts->casesensitive = 0; + opts->errors = EXFAT_ERRORS_RO; +#ifdef CONFIG_EXFAT_DISCARD + opts->discard = 0; +#endif + *debug = 0; + + if (!options) + goto out; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + + if (!*p) + continue; + + token = match_token(p, exfat_tokens, args); + switch (token) { + case Opt_uid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_uid = KUIDT_INIT(option); + break; + case Opt_gid: + if (match_int(&args[0], &option)) + return 0; + opts->fs_gid = KGIDT_INIT(option); + break; + case Opt_umask: + case Opt_dmask: + case Opt_fmask: + if (match_octal(&args[0], &option)) + return 0; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; + break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & 0022; + break; + case Opt_codepage: + if (match_int(&args[0], &option)) + return 0; + opts->codepage = option; + break; + case Opt_charset: + if (opts->iocharset != exfat_default_iocharset) + kfree(opts->iocharset); + iocharset = match_strdup(&args[0]); + if (!iocharset) + return -ENOMEM; + opts->iocharset = iocharset; + break; + case Opt_namecase: + if (match_int(&args[0], &option)) + return 0; + opts->casesensitive = option; + break; + case Opt_err_cont: + opts->errors = EXFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = EXFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = EXFAT_ERRORS_RO; + break; + case Opt_debug: + *debug = 1; + break; +#ifdef CONFIG_EXFAT_DISCARD + case Opt_discard: + opts->discard = 1; + break; +#endif /* CONFIG_EXFAT_DISCARD */ + case Opt_utf8_hack: + break; + default: + if (!silent) + pr_err("[EXFAT] Unrecognized mount option %s or missing value\n", + p); + return -EINVAL; + } + } + +out: + if (opts->allow_utime == (unsigned short) -1) + opts->allow_utime = ~opts->fs_dmask & 0022; + + return 0; +} + +static void exfat_hash_init(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < EXFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int exfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct fs_info_t *p_fs = &(sbi->fs_info); + struct dir_entry_t info; + + EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; + EXFAT_I(inode)->fid.dir.flags = 0x01; + EXFAT_I(inode)->fid.entry = -1; + EXFAT_I(inode)->fid.start_clu = p_fs->root_dir; + EXFAT_I(inode)->fid.flags = 0x01; + EXFAT_I(inode)->fid.type = TYPE_DIR; + EXFAT_I(inode)->fid.rwoffset = 0; + EXFAT_I(inode)->fid.hint_last_off = -1; + + EXFAT_I(inode)->target = NULL; + + ffsReadStat(inode, &info); + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + INC_IVERSION(inode); + inode->i_generation = 0; + inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, 0777); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + EXFAT_I(inode)->i_pos = ((loff_t) p_fs->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + set_nlink(inode, info.NumSubdirs + 2); + + return 0; +} + +static void setup_dops(struct super_block *sb) +{ + if (EXFAT_SB(sb)->options.casesensitive == 0) + sb->s_d_op = &exfat_ci_dentry_ops; + else + sb->s_d_op = &exfat_dentry_ops; +} + +static int exfat_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode = NULL; + struct exfat_sb_info *sbi; + int debug, ret; + long error; + char buf[50]; + + /* + * GFP_KERNEL is ok here, because while we do hold the + * supeblock lock, memory pressure can't call back into + * the filesystem, since we're only just about to mount + * it and have no inodes etc active! + */ + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + mutex_init(&sbi->s_lock); + sb->s_fs_info = sbi; + sb->s_flags |= SB_NODIRATIME; + sb->s_magic = EXFAT_SUPER_MAGIC; + sb->s_op = &exfat_sops; + sb->s_export_op = &exfat_export_ops; + + error = parse_options(data, silent, &debug, &sbi->options); + if (error) + goto out_fail; + + setup_dops(sb); + + error = -EIO; + sb_min_blocksize(sb, 512); + sb->s_maxbytes = 0x7fffffffffffffffLL; /* maximum file size */ + + ret = ffsMountVol(sb); + if (ret) { + if (!silent) + pr_err("[EXFAT] ffsMountVol failed\n"); + + goto out_fail; + } + + /* set up enough so that it can read an inode */ + exfat_hash_init(sb); + + /* + * The low byte of FAT's first entry must have same value with + * media-field. But in real world, too many devices is + * writing wrong value. So, removed that validity check. + * + * if (FAT_FIRST_ENT(sb, media) != first) + */ + + /* codepage is not meaningful in exfat */ + if (sbi->fs_info.vol_type != EXFAT) { + error = -EINVAL; + sprintf(buf, "cp%d", sbi->options.codepage); + sbi->nls_disk = load_nls(buf); + if (!sbi->nls_disk) { + pr_err("[EXFAT] Codepage %s not found\n", buf); + goto out_fail2; + } + } + + sbi->nls_io = load_nls(sbi->options.iocharset); + + error = -ENOMEM; + root_inode = new_inode(sb); + if (!root_inode) + goto out_fail2; + root_inode->i_ino = EXFAT_ROOT_INO; + SET_IVERSION(root_inode, 1); + + error = exfat_read_root(root_inode); + if (error < 0) + goto out_fail2; + error = -ENOMEM; + exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); + sb->s_root = d_make_root(root_inode); + if (!sb->s_root) { + pr_err("[EXFAT] Getting the root inode failed\n"); + goto out_fail2; + } + + return 0; + +out_fail2: + ffsUmountVol(sb); +out_fail: + if (root_inode) + iput(root_inode); + sb->s_fs_info = NULL; + exfat_free_super(sbi); + return error; +} + +static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); +} + +static void init_once(void *foo) +{ + struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init exfat_init_inodecache(void) +{ + exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", + sizeof(struct exfat_inode_info), + 0, + (SLAB_RECLAIM_ACCOUNT | + SLAB_MEM_SPREAD), + init_once); + if (exfat_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + +static void __exit exfat_destroy_inodecache(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(exfat_inode_cachep); +} + +#ifdef CONFIG_EXFAT_KERNEL_DEBUG +static void exfat_debug_kill_sb(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct block_device *bdev = sb->s_bdev; + struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); + + long flags; + + if (sbi) { + flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) { + /* + * invalidate_bdev drops all device cache include + * dirty. We use this to simulate device removal. + */ + down(&p_fs->v_sem); + FAT_release_all(sb); + buf_release_all(sb); + up(&p_fs->v_sem); + + invalidate_bdev(bdev); + } + } + + kill_block_super(sb); +} +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + +static struct file_system_type exfat_fs_type = { + .owner = THIS_MODULE, + .name = "exfat", + .mount = exfat_fs_mount, +#ifdef CONFIG_EXFAT_KERNEL_DEBUG + .kill_sb = exfat_debug_kill_sb, +#else + .kill_sb = kill_block_super, +#endif /* CONFIG_EXFAT_KERNEL_DEBUG */ + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_exfat(void) +{ + int err; + + BUILD_BUG_ON(sizeof(struct dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct dos_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct ext_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct file_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct strm_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct name_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct bmap_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct case_dentry_t) != DENTRY_SIZE); + BUILD_BUG_ON(sizeof(struct volm_dentry_t) != DENTRY_SIZE); + + pr_info("exFAT: Version %s\n", EXFAT_VERSION); + + err = exfat_init_inodecache(); + if (err) + return err; + + err = register_filesystem(&exfat_fs_type); + if (err) + return err; + + return 0; +} + +static void __exit exit_exfat(void) +{ + exfat_destroy_inodecache(); + unregister_filesystem(&exfat_fs_type); +} + +module_init(init_exfat); +module_exit(exit_exfat); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("exFAT Filesystem Driver"); +MODULE_ALIAS_FS("exfat"); diff --git a/drivers/staging/exfat/exfat_upcase.c b/drivers/staging/exfat/exfat_upcase.c new file mode 100644 index 000000000000..366082fb3dab --- /dev/null +++ b/drivers/staging/exfat/exfat_upcase.c @@ -0,0 +1,740 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + */ + +#include +#include "exfat.h" + +const u8 uni_upcase[NUM_UPCASE << 1] = { + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, + 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, + 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, + 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, + 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, + 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, + 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, + 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, + 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, + 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, + 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, + 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, + 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, + 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, + 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, + 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, + 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, + 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, + 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, + 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, + 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, + 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, + 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, + 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, + 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, + 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, + 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, + 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, + 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, + 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, + 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, + 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, + 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, + 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, + 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, + 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, + 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, + 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, + 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, + 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, + 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, + 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, + 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, + 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, + 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, + 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, + 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, + 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, + 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, + 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, + 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, + 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, + 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, + 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, + 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, + 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, + 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, + 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, + 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, + 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, + 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, + 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, + 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, + 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, + 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, + 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, + 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, + 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, + 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, + 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, + 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, + 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, + 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, + 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, + 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, + 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, + 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, + 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, + 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, + 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, + 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, + 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, + 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, + 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, + 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, + 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, + 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, + 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, + 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, + 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, + 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, + 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, + 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, + 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, + 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, + 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, + 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, + 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, + 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, + 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, + 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, + 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, + 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, + 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, + 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, + 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, + 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, + 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, + 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, + 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, + 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, + 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, + 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, + 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, + 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, + 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, + 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, + 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, + 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, + 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, + 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, + 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, + 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, + 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, + 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, + 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, + 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, + 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, + 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, + 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, + 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, + 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, + 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, + 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, + 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, + 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, + 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, + 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, + 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, + 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, + 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, + 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, + 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, + 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, + 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, + 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, + 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, + 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, + 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, + 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, + 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, + 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, + 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, + 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, + 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, + 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, + 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, + 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, + 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, + 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, + 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, + 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, + 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, + 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, + 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, + 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, + 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, + 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, + 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, + 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, + 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, + 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, + 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, + 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, + 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, + 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, + 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, + 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, + 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, + 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, + 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, + 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, + 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, + 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, + 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, + 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, + 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, + 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, + 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, + 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, + 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, + 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, + 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, + 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, + 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, + 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, + 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, + 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, + 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, + 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, + 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, + 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, + 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, + 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, + 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, + 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, + 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, + 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, + 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, + 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, + 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, + 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, + 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, + 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, + 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, + 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, + 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, + 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, + 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, + 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, + 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, + 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, + 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, + 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, + 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, + 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, + 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, + 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, + 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, + 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, + 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, + 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, + 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, + 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, + 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, + 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, + 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, + 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, + 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, + 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, + 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, + 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, + 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, + 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, + 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, + 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, + 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, + 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, + 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, + 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, + 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, + 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, + 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, + 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, + 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, + 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, + 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, + 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, + 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, + 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, + 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, + 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, + 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, + 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, + 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, + 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, + 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, + 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, + 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, + 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, + 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, + 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, + 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, + 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, + 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, + 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, + 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, + 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, + 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, + 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, + 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, + 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, + 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, + 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, + 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, + 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, + 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, + 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, + 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, + 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, + 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, + 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, + 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, + 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, + 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, + 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, + 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, + 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, + 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, + 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, + 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, + 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, + 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, + 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, + 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, + 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, + 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, + 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, + 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, + 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, + 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, + 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, + 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, + 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, + 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, + 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, + 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, + 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, + 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, + 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, + 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, + 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, + 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, + 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, + 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, + 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, + 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, + 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, + 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, + 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, + 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, + 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, + 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, + 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, + 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, + 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, + 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, + 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, + 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, + 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, + 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, + 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, + 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, + 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, + 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, + 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, + 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, + 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, + 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, + 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, + 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, + 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, + 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, + 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, + 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, + 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, + 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, + 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, + 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, + 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, + 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, + 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, + 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, + 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, + 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, + 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, + 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, + 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, + 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, + 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, + 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, + 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, + 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, + 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, + 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, + 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, + 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, + 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, + 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, + 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, + 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, + 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, + 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, + 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, + 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, + 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, + 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, + 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, + 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, + 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, + 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, + 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, + 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, + 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, + 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, + 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, + 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, + 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, + 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, + 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, + 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, + 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, + 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, + 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, + 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, + 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, + 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, + 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, + 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, + 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, + 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, + 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, + 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, + 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, + 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, + 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, + 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, + 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, + 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, + 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, + 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, + 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, + 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, + 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, + 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, + 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, + 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, + 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, + 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, + 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, + 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, + 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, + 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, + 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, + 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, + 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, + 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, + 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, + 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, + 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, + 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, + 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, + 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, + 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, + 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, + 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, + 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, + 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, + 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, + 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, + 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, + 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, + 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, + 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, + 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, + 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, + 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, + 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, + 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, + 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, + 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, + 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, + 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, + 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, + 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, + 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, + 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, + 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, + 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, + 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, + 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, + 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, + 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, + 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, + 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, + 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, + 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, + 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, + 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, + 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, + 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, + 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, + 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, + 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, + 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, + 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, + 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, + 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, + 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, + 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, + 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, + 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, + 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, + 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, + 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, + 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, + 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, + 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, + 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, + 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, + 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, + 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, + 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, + 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, + 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, + 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, + 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, + 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, + 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, + 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, + 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, + 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, + 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, + 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, + 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, + 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, + 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, + 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, + 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, + 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, + 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, + 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, + 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, + 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, + 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, + 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, + 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, + 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, + 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, + 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, + 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, + 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, + 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, + 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, + 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, + 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, + 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, + 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, + 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, + 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, + 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, + 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, + 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, + 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, + 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, + 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, + 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, + 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, + 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, + 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, + 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, + 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, + 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, + 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, + 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, + 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, + 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, + 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, + 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, + 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, + 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, + 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, + 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, + 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, + 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, + 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, + 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, + 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, + 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, + 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, + 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, + 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, + 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, + 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, + 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, + 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, + 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, + 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, + 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, + 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, + 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, + 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, + 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, + 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, + 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, + 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, + 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, + 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, + 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, + 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, + 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, + 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, + 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, + 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, + 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, + 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, + 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, + 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, + 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, + 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, + 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, + 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, + 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, + 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, + 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, + 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, + 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, + 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, + 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, + 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, + 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, + 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, + 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, + 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, + 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, + 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, + 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, + 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, + 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, + 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, + 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, + 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, + 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, + 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, + 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, + 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, + 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, + 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, + 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, + 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, + 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, + 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, + 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, + 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, + 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, + 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, + 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, + 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, + 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, + 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, + 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, + 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, + 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF +}; -- cgit v1.2.3-59-g8ed1b From 58985a9d2d03e977db93bf574a16162766a318fe Mon Sep 17 00:00:00 2001 From: Valdis Klētnieks Date: Fri, 30 Aug 2019 12:42:39 -0400 Subject: drivers/staging/exfat - by default, prohibit mount of fat/vfat Concerns have been raised about the exfat driver accidentally mounting fat/vfat file systems. Add an extra configure option to help prevent that. Signed-off-by: Valdis Kletnieks Link: https://lore.kernel.org/r/245727.1567183359@turing-police Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/Kconfig | 8 ++++++++ drivers/staging/exfat/exfat_super.c | 6 ++++++ 2 files changed, 14 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig index 78b32aa2ca19..f52129c67f97 100644 --- a/drivers/staging/exfat/Kconfig +++ b/drivers/staging/exfat/Kconfig @@ -4,6 +4,14 @@ config EXFAT_FS help This adds support for the exFAT file system. +config EXFAT_DONT_MOUNT_VFAT + bool "Prohibit mounting of fat/vfat filesysems by exFAT" + default y + help + By default, the exFAT driver will only mount exFAT filesystems, and refuse + to mount fat/vfat filesystems. Set this to 'n' to allow the exFAT driver + to mount these filesystems. + config EXFAT_DISCARD bool "enable discard support" depends on EXFAT_FS diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 5b5c2ca8c9aa..d9787635a373 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -486,10 +486,16 @@ static int ffsMountVol(struct super_block *sb) break; if (i < 53) { +#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT + ret = -EINVAL; + printk(KERN_INFO "EXFAT: Attempted to mount VFAT filesystem\n"); + goto out; +#else if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */ ret = fat16_mount(sb, p_pbr); else ret = fat32_mount(sb, p_pbr); +#endif } else { ret = exfat_mount(sb, p_pbr); } -- cgit v1.2.3-59-g8ed1b From 544b3e7fd2d39b571298c64000423df21b912a3b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 2 Sep 2019 19:45:06 +0200 Subject: staging: exfat: make exfat depend on BLOCK This should fix a build error in some configurations when CONFIG_BLOCK is not selected. Also properly set the dependancy for no FAT support at the same time. Reported-by: Randy Dunlap Cc: Valdis Kletnieks Link: https://lore.kernel.org/r/20190902174631.GB31445@kroah.com Acked-by: Randy Dunlap # build-tested Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig index f52129c67f97..290dbfc7ace1 100644 --- a/drivers/staging/exfat/Kconfig +++ b/drivers/staging/exfat/Kconfig @@ -1,11 +1,13 @@ config EXFAT_FS tristate "exFAT fs support" + depends on BLOCK select NLS help This adds support for the exFAT file system. config EXFAT_DONT_MOUNT_VFAT bool "Prohibit mounting of fat/vfat filesysems by exFAT" + depends on EXFAT_FS default y help By default, the exFAT driver will only mount exFAT filesystems, and refuse -- cgit v1.2.3-59-g8ed1b From 5b489e2ff650ba7d3ff50e80e8dec2305be6bb62 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Mon, 2 Sep 2019 21:03:29 +0200 Subject: staging: exfat: cleanup blank line warnings Fixes checkpatch.pl warnings: CHECK: Please don't use multiple blank lines CHECK: Blank lines aren't necessary after an open brace '{' CHECK: Please use a blank line after function/struct/union/enum declarations Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190902190329.18685-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat.h | 1 + drivers/staging/exfat/exfat_core.c | 4 ---- drivers/staging/exfat/exfat_super.c | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h index bae180e10609..e41754bbdeab 100644 --- a/drivers/staging/exfat/exfat.h +++ b/drivers/staging/exfat/exfat.h @@ -170,6 +170,7 @@ static inline u16 get_col_index(u16 i) { return i >> LOW_INDEX_BIT; } + static inline u16 get_row_index(u16 i) { return i & ~HIGH_INDEX_MASK; diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 9f76ca175c80..46b9f4455da1 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -11,7 +11,6 @@ #include #include "exfat.h" - static void __set_sb_dirty(struct super_block *sb) { struct exfat_sb_info *sbi = EXFAT_SB(sb); @@ -1711,7 +1710,6 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, if (ret != FFS_SUCCESS) return NULL; - /* byte offset in cluster */ byte_offset &= p_fs->cluster_size - 1; @@ -1726,7 +1724,6 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, if (buf == NULL) goto err_out; - ep = (struct dentry_t *)(buf + off); entry_type = p_fs->fs_func->get_entry_type(ep); @@ -1853,7 +1850,6 @@ void release_entry_set(struct entry_set_cache_t *es) kfree(es); } - static s32 __write_partial_entries_in_entry_set(struct super_block *sb, struct entry_set_cache_t *es, sector_t sec, s32 off, u32 count) diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index d9787635a373..15970b34e38f 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -3017,7 +3017,6 @@ out: static int exfat_setattr(struct dentry *dentry, struct iattr *attr) { - struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); struct inode *inode = dentry->d_inode; unsigned int ia_valid; -- cgit v1.2.3-59-g8ed1b From ef16b89c8243f8407938e5f3e2134444338c1b45 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Mon, 2 Sep 2019 20:43:19 +0200 Subject: staging: exfat: use BIT macro for defining sizes Fixes checkpatch.pl warning: CHECK: Prefer using the BIT macro Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190902184319.11971-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h index e41754bbdeab..816681d1103a 100644 --- a/drivers/staging/exfat/exfat.h +++ b/drivers/staging/exfat/exfat.h @@ -163,8 +163,8 @@ #define HIGH_INDEX_BIT (8) #define HIGH_INDEX_MASK (0xFF00) #define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) -#define UTBL_ROW_COUNT (1< Date: Fri, 30 Aug 2019 19:46:44 +0100 Subject: staging: exfat: fix uninitialized variable ret Currently there are error return paths in ffsReadFile that exit via lable err_out that return and uninitialized error return in variable ret. Fix this by initializing ret to zero. Addresses-Coverity: ("Uninitialized scalar variable") Fixes: c48c9f7ff32b ("staging: exfat: add exfat filesystem code to staging") Signed-off-by: Colin Ian King Cc: Valdis Kletnieks , Reviewed-by: Nathan Chancellor Link: https://lore.kernel.org/r/20190830184644.15590-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 15970b34e38f..aaebd40ee6f3 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -779,7 +779,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, { s32 offset, sec_offset, clu_offset; u32 clu; - int ret; + int ret = 0; sector_t LogSector; u64 oneblkread, read_bytes; struct buffer_head *tmp_bh = NULL; -- cgit v1.2.3-59-g8ed1b From be22bc7ceb5f4a713924c2ccaa9db1c27992b739 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 2 Sep 2019 10:40:52 +0100 Subject: staging: exfat: remove return and error return via a goto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return statement is incorrect, the error exit should be by assigning ret with the error code and exiting via label out. Thanks to Valdis Klētnieks for correcting my original fix. Addresses-Coverity: ("Structurally dead code") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190902094052.28029-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index aaebd40ee6f3..881cd85cf677 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -670,7 +670,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, &dos_name, TYPE_ALL); if (dentry < -1) { - return FFS_NOTFOUND; + ret = FFS_NOTFOUND; goto out; } -- cgit v1.2.3-59-g8ed1b From 2e63a4a4b78e2a68a475be98cdefedea30dc0d5c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 30 Aug 2019 09:10:47 +0100 Subject: staging: rts5208: remove redundant sd30_mode checks There are two hunks of code that check if sd30_mode is true however an earlier check in an outer code block on sd30_mode being false means that sd30_mode can never be true at these points so these checks are redundant. Remove the dead code. Addresses-Coverity: ("Logically dead code") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190830081047.13630-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index a06045344301..25c31496757e 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -2573,17 +2573,13 @@ SD_UNLOCK_ENTRY: retval = sd_sdr_tuning(chip); if (retval != STATUS_SUCCESS) { - if (sd20_mode) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) goto status_fail; - } else { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - try_sdio = false; - sd20_mode = true; - goto switch_fail; - } + try_sdio = false; + sd20_mode = true; + goto switch_fail; } sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, @@ -2598,17 +2594,13 @@ SD_UNLOCK_ENTRY: if (read_lba0) { retval = sd_read_lba0(chip); if (retval != STATUS_SUCCESS) { - if (sd20_mode) { + retval = sd_init_power(chip); + if (retval != STATUS_SUCCESS) goto status_fail; - } else { - retval = sd_init_power(chip); - if (retval != STATUS_SUCCESS) - goto status_fail; - try_sdio = false; - sd20_mode = true; - goto switch_fail; - } + try_sdio = false; + sd20_mode = true; + goto switch_fail; } } } -- cgit v1.2.3-59-g8ed1b From 21d48f69d6fdf4542bab41122e54ccb2d6441dfd Mon Sep 17 00:00:00 2001 From: Prakhar Sinha Date: Fri, 30 Aug 2019 17:46:56 +0530 Subject: staging: rts5208: Fixed checkpath warning. This patch solves the following checkpatch.pl's message in drivers/staging/rts5208/rtsx_transport.c:397. WARNING: line over 80 characters + option = RTSX_SG_VALID | RTSX_SG_END | RTSX_SG_TRANS_DATA; Signed-off-by: Prakhar Sinha Link: https://lore.kernel.org/r/20190830121656.GA2740@MeraComputer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_transport.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index 8277d7895608..e61bc7c6ac33 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -393,10 +393,9 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, *offset = 0; *index = *index + 1; } - if ((i == (sg_cnt - 1)) || !resid) - option = RTSX_SG_VALID | RTSX_SG_END | RTSX_SG_TRANS_DATA; - else - option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; + option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; + if ((i == sg_cnt - 1) || !resid) + option |= RTSX_SG_END; rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); -- cgit v1.2.3-59-g8ed1b From 20738057210365bbcd8a718c04ded6c93a262b95 Mon Sep 17 00:00:00 2001 From: P SAI PRASANTH Date: Sat, 31 Aug 2019 09:19:26 +0530 Subject: staging: rts5208: Fix checkpath warning This patch fixes the following checkpath warning in the file drivers/staging/rts5208/rtsx_transport.c:546 WARNING: line over 80 characters + option = RTSX_SG_VALID | RTSX_SG_END | RTSX_SG_TRANS_DATA; Signed-off-by: P SAI PRASANTH Link: https://lore.kernel.org/r/20190831034926.GA17810@dell-inspiron Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/rtsx_transport.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index e61bc7c6ac33..561851cc8780 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -540,10 +540,9 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); + option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; if (j == (sg_cnt - 1)) - option = RTSX_SG_VALID | RTSX_SG_END | RTSX_SG_TRANS_DATA; - else - option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA; + option |= RTSX_SG_END; rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option); -- cgit v1.2.3-59-g8ed1b From 329101244f214952606359d254ae883b7109e1a5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 29 Aug 2019 15:28:39 +0300 Subject: staging: greybus: light: fix a couple double frees The problem is in gb_lights_request_handler(). If we get a request to change the config then we release the light with gb_lights_light_release() and re-allocated it. However, if the allocation fails part way through then we call gb_lights_light_release() again. This can lead to a couple different double frees where we haven't cleared out the original values: gb_lights_light_v4l2_unregister(light); ... kfree(light->channels); kfree(light->name); I also made a small change to how we set "light->channels_count = 0;". The original code handled this part fine and did not cause a use after free but it was sort of complicated to read. Fixes: 2870b52bae4c ("greybus: lights: add lights implementation") Signed-off-by: Dan Carpenter Acked-by: Rui Miguel Silva Link: https://lore.kernel.org/r/20190829122839.GA20116@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/light.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index b3b1b253d112..d6ba25f21d80 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -1096,21 +1096,21 @@ static void gb_lights_channel_release(struct gb_channel *channel) static void gb_lights_light_release(struct gb_light *light) { int i; - int count; light->ready = false; - count = light->channels_count; - if (light->has_flash) gb_lights_light_v4l2_unregister(light); + light->has_flash = false; - for (i = 0; i < count; i++) { + for (i = 0; i < light->channels_count; i++) gb_lights_channel_release(&light->channels[i]); - light->channels_count--; - } + light->channels_count = 0; + kfree(light->channels); + light->channels = NULL; kfree(light->name); + light->name = NULL; } static void gb_lights_release(struct gb_lights *glights) -- cgit v1.2.3-59-g8ed1b From dab8fe7ea267711cf28bb7c87361fa3c2293fa97 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 30 Aug 2019 18:50:50 +0100 Subject: staging: exfat: check for null return from call to FAT_getblk A call to FAT_getblk is missing a null return check which can lead to a null pointer dereference. Fix this by adding a null check to match all the other FAT_getblk return sanity checks. Addresses-Coverity: ("Dereference null return") Fixes: c48c9f7ff32b ("staging: exfat: add exfat filesystem code to staging") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190830175050.12706-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_cache.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c index f05d692c2b1e..1565ce65d39f 100644 --- a/drivers/staging/exfat/exfat_cache.c +++ b/drivers/staging/exfat/exfat_cache.c @@ -369,6 +369,8 @@ static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content) FAT_modify(sb, sec); fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; fat_sector[0] = (u8)((fat_sector[0] & 0xF0) | (content >> 8)); } else { -- cgit v1.2.3-59-g8ed1b From f08ab0abb6990db3d93b917f6e701ba6b05d604e Mon Sep 17 00:00:00 2001 From: Harsh Jain Date: Sat, 31 Aug 2019 17:25:32 +0530 Subject: staging: kpc2000: Fix long constant sparse warning It fixed following warning in kpc2000 driver "constant XXXX is so big it is unsigned long" Signed-off-by: Harsh Jain Link: https://lore.kernel.org/r/20190831115532.2398-1-harshjain32@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/kpc2000/kpc2000/cell_probe.c | 18 +++++++++--------- drivers/staging/kpc2000/kpc2000/core.c | 18 +++++++++--------- drivers/staging/kpc2000/kpc_dma/fileops.c | 8 ++++---- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/kpc2000/kpc2000/cell_probe.c b/drivers/staging/kpc2000/kpc2000/cell_probe.c index c124a836db27..738122afc2ae 100644 --- a/drivers/staging/kpc2000/kpc2000/cell_probe.c +++ b/drivers/staging/kpc2000/kpc2000/cell_probe.c @@ -53,15 +53,15 @@ struct core_table_entry { static void parse_core_table_entry_v0(struct core_table_entry *cte, const u64 read_val) { - cte->type = ((read_val & 0xFFF0000000000000) >> 52); - cte->offset = ((read_val & 0x00000000FFFF0000) >> 16) * 4096; - cte->length = ((read_val & 0x0000FFFF00000000) >> 32) * 8; - cte->s2c_dma_present = ((read_val & 0x0008000000000000) >> 51); - cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000) >> 48); - cte->c2s_dma_present = ((read_val & 0x0000000000008000) >> 15); - cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000) >> 12); - cte->irq_count = ((read_val & 0x0000000000000C00) >> 10); - cte->irq_base_num = ((read_val & 0x00000000000003F8) >> 3); + cte->type = ((read_val & 0xFFF0000000000000UL) >> 52); + cte->offset = ((read_val & 0x00000000FFFF0000UL) >> 16) * 4096; + cte->length = ((read_val & 0x0000FFFF00000000UL) >> 32) * 8; + cte->s2c_dma_present = ((read_val & 0x0008000000000000UL) >> 51); + cte->s2c_dma_channel_num = ((read_val & 0x0007000000000000UL) >> 48); + cte->c2s_dma_present = ((read_val & 0x0000000000008000UL) >> 15); + cte->c2s_dma_channel_num = ((read_val & 0x0000000000007000UL) >> 12); + cte->irq_count = ((read_val & 0x0000000000000C00UL) >> 10); + cte->irq_base_num = ((read_val & 0x00000000000003F8UL) >> 3); } static diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c index cb05cca687e1..0a23727d0dc3 100644 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ b/drivers/staging/kpc2000/kpc2000/core.c @@ -205,7 +205,7 @@ static void wait_and_read_ssid(struct kp2000_device *pcard) u64 read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); unsigned long timeout; - if (read_val & 0x8000000000000000) { + if (read_val & 0x8000000000000000UL) { pcard->ssid = read_val; return; } @@ -213,7 +213,7 @@ static void wait_and_read_ssid(struct kp2000_device *pcard) timeout = jiffies + (HZ * 2); do { read_val = readq(pcard->sysinfo_regs_base + REG_FPGA_SSID); - if (read_val & 0x8000000000000000) { + if (read_val & 0x8000000000000000UL) { pcard->ssid = read_val; return; } @@ -241,16 +241,16 @@ static int read_system_regs(struct kp2000_device *pcard) } read_val = readq(pcard->sysinfo_regs_base + REG_CARD_ID_AND_BUILD); - pcard->card_id = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->build_version = (read_val & 0x00000000FFFFFFFF) >> 0; + pcard->card_id = (read_val & 0xFFFFFFFF00000000UL) >> 32; + pcard->build_version = (read_val & 0x00000000FFFFFFFFUL) >> 0; read_val = readq(pcard->sysinfo_regs_base + REG_DATE_AND_TIME_STAMPS); - pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->build_timestamp = (read_val & 0x00000000FFFFFFFF) >> 0; + pcard->build_datestamp = (read_val & 0xFFFFFFFF00000000UL) >> 32; + pcard->build_timestamp = (read_val & 0x00000000FFFFFFFFUL) >> 0; read_val = readq(pcard->sysinfo_regs_base + REG_CORE_TABLE_OFFSET); - pcard->core_table_length = (read_val & 0xFFFFFFFF00000000) >> 32; - pcard->core_table_offset = (read_val & 0x00000000FFFFFFFF) >> 0; + pcard->core_table_length = (read_val & 0xFFFFFFFF00000000UL) >> 32; + pcard->core_table_offset = (read_val & 0x00000000FFFFFFFFUL) >> 0; wait_and_read_ssid(pcard); @@ -401,7 +401,7 @@ static int kp2000_pcie_probe(struct pci_dev *pdev, goto err_release_dma; // Disable all "user" interrupts because they're not used yet. - writeq(0xFFFFFFFFFFFFFFFF, + writeq(0xFFFFFFFFFFFFFFFFUL, pcard->sysinfo_regs_base + REG_INTERRUPT_MASK); // let the card master PCIe diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c index 48ca88bc6b0b..cb52bd9a6d2f 100644 --- a/drivers/staging/kpc2000/kpc_dma/fileops.c +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c @@ -146,15 +146,15 @@ static int kpc_dma_transfer(struct dev_private_data *priv, card_addr += desc->DescByteCount; dma_addr = sg_dma_address(sg) + (p * 0x80000); - desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFF) >> 0; - desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000) >> 32; + desc->DescSystemAddrLS = (dma_addr & 0x00000000FFFFFFFFUL) >> 0; + desc->DescSystemAddrMS = (dma_addr & 0xFFFFFFFF00000000UL) >> 32; user_ctl = acd->priv->user_ctl; if (i == acd->mapped_entry_count-1 && p == pcnt-1) { user_ctl = acd->priv->user_ctl_last; } - desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFF) >> 0; - desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000) >> 32; + desc->DescUserControlLS = (user_ctl & 0x00000000FFFFFFFFUL) >> 0; + desc->DescUserControlMS = (user_ctl & 0xFFFFFFFF00000000UL) >> 32; if (i == acd->mapped_entry_count-1 && p == pcnt-1) desc->acd = acd; -- cgit v1.2.3-59-g8ed1b From 39a4916b19e1fdbef987e52fcd4870d3423c470a Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Sun, 1 Sep 2019 22:53:01 +0300 Subject: staging: r8188eu: use skb_put_data instead of skb_put/memcpy pair skb_put_data is shorter and clear. Signed-off-by: Ivan Safonov Link: https://lore.kernel.org/r/20190901195301.GA16043@alpha Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 6 +----- drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 620da6c003d8..d4278361e002 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1373,11 +1373,7 @@ static struct recv_frame *recvframe_defrag(struct adapter *adapter, /* append to first fragment frame's tail (if privacy frame, pull the ICV) */ skb_trim(prframe->pkt, prframe->pkt->len - prframe->attrib.icv_len); - /* memcpy */ - memcpy(skb_tail_pointer(prframe->pkt), pnfhdr->pkt->data, - pnfhdr->pkt->len); - - skb_put(prframe->pkt, pnfhdr->pkt->len); + skb_put_data(prframe->pkt, pnfhdr->pkt->data, pnfhdr->pkt->len); prframe->attrib.icv_len = pnfhdr->attrib.icv_len; plist = plist->next; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index eedf2cd831d1..aaab0d577453 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -122,8 +122,7 @@ static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb) precvframe->pkt = pkt_copy; skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */ skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */ - memcpy(pkt_copy->data, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len); - skb_put(precvframe->pkt, skb_len); + skb_put_data(pkt_copy, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len); } else { DBG_88E("%s: alloc_skb fail , drop frag frame\n", __func__); -- cgit v1.2.3-59-g8ed1b From 4a39752151362c04019daebe6ba4a1e8c6a8241f Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Sat, 31 Aug 2019 01:15:22 +0200 Subject: staging: rtl8723bs: replace __inline by inline Currently, __inline is #defined as inline in compiler_types.h, so this should not change functionality. It is preparation for removing said #define. While at it, change some "inline static" to the customary "static inline" order. Signed-off-by: Rasmus Villemoes Link: https://lore.kernel.org/r/20190830231527.22304-2-linux@rasmusvillemoes.dk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_pwrctrl.c | 4 ++-- drivers/staging/rtl8723bs/core/rtw_wlan_util.c | 2 +- drivers/staging/rtl8723bs/include/drv_types.h | 6 +++--- drivers/staging/rtl8723bs/include/osdep_service.h | 10 +++++----- drivers/staging/rtl8723bs/include/osdep_service_linux.h | 14 +++++++------- drivers/staging/rtl8723bs/include/rtw_mlme.h | 14 +++++++------- drivers/staging/rtl8723bs/include/rtw_recv.h | 16 ++++++++-------- drivers/staging/rtl8723bs/include/sta_info.h | 2 +- drivers/staging/rtl8723bs/include/wifi.h | 14 +++++++------- drivers/staging/rtl8723bs/include/wlan_bssdef.h | 2 +- 10 files changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index 62b42e29e4fd..4075de07e0a9 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -821,12 +821,12 @@ static void pwr_rpwm_timeout_handler(struct timer_list *t) _set_workitem(&pwrpriv->rpwmtimeoutwi); } -static __inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) +static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) { pwrctrl->alives |= tag; } -static __inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) +static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag) { pwrctrl->alives &= ~tag; } diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index d78fbbc98fa2..ea3ea2a6b314 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -451,7 +451,7 @@ void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigne mutex_unlock(&(adapter_to_dvobj(padapter)->setch_mutex)); } -__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) +inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) { return pnetwork->MacAddress; } diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index 8c1ade44ed81..8d7fce1e39b7 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -478,7 +478,7 @@ struct sdio_data intf_data; #define dvobj_to_pwrctl(dvobj) (&(dvobj->pwrctl_priv)) #define pwrctl_to_dvobj(pwrctl) container_of(pwrctl, struct dvobj_priv, pwrctl_priv) -__inline static struct device *dvobj_to_dev(struct dvobj_priv *dvobj) +static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj) { /* todo: get interface type from dvobj and the return the dev accordingly */ #ifdef RTW_DVOBJ_CHIP_HW_TYPE @@ -634,14 +634,14 @@ struct adapter { /* define RTW_DISABLE_FUNC(padapter, func) (atomic_add(&adapter_to_dvobj(padapter)->disable_func, (func))) */ /* define RTW_ENABLE_FUNC(padapter, func) (atomic_sub(&adapter_to_dvobj(padapter)->disable_func, (func))) */ -__inline static void RTW_DISABLE_FUNC(struct adapter *padapter, int func_bit) +static inline void RTW_DISABLE_FUNC(struct adapter *padapter, int func_bit) { int df = atomic_read(&adapter_to_dvobj(padapter)->disable_func); df |= func_bit; atomic_set(&adapter_to_dvobj(padapter)->disable_func, df); } -__inline static void RTW_ENABLE_FUNC(struct adapter *padapter, int func_bit) +static inline void RTW_ENABLE_FUNC(struct adapter *padapter, int func_bit) { int df = atomic_read(&adapter_to_dvobj(padapter)->disable_func); df &= ~(func_bit); diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h index d2616af95ffa..81a9c19ecc6a 100644 --- a/drivers/staging/rtl8723bs/include/osdep_service.h +++ b/drivers/staging/rtl8723bs/include/osdep_service.h @@ -110,12 +110,12 @@ int _rtw_netif_rx(_nic_hdl ndev, struct sk_buff *skb); extern void _rtw_init_queue(struct __queue *pqueue); -static __inline void thread_enter(char *name) +static inline void thread_enter(char *name) { allow_signal(SIGTERM); } -__inline static void flush_signals_thread(void) +static inline void flush_signals_thread(void) { if (signal_pending (current)) { @@ -125,7 +125,7 @@ __inline static void flush_signals_thread(void) #define rtw_warn_on(condition) WARN_ON(condition) -__inline static int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *parg4) +static inline int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *parg4) { int ret = true; @@ -136,7 +136,7 @@ __inline static int rtw_bug_check(void *parg1, void *parg2, void *parg3, void *p #define _RND(sz, r) ((((sz)+((r)-1))/(r))*(r)) #define RND4(x) (((x >> 2) + (((x & 3) == 0) ? 0: 1)) << 2) -__inline static u32 _RND4(u32 sz) +static inline u32 _RND4(u32 sz) { u32 val; @@ -147,7 +147,7 @@ __inline static u32 _RND4(u32 sz) } -__inline static u32 _RND8(u32 sz) +static inline u32 _RND8(u32 sz) { u32 val; diff --git a/drivers/staging/rtl8723bs/include/osdep_service_linux.h b/drivers/staging/rtl8723bs/include/osdep_service_linux.h index 2f1b51e614fb..c582ede1ac12 100644 --- a/drivers/staging/rtl8723bs/include/osdep_service_linux.h +++ b/drivers/staging/rtl8723bs/include/osdep_service_linux.h @@ -64,12 +64,12 @@ typedef struct work_struct _workitem; -__inline static struct list_head *get_next(struct list_head *list) +static inline struct list_head *get_next(struct list_head *list) { return list->next; } -__inline static struct list_head *get_list_head(struct __queue *queue) +static inline struct list_head *get_list_head(struct __queue *queue) { return (&(queue->queue)); } @@ -78,28 +78,28 @@ __inline static struct list_head *get_list_head(struct __queue *queue) #define LIST_CONTAINOR(ptr, type, member) \ container_of(ptr, type, member) -__inline static void _set_timer(_timer *ptimer, u32 delay_time) +static inline void _set_timer(_timer *ptimer, u32 delay_time) { mod_timer(ptimer , (jiffies+(delay_time*HZ/1000))); } -__inline static void _cancel_timer(_timer *ptimer, u8 *bcancelled) +static inline void _cancel_timer(_timer *ptimer, u8 *bcancelled) { del_timer_sync(ptimer); *bcancelled = true;/* true == 1; false == 0 */ } -__inline static void _init_workitem(_workitem *pwork, void *pfunc, void *cntx) +static inline void _init_workitem(_workitem *pwork, void *pfunc, void *cntx) { INIT_WORK(pwork, pfunc); } -__inline static void _set_workitem(_workitem *pwork) +static inline void _set_workitem(_workitem *pwork) { schedule_work(pwork); } -__inline static void _cancel_workitem_sync(_workitem *pwork) +static inline void _cancel_workitem_sync(_workitem *pwork) { cancel_work_sync(pwork); } diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index 2223e1f139f2..362737b83c3a 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -496,13 +496,13 @@ extern sint rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv); extern sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, sint keyid, u8 set_tx, bool enqueue); extern sint rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv); -__inline static u8 *get_bssid(struct mlme_priv *pmlmepriv) +static inline u8 *get_bssid(struct mlme_priv *pmlmepriv) { /* if sta_mode:pmlmepriv->cur_network.network.MacAddress => bssid */ /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress => ibss mac address */ return pmlmepriv->cur_network.network.MacAddress; } -__inline static sint check_fwstate(struct mlme_priv *pmlmepriv, sint state) +static inline sint check_fwstate(struct mlme_priv *pmlmepriv, sint state) { if (pmlmepriv->fw_state & state) return true; @@ -510,7 +510,7 @@ __inline static sint check_fwstate(struct mlme_priv *pmlmepriv, sint state) return false; } -__inline static sint get_fwstate(struct mlme_priv *pmlmepriv) +static inline sint get_fwstate(struct mlme_priv *pmlmepriv) { return pmlmepriv->fw_state; } @@ -522,7 +522,7 @@ __inline static sint get_fwstate(struct mlme_priv *pmlmepriv) * ### NOTE:#### (!!!!) * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock */ -__inline static void set_fwstate(struct mlme_priv *pmlmepriv, sint state) +static inline void set_fwstate(struct mlme_priv *pmlmepriv, sint state) { pmlmepriv->fw_state |= state; /* FOR HW integration */ @@ -531,7 +531,7 @@ __inline static void set_fwstate(struct mlme_priv *pmlmepriv, sint state) } } -__inline static void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) +static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) { pmlmepriv->fw_state &= ~state; /* FOR HW integration */ @@ -544,7 +544,7 @@ __inline static void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state) * No Limit on the calling context, * therefore set it to be the critical section... */ -__inline static void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) +static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) { spin_lock_bh(&pmlmepriv->lock); if (check_fwstate(pmlmepriv, state) == true) @@ -552,7 +552,7 @@ __inline static void clr_fwstate(struct mlme_priv *pmlmepriv, sint state) spin_unlock_bh(&pmlmepriv->lock); } -__inline static void set_scanned_network_val(struct mlme_priv *pmlmepriv, sint val) +static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv, sint val) { spin_lock_bh(&pmlmepriv->lock); pmlmepriv->num_of_scanned = val; diff --git a/drivers/staging/rtl8723bs/include/rtw_recv.h b/drivers/staging/rtl8723bs/include/rtw_recv.h index 5de946e66302..012d8f54814f 100644 --- a/drivers/staging/rtl8723bs/include/rtw_recv.h +++ b/drivers/staging/rtl8723bs/include/rtw_recv.h @@ -405,7 +405,7 @@ struct recv_buf *rtw_dequeue_recvbuf (struct __queue *queue); void rtw_reordering_ctrl_timeout_handler(struct timer_list *t); -__inline static u8 *get_rxmem(union recv_frame *precvframe) +static inline u8 *get_rxmem(union recv_frame *precvframe) { /* always return rx_head... */ if (precvframe == NULL) @@ -414,7 +414,7 @@ __inline static u8 *get_rxmem(union recv_frame *precvframe) return precvframe->u.hdr.rx_head; } -__inline static u8 *get_recvframe_data(union recv_frame *precvframe) +static inline u8 *get_recvframe_data(union recv_frame *precvframe) { /* alwasy return rx_data */ @@ -425,7 +425,7 @@ __inline static u8 *get_recvframe_data(union recv_frame *precvframe) } -__inline static u8 *recvframe_pull(union recv_frame *precvframe, sint sz) +static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz) { /* rx_data += sz; move rx_data sz bytes hereafter */ @@ -450,7 +450,7 @@ __inline static u8 *recvframe_pull(union recv_frame *precvframe, sint sz) } -__inline static u8 *recvframe_put(union recv_frame *precvframe, sint sz) +static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz) { /* rx_tai += sz; move rx_tail sz bytes hereafter */ @@ -479,7 +479,7 @@ __inline static u8 *recvframe_put(union recv_frame *precvframe, sint sz) -__inline static u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) +static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) { /* rmv data from rx_tail (by yitsen) */ @@ -503,7 +503,7 @@ __inline static u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz) } -__inline static union recv_frame *rxmem_to_recvframe(u8 *rxmem) +static inline union recv_frame *rxmem_to_recvframe(u8 *rxmem) { /* due to the design of 2048 bytes alignment of recv_frame, we can reference the union recv_frame */ /* from any given member of recv_frame. */ @@ -513,13 +513,13 @@ __inline static union recv_frame *rxmem_to_recvframe(u8 *rxmem) } -__inline static sint get_recvframe_len(union recv_frame *precvframe) +static inline sint get_recvframe_len(union recv_frame *precvframe) { return precvframe->u.hdr.len; } -__inline static s32 translate_percentage_to_dbm(u32 SignalStrengthIndex) +static inline s32 translate_percentage_to_dbm(u32 SignalStrengthIndex) { s32 SignalPower; /* in dBm. */ diff --git a/drivers/staging/rtl8723bs/include/sta_info.h b/drivers/staging/rtl8723bs/include/sta_info.h index b9df42d0677e..3acce5630f8e 100644 --- a/drivers/staging/rtl8723bs/include/sta_info.h +++ b/drivers/staging/rtl8723bs/include/sta_info.h @@ -348,7 +348,7 @@ struct sta_priv { }; -__inline static u32 wifi_mac_hash(u8 *mac) +static inline u32 wifi_mac_hash(u8 *mac) { u32 x; diff --git a/drivers/staging/rtl8723bs/include/wifi.h b/drivers/staging/rtl8723bs/include/wifi.h index 8c50bbb20f3b..2faf83704ff0 100644 --- a/drivers/staging/rtl8723bs/include/wifi.h +++ b/drivers/staging/rtl8723bs/include/wifi.h @@ -347,7 +347,7 @@ enum WIFI_REG_DOMAIN { (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \ ) -__inline static int IS_MCAST(unsigned char *da) +static inline int IS_MCAST(unsigned char *da) { if ((*da) & 0x01) return true; @@ -355,20 +355,20 @@ __inline static int IS_MCAST(unsigned char *da) return false; } -__inline static unsigned char * get_ra(unsigned char *pframe) +static inline unsigned char * get_ra(unsigned char *pframe) { unsigned char *ra; ra = GetAddr1Ptr(pframe); return ra; } -__inline static unsigned char * get_ta(unsigned char *pframe) +static inline unsigned char * get_ta(unsigned char *pframe) { unsigned char *ta; ta = GetAddr2Ptr(pframe); return ta; } -__inline static unsigned char * get_da(unsigned char *pframe) +static inline unsigned char * get_da(unsigned char *pframe) { unsigned char *da; unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); @@ -392,7 +392,7 @@ __inline static unsigned char * get_da(unsigned char *pframe) } -__inline static unsigned char * get_sa(unsigned char *pframe) +static inline unsigned char * get_sa(unsigned char *pframe) { unsigned char *sa; unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); @@ -415,7 +415,7 @@ __inline static unsigned char * get_sa(unsigned char *pframe) return sa; } -__inline static unsigned char * get_hdr_bssid(unsigned char *pframe) +static inline unsigned char * get_hdr_bssid(unsigned char *pframe) { unsigned char *sa = NULL; unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); @@ -439,7 +439,7 @@ __inline static unsigned char * get_hdr_bssid(unsigned char *pframe) } -__inline static int IsFrameTypeCtrl(unsigned char *pframe) +static inline int IsFrameTypeCtrl(unsigned char *pframe) { if (WIFI_CTRL_TYPE == GetFrameType(pframe)) return true; diff --git a/drivers/staging/rtl8723bs/include/wlan_bssdef.h b/drivers/staging/rtl8723bs/include/wlan_bssdef.h index 88890b1c3c4c..723fc5b546ef 100644 --- a/drivers/staging/rtl8723bs/include/wlan_bssdef.h +++ b/drivers/staging/rtl8723bs/include/wlan_bssdef.h @@ -223,7 +223,7 @@ struct wlan_bssid_ex { u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and capability information) */ } __packed; -__inline static uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) +static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss) { return (sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength); } -- cgit v1.2.3-59-g8ed1b From a70cfd89dc9ac0f5981741812dc5eaab53356846 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Tue, 3 Sep 2019 18:47:32 +0200 Subject: staging: exfat: cleanup braces for if/else statements Fixes checkpatch.pl warnings: CHECK: Unbalanced braces around else statement CHECK: braces {} should be used on all arms of this statement Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190903164732.14194-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_core.c | 12 ++++++------ drivers/staging/exfat/exfat_super.c | 16 +++++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 46b9f4455da1..1246afcffb8d 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -743,11 +743,11 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); skip = FALSE; - } else if (uni == index) + } else if (uni == index) { index++; - else if (uni == 0xFFFF) + } else if (uni == 0xFFFF) { skip = TRUE; - else { /* uni != index , uni != 0xFFFF */ + } else { /* uni != index , uni != 0xFFFF */ u16 col_index = get_col_index(index); if (upcase_table[col_index] == NULL) { @@ -805,11 +805,11 @@ static s32 __load_default_upcase_table(struct super_block *sb) index += uni; pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); skip = FALSE; - } else if (uni == index) + } else if (uni == index) { index++; - else if (uni == 0xFFFF) + } else if (uni == 0xFFFF) { skip = TRUE; - else { /* uni != index , uni != 0xFFFF */ + } else { /* uni != index , uni != 0xFFFF */ u16 col_index = get_col_index(index); if (upcase_table[col_index] == NULL) { diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 881cd85cf677..e44b860e35e8 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -344,8 +344,10 @@ static int exfat_cmpi(const struct dentry *dentry, unsigned int len, if (t == NULL) { if (strncasecmp(name->name, str, alen) == 0) return 0; - } else if (nls_strnicmp(t, name->name, str, alen) == 0) - return 0; + } else { + if (nls_strnicmp(t, name->name, str, alen) == 0) + return 0; + } } return 1; } @@ -999,7 +1001,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, &new_clu); if (num_alloced == 0) break; - else if (num_alloced < 0) { + if (num_alloced < 0) { ret = FFS_MEDIAERR; goto out; } @@ -1248,9 +1250,9 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); } - if (p_fs->vol_type != EXFAT) + if (p_fs->vol_type != EXFAT) { buf_modify(sb, sector); - else { + } else { update_dir_checksum_with_entry_set(sb, es); release_entry_set(es); } @@ -1561,9 +1563,9 @@ static int ffsSetAttr(struct inode *inode, u32 attr) fid->attr = attr; p_fs->fs_func->set_entry_attr(ep, attr); - if (p_fs->vol_type != EXFAT) + if (p_fs->vol_type != EXFAT) { buf_modify(sb, sector); - else { + } else { update_dir_checksum_with_entry_set(sb, es); release_entry_set(es); } -- cgit v1.2.3-59-g8ed1b From ab050766f94271211fed72e505a378de00217ee1 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Tue, 3 Sep 2019 18:54:08 +0200 Subject: staging: exfat: fix spelling errors in comments Fixes checkpatch.pl warnings: CHECK: 'consistancy' may be misspelled - perhaps 'consistency'? CHECK: 'stuct' may be misspelled - perhaps 'struct'? Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190903165408.16010-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_core.c | 2 +- drivers/staging/exfat/exfat_super.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 1246afcffb8d..73b9991c272a 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -1754,7 +1754,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, while (num_entries) { /* * instead of copying whole sector, we will check every entry. - * this will provide minimum stablity and consistancy. + * this will provide minimum stablity and consistency. */ entry_type = p_fs->fs_func->get_entry_type(ep); diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index e44b860e35e8..359c749278cb 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -482,7 +482,7 @@ static int ffsMountVol(struct super_block *sb) goto out; } - /* fill fs_stuct */ + /* fill fs_struct */ for (i = 0; i < 53; i++) if (p_pbr->bpb[i]) break; -- cgit v1.2.3-59-g8ed1b From dfa5b30b12aa8c324d6b90c369e71c90061a8a33 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Tue, 3 Sep 2019 20:55:37 +0200 Subject: staging: exfat: drop local TRUE/FALSE defines Replace with bool where it makes sense. Also drop unused local variable lossy in fat_find_dir_entry. Reported-by: Al Viro Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190903185537.25099-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat.h | 3 -- drivers/staging/exfat/exfat_core.c | 81 +++++++++++++++++++------------------ drivers/staging/exfat/exfat_nls.c | 2 +- drivers/staging/exfat/exfat_super.c | 18 +++++---- 4 files changed, 53 insertions(+), 51 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h index 816681d1103a..0aa14dea4e09 100644 --- a/drivers/staging/exfat/exfat.h +++ b/drivers/staging/exfat/exfat.h @@ -86,9 +86,6 @@ #define CLUSTER_16(x) ((u16)(x)) #define CLUSTER_32(x) ((u32)(x)) -#define FALSE 0 -#define TRUE 1 - #define START_SECTOR(x) \ ((((sector_t)((x) - 2)) << p_fs->sectors_per_clu_bits) + \ p_fs->data_start_sector) diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 73b9991c272a..da8c58149c35 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -705,7 +705,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, struct buffer_head *tmp_bh = NULL; sector_t end_sector = num_sectors + sector; - u8 skip = FALSE; + bool skip = false; u32 index = 0; u16 uni = 0; u16 **upcase_table; @@ -742,11 +742,11 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, index += uni; pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); - skip = FALSE; + skip = false; } else if (uni == index) { index++; } else if (uni == 0xFFFF) { - skip = TRUE; + skip = true; } else { /* uni != index , uni != 0xFFFF */ u16 col_index = get_col_index(index); @@ -787,7 +787,7 @@ static s32 __load_default_upcase_table(struct super_block *sb) u32 j; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - u8 skip = FALSE; + bool skip = false; u32 index = 0; u16 uni = 0; u16 **upcase_table; @@ -804,11 +804,11 @@ static s32 __load_default_upcase_table(struct super_block *sb) pr_debug("skip from 0x%X ", index); index += uni; pr_debug("to 0x%X (amount of 0x%X)\n", index, uni); - skip = FALSE; + skip = false; } else if (uni == index) { index++; } else if (uni == 0xFFFF) { - skip = TRUE; + skip = true; } else { /* uni != index , uni != 0xFFFF */ u16 col_index = get_col_index(index); @@ -1399,7 +1399,7 @@ void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu) void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) { int i; - u8 end = FALSE; + bool end = false; fat_set_entry_type((struct dentry_t *) ep, TYPE_EXTEND); ep->order = (u8) order; @@ -1411,7 +1411,7 @@ void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) if (!end) { SET16(ep->unicode_0_4+i, *uniname); if (*uniname == 0x0) - end = TRUE; + end = true; else uniname++; } else { @@ -1423,7 +1423,7 @@ void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) if (!end) { SET16_A(ep->unicode_5_10 + i, *uniname); if (*uniname == 0x0) - end = TRUE; + end = true; else uniname++; } else { @@ -1435,7 +1435,7 @@ void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) if (!end) { SET16_A(ep->unicode_11_12 + i, *uniname); if (*uniname == 0x0) - end = TRUE; + end = true; else uniname++; } else { @@ -2146,8 +2146,9 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, struct uni_name_t *p_uniname, s32 num_entries, struct dos_name_t *p_dosname, u32 type) { - int i, dentry = 0, lossy = FALSE, len; - s32 order = 0, is_feasible_entry = TRUE, has_ext_entry = FALSE; + int i, dentry = 0, len; + s32 order = 0; + bool is_feasible_entry = true, has_ext_entry = false; s32 dentries_per_clu; u32 entry_type; u16 entry_uniname[14], *uniname = NULL, unichar; @@ -2190,11 +2191,11 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, return dentry; dos_ep = (struct dos_dentry_t *) ep; - if ((!lossy) && (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name))) + if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name)) return dentry; } - is_feasible_entry = TRUE; - has_ext_entry = FALSE; + is_feasible_entry = true; + has_ext_entry = false; } else if (entry_type == TYPE_EXTEND) { if (is_feasible_entry) { ext_ep = (struct ext_dentry_t *) ep; @@ -2212,16 +2213,16 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, *(uniname+len) = 0x0; if (nls_uniname_cmp(sb, uniname, entry_uniname)) - is_feasible_entry = FALSE; + is_feasible_entry = false; *(uniname+len) = unichar; } - has_ext_entry = TRUE; + has_ext_entry = true; } else if (entry_type == TYPE_UNUSED) { return -2; } - is_feasible_entry = TRUE; - has_ext_entry = FALSE; + is_feasible_entry = true; + has_ext_entry = false; } if (p_dir->dir == CLUSTER_32(0)) @@ -2244,7 +2245,8 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, struct dos_name_t *p_dosname, u32 type) { int i = 0, dentry = 0, num_ext_entries = 0, len, step; - s32 order = 0, is_feasible_entry = FALSE; + s32 order = 0; + bool is_feasible_entry = false; s32 dentries_per_clu, num_empty = 0; u32 entry_type; u16 entry_uniname[16], *uniname = NULL, unichar; @@ -2288,7 +2290,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, step = 1; if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { - is_feasible_entry = FALSE; + is_feasible_entry = false; if (p_fs->hint_uentry.entry == -1) { num_empty++; @@ -2311,9 +2313,9 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, file_ep = (struct file_dentry_t *) ep; if ((type == TYPE_ALL) || (type == entry_type)) { num_ext_entries = file_ep->num_ext; - is_feasible_entry = TRUE; + is_feasible_entry = true; } else { - is_feasible_entry = FALSE; + is_feasible_entry = false; step = file_ep->num_ext + 1; } } else if (entry_type == TYPE_STREAM) { @@ -2323,7 +2325,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, p_uniname->name_len == strm_ep->name_len) { order = 1; } else { - is_feasible_entry = FALSE; + is_feasible_entry = false; step = num_ext_entries; } } @@ -2343,7 +2345,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, *(uniname+len) = 0x0; if (nls_uniname_cmp(sb, uniname, entry_uniname)) { - is_feasible_entry = FALSE; + is_feasible_entry = false; step = num_ext_entries - order + 1; } else if (order == num_ext_entries) { p_fs->hint_uentry.dir = CLUSTER_32(~0); @@ -2354,7 +2356,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, *(uniname+len) = unichar; } } else { - is_feasible_entry = FALSE; + is_feasible_entry = false; } } @@ -2522,17 +2524,17 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir) type = p_fs->fs_func->get_entry_type(ep); if (type == TYPE_UNUSED) - return TRUE; + return true; if ((type != TYPE_FILE) && (type != TYPE_DIR)) continue; if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ - return FALSE; + return false; if (p_fs->vol_type == EXFAT) - return FALSE; + return false; if ((p_dir->dir == p_fs->root_dir) || ((++count) > 2)) - return FALSE; + return false; } if (p_dir->dir == CLUSTER_32(0)) @@ -2548,7 +2550,7 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir) break; } - return TRUE; + return true; } /* @@ -2741,7 +2743,8 @@ s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname, s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, struct dos_name_t *p_dosname) { - int i, j, count = 0, count_begin = FALSE; + int i, j, count = 0; + bool count_begin = false; s32 dentries_per_clu; u32 type; u8 bmap[128/* 1 ~ 1023 */]; @@ -2779,14 +2782,14 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, continue; count = 0; - count_begin = FALSE; + count_begin = false; for (j = 0; j < 8; j++) { if (ep->name[j] == ' ') break; if (ep->name[j] == '~') { - count_begin = TRUE; + count_begin = true; } else if (count_begin) { if ((ep->name[j] >= '0') && (ep->name[j] <= '9')) { @@ -2794,7 +2797,7 @@ s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir, (ep->name[j] - '0'); } else { count = 0; - count_begin = FALSE; + count_begin = false; } } } @@ -3613,7 +3616,7 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh, if (!p_fs->dev_ejected) { ret = bdev_read(sb, sec, bh, 1, read); if (ret != FFS_SUCCESS) - p_fs->dev_ejected = TRUE; + p_fs->dev_ejected = 1; } return ret; @@ -3642,7 +3645,7 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh, if (!p_fs->dev_ejected) { ret = bdev_write(sb, sec, bh, 1, sync); if (ret != FFS_SUCCESS) - p_fs->dev_ejected = TRUE; + p_fs->dev_ejected = 1; } return ret; @@ -3665,7 +3668,7 @@ int multi_sector_read(struct super_block *sb, sector_t sec, if (!p_fs->dev_ejected) { ret = bdev_read(sb, sec, bh, num_secs, read); if (ret != FFS_SUCCESS) - p_fs->dev_ejected = TRUE; + p_fs->dev_ejected = 1; } return ret; @@ -3693,7 +3696,7 @@ int multi_sector_write(struct super_block *sb, sector_t sec, if (!p_fs->dev_ejected) { ret = bdev_write(sb, sec, bh, num_secs, sync); if (ret != FFS_SUCCESS) - p_fs->dev_ejected = TRUE; + p_fs->dev_ejected = 1; } return ret; diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c index 2ca58616159b..03cb8290b5d2 100644 --- a/drivers/staging/exfat/exfat_nls.c +++ b/drivers/staging/exfat/exfat_nls.c @@ -225,7 +225,7 @@ void nls_uniname_to_dosname(struct super_block *sb, *dosname = 0x05; if (*uniname != 0x0) - lossy = TRUE; + lossy = true; if (upper & lower) p_dosname->name_case = 0xFF; diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 359c749278cb..280bf0d1cf0b 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -452,7 +452,7 @@ static int ffsMountVol(struct super_block *sb) buf_init(sb); sema_init(&p_fs->v_sem, 1); - p_fs->dev_ejected = FALSE; + p_fs->dev_ejected = 0; /* open the block device */ bdev_open(sb); @@ -903,7 +903,8 @@ out: static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, void *buffer, u64 count, u64 *wcount) { - s32 modified = FALSE, offset, sec_offset, clu_offset; + bool modified = false; + s32 offset, sec_offset, clu_offset; s32 num_clusters, num_alloc, num_alloced = (s32) ~0; int ret = 0; u32 clu, last_clu; @@ -1011,14 +1012,14 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (new_clu.flags == 0x01) fid->flags = 0x01; fid->start_clu = new_clu.dir; - modified = TRUE; + modified = true; } else { if (new_clu.flags != fid->flags) { exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters); fid->flags = 0x01; - modified = TRUE; + modified = true; } if (new_clu.flags == 0x01) FAT_write(sb, last_clu, new_clu.dir); @@ -1088,7 +1089,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (fid->size < fid->rwoffset) { fid->size = fid->rwoffset; - modified = TRUE; + modified = true; } } @@ -1828,7 +1829,8 @@ out: static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) { - s32 num_clusters, num_alloced, modified = FALSE; + s32 num_clusters, num_alloced; + bool modified = false; u32 last_clu; int ret = FFS_SUCCESS; sector_t sector = 0; @@ -1906,13 +1908,13 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) if (new_clu.flags == 0x01) fid->flags = 0x01; fid->start_clu = new_clu.dir; - modified = TRUE; + modified = true; } else { if (new_clu.flags != fid->flags) { exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters); fid->flags = 0x01; - modified = TRUE; + modified = true; } if (new_clu.flags == 0x01) FAT_write(sb, last_clu, new_clu.dir); -- cgit v1.2.3-59-g8ed1b From 4e690bf985bd2e1517f58d514bd73222062e0ce8 Mon Sep 17 00:00:00 2001 From: zhong jiang Date: Wed, 4 Sep 2019 11:01:19 +0800 Subject: Staging: rtl8723bs: Use kzfree rather than its implementation Use kzfree instead of memset() + kfree(). Signed-off-by: zhong jiang Link: https://lore.kernel.org/r/1567566079-7412-4-git-send-email-zhongjiang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_security.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c index 979056c3d397..57cfe06d7d73 100644 --- a/drivers/staging/rtl8723bs/core/rtw_security.c +++ b/drivers/staging/rtl8723bs/core/rtw_security.c @@ -2290,8 +2290,7 @@ static void gf_mulx(u8 *pad) static void aes_encrypt_deinit(void *ctx) { - memset(ctx, 0, AES_PRIV_SIZE); - kfree(ctx); + kzfree(ctx); } -- cgit v1.2.3-59-g8ed1b From 3b531807e605bfa8290531a63886d1972809e310 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Tue, 3 Sep 2019 22:56:59 +0200 Subject: staging: exfat: cleanup explicit comparisons to NULL Fixes checkpatch.pl warnings: CHECK: Comparison to NULL could be written "expr" CHECK: Comparison to NULL could be written "!expr" Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190903205659.18856-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_core.c | 34 +++++++++++----------- drivers/staging/exfat/exfat_super.c | 58 ++++++++++++++++++------------------- 2 files changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index da8c58149c35..995358cc7c79 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -100,7 +100,7 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag) p_fs->vol_flag = new_flag; if (p_fs->vol_type == EXFAT) { - if (p_fs->pbr_bh == NULL) { + if (!p_fs->pbr_bh) { if (sector_read(sb, p_fs->PBR_sector, &p_fs->pbr_bh, 1) != FFS_SUCCESS) return; @@ -543,7 +543,7 @@ s32 load_alloc_bitmap(struct super_block *sb) p_fs->vol_amap = kmalloc_array(p_fs->map_sectors, sizeof(struct buffer_head *), GFP_KERNEL); - if (p_fs->vol_amap == NULL) + if (!p_fs->vol_amap) return FFS_MEMORYERR; sector = START_SECTOR(p_fs->map_clu); @@ -685,7 +685,7 @@ void sync_alloc_bitmap(struct super_block *sb) int i; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - if (p_fs->vol_amap == NULL) + if (!p_fs->vol_amap) return; for (i = 0; i < p_fs->map_sectors; i++) @@ -714,7 +714,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *), GFP_KERNEL); - if (upcase_table == NULL) + if (!upcase_table) return FFS_MEMORYERR; memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); @@ -750,11 +750,11 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, } else { /* uni != index , uni != 0xFFFF */ u16 col_index = get_col_index(index); - if (upcase_table[col_index] == NULL) { + if (!upcase_table[col_index]) { pr_debug("alloc = 0x%X\n", col_index); upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, sizeof(u16), GFP_KERNEL); - if (upcase_table[col_index] == NULL) { + if (!upcase_table[col_index]) { ret = FFS_MEMORYERR; goto error; } @@ -794,7 +794,7 @@ static s32 __load_default_upcase_table(struct super_block *sb) upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *), GFP_KERNEL); - if (upcase_table == NULL) + if (!upcase_table) return FFS_MEMORYERR; memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); @@ -812,12 +812,12 @@ static s32 __load_default_upcase_table(struct super_block *sb) } else { /* uni != index , uni != 0xFFFF */ u16 col_index = get_col_index(index); - if (upcase_table[col_index] == NULL) { + if (!upcase_table[col_index]) { pr_debug("alloc = 0x%X\n", col_index); upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT, sizeof(u16), GFP_KERNEL); - if (upcase_table[col_index] == NULL) { + if (!upcase_table[col_index]) { ret = FFS_MEMORYERR; goto error; } @@ -1640,7 +1640,7 @@ struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector, buf = buf_getblk(sb, sector); - if (buf == NULL) + if (!buf) return NULL; return (struct dentry_t *)(buf + offset); @@ -1658,10 +1658,10 @@ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir, buf = buf_getblk(sb, sec); - if (buf == NULL) + if (!buf) return NULL; - if (sector != NULL) + if (sector) *sector = sec; return (struct dentry_t *)(buf + off); } @@ -1721,7 +1721,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, sec += START_SECTOR(clu); buf = buf_getblk(sb, sec); - if (buf == NULL) + if (!buf) goto err_out; ep = (struct dentry_t *)(buf + off); @@ -1741,7 +1741,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, pr_debug("%s: trying to kmalloc %zx bytes for %d entries\n", __func__, bufsize, num_entries); es = kmalloc(bufsize, GFP_KERNEL); - if (es == NULL) + if (!es) goto err_out; es->num_entries = num_entries; @@ -1820,7 +1820,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, sec++; } buf = buf_getblk(sb, sec); - if (buf == NULL) + if (!buf) goto err_out; off = 0; ep = (struct dentry_t *)(buf); @@ -1872,7 +1872,7 @@ static s32 __write_partial_entries_in_entry_set(struct super_block *sb, remaining_byte_in_sector >> DENTRY_SIZE_BITS, num_entries); buf = buf_getblk(sb, sec); - if (buf == NULL) + if (!buf) goto err_out; pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off); pr_debug("copying %d entries from %p to sector %llu\n", @@ -2651,7 +2651,7 @@ void exfat_get_uni_name_from_ext_entry(struct super_block *sb, struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); - if (es == NULL || es->num_entries < 3) { + if (!es || es->num_entries < 3) { if (es) release_entry_set(es); return; diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 280bf0d1cf0b..0cd93b9742a6 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -341,7 +341,7 @@ static int exfat_cmpi(const struct dentry *dentry, unsigned int len, alen = exfat_striptail_len(name); blen = __exfat_striptail_len(len, str); if (alen == blen) { - if (t == NULL) { + if (!t) { if (strncasecmp(name->name, str, alen) == 0) return 0; } else { @@ -589,7 +589,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); /* check the validity of pointer parameters */ - if (info == NULL) + if (!info) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -652,7 +652,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) pr_debug("%s entered\n", __func__); /* check the validity of pointer parameters */ - if ((fid == NULL) || (path == NULL) || (*path == '\0')) + if (!fid || !path || (*path == '\0')) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -745,7 +745,7 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode, int ret; /* check the validity of pointer parameters */ - if ((fid == NULL) || (path == NULL) || (*path == '\0')) + if (!fid || !path || (*path == '\0')) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -790,11 +790,11 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); /* check the validity of the given file id */ - if (fid == NULL) + if (!fid) return FFS_INVALIDFID; /* check the validity of pointer parameters */ - if (buffer == NULL) + if (!buffer) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -813,7 +813,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, count = fid->size - fid->rwoffset; if (count == 0) { - if (rcount != NULL) + if (rcount) *rcount = 0; ret = FFS_EOF; goto out; @@ -887,7 +887,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, /* How did this ever work and not leak a brlse()?? */ err_out: /* set the size of read bytes */ - if (rcount != NULL) + if (rcount) *rcount = read_bytes; if (p_fs->dev_ejected) @@ -920,11 +920,11 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); /* check the validity of the given file id */ - if (fid == NULL) + if (!fid) return FFS_INVALIDFID; /* check the validity of pointer parameters */ - if (buffer == NULL) + if (!buffer) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -940,7 +940,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, fid->rwoffset = fid->size; if (count == 0) { - if (wcount != NULL) + if (wcount) *wcount = 0; ret = FFS_SUCCESS; goto out; @@ -1099,7 +1099,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (p_fs->vol_type == EXFAT) { es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); - if (es == NULL) + if (!es) goto err_out; ep2 = ep+1; } else { @@ -1141,7 +1141,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, err_out: /* set the size of written bytes */ - if (wcount != NULL) + if (wcount) *wcount = write_bytes; if (num_alloced == 0) @@ -1228,7 +1228,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) if (p_fs->vol_type == EXFAT) { es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, ES_ALL_ENTRIES, &ep); - if (es == NULL) { + if (!es) { ret = FFS_MEDIAERR; goto out; } @@ -1323,11 +1323,11 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, s32 new_entry = 0; /* check the validity of the given file id */ - if (fid == NULL) + if (!fid) return FFS_INVALIDFID; /* check the validity of pointer parameters */ - if ((new_path == NULL) || (*new_path == '\0')) + if (!new_path || (*new_path == '\0')) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -1444,7 +1444,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); /* check the validity of the given file id */ - if (fid == NULL) + if (!fid) return FFS_INVALIDFID; /* acquire the lock for file system critical section */ @@ -1532,7 +1532,7 @@ static int ffsSetAttr(struct inode *inode, u32 attr) if (p_fs->vol_type == EXFAT) { es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); - if (es == NULL) { + if (!es) { ret = FFS_MEDIAERR; goto out; } @@ -1648,7 +1648,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) if (p_fs->vol_type == EXFAT) { es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep); - if (es == NULL) { + if (!es) { ret = FFS_MEDIAERR; goto out; } @@ -1772,7 +1772,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) if (p_fs->vol_type == EXFAT) { es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); - if (es == NULL) { + if (!es) { ret = FFS_MEDIAERR; goto out; } @@ -1842,7 +1842,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) struct file_id_t *fid = &(EXFAT_I(inode)->fid); /* check the validity of pointer parameters */ - if (clu == NULL) + if (!clu) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -1926,7 +1926,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) if (p_fs->vol_type == EXFAT) { es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, ES_ALL_ENTRIES, &ep); - if (es == NULL) { + if (!es) { ret = FFS_MEDIAERR; goto out; } @@ -1994,7 +1994,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) pr_debug("%s entered\n", __func__); /* check the validity of pointer parameters */ - if ((fid == NULL) || (path == NULL) || (*path == '\0')) + if (!fid || !path || (*path == '\0')) return FFS_ERROR; /* acquire the lock for file system critical section */ @@ -2040,7 +2040,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) struct file_id_t *fid = &(EXFAT_I(inode)->fid); /* check the validity of pointer parameters */ - if (dir_entry == NULL) + if (!dir_entry) return FFS_ERROR; /* check if the given file ID is opened */ @@ -2231,7 +2231,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); /* check the validity of the given file id */ - if (fid == NULL) + if (!fid) return FFS_INVALIDFID; dir.dir = fid->dir.dir; @@ -3119,10 +3119,10 @@ static const char *exfat_get_link(struct dentry *dentry, struct inode *inode, { struct exfat_inode_info *ei = EXFAT_I(inode); - if (ei->target != NULL) { + if (ei->target) { char *cookie = ei->target; - if (cookie != NULL) + if (cookie) return (char *)(ei->target); } return NULL; @@ -3784,7 +3784,7 @@ static int parse_options(char *options, int silent, int *debug, if (!options) goto out; - while ((p = strsep(&options, ",")) != NULL) { + while ((p = strsep(&options, ","))) { int token; if (!*p) @@ -4048,7 +4048,7 @@ static int __init exfat_init_inodecache(void) (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD), init_once); - if (exfat_inode_cachep == NULL) + if (!exfat_inode_cachep) return -ENOMEM; return 0; } -- cgit v1.2.3-59-g8ed1b From 7f95bb6aa3dd4f732edb05fe64b255b27bcc97d2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Sep 2019 12:59:08 +0300 Subject: staging: exfat: Fix two missing unlocks on error paths These two error paths need to unlock before we can return. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20190904095908.GA7007@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 0cd93b9742a6..95bb606766b6 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -1208,8 +1208,10 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) } else { while (num_clusters > 0) { last_clu = clu.dir; - if (FAT_read(sb, clu.dir, &clu.dir) == -1) - return FFS_MEDIAERR; + if (FAT_read(sb, clu.dir, &clu.dir) == -1) { + ret = FFS_MEDIAERR; + goto out; + } num_clusters--; } } -- cgit v1.2.3-59-g8ed1b From 59d45f2a4d4a9fbea07f285994cae31ac13f2493 Mon Sep 17 00:00:00 2001 From: zhong jiang Date: Wed, 4 Sep 2019 18:03:28 +0800 Subject: staging: exfat: remove the redundant check when kfree an object in exfat_destroy_inode kfree has taken the null check in account. hence it is unnecessary to add the null check before kfree the object. Just remove it. Reported-by: Julia Lawall Signed-off-by: zhong jiang Link: https://lore.kernel.org/r/1567591408-24268-1-git-send-email-zhongjiang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 95bb606766b6..46ff33688c42 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -3498,8 +3498,7 @@ static struct inode *exfat_alloc_inode(struct super_block *sb) static void exfat_destroy_inode(struct inode *inode) { - if (EXFAT_I(inode)->target) - kfree(EXFAT_I(inode)->target); + kfree(EXFAT_I(inode)->target); EXFAT_I(inode)->target = NULL; kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); -- cgit v1.2.3-59-g8ed1b From 0f16ebb9dcd60021e1a496b64b0b44f97cc2d8d9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 5 Sep 2019 02:56:08 +0000 Subject: staging: exfat: remove duplicated include from exfat_super.c Remove duplicated include. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190905025608.61884-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 46ff33688c42..67d25a3694a5 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3-59-g8ed1b From 981cdf7d577904aef003c878710e479eec60a1be Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 5 Sep 2019 02:56:23 +0000 Subject: staging: exfat: remove unused including Remove including that don't need it. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190905025623.63210-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 67d25a3694a5..38b5811fb6c7 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -3,7 +3,6 @@ * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. */ -#include #include #include #include -- cgit v1.2.3-59-g8ed1b From f30bd2989b110cfa5050bd98dcf4bc1ec32f9000 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 5 Sep 2019 03:00:47 +0000 Subject: staging: exfat: Use kmemdup in exfat_symlink() Use kmemdup rather than duplicating its implementation Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20190905030047.88401-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 38b5811fb6c7..da6d3afa1f89 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -2706,12 +2706,11 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); /* timestamp is already written, so mark_inode_dirty() is unneeded. */ - EXFAT_I(inode)->target = kmalloc(len+1, GFP_KERNEL); + EXFAT_I(inode)->target = kmemdup(target, len + 1, GFP_KERNEL); if (!EXFAT_I(inode)->target) { err = -ENOMEM; goto out; } - memcpy(EXFAT_I(inode)->target, target, len+1); dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); d_instantiate(dentry, inode); -- cgit v1.2.3-59-g8ed1b From 21ba22e6214aacd00b31f64023f00418cc5f4c5d Mon Sep 17 00:00:00 2001 From: Beatriz Martins de Carvalho Date: Wed, 4 Sep 2019 21:03:26 +0000 Subject: staging: rtl8192e: remove unnecessary blank line Fix checkpath error "CHECK: Blank lines aren't necessary after an open brace '{'" in rtllib.h:482. Signed-off-by: Beatriz Martins de Carvalho Link: https://lore.kernel.org/r/20190904210326.17983-1-martinsdecarvalhobeatriz@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 7a012881578f..328f410daa03 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -479,7 +479,6 @@ enum wireless_mode { #define P80211_OUI_LEN 3 struct rtllib_snap_hdr { - u8 dsap; /* always 0xAA */ u8 ssap; /* always 0xAA */ u8 ctrl; /* always 0x03 */ -- cgit v1.2.3-59-g8ed1b From 3ee8b9de9142c6e0736f6f93e5ca3b544636ac8f Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Wed, 4 Sep 2019 21:06:31 +0000 Subject: staging: rtl8723bs: Remove return statement from void function Fix the following checkpatch warning: "WARNING: void function return statements are not generally useful" Signed-off-by: Leandro Ribeiro Link: https://lore.kernel.org/r/20190904210631.13599-1-leandrohr@riseup.net Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 79c1e3edb189..7760fd0eb6c9 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -1406,7 +1406,6 @@ void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable) rtl8723b_set_Fw_AP_Offload_Cmd(padapter, enable); msleep(10); DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__); - return ; } #endif /* CONFIG_AP_WOWLAN */ -- cgit v1.2.3-59-g8ed1b From 26cf7660919e4f0b2cf26d0ea6c95f58cbbd7ec7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 6 Sep 2019 17:09:04 +0200 Subject: staging: exfat: stopusing CONFIG_FAT_DEFAULT_IOCHARSET When CONFIG_VFAT_FS is disabled, the reference to CONFIG_FAT_DEFAULT_IOCHARSET causes a link failure: drivers/staging/exfat/exfat_super.c:46:41: error: use of undeclared identifier 'CONFIG_FAT_DEFAULT_IOCHARSET' static char exfat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; I could not figure out why the correct code is commented out, but using that fixes the problem. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190906150917.1025250-1-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index da6d3afa1f89..68d89cee359e 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -37,11 +37,8 @@ static struct kmem_cache *exfat_inode_cachep; -// FIXME use commented lines -// static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; -// static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; -static int exfat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE; -static char exfat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET; +static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; +static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; #define INC_IVERSION(x) (inode_inc_iversion(x)) #define GET_IVERSION(x) (inode_peek_iversion_raw(x)) -- cgit v1.2.3-59-g8ed1b From 44f6b40c225eb8e82eba8fd96d8f3fb843bc5a09 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 6 Sep 2019 17:09:05 +0200 Subject: staging: exfat: stop using 32-bit time_t time_t suffers from overflow problems and should not be used. In exfat, it is currently used in two open-coded time64_to_tm() implementations. Changes those to use the existing function instead. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20190906150917.1025250-2-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 164 +++++++++--------------------------- 1 file changed, 38 insertions(+), 126 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 68d89cee359e..60dfea73a7a4 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -53,129 +53,65 @@ static int exfat_write_inode(struct inode *inode, static void exfat_write_super(struct super_block *sb); #define UNIX_SECS_1980 315532800L - -#if BITS_PER_LONG == 64 #define UNIX_SECS_2108 4354819200L -#endif - -/* days between 1.1.70 and 1.1.80 (2 leap days) */ -#define DAYS_DELTA_DECADE (365 * 10 + 2) -/* 120 (2100 - 1980) isn't leap year */ -#define NO_LEAP_YEAR_2100 (120) -#define IS_LEAP_YEAR(y) (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100) - -#define SECS_PER_MIN (60) -#define SECS_PER_HOUR (60 * SECS_PER_MIN) -#define SECS_PER_DAY (24 * SECS_PER_HOUR) - -#define MAKE_LEAP_YEAR(leap_year, year) \ - do { \ - if (unlikely(year > NO_LEAP_YEAR_2100)) \ - leap_year = ((year + 3) / 4) - 1; \ - else \ - leap_year = ((year + 3) / 4); \ - } while (0) - -/* Linear day numbers of the respective 1sts in non-leap years. */ -static time_t accum_days_in_year[] = { - /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ - 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, -}; /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ static void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec64 *ts, struct date_time_t *tp) { - time_t year = tp->Year; - time_t ld; - - MAKE_LEAP_YEAR(ld, year); - - if (IS_LEAP_YEAR(year) && (tp->Month) > 2) - ld++; - - ts->tv_sec = tp->Second + - tp->Minute * SECS_PER_MIN + - tp->Hour * SECS_PER_HOUR + - (ld + accum_days_in_year[(tp->Month)] + - (tp->Day - 1)) * SECS_PER_DAY + - (year * 365 + DAYS_DELTA_DECADE) * SECS_PER_DAY + - sys_tz.tz_minuteswest * SECS_PER_MIN; + ts->tv_sec = mktime64(tp->Year + 1980, tp->Month + 1, tp->Day, + tp->Hour, tp->Minute, tp->Second); - ts->tv_nsec = 0; + ts->tv_nsec = tp->MilliSecond * NSEC_PER_MSEC; } /* Convert linear UNIX date to a FAT time/date pair. */ static void exfat_time_unix2fat(struct exfat_sb_info *sbi, struct timespec64 *ts, struct date_time_t *tp) { - time_t second = ts->tv_sec; - time_t day, month, year; - time_t ld; + time64_t second = ts->tv_sec; + struct tm tm; - second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + time64_to_tm(second, 0, &tm); - /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ if (second < UNIX_SECS_1980) { - tp->Second = 0; - tp->Minute = 0; - tp->Hour = 0; - tp->Day = 1; - tp->Month = 1; - tp->Year = 0; + tp->MilliSecond = 0; + tp->Second = 0; + tp->Minute = 0; + tp->Hour = 0; + tp->Day = 1; + tp->Month = 1; + tp->Year = 0; return; } -#if (BITS_PER_LONG == 64) + if (second >= UNIX_SECS_2108) { - tp->Second = 59; - tp->Minute = 59; - tp->Hour = 23; - tp->Day = 31; - tp->Month = 12; - tp->Year = 127; + tp->MilliSecond = 999; + tp->Second = 59; + tp->Minute = 59; + tp->Hour = 23; + tp->Day = 31; + tp->Month = 12; + tp->Year = 127; return; } -#endif - day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; - year = day / 365; - MAKE_LEAP_YEAR(ld, year); - if (year * 365 + ld > day) - year--; - - MAKE_LEAP_YEAR(ld, year); - day -= year * 365 + ld; - if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { - month = 2; - } else { - if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) - day--; - for (month = 1; month < 12; month++) { - if (accum_days_in_year[month + 1] > day) - break; - } - } - day -= accum_days_in_year[month]; - - tp->Second = second % SECS_PER_MIN; - tp->Minute = (second / SECS_PER_MIN) % 60; - tp->Hour = (second / SECS_PER_HOUR) % 24; - tp->Day = day + 1; - tp->Month = month; - tp->Year = year; + tp->MilliSecond = ts->tv_nsec / NSEC_PER_MSEC; + tp->Second = tm.tm_sec; + tp->Minute = tm.tm_min; + tp->Hour = tm.tm_hour; + tp->Day = tm.tm_mday; + tp->Month = tm.tm_mon + 1; + tp->Year = tm.tm_year + 1900 - 1980; } struct timestamp_t *tm_current(struct timestamp_t *tp) { - struct timespec64 ts; - time_t second, day, leap_day, month, year; - - ktime_get_real_ts64(&ts); + time64_t second = ktime_get_real_seconds(); + struct tm tm; - second = ts.tv_sec; - second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + time64_to_tm(second, 0, &tm); - /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ if (second < UNIX_SECS_1980) { tp->sec = 0; tp->min = 0; @@ -185,7 +121,7 @@ struct timestamp_t *tm_current(struct timestamp_t *tp) tp->year = 0; return tp; } -#if BITS_PER_LONG == 64 + if (second >= UNIX_SECS_2108) { tp->sec = 59; tp->min = 59; @@ -195,37 +131,13 @@ struct timestamp_t *tm_current(struct timestamp_t *tp) tp->year = 127; return tp; } -#endif - - day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; - year = day / 365; - - MAKE_LEAP_YEAR(leap_day, year); - if (year * 365 + leap_day > day) - year--; - MAKE_LEAP_YEAR(leap_day, year); - - day -= year * 365 + leap_day; - - if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { - month = 2; - } else { - if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) - day--; - for (month = 1; month < 12; month++) { - if (accum_days_in_year[month + 1] > day) - break; - } - } - day -= accum_days_in_year[month]; - - tp->sec = second % SECS_PER_MIN; - tp->min = (second / SECS_PER_MIN) % 60; - tp->hour = (second / SECS_PER_HOUR) % 24; - tp->day = day + 1; - tp->mon = month; - tp->year = year; + tp->sec = tm.tm_sec; + tp->min = tm.tm_min; + tp->hour = tm.tm_hour; + tp->day = tm.tm_mday; + tp->mon = tm.tm_mon + 1; + tp->year = tm.tm_year + 1900 - 1980; return tp; } -- cgit v1.2.3-59-g8ed1b From f0c7686dd7461cdd49097faba397379a16adc437 Mon Sep 17 00:00:00 2001 From: Rohit Sarkar Date: Thu, 5 Sep 2019 18:52:19 +0530 Subject: staging: pi433: Fix typo in documentation Fixes a typo in the documentation. Signed-off-by: Rohit Sarkar Link: https://lore.kernel.org/r/20190905132219.GA1004@SARKAR Signed-off-by: Greg Kroah-Hartman --- drivers/staging/pi433/Documentation/pi433.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/pi433/Documentation/pi433.txt b/drivers/staging/pi433/Documentation/pi433.txt index 21cffdb86ecf..4a0d34b4ad37 100644 --- a/drivers/staging/pi433/Documentation/pi433.txt +++ b/drivers/staging/pi433/Documentation/pi433.txt @@ -14,7 +14,7 @@ until something gets received terminates the read request. The driver supports on the fly reloading of the hardware fifo of the rf chip, thus enabling for much longer telegrams than the hardware fifo size. -Discription of driver operation +Description of driver operation =============================== a) transmission -- cgit v1.2.3-59-g8ed1b From b33f56a1e40588214320926293585f088fb390b0 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 5 Sep 2019 16:22:27 +0100 Subject: staging: rtl8723bs: hal: remove redundant variable n The variable n is being assigned a value that is never read inside an if statement block, the assignment is redundant and can be removed. With this removed, n is only being used for a constant loop bounds check, so replace n with that value instead and remove n completely. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190905152227.4610-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index 032d01834f3f..0f3301091258 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -502,7 +502,7 @@ exit: */ void rtl8723bs_free_recv_priv(struct adapter *padapter) { - u32 i, n; + u32 i; struct recv_priv *precvpriv; struct recv_buf *precvbuf; @@ -514,9 +514,8 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter) /* 3 2. free all recv buffers */ precvbuf = (struct recv_buf *)precvpriv->precv_buf; if (precvbuf) { - n = NR_RECVBUFF; precvpriv->free_recv_buf_queue_cnt = 0; - for (i = 0; i < n ; i++) { + for (i = 0; i < NR_RECVBUFF; i++) { list_del_init(&precvbuf->list); rtw_os_recvbuf_resource_free(padapter, precvbuf); precvbuf++; @@ -525,7 +524,6 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter) } if (precvpriv->pallocated_recv_buf) { - n = NR_RECVBUFF * sizeof(struct recv_buf) + 4; kfree(precvpriv->pallocated_recv_buf); precvpriv->pallocated_recv_buf = NULL; } -- cgit v1.2.3-59-g8ed1b From 179e14c8e6aff75d74792dc2ee4d0393c9f23ab2 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Sun, 8 Sep 2019 15:26:14 +0000 Subject: staging: exfat: cleanup spacing for operators Fixes checkpatch.pl warnings: CHECK: spaces preferred around that '-' (ctx:VxV) CHECK: spaces preferred around that '+' (ctx:VxV) CHECK: spaces preferred around that '*' (ctx:VxV) CHECK: spaces preferred around that '|' (ctx:VxV) Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190908152616.25459-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat.h | 2 +- drivers/staging/exfat/exfat_core.c | 76 ++++++++++++++++++------------------- drivers/staging/exfat/exfat_super.c | 44 ++++++++++----------- 3 files changed, 61 insertions(+), 61 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h index 0aa14dea4e09..6c12f2d79f4d 100644 --- a/drivers/staging/exfat/exfat.h +++ b/drivers/staging/exfat/exfat.h @@ -159,7 +159,7 @@ /* Upcase table macro */ #define HIGH_INDEX_BIT (8) #define HIGH_INDEX_MASK (0xFF00) -#define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) +#define LOW_INDEX_BIT (16 - HIGH_INDEX_BIT) #define UTBL_ROW_COUNT BIT(LOW_INDEX_BIT) #define UTBL_COL_COUNT BIT(HIGH_INDEX_BIT) diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 995358cc7c79..8fb4ce16010c 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -230,7 +230,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, hint_clu = p_chain->dir; if (hint_clu == CLUSTER_32(~0)) { - hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2); + hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr - 2); if (hint_clu == CLUSTER_32(~0)) return 0; } else if (hint_clu >= p_fs->num_clusters) { @@ -242,7 +242,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, p_chain->dir = CLUSTER_32(~0); - while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) { + while ((new_clu = test_alloc_bitmap(sb, hint_clu - 2)) != CLUSTER_32(~0)) { if (new_clu != hint_clu) { if (p_chain->flags == 0x03) { exfat_chain_cont_cluster(sb, p_chain->dir, @@ -251,7 +251,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, } } - if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS) + if (set_alloc_bitmap(sb, new_clu - 2) != FFS_SUCCESS) return -1; num_clusters++; @@ -324,7 +324,7 @@ void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, if (do_relse) { sector = START_SECTOR(clu); for (i = 0; i < p_fs->sectors_per_clu; i++) - buf_release(sb, sector+i); + buf_release(sb, sector + i); } prev = clu; @@ -367,10 +367,10 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, if (do_relse) { sector = START_SECTOR(clu); for (i = 0; i < p_fs->sectors_per_clu; i++) - buf_release(sb, sector+i); + buf_release(sb, sector + i); } - if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS) break; clu++; @@ -384,10 +384,10 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, if (do_relse) { sector = START_SECTOR(clu); for (i = 0; i < p_fs->sectors_per_clu; i++) - buf_release(sb, sector+i); + buf_release(sb, sector + i); } - if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS) break; if (FAT_read(sb, clu, &clu) == -1) @@ -491,7 +491,7 @@ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len) return; while (len > 1) { - if (FAT_write(sb, chain, chain+1) < 0) + if (FAT_write(sb, chain, chain + 1) < 0) break; chain++; len--; @@ -538,7 +538,7 @@ s32 load_alloc_bitmap(struct super_block *sb) p_fs->map_clu = GET32_A(ep->start_clu); map_size = (u32) GET64_A(ep->size); - p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1; + p_fs->map_sectors = ((map_size - 1) >> p_bd->sector_size_bits) + 1; p_fs->vol_amap = kmalloc_array(p_fs->map_sectors, sizeof(struct buffer_head *), @@ -550,7 +550,7 @@ s32 load_alloc_bitmap(struct super_block *sb) for (j = 0; j < p_fs->map_sectors; j++) { p_fs->vol_amap[j] = NULL; - ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1); + ret = sector_read(sb, sector + j, &(p_fs->vol_amap[j]), 1); if (ret != FFS_SUCCESS) { /* release all buffers and free vol_amap */ i = 0; @@ -728,7 +728,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, sector++; for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { - uni = GET16(((u8 *) tmp_bh->b_data)+i); + uni = GET16(((u8 *) tmp_bh->b_data) + i); checksum = ((checksum & 1) ? 0x80000000 : 0) + (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + @@ -798,7 +798,7 @@ static s32 __load_default_upcase_table(struct super_block *sb) return FFS_MEMORYERR; memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *)); - for (i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) { + for (i = 0; index <= 0xFFFF && i < NUM_UPCASE * 2; i += 2) { uni = GET16(uni_upcase + i); if (skip) { pr_debug("skip from 0x%X ", index); @@ -875,7 +875,7 @@ s32 load_upcase_table(struct super_block *sb) tbl_size = (u32) GET64_A(ep->size); sector = START_SECTOR(tbl_clu); - num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1; + num_sectors = ((tbl_size - 1) >> p_bd->sector_size_bits) + 1; if (__load_upcase_table(sb, sector, num_sectors, GET32_A(ep->checksum)) != FFS_SUCCESS) break; @@ -919,10 +919,10 @@ u32 fat_get_entry_type(struct dentry_t *p_entry) else if (ep->attr == ATTR_EXTEND) return TYPE_EXTEND; - else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME) + else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_VOLUME) return TYPE_VOLUME; - else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR) + else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_SUBDIR) return TYPE_DIR; return TYPE_FILE; @@ -1269,7 +1269,7 @@ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, if (!file_ep) return FFS_MEDIAERR; - strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry+1, + strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1, §or); if (!strm_ep) return FFS_MEDIAERR; @@ -1327,7 +1327,7 @@ static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, if (!ext_ep) return FFS_MEDIAERR; - init_ext_entry(ext_ep, i+0x40, chksum, uniname); + init_ext_entry(ext_ep, i + 0x40, chksum, uniname); buf_modify(sb, sector); } @@ -1354,7 +1354,7 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir, file_ep->num_ext = (u8)(num_entries - 1); buf_modify(sb, sector); - strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry+1, + strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1, §or); if (!strm_ep) return FFS_MEDIAERR; @@ -1409,13 +1409,13 @@ void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) for (i = 0; i < 10; i += 2) { if (!end) { - SET16(ep->unicode_0_4+i, *uniname); + SET16(ep->unicode_0_4 + i, *uniname); if (*uniname == 0x0) end = true; else uniname++; } else { - SET16(ep->unicode_0_4+i, 0xFFFF); + SET16(ep->unicode_0_4 + i, 0xFFFF); } } @@ -1476,7 +1476,7 @@ void init_name_entry(struct name_dentry_t *ep, u16 *uniname) ep->flags = 0x0; for (i = 0; i < 30; i++, i++) { - SET16_A(ep->unicode_0_14+i, *uniname); + SET16_A(ep->unicode_0_14 + i, *uniname); if (*uniname == 0x0) break; uniname++; @@ -1491,8 +1491,8 @@ void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, struct dentry_t *ep; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - for (i = num_entries-1; i >= order; i--) { - ep = get_entry_in_dir(sb, p_dir, entry-i, §or); + for (i = num_entries - 1; i >= order; i--) { + ep = get_entry_in_dir(sb, p_dir, entry - i, §or); if (!ep) return; @@ -1510,7 +1510,7 @@ void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir, struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); for (i = order; i < num_entries; i++) { - ep = get_entry_in_dir(sb, p_dir, entry+i, §or); + ep = get_entry_in_dir(sb, p_dir, entry + i, §or); if (!ep) return; @@ -1540,7 +1540,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, CS_DIR_ENTRY); for (i = 1; i < num_entries; i++) { - ep = get_entry_in_dir(sb, p_dir, entry+i, NULL); + ep = get_entry_in_dir(sb, p_dir, entry + i, NULL); if (!ep) { buf_unlock(sb, sector); return; @@ -1732,7 +1732,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, goto err_out; if (type == ES_ALL_ENTRIES) - num_entries = ((struct file_dentry_t *)ep)->num_ext+1; + num_entries = ((struct file_dentry_t *)ep)->num_ext + 1; else num_entries = type; @@ -1998,7 +1998,7 @@ s32 search_deleted_or_unused_entry(struct super_block *sb, if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ i = dentry % dentries_per_clu; else - i = dentry & (dentries_per_clu-1); + i = dentry & (dentries_per_clu - 1); for (; i < dentries_per_clu; i++, dentry++) { ep = get_entry_in_dir(sb, &clu, i, NULL); @@ -2028,7 +2028,7 @@ s32 search_deleted_or_unused_entry(struct super_block *sb, p_fs->hint_uentry.entry = -1; if (p_fs->vol_type == EXFAT) - return dentry - (num_entries-1); + return dentry - (num_entries - 1); else return dentry; } @@ -2127,7 +2127,7 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries } } - i_size_write(inode, i_size_read(inode)+p_fs->cluster_size); + i_size_write(inode, i_size_read(inode) + p_fs->cluster_size); EXFAT_I(inode)->mmu_private += p_fs->cluster_size; EXFAT_I(inode)->fid.size += p_fs->cluster_size; EXFAT_I(inode)->fid.flags = p_dir->flags; @@ -2201,7 +2201,7 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, ext_ep = (struct ext_dentry_t *) ep; if (ext_ep->order > 0x40) { order = (s32)(ext_ep->order - 0x40); - uniname = p_uniname->name + 13 * (order-1); + uniname = p_uniname->name + 13 * (order - 1); } else { order = (s32) ext_ep->order; uniname -= 13; @@ -2209,13 +2209,13 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order); - unichar = *(uniname+len); - *(uniname+len) = 0x0; + unichar = *(uniname + len); + *(uniname + len) = 0x0; if (nls_uniname_cmp(sb, uniname, entry_uniname)) is_feasible_entry = false; - *(uniname+len) = unichar; + *(uniname + len) = unichar; } has_ext_entry = true; } else if (entry_type == TYPE_UNUSED) { @@ -2301,7 +2301,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, p_fs->hint_uentry.clu.flags = clu.flags; } if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED)) - p_fs->hint_uentry.entry = dentry - (num_empty-1); + p_fs->hint_uentry.entry = dentry - (num_empty - 1); } if (entry_type == TYPE_UNUSED) @@ -2341,8 +2341,8 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, len = extract_uni_name_from_name_entry(name_ep, entry_uniname, order); - unichar = *(uniname+len); - *(uniname+len) = 0x0; + unichar = *(uniname + len); + *(uniname + len) = 0x0; if (nls_uniname_cmp(sb, uniname, entry_uniname)) { is_feasible_entry = false; @@ -2353,7 +2353,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, return dentry - (num_ext_entries); } - *(uniname+len) = unichar; + *(uniname + len) = unichar; } } else { is_feasible_entry = false; diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 60dfea73a7a4..131f60a07bb9 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -605,7 +605,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) ret = FFS_MEDIAERR; goto out; } - ep2 = ep+1; + ep2 = ep + 1; } else { ep = get_entry_in_dir(sb, &dir, dentry, NULL); if (!ep) { @@ -757,7 +757,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, fid->hint_last_clu = clu; /* byte offset in cluster */ - offset = (s32)(fid->rwoffset & (p_fs->cluster_size-1)); + offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1)); /* sector offset in cluster */ sec_offset = offset >> p_bd->sector_size_bits; @@ -858,7 +858,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (fid->size == 0) num_clusters = 0; else - num_clusters = (s32)((fid->size-1) >> + num_clusters = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; write_bytes = 0; @@ -899,7 +899,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, num_alloc = (s32)((count - 1) >> p_fs->cluster_size_bits) + 1; new_clu.dir = (last_clu == CLUSTER_32(~0)) ? - CLUSTER_32(~0) : last_clu+1; + CLUSTER_32(~0) : last_clu + 1; new_clu.size = 0; new_clu.flags = fid->flags; @@ -969,7 +969,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, } } else { if ((offset > 0) || - ((fid->rwoffset+oneblkwrite) < fid->size)) { + ((fid->rwoffset + oneblkwrite) < fid->size)) { if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) goto err_out; @@ -1008,7 +1008,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, ES_ALL_ENTRIES, &ep); if (!es) goto err_out; - ep2 = ep+1; + ep2 = ep + 1; } else { ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); if (!ep) @@ -1103,11 +1103,11 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) fs_set_vol_flags(sb, VOL_DIRTY); clu.dir = fid->start_clu; - clu.size = (s32)((old_size-1) >> p_fs->cluster_size_bits) + 1; + clu.size = (s32)((old_size - 1) >> p_fs->cluster_size_bits) + 1; clu.flags = fid->flags; if (new_size > 0) { - num_clusters = (s32)((new_size-1) >> + num_clusters = (s32)((new_size - 1) >> p_fs->cluster_size_bits) + 1; if (clu.flags == 0x03) { @@ -1141,7 +1141,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) ret = FFS_MEDIAERR; goto out; } - ep2 = ep+1; + ep2 = ep + 1; } else { ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); if (!ep) { @@ -1209,7 +1209,7 @@ static void update_parent_info(struct file_id_t *fid, (parent_fid->start_clu != fid->dir.dir))) { fid->dir.dir = parent_fid->start_clu; fid->dir.flags = parent_fid->flags; - fid->dir.size = ((parent_fid->size + (p_fs->cluster_size-1)) + fid->dir.size = ((parent_fid->size + (p_fs->cluster_size - 1)) >> p_fs->cluster_size_bits); } } @@ -1326,7 +1326,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, if (num_entries < 0) goto out; p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, - num_entries+1); + num_entries + 1); } out: #ifdef CONFIG_EXFAT_DELAYED_SYNC @@ -1381,7 +1381,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) remove_file(inode, &dir, dentry); clu_to_free.dir = fid->start_clu; - clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; clu_to_free.flags = fid->flags; /* (2) free the clusters */ @@ -1561,7 +1561,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) ret = FFS_MEDIAERR; goto out; } - ep2 = ep+1; + ep2 = ep + 1; } else { ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); if (!ep) { @@ -1685,7 +1685,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) ret = FFS_MEDIAERR; goto out; } - ep2 = ep+1; + ep2 = ep + 1; } else { /* for other than exfat */ ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); @@ -2019,7 +2019,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */ i = dentry % dentries_per_clu; else - i = dentry & (dentries_per_clu-1); + i = dentry & (dentries_per_clu - 1); for ( ; i < dentries_per_clu; i++, dentry++) { ep = get_entry_in_dir(sb, &clu, i, §or); @@ -2070,7 +2070,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) buf_unlock(sb, sector); if (p_fs->vol_type == EXFAT) { - ep = get_entry_in_dir(sb, &clu, i+1, NULL); + ep = get_entry_in_dir(sb, &clu, i + 1, NULL); if (!ep) { ret = FFS_MEDIAERR; goto out; @@ -2159,7 +2159,7 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) down(&p_fs->v_sem); clu_to_free.dir = fid->start_clu; - clu_to_free.size = (s32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; clu_to_free.flags = fid->flags; if (!is_dir_empty(sb, &clu_to_free)) { @@ -2247,7 +2247,7 @@ get_new: */ if (err == FFS_MEDIAERR) { cpos += 1 << p_bd->sector_size_bits; - cpos &= ~((1 << p_bd->sector_size_bits)-1); + cpos &= ~((1 << p_bd->sector_size_bits) - 1); } err = -EIO; @@ -2265,7 +2265,7 @@ get_new: inum = parent_ino(filp->f_path.dentry); } else { loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) | - ((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); + ((EXFAT_I(inode)->fid.rwoffset - 1) & 0xffffffff); struct inode *tmp = exfat_iget(sb, i_pos); if (tmp) { @@ -3089,7 +3089,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, if (inode->i_ino == EXFAT_ROOT_INO) { if (sector < (p_fs->dentries_in_root >> - (p_bd->sector_size_bits-DENTRY_SIZE_BITS))) { + (p_bd->sector_size_bits - DENTRY_SIZE_BITS))) { *phys = sector + p_fs->root_start_sector; *mapped_blocks = 1; } @@ -3206,7 +3206,7 @@ static int exfat_write_begin(struct file *file, struct address_space *mapping, &EXFAT_I(mapping->host)->mmu_private); if (ret < 0) - exfat_write_failed(mapping, pos+len); + exfat_write_failed(mapping, pos + len); return ret; } @@ -3221,7 +3221,7 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); if (err < len) - exfat_write_failed(mapping, pos+len); + exfat_write_failed(mapping, pos + len); if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { inode->i_mtime = inode->i_ctime = current_time(inode); -- cgit v1.2.3-59-g8ed1b From 0e739ba8e269b675b403e0989a02ea5b476421fd Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Sun, 8 Sep 2019 15:26:15 +0000 Subject: staging: exfat: cleanup spacing for casts Fix checkpatch.pl warnings: CHECK: No space is necessary after a cast Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190908152616.25459-2-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_core.c | 88 ++++++++++++++++++------------------- drivers/staging/exfat/exfat_super.c | 66 ++++++++++++++-------------- 2 files changed, 77 insertions(+), 77 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 8fb4ce16010c..8965e8453fcb 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -204,7 +204,7 @@ s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, if ((--num_alloc) == 0) { p_fs->clu_srch_ptr = new_clu; - if (p_fs->used_clusters != (u32) ~0) + if (p_fs->used_clusters != (u32)~0) p_fs->used_clusters += num_clusters; return num_clusters; @@ -215,7 +215,7 @@ s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, } p_fs->clu_srch_ptr = new_clu; - if (p_fs->used_clusters != (u32) ~0) + if (p_fs->used_clusters != (u32)~0) p_fs->used_clusters += num_clusters; return num_clusters; @@ -273,7 +273,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, if ((--num_alloc) == 0) { p_fs->clu_srch_ptr = hint_clu; - if (p_fs->used_clusters != (u32) ~0) + if (p_fs->used_clusters != (u32)~0) p_fs->used_clusters += num_clusters; p_chain->size += num_clusters; @@ -293,7 +293,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, } p_fs->clu_srch_ptr = hint_clu; - if (p_fs->used_clusters != (u32) ~0) + if (p_fs->used_clusters != (u32)~0) p_fs->used_clusters += num_clusters; p_chain->size += num_clusters; @@ -337,7 +337,7 @@ void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, } while (clu != CLUSTER_32(~0)); - if (p_fs->used_clusters != (u32) ~0) + if (p_fs->used_clusters != (u32)~0) p_fs->used_clusters -= num_clusters; } @@ -396,7 +396,7 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); } - if (p_fs->used_clusters != (u32) ~0) + if (p_fs->used_clusters != (u32)~0) p_fs->used_clusters -= num_clusters; } @@ -473,7 +473,7 @@ s32 exfat_count_used_clusters(struct super_block *sb) map_i = map_b = 0; for (i = 2; i < p_fs->num_clusters; i += 8) { - k = *(((u8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b); count += used_bit[k]; if ((++map_b) >= p_bd->sector_size) { @@ -536,7 +536,7 @@ s32 load_alloc_bitmap(struct super_block *sb) if (ep->flags == 0x0) { p_fs->map_clu = GET32_A(ep->start_clu); - map_size = (u32) GET64_A(ep->size); + map_size = (u32)GET64_A(ep->size); p_fs->map_sectors = ((map_size - 1) >> p_bd->sector_size_bits) + 1; @@ -601,7 +601,7 @@ s32 set_alloc_bitmap(struct super_block *sb, u32 clu) sector = START_SECTOR(p_fs->map_clu) + i; - exfat_bitmap_set((u8 *) p_fs->vol_amap[i]->b_data, b); + exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b); return sector_write(sb, sector, p_fs->vol_amap[i], 0); } @@ -623,7 +623,7 @@ s32 clr_alloc_bitmap(struct super_block *sb, u32 clu) sector = START_SECTOR(p_fs->map_clu) + i; - exfat_bitmap_clear((u8 *) p_fs->vol_amap[i]->b_data, b); + exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b); return sector_write(sb, sector, p_fs->vol_amap[i], 0); @@ -655,7 +655,7 @@ u32 test_alloc_bitmap(struct super_block *sb, u32 clu) map_b = (clu >> 3) & p_bd->sector_size_mask; for (i = 2; i < p_fs->num_clusters; i += 8) { - k = *(((u8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b); if (clu_mask > 0) { k |= clu_mask; clu_mask = 0; @@ -728,7 +728,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector, sector++; for (i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { - uni = GET16(((u8 *) tmp_bh->b_data) + i); + uni = GET16(((u8 *)tmp_bh->b_data) + i); checksum = ((checksum & 1) ? 0x80000000 : 0) + (checksum >> 1) + *(((u8 *)tmp_bh->b_data) + @@ -872,7 +872,7 @@ s32 load_upcase_table(struct super_block *sb) continue; tbl_clu = GET32_A(ep->start_clu); - tbl_size = (u32) GET64_A(ep->size); + tbl_size = (u32)GET64_A(ep->size); sector = START_SECTOR(tbl_clu); num_sectors = ((tbl_size - 1) >> p_bd->sector_size_bits) + 1; @@ -908,7 +908,7 @@ void free_upcase_table(struct super_block *sb) u32 fat_get_entry_type(struct dentry_t *p_entry) { - struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; if (*(ep->name) == 0x0) return TYPE_UNUSED; @@ -930,7 +930,7 @@ u32 fat_get_entry_type(struct dentry_t *p_entry) u32 exfat_get_entry_type(struct dentry_t *p_entry) { - struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; if (ep->type == 0x0) { return TYPE_UNUSED; @@ -975,7 +975,7 @@ u32 exfat_get_entry_type(struct dentry_t *p_entry) void fat_set_entry_type(struct dentry_t *p_entry, u32 type) { - struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; if (type == TYPE_UNUSED) *(ep->name) = 0x0; @@ -998,7 +998,7 @@ void fat_set_entry_type(struct dentry_t *p_entry, u32 type) void exfat_set_entry_type(struct dentry_t *p_entry, u32 type) { - struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; if (type == TYPE_UNUSED) { ep->type = 0x0; @@ -1028,30 +1028,30 @@ void exfat_set_entry_type(struct dentry_t *p_entry, u32 type) u32 fat_get_entry_attr(struct dentry_t *p_entry) { - struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; - return (u32) ep->attr; + return (u32)ep->attr; } u32 exfat_get_entry_attr(struct dentry_t *p_entry) { - struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - return (u32) GET16_A(ep->attr); + return (u32)GET16_A(ep->attr); } void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr) { - struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; - ep->attr = (u8) attr; + ep->attr = (u8)attr; } void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr) { - struct file_dentry_t *ep = (struct file_dentry_t *) p_entry; + struct file_dentry_t *ep = (struct file_dentry_t *)p_entry; - SET16_A(ep->attr, (u16) attr); + SET16_A(ep->attr, (u16)attr); } u8 fat_get_entry_flag(struct dentry_t *p_entry) @@ -1061,7 +1061,7 @@ u8 fat_get_entry_flag(struct dentry_t *p_entry) u8 exfat_get_entry_flag(struct dentry_t *p_entry) { - struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry; + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; return ep->flags; } @@ -1072,14 +1072,14 @@ void fat_set_entry_flag(struct dentry_t *p_entry, u8 flags) void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags) { - struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry; + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; ep->flags = flags; } u32 fat_get_entry_clu0(struct dentry_t *p_entry) { - struct dos_dentry_t *ep = (struct dos_dentry_t *) p_entry; + struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; return ((u32)GET16_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo); @@ -1087,7 +1087,7 @@ u32 fat_get_entry_clu0(struct dentry_t *p_entry) u32 exfat_get_entry_clu0(struct dentry_t *p_entry) { - struct strm_dentry_t *ep = (struct strm_dentry_t *) p_entry; + struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry; return GET32_A(ep->start_clu); } @@ -1111,7 +1111,7 @@ u64 fat_get_entry_size(struct dentry_t *p_entry) { struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; - return (u64) GET32_A(ep->size); + return (u64)GET32_A(ep->size); } u64 exfat_get_entry_size(struct dentry_t *p_entry) @@ -1125,7 +1125,7 @@ void fat_set_entry_size(struct dentry_t *p_entry, u64 size) { struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry; - SET32_A(ep->size, (u32) size); + SET32_A(ep->size, (u32)size); } void exfat_set_entry_size(struct dentry_t *p_entry, u64 size) @@ -1384,14 +1384,14 @@ void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu) { struct timestamp_t tm, *tp; - fat_set_entry_type((struct dentry_t *) ep, type); + fat_set_entry_type((struct dentry_t *)ep, type); SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); SET32_A(ep->size, 0); tp = tm_current(&tm); - fat_set_entry_time((struct dentry_t *) ep, tp, TM_CREATE); - fat_set_entry_time((struct dentry_t *) ep, tp, TM_MODIFY); + fat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE); + fat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY); SET16_A(ep->access_date, 0); ep->create_time_ms = 0; } @@ -1401,8 +1401,8 @@ void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname) int i; bool end = false; - fat_set_entry_type((struct dentry_t *) ep, TYPE_EXTEND); - ep->order = (u8) order; + fat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND); + ep->order = (u8)order; ep->sysid = 0; ep->checksum = chksum; SET16_A(ep->start_clu, 0); @@ -1535,7 +1535,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir, buf_lock(sb, sector); - num_entries = (s32) file_ep->num_ext + 1; + num_entries = (s32)file_ep->num_ext + 1; chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0, CS_DIR_ENTRY); @@ -1749,7 +1749,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb, es->offset = off; es->alloc_flag = p_dir->flags; - pos = (struct dentry_t *) &(es->__buf); + pos = (struct dentry_t *)&es->__buf; while (num_entries) { /* @@ -2190,7 +2190,7 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, if (is_feasible_entry && has_ext_entry) return dentry; - dos_ep = (struct dos_dentry_t *) ep; + dos_ep = (struct dos_dentry_t *)ep; if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name)) return dentry; } @@ -2198,12 +2198,12 @@ s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, has_ext_entry = false; } else if (entry_type == TYPE_EXTEND) { if (is_feasible_entry) { - ext_ep = (struct ext_dentry_t *) ep; + ext_ep = (struct ext_dentry_t *)ep; if (ext_ep->order > 0x40) { order = (s32)(ext_ep->order - 0x40); uniname = p_uniname->name + 13 * (order - 1); } else { - order = (s32) ext_ep->order; + order = (s32)ext_ep->order; uniname -= 13; } @@ -2310,7 +2310,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir, num_empty = 0; if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { - file_ep = (struct file_dentry_t *) ep; + file_ep = (struct file_dentry_t *)ep; if ((type == TYPE_ALL) || (type == entry_type)) { num_ext_entries = file_ep->num_ext; is_feasible_entry = true; @@ -2388,11 +2388,11 @@ s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir, { s32 count = 0; u8 chksum; - struct dos_dentry_t *dos_ep = (struct dos_dentry_t *) p_entry; + struct dos_dentry_t *dos_ep = (struct dos_dentry_t *)p_entry; struct ext_dentry_t *ext_ep; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + chksum = calc_checksum_1byte((void *)dos_ep->name, DOS_NAME_LENGTH, 0); for (entry--; entry >= 0; entry--) { ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 131f60a07bb9..1cb0ec06c54e 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -379,7 +379,7 @@ static int ffsMountVol(struct super_block *sb) p_fs->PBR_sector = 0; - p_pbr = (struct pbr_sector_t *) tmp_bh->b_data; + p_pbr = (struct pbr_sector_t *)tmp_bh->b_data; /* check the validity of PBR */ if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { @@ -502,7 +502,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) /* acquire the lock for file system critical section */ down(&p_fs->v_sem); - if (p_fs->used_clusters == (u32) ~0) + if (p_fs->used_clusters == (u32)~0) p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); info->FatType = p_fs->vol_type; @@ -812,7 +812,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, { bool modified = false; s32 offset, sec_offset, clu_offset; - s32 num_clusters, num_alloc, num_alloced = (s32) ~0; + s32 num_clusters, num_alloc, num_alloced = (s32)~0; int ret = 0; u32 clu, last_clu; sector_t LogSector, sector = 0; @@ -1225,7 +1225,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, struct dentry_t *ep; struct super_block *sb = old_parent_inode->i_sb; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - u8 *new_path = (u8 *) new_dentry->d_name.name; + u8 *new_path = (u8 *)new_dentry->d_name.name; struct inode *new_inode = new_dentry->d_inode; int num_entries; struct file_id_t *new_fid = NULL; @@ -1593,7 +1593,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) info->ModifyTimestamp.Second = tm.sec; info->ModifyTimestamp.MilliSecond = 0; - memset((char *) &info->AccessTimestamp, 0, sizeof(struct date_time_t)); + memset((char *)&info->AccessTimestamp, 0, sizeof(struct date_time_t)); *(uni_name.name) = 0x0; /* XXX this is very bad for exfat cuz name is already included in es. @@ -2093,7 +2093,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) fid->hint_last_clu = clu.dir; } - fid->rwoffset = (s64) ++dentry; + fid->rwoffset = (s64)(++dentry); if (p_fs->dev_ejected) ret = FFS_MEDIAERR; @@ -2119,7 +2119,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) *(dir_entry->Name) = '\0'; - fid->rwoffset = (s64) ++dentry; + fid->rwoffset = (s64)(++dentry); if (p_fs->dev_ejected) ret = FFS_MEDIAERR; @@ -2264,7 +2264,7 @@ get_new: } else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { inum = parent_ino(filp->f_path.dentry); } else { - loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) | + loff_t i_pos = ((loff_t)EXFAT_I(inode)->fid.start_clu << 32) | ((EXFAT_I(inode)->fid.rwoffset - 1) & 0xffffffff); struct inode *tmp = exfat_iget(sb, i_pos); @@ -2325,7 +2325,7 @@ struct inode *inode = filp->f_path.dentry->d_inode; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (get_user(flags, (int __user *) arg)) + if (get_user(flags, (int __user *)arg)) return -EFAULT; __lock_super(sb); @@ -2361,7 +2361,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, pr_debug("%s entered\n", __func__); - err = ffsCreateFile(dir, (u8 *) dentry->d_name.name, FM_REGULAR, &fid); + err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid); if (err) { if (err == FFS_INVALIDPATH) err = -EINVAL; @@ -2378,11 +2378,11 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, INC_IVERSION(dir); dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); if (IS_DIRSYNC(dir)) - (void) exfat_sync_inode(dir); + (void)exfat_sync_inode(dir); else mark_inode_dirty(dir); - i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); inode = exfat_build_inode(sb, &fid, i_pos); if (IS_ERR(inode)) { @@ -2412,7 +2412,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, if (qname->len == 0) return -ENOENT; - err = ffsLookupFile(dir, (u8 *) qname->name, fid); + err = ffsLookupFile(dir, (u8 *)qname->name, fid); if (err) return -ENOENT; @@ -2447,7 +2447,7 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, goto error; } - i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); inode = exfat_build_inode(sb, &fid, i_pos); if (IS_ERR(inode)) { err = PTR_ERR(inode); @@ -2542,7 +2542,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) INC_IVERSION(dir); dir->i_mtime = dir->i_atime = current_time(dir); if (IS_DIRSYNC(dir)) - (void) exfat_sync_inode(dir); + (void)exfat_sync_inode(dir); else mark_inode_dirty(dir); @@ -2565,14 +2565,14 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, struct file_id_t fid; loff_t i_pos; int err; - u64 len = (u64) strlen(target); + u64 len = (u64)strlen(target); u64 ret; __lock_super(sb); pr_debug("%s entered\n", __func__); - err = ffsCreateFile(dir, (u8 *) dentry->d_name.name, FM_SYMLINK, &fid); + err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid); if (err) { if (err == FFS_INVALIDPATH) err = -EINVAL; @@ -2585,7 +2585,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, goto out; } - err = ffsWriteFile(dir, &fid, (char *) target, len, &ret); + err = ffsWriteFile(dir, &fid, (char *)target, len, &ret); if (err) { ffsRemoveFile(dir, &fid); @@ -2600,11 +2600,11 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, INC_IVERSION(dir); dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); if (IS_DIRSYNC(dir)) - (void) exfat_sync_inode(dir); + (void)exfat_sync_inode(dir); else mark_inode_dirty(dir); - i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); inode = exfat_build_inode(sb, &fid, i_pos); if (IS_ERR(inode)) { @@ -2642,7 +2642,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) pr_debug("%s entered\n", __func__); - err = ffsCreateDir(dir, (u8 *) dentry->d_name.name, &fid); + err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid); if (err) { if (err == FFS_INVALIDPATH) err = -EINVAL; @@ -2659,12 +2659,12 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) INC_IVERSION(dir); dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir); if (IS_DIRSYNC(dir)) - (void) exfat_sync_inode(dir); + (void)exfat_sync_inode(dir); else mark_inode_dirty(dir); inc_nlink(dir); - i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff); inode = exfat_build_inode(sb, &fid, i_pos); if (IS_ERR(inode)) { @@ -2713,7 +2713,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) INC_IVERSION(dir); dir->i_mtime = dir->i_atime = current_time(dir); if (IS_DIRSYNC(dir)) - (void) exfat_sync_inode(dir); + (void)exfat_sync_inode(dir); else mark_inode_dirty(dir); drop_nlink(dir); @@ -2771,17 +2771,17 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = current_time(new_dir); if (IS_DIRSYNC(new_dir)) - (void) exfat_sync_inode(new_dir); + (void)exfat_sync_inode(new_dir); else mark_inode_dirty(new_dir); - i_pos = ((loff_t) EXFAT_I(old_inode)->fid.dir.dir << 32) | + i_pos = ((loff_t)EXFAT_I(old_inode)->fid.dir.dir << 32) | (EXFAT_I(old_inode)->fid.entry & 0xffffffff); exfat_detach(old_inode); exfat_attach(old_inode, i_pos); if (IS_DIRSYNC(new_dir)) - (void) exfat_sync_inode(old_inode); + (void)exfat_sync_inode(old_inode); else mark_inode_dirty(old_inode); @@ -2793,7 +2793,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, INC_IVERSION(old_dir); old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); if (IS_DIRSYNC(old_dir)) - (void) exfat_sync_inode(old_dir); + (void)exfat_sync_inode(old_dir); else mark_inode_dirty(old_dir); @@ -2917,7 +2917,7 @@ static void exfat_truncate(struct inode *inode, loff_t old_size) inode->i_ctime = inode->i_mtime = current_time(inode); if (IS_DIRSYNC(inode)) - (void) exfat_sync_inode(inode); + (void)exfat_sync_inode(inode); else mark_inode_dirty(inode); @@ -3503,7 +3503,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); struct vol_info_t info; - if (p_fs->used_clusters == (u32) ~0) { + if (p_fs->used_clusters == (u32)~0) { if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR) return -EIO; @@ -3678,7 +3678,7 @@ static int parse_options(char *options, int silent, int *debug, opts->fs_uid = current_uid(); opts->fs_gid = current_gid(); opts->fs_fmask = opts->fs_dmask = current->fs->umask; - opts->allow_utime = (unsigned short) -1; + opts->allow_utime = (unsigned short)-1; opts->codepage = exfat_default_codepage; opts->iocharset = exfat_default_iocharset; opts->casesensitive = 0; @@ -3770,7 +3770,7 @@ static int parse_options(char *options, int silent, int *debug, } out: - if (opts->allow_utime == (unsigned short) -1) + if (opts->allow_utime == (unsigned short)-1) opts->allow_utime = ~opts->fs_dmask & 0022; return 0; @@ -3817,7 +3817,7 @@ static int exfat_read_root(struct inode *inode) i_size_write(inode, info.Size); inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) & ~((loff_t)p_fs->cluster_size - 1)) >> 9; - EXFAT_I(inode)->i_pos = ((loff_t) p_fs->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->i_pos = ((loff_t)p_fs->root_dir << 32) | 0xffffffff; EXFAT_I(inode)->mmu_private = i_size_read(inode); exfat_save_attr(inode, ATTR_SUBDIR); -- cgit v1.2.3-59-g8ed1b From 4e35a0d87cbd16553293f7d48a4ffddbd36cec77 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Sun, 8 Sep 2019 15:26:16 +0000 Subject: staging: exfat: use integer constants Replace manually generated values with predefined constants. Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190908152616.25459-3-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_core.c | 18 +++++++++--------- drivers/staging/exfat/exfat_super.c | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 8965e8453fcb..6eee2aa06bd7 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -204,7 +204,7 @@ s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, if ((--num_alloc) == 0) { p_fs->clu_srch_ptr = new_clu; - if (p_fs->used_clusters != (u32)~0) + if (p_fs->used_clusters != UINT_MAX) p_fs->used_clusters += num_clusters; return num_clusters; @@ -215,7 +215,7 @@ s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc, } p_fs->clu_srch_ptr = new_clu; - if (p_fs->used_clusters != (u32)~0) + if (p_fs->used_clusters != UINT_MAX) p_fs->used_clusters += num_clusters; return num_clusters; @@ -273,7 +273,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, if ((--num_alloc) == 0) { p_fs->clu_srch_ptr = hint_clu; - if (p_fs->used_clusters != (u32)~0) + if (p_fs->used_clusters != UINT_MAX) p_fs->used_clusters += num_clusters; p_chain->size += num_clusters; @@ -293,7 +293,7 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, } p_fs->clu_srch_ptr = hint_clu; - if (p_fs->used_clusters != (u32)~0) + if (p_fs->used_clusters != UINT_MAX) p_fs->used_clusters += num_clusters; p_chain->size += num_clusters; @@ -337,7 +337,7 @@ void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain, } while (clu != CLUSTER_32(~0)); - if (p_fs->used_clusters != (u32)~0) + if (p_fs->used_clusters != UINT_MAX) p_fs->used_clusters -= num_clusters; } @@ -396,7 +396,7 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain, } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); } - if (p_fs->used_clusters != (u32)~0) + if (p_fs->used_clusters != UINT_MAX) p_fs->used_clusters -= num_clusters; } @@ -3064,7 +3064,7 @@ s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) p_fs->vol_flag = VOL_CLEAN; p_fs->clu_srch_ptr = 2; - p_fs->used_clusters = (u32)~0; + p_fs->used_clusters = UINT_MAX; p_fs->fs_func = &fat_fs_func; @@ -3117,7 +3117,7 @@ s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) p_fs->vol_flag = VOL_CLEAN; p_fs->clu_srch_ptr = 2; - p_fs->used_clusters = (u32)~0; + p_fs->used_clusters = UINT_MAX; p_fs->fs_func = &fat_fs_func; @@ -3192,7 +3192,7 @@ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr) p_fs->vol_flag = (u32)GET16(p_bpb->vol_flags); p_fs->clu_srch_ptr = 2; - p_fs->used_clusters = (u32)~0; + p_fs->used_clusters = UINT_MAX; p_fs->fs_func = &exfat_fs_func; diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 1cb0ec06c54e..610f20683611 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -502,7 +502,7 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) /* acquire the lock for file system critical section */ down(&p_fs->v_sem); - if (p_fs->used_clusters == (u32)~0) + if (p_fs->used_clusters == UINT_MAX) p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); info->FatType = p_fs->vol_type; @@ -3503,7 +3503,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); struct vol_info_t info; - if (p_fs->used_clusters == (u32)~0) { + if (p_fs->used_clusters == UINT_MAX) { if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR) return -EIO; @@ -3678,7 +3678,7 @@ static int parse_options(char *options, int silent, int *debug, opts->fs_uid = current_uid(); opts->fs_gid = current_gid(); opts->fs_fmask = opts->fs_dmask = current->fs->umask; - opts->allow_utime = (unsigned short)-1; + opts->allow_utime = U16_MAX; opts->codepage = exfat_default_codepage; opts->iocharset = exfat_default_iocharset; opts->casesensitive = 0; @@ -3770,7 +3770,7 @@ static int parse_options(char *options, int silent, int *debug, } out: - if (opts->allow_utime == (unsigned short)-1) + if (opts->allow_utime == U16_MAX) opts->allow_utime = ~opts->fs_dmask & 0022; return 0; -- cgit v1.2.3-59-g8ed1b From 56a583d264b97e34d3c6009f50f113450e63a1de Mon Sep 17 00:00:00 2001 From: Sandro Volery Date: Thu, 12 Sep 2019 10:25:59 +0200 Subject: Staging: exfat: Avoid use of strcpy Use strscpy instead of strcpy in exfat_core.c, and add a check for length that will return already known FFS_INVALIDPATH. Suggested-by: Rasmus Villemoes Signed-off-by: Sandro Volery Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190912082559.GA5043@volery Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c index 6eee2aa06bd7..b3e9cf725cf5 100644 --- a/drivers/staging/exfat/exfat_core.c +++ b/drivers/staging/exfat/exfat_core.c @@ -2961,11 +2961,9 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir, struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); struct file_id_t *fid = &(EXFAT_I(inode)->fid); - if (strlen(path) >= (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + if (strscpy(name_buf, path, sizeof(name_buf)) < 0) return FFS_INVALIDPATH; - strcpy(name_buf, path); - nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy); if (lossy) return FFS_INVALIDPATH; -- cgit v1.2.3-59-g8ed1b From 2d70718dd576a53ae12a04d16d9f31812bb09b84 Mon Sep 17 00:00:00 2001 From: Valentin Vidic Date: Sun, 8 Sep 2019 17:35:36 +0000 Subject: staging: exfat: drop unused function parameter sbi parameter not used inside the function so remove it. Also cleanup unused variables generated by this change. Signed-off-by: Valentin Vidic Link: https://lore.kernel.org/r/20190908173539.26963-1-vvidic@valentin-vidic.from.hr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/exfat/exfat_super.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 610f20683611..5f6caee819a6 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -56,8 +56,7 @@ static void exfat_write_super(struct super_block *sb); #define UNIX_SECS_2108 4354819200L /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ -static void exfat_time_fat2unix(struct exfat_sb_info *sbi, - struct timespec64 *ts, struct date_time_t *tp) +static void exfat_time_fat2unix(struct timespec64 *ts, struct date_time_t *tp) { ts->tv_sec = mktime64(tp->Year + 1980, tp->Month + 1, tp->Day, tp->Hour, tp->Minute, tp->Second); @@ -66,8 +65,7 @@ static void exfat_time_fat2unix(struct exfat_sb_info *sbi, } /* Convert linear UNIX date to a FAT time/date pair. */ -static void exfat_time_unix2fat(struct exfat_sb_info *sbi, - struct timespec64 *ts, struct date_time_t *tp) +static void exfat_time_unix2fat(struct timespec64 *ts, struct date_time_t *tp) { time64_t second = ts->tv_sec; struct tm tm; @@ -3349,9 +3347,9 @@ static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid) inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) & ~((loff_t)p_fs->cluster_size - 1)) >> 9; - exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp); - exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp); - exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp); + exfat_time_fat2unix(&inode->i_mtime, &info.ModifyTimestamp); + exfat_time_fat2unix(&inode->i_ctime, &info.CreateTimestamp); + exfat_time_fat2unix(&inode->i_atime, &info.AccessTimestamp); return 0; } @@ -3412,8 +3410,6 @@ static void exfat_destroy_inode(struct inode *inode) static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) { - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); struct dir_entry_t info; if (inode->i_ino == EXFAT_ROOT_INO) @@ -3422,9 +3418,9 @@ static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) info.Attr = exfat_make_attr(inode); info.Size = i_size_read(inode); - exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp); - exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp); - exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp); + exfat_time_unix2fat(&inode->i_mtime, &info.ModifyTimestamp); + exfat_time_unix2fat(&inode->i_ctime, &info.CreateTimestamp); + exfat_time_unix2fat(&inode->i_atime, &info.AccessTimestamp); ffsWriteStat(inode, &info); -- cgit v1.2.3-59-g8ed1b From 77b0a8412ccfa079c5213b35ea1270e4817b3c6f Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 8 Sep 2019 15:11:01 +0530 Subject: staging: nvec: make use of devm_platform_ioremap_resource fix below issue reported by coccicheck drivers/staging//nvec/nvec.c:794:1-5: WARNING: Use devm_platform_ioremap_resource for base Signed-off-by: Hariprasad Kelam Acked-by: Marc Dietrich Link: https://lore.kernel.org/r/1567935662-8006-1-git-send-email-hariprasad.kelam@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 1cbd7b71fc38..360ec0407740 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -767,7 +767,6 @@ static int tegra_nvec_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct nvec_chip *nvec; struct nvec_msg *msg; - struct resource *res; void __iomem *base; char get_firmware_version[] = { NVEC_CNTL, GET_FIRMWARE_VERSION }, unmute_speakers[] = { NVEC_OEM0, 0x10, 0x59, 0x95 }, @@ -790,8 +789,7 @@ static int tegra_nvec_probe(struct platform_device *pdev) return -ENODEV; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); -- cgit v1.2.3-59-g8ed1b From ae8779e1983d6361620f1f6d3f76064edee733c0 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Mon, 9 Sep 2019 14:12:25 +0000 Subject: staging: dt-bindings: wilc1000: add optional rtc_clk property Add bindings for optional rtc clock pin. Signed-off-by: Eugen Hristev Acked-by: Ajay Singh Link: https://lore.kernel.org/r/1568037993-4646-1-git-send-email-eugen.hristev@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/microchip,wilc1000,sdio.txt | 8 +++++++- drivers/staging/wilc1000/microchip,wilc1000,spi.txt | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt b/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt index 4f7d1c2be4d0..da5235950a70 100644 --- a/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt +++ b/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt @@ -10,7 +10,9 @@ Required properties: Optional: - bus-width : Number of data lines wired up the slot. Default 1 bit. - +- rtc_clk : Clock connected on the rtc clock line. Must be assigned + a frequency with assigned-clocks property, and must be + connected to a clock provider. Examples: mmc1: mmc@fc000000 { @@ -24,6 +26,10 @@ mmc1: mmc@fc000000 { wilc_sdio@0 { compatible = "microchip,wilc1000-sdio"; irq-gpios = <&pioC 27 0>; + clocks = <&pck1>; + clock-names = "rtc_clk"; + assigned-clocks = <&pck1>; + assigned-clock-rates = <32768>; status = "okay"; reg = <0>; bus-width = <4>; diff --git a/drivers/staging/wilc1000/microchip,wilc1000,spi.txt b/drivers/staging/wilc1000/microchip,wilc1000,spi.txt index 87db87b2d901..34236932dbb6 100644 --- a/drivers/staging/wilc1000/microchip,wilc1000,spi.txt +++ b/drivers/staging/wilc1000/microchip,wilc1000,spi.txt @@ -9,6 +9,10 @@ Required properties: - reg : Chip select address of device - irq-gpios : Connect to a host IRQ +Optional: +- rtc_clk : Clock connected on the rtc clock line. Must be assigned + a frequency with assigned-clocks property, and must be + connected to a clock provider. Examples: @@ -21,6 +25,10 @@ spi1: spi@fc018000 { spi-max-frequency = <48000000>; reg = <0>; irq-gpios = <&pioC 27 0>; + clocks = <&pck1>; + clock-names = "rtc_clk"; + assigned-clocks = <&pck1>; + assigned-clock-rates = <32768>; status = "okay"; }; }; -- cgit v1.2.3-59-g8ed1b From 8692b047e86cff448af1564a8bdda770d2deb567 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Mon, 9 Sep 2019 14:12:29 +0000 Subject: staging: wilc1000: look for rtc_clk clock If rtc_clk is provided from DT, use it and enable it. This is optional. The signal may be hardcoded and no need to be requested, but if DT provides it, use it. Signed-off-by: Eugen Hristev Acked-by: Ajay Singh Link: https://lore.kernel.org/r/1568037993-4646-2-git-send-email-eugen.hristev@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 14 ++++++++++++++ drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 + 2 files changed, 15 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 2f9aa36e0114..c787c5da8f2b 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -4,6 +4,7 @@ * All rights reserved. */ +#include #include #include @@ -151,6 +152,12 @@ static int wilc_sdio_probe(struct sdio_func *func, wilc->dev = &func->dev; wilc->gpio_irq = gpio; + wilc->rtc_clk = devm_clk_get(&func->card->dev, "rtc_clk"); + if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + else if (!IS_ERR(wilc->rtc_clk)) + clk_prepare_enable(wilc->rtc_clk); + dev_info(&func->dev, "Driver Initializing success\n"); return 0; } @@ -162,6 +169,10 @@ static void wilc_sdio_remove(struct sdio_func *func) /* free the GPIO in module remove */ if (wilc->gpio_irq) gpiod_put(wilc->gpio_irq); + + if (!IS_ERR(wilc->rtc_clk)) + clk_disable_unprepare(wilc->rtc_clk); + wilc_netdev_cleanup(wilc); } @@ -193,6 +204,9 @@ static int wilc_sdio_suspend(struct device *dev) dev_info(dev, "sdio suspend\n"); chip_wakeup(wilc); + if (!IS_ERR(wilc->rtc_clk)) + clk_disable_unprepare(wilc->rtc_clk); + if (wilc->suspend_event) { host_sleep_notify(wilc); chip_allow_sleep(wilc); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 7e7ce9471f67..978a8bdbfc40 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -216,6 +216,7 @@ struct wilc { int io_type; s8 mac_status; struct gpio_desc *gpio_irq; + struct clk *rtc_clk; bool initialized; int dev_irq_num; int close; -- cgit v1.2.3-59-g8ed1b From 8b77d94e69c33f53cbb7a70ad43ba8881dfc9e32 Mon Sep 17 00:00:00 2001 From: Saiyam Doshi Date: Sun, 8 Sep 2019 23:22:47 +0530 Subject: staging: emxx_udc: remove local TRUE/FALSE definition As the function argument and variables are defined as type 'bool', remove local TRUE/FALSE define and change usage of those macros with boolean value. Signed-off-by: Saiyam Doshi Link: https://lore.kernel.org/r/20190908175247.GA20699@SD Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 76 ++++++++++++++++++------------------- drivers/staging/emxx_udc/emxx_udc.h | 5 --- 2 files changed, 38 insertions(+), 43 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 489cde4e915e..147481bf680c 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -165,7 +165,7 @@ static void _nbu2ss_create_ep0_packet(struct nbu2ss_udc *udc, udc->ep0_req.req.buf = p_buf; udc->ep0_req.req.length = length; udc->ep0_req.req.dma = 0; - udc->ep0_req.req.zero = TRUE; + udc->ep0_req.req.zero = true; udc->ep0_req.req.complete = _nbu2ss_ep0_complete; udc->ep0_req.req.status = -EINPROGRESS; udc->ep0_req.req.context = udc; @@ -668,7 +668,7 @@ static int _nbu2ss_ep0_in_transfer(struct nbu2ss_udc *udc, if ((req->req.actual % EP0_PACKETSIZE) == 0) { if (req->zero) { req->zero = false; - EP0_send_NULL(udc, FALSE); + EP0_send_NULL(udc, false); return 1; } } @@ -695,7 +695,7 @@ static int _nbu2ss_ep0_in_transfer(struct nbu2ss_udc *udc, i_remain_size -= result; if (i_remain_size == 0) { - EP0_send_NULL(udc, FALSE); + EP0_send_NULL(udc, false); return result; } @@ -754,7 +754,7 @@ static int _nbu2ss_ep0_out_transfer(struct nbu2ss_udc *udc, if ((req->req.actual % EP0_PACKETSIZE) == 0) { if (req->zero) { req->zero = false; - EP0_receive_NULL(udc, FALSE); + EP0_receive_NULL(udc, false); return 1; } } @@ -799,7 +799,7 @@ static int _nbu2ss_out_dma(struct nbu2ss_udc *udc, struct nbu2ss_req *req, if (req->dma_flag) return 1; /* DMA is forwarded */ - req->dma_flag = TRUE; + req->dma_flag = true; p_buffer = req->req.dma; p_buffer += req->req.actual; @@ -997,7 +997,7 @@ static int _nbu2ss_in_dma(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep, if (req->req.actual == 0) _nbu2ss_dma_map_single(udc, ep, req, USB_DIR_IN); #endif - req->dma_flag = TRUE; + req->dma_flag = true; /* MAX Packet Size */ mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPN_MPKT; @@ -1166,7 +1166,7 @@ static int _nbu2ss_start_transfer(struct nbu2ss_udc *udc, { int nret = -EINVAL; - req->dma_flag = FALSE; + req->dma_flag = false; req->div_len = 0; if (req->req.length == 0) { @@ -1190,7 +1190,7 @@ static int _nbu2ss_start_transfer(struct nbu2ss_udc *udc, break; case EP0_IN_STATUS_PHASE: - nret = EP0_send_NULL(udc, TRUE); + nret = EP0_send_NULL(udc, true); break; default: @@ -1216,7 +1216,7 @@ static int _nbu2ss_start_transfer(struct nbu2ss_udc *udc, static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) { u32 length; - bool bflag = FALSE; + bool bflag = false; struct nbu2ss_req *req; req = list_first_entry_or_null(&ep->queue, struct nbu2ss_req, queue); @@ -1229,7 +1229,7 @@ static void _nbu2ss_restert_transfer(struct nbu2ss_ep *ep) length &= EPN_LDATA; if (length < ep->ep.maxpacket) - bflag = TRUE; + bflag = true; } _nbu2ss_start_transfer(ep->udc, ep, req, bflag); @@ -1280,7 +1280,7 @@ static void _nbu2ss_set_endpoint_stall(struct nbu2ss_udc *udc, if (bstall) { /* Set STALL */ - ep->halted = TRUE; + ep->halted = true; if (ep_adrs & USB_DIR_IN) data = EPN_BCLR | EPN_ISTL; @@ -1290,7 +1290,7 @@ static void _nbu2ss_set_endpoint_stall(struct nbu2ss_udc *udc, _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data); } else { /* Clear STALL */ - ep->stalled = FALSE; + ep->stalled = false; if (ep_adrs & USB_DIR_IN) { _nbu2ss_bitclr(&preg->EP_REGS[num].EP_CONTROL , EPN_ISTL); @@ -1305,9 +1305,9 @@ static void _nbu2ss_set_endpoint_stall(struct nbu2ss_udc *udc, , data); } - ep->stalled = FALSE; + ep->stalled = false; if (ep->halted) { - ep->halted = FALSE; + ep->halted = false; _nbu2ss_restert_transfer(ep); } } @@ -1533,13 +1533,13 @@ static int std_req_get_status(struct nbu2ss_udc *udc) /*-------------------------------------------------------------------------*/ static int std_req_clear_feature(struct nbu2ss_udc *udc) { - return _nbu2ss_req_feature(udc, FALSE); + return _nbu2ss_req_feature(udc, false); } /*-------------------------------------------------------------------------*/ static int std_req_set_feature(struct nbu2ss_udc *udc) { - return _nbu2ss_req_feature(udc, TRUE); + return _nbu2ss_req_feature(udc, true); } /*-------------------------------------------------------------------------*/ @@ -1601,7 +1601,7 @@ static inline void _nbu2ss_read_request_data(struct nbu2ss_udc *udc, u32 *pdata) /*-------------------------------------------------------------------------*/ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc) { - bool bcall_back = TRUE; + bool bcall_back = true; int nret = -EINVAL; struct usb_ctrlrequest *p_ctrl; @@ -1623,22 +1623,22 @@ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc) switch (p_ctrl->bRequest) { case USB_REQ_GET_STATUS: nret = std_req_get_status(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_CLEAR_FEATURE: nret = std_req_clear_feature(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_SET_FEATURE: nret = std_req_set_feature(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_SET_ADDRESS: nret = std_req_set_address(udc); - bcall_back = FALSE; + bcall_back = false; break; case USB_REQ_SET_CONFIGURATION: @@ -1655,7 +1655,7 @@ static inline int _nbu2ss_decode_request(struct nbu2ss_udc *udc) if (nret >= 0) { /*--------------------------------------*/ /* Status Stage */ - nret = EP0_send_NULL(udc, TRUE); + nret = EP0_send_NULL(udc, true); } } @@ -1688,7 +1688,7 @@ static inline int _nbu2ss_ep0_in_data_stage(struct nbu2ss_udc *udc) nret = _nbu2ss_ep0_in_transfer(udc, req); if (nret == 0) { udc->ep0state = EP0_OUT_STATUS_PAHSE; - EP0_receive_NULL(udc, TRUE); + EP0_receive_NULL(udc, true); } return 0; @@ -1708,7 +1708,7 @@ static inline int _nbu2ss_ep0_out_data_stage(struct nbu2ss_udc *udc) nret = _nbu2ss_ep0_out_transfer(udc, req); if (nret == 0) { udc->ep0state = EP0_IN_STATUS_PHASE; - EP0_send_NULL(udc, TRUE); + EP0_send_NULL(udc, true); } else if (nret < 0) { _nbu2ss_bitset(&udc->p_regs->EP0_CONTROL, EP0_BCLR); @@ -1817,7 +1817,7 @@ static inline void _nbu2ss_ep0_int(struct nbu2ss_udc *udc) if (nret < 0) { /* Send Stall */ - _nbu2ss_set_endpoint_stall(udc, 0, TRUE); + _nbu2ss_set_endpoint_stall(udc, 0, true); } } @@ -1925,7 +1925,7 @@ static inline void _nbu2ss_epn_in_dma_int(struct nbu2ss_udc *udc, preq->actual += req->div_len; req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; #ifdef USE_DMA _nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_IN); @@ -1961,7 +1961,7 @@ static inline void _nbu2ss_epn_out_dma_int(struct nbu2ss_udc *udc, if (req->req.actual == req->req.length) { if ((req->req.length % ep->ep.maxpacket) && !req->zero) { req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; _nbu2ss_ep_done(ep, req, 0); return; } @@ -1990,7 +1990,7 @@ static inline void _nbu2ss_epn_out_dma_int(struct nbu2ss_udc *udc, if ((req->req.actual % ep->ep.maxpacket) > 0) { if (req->req.actual == req->div_len) { req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; _nbu2ss_ep_done(ep, req, 0); return; } @@ -1998,7 +1998,7 @@ static inline void _nbu2ss_epn_out_dma_int(struct nbu2ss_udc *udc, req->req.actual += req->div_len; req->div_len = 0; - req->dma_flag = FALSE; + req->dma_flag = false; _nbu2ss_epn_out_int(udc, ep, req); } @@ -2187,7 +2187,7 @@ static int _nbu2ss_enable_controller(struct nbu2ss_udc *udc) /* USB Interrupt Enable */ _nbu2ss_bitset(&udc->p_regs->USB_INT_ENA, USB_INT_EN_BIT); - udc->udc_enabled = TRUE; + udc->udc_enabled = true; return 0; } @@ -2203,7 +2203,7 @@ static void _nbu2ss_reset_controller(struct nbu2ss_udc *udc) static void _nbu2ss_disable_controller(struct nbu2ss_udc *udc) { if (udc->udc_enabled) { - udc->udc_enabled = FALSE; + udc->udc_enabled = false; _nbu2ss_reset_controller(udc); _nbu2ss_bitset(&udc->p_regs->EPCTR, (DIRPD | EPC_RST)); } @@ -2456,8 +2456,8 @@ static int nbu2ss_ep_enable(struct usb_ep *_ep, ep->direct = desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK; ep->ep_type = ep_type; ep->wedged = 0; - ep->halted = FALSE; - ep->stalled = FALSE; + ep->halted = false; + ep->stalled = false; ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); @@ -2588,9 +2588,9 @@ static int nbu2ss_ep_queue(struct usb_ep *_ep, #ifdef USE_DMA if ((uintptr_t)req->req.buf & 0x3) - req->unaligned = TRUE; + req->unaligned = true; else - req->unaligned = FALSE; + req->unaligned = false; if (req->unaligned) { if (!ep->virt_buf) @@ -2616,7 +2616,7 @@ static int nbu2ss_ep_queue(struct usb_ep *_ep, list_add_tail(&req->queue, &ep->queue); if (bflag && !ep->stalled) { - result = _nbu2ss_start_transfer(udc, ep, req, FALSE); + result = _nbu2ss_start_transfer(udc, ep, req, false); if (result < 0) { dev_err(udc->dev, " *** %s, result = %d\n", __func__, result); @@ -2704,12 +2704,12 @@ static int nbu2ss_ep_set_halt(struct usb_ep *_ep, int value) ep_adrs = ep->epnum | ep->direct; if (value == 0) { _nbu2ss_set_endpoint_stall(udc, ep_adrs, value); - ep->stalled = FALSE; + ep->stalled = false; } else { if (list_empty(&ep->queue)) _nbu2ss_epn_set_stall(udc, ep); else - ep->stalled = TRUE; + ep->stalled = true; } if (value == 0) diff --git a/drivers/staging/emxx_udc/emxx_udc.h b/drivers/staging/emxx_udc/emxx_udc.h index b8c3dee5626c..9c2671cb32f7 100644 --- a/drivers/staging/emxx_udc/emxx_udc.h +++ b/drivers/staging/emxx_udc/emxx_udc.h @@ -19,11 +19,6 @@ #define USE_DMA 1 #define USE_SUSPEND_WAIT 1 -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - /*------------ Board dependence(Resource) */ #define VBUS_VALUE GPIO_VBUS -- cgit v1.2.3-59-g8ed1b From 5e0127455737d43d4ac45ecdcee42c7521aefe1a Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Sun, 8 Sep 2019 09:48:05 -0400 Subject: dt-bindings: anybus-controller: move to staging/ tree The devicetree bindings for anybus-controller were mistakenly merged into the main Linux tree. Its driver resides in staging/, so the bindings belong in staging/ too. Cc: Greg Kroah-Hartman Fixes: 20a980e957bf ("dt-bindings: anybus-controller: document devicetree binding") Signed-off-by: Sven Van Asbroeck Link: https://lore.kernel.org/r/20190908134805.30957-1-TheSven73@gmail.com Signed-off-by: Greg Kroah-Hartman --- .../bindings/fieldbus/arcx,anybus-controller.txt | 71 ---------------------- .../bindings/fieldbus/arcx,anybus-controller.txt | 71 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 71 deletions(-) delete mode 100644 Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt create mode 100644 drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt (limited to 'drivers/staging') diff --git a/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt b/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt deleted file mode 100644 index b1f9474f36d5..000000000000 --- a/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt +++ /dev/null @@ -1,71 +0,0 @@ -* Arcx Anybus-S controller - -This chip communicates with the SoC over a parallel bus. It is -expected that its Device Tree node is specified as the child of a node -corresponding to the parallel bus used for communication. - -Required properties: --------------------- - - - compatible : The following chip-specific string: - "arcx,anybus-controller" - - - reg : three areas: - index 0: bus memory area where the cpld registers are located. - index 1: bus memory area of the first host's dual-port ram. - index 2: bus memory area of the second host's dual-port ram. - - - reset-gpios : the GPIO pin connected to the reset line of the controller. - - - interrupts : two interrupts: - index 0: interrupt connected to the first host - index 1: interrupt connected to the second host - Generic interrupt client node bindings are described in - interrupt-controller/interrupts.txt - -Optional: use of subnodes -------------------------- - -The card connected to a host may need additional properties. These can be -specified in subnodes to the controller node. - -The subnodes are identified by the standard 'reg' property. Which information -exactly can be specified depends on the bindings for the function driver -for the subnode. - -Required controller node properties when using subnodes: -- #address-cells: should be one. -- #size-cells: should be zero. - -Required subnode properties: -- reg: Must contain the host index of the card this subnode describes: - <0> for the first host on the controller - <1> for the second host on the controller - Note that only a single card can be plugged into a host, so the host - index uniquely describes the card location. - -Example of usage: ------------------ - -This example places the bridge on top of the i.MX WEIM parallel bus, see: -Documentation/devicetree/bindings/bus/imx-weim.txt - -&weim { - controller@0,0 { - compatible = "arcx,anybus-controller"; - reg = <0 0 0x100>, <0 0x400000 0x800>, <1 0x400000 0x800>; - reset-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; - interrupt-parent = <&gpio1>; - interrupts = <1 IRQ_TYPE_LEVEL_LOW>, <5 IRQ_TYPE_LEVEL_LOW>; - /* fsl,weim-cs-timing is a i.MX WEIM bus specific property */ - fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100 - 0x00000000 0xa0000240 0x00000000>; - /* optional subnode for a card plugged into the first host */ - #address-cells = <1>; - #size-cells = <0>; - card@0 { - reg = <0>; - /* card specific properties go here */ - }; - }; -}; diff --git a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt new file mode 100644 index 000000000000..b1f9474f36d5 --- /dev/null +++ b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt @@ -0,0 +1,71 @@ +* Arcx Anybus-S controller + +This chip communicates with the SoC over a parallel bus. It is +expected that its Device Tree node is specified as the child of a node +corresponding to the parallel bus used for communication. + +Required properties: +-------------------- + + - compatible : The following chip-specific string: + "arcx,anybus-controller" + + - reg : three areas: + index 0: bus memory area where the cpld registers are located. + index 1: bus memory area of the first host's dual-port ram. + index 2: bus memory area of the second host's dual-port ram. + + - reset-gpios : the GPIO pin connected to the reset line of the controller. + + - interrupts : two interrupts: + index 0: interrupt connected to the first host + index 1: interrupt connected to the second host + Generic interrupt client node bindings are described in + interrupt-controller/interrupts.txt + +Optional: use of subnodes +------------------------- + +The card connected to a host may need additional properties. These can be +specified in subnodes to the controller node. + +The subnodes are identified by the standard 'reg' property. Which information +exactly can be specified depends on the bindings for the function driver +for the subnode. + +Required controller node properties when using subnodes: +- #address-cells: should be one. +- #size-cells: should be zero. + +Required subnode properties: +- reg: Must contain the host index of the card this subnode describes: + <0> for the first host on the controller + <1> for the second host on the controller + Note that only a single card can be plugged into a host, so the host + index uniquely describes the card location. + +Example of usage: +----------------- + +This example places the bridge on top of the i.MX WEIM parallel bus, see: +Documentation/devicetree/bindings/bus/imx-weim.txt + +&weim { + controller@0,0 { + compatible = "arcx,anybus-controller"; + reg = <0 0 0x100>, <0 0x400000 0x800>, <1 0x400000 0x800>; + reset-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>, <5 IRQ_TYPE_LEVEL_LOW>; + /* fsl,weim-cs-timing is a i.MX WEIM bus specific property */ + fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100 + 0x00000000 0xa0000240 0x00000000>; + /* optional subnode for a card plugged into the first host */ + #address-cells = <1>; + #size-cells = <0>; + card@0 { + reg = <0>; + /* card specific properties go here */ + }; + }; +}; -- cgit v1.2.3-59-g8ed1b From d9c35cca30d326df271e3f8a5e723dc4fe9a1457 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Sun, 8 Sep 2019 14:39:35 +0530 Subject: staging: rtl8723bs: core: Remove Macro "IS_MAC_ADDRESS_BROADCAST" Remove unused macro IS_MAC_ADDRESS_BROADCAST. In future if one wants use it ,use generic API "is_broadcast_ether_addr" Signed-off-by: Hariprasad Kelam Link: https://lore.kernel.org/r/1567933780-2790-1-git-send-email-hariprasad.kelam@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723bs/core/rtw_ioctl_set.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c index 8eb0ff57925f..eb08569db5ea 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c +++ b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c @@ -9,13 +9,6 @@ #include #include -#define IS_MAC_ADDRESS_BROADCAST(addr) \ -(\ - ((addr[0] == 0xff) && (addr[1] == 0xff) && \ - (addr[2] == 0xff) && (addr[3] == 0xff) && \ - (addr[4] == 0xff) && (addr[5] == 0xff)) ? true : false \ -) - u8 rtw_validate_bssid(u8 *bssid) { u8 ret = true; -- cgit v1.2.3-59-g8ed1b From 0ba4d388d70ed5f6756887ee9184d800110ef23b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 6 Sep 2019 18:39:49 +0100 Subject: staging: rtl8188eu: make two arrays static const, makes object smaller Don't populate two arrays on the stack but instead make them static const. Makes the object code smaller by 49 bytes. Before: text data bss dec hex filename 26821 5616 0 32437 7eb5 rtl8188eu/core/rtw_ieee80211.o After: text data bss dec hex filename 26612 5776 0 32388 7e84 rtl8188eu/core/rtw_ieee80211.o (gcc version 9.2.1, amd64) Signed-off-by: Colin Ian King Acked-by: Larry Finger Link: https://lore.kernel.org/r/20190906173949.21860-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 28b3cdd10397..cc1b5438c04c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -59,7 +59,7 @@ static u8 WIFI_OFDMRATES[] = { int rtw_get_bit_value_from_ieee_value(u8 val) { - unsigned char dot11_rate_table[] = { + static const unsigned char dot11_rate_table[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; /* last element must be zero!! */ int i = 0; @@ -275,7 +275,7 @@ unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit) uint len; u16 val16; __le16 le_tmp; - unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; + static const unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; u8 *pbuf = pie; int limit_new = limit; -- cgit v1.2.3-59-g8ed1b From 5817eca06747cbb1d46908ac54dfa807f7954945 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 6 Sep 2019 16:30:52 +0100 Subject: staging: fbtft: make several arrays static const, makes object smaller Don't populate the arrays on the stack but instead make them static const. Makes the object code smaller by 1329 bytes. Before: text data bss dec hex filename 5581 1488 64 7133 1bdd drivers/staging/fbtft/fb_hx8340bn.o 5444 1264 0 6708 1a34 drivers/staging/fbtft/fb_hx8347d.o 3581 1360 0 4941 134d drivers/staging/fbtft/fb_ili9163.o 7154 1552 0 8706 2202 drivers/staging/fbtft/fb_ili9320.o 7478 2544 0 10022 2726 drivers/staging/fbtft/fb_ili9325.o 6327 1424 0 7751 1e47 drivers/staging/fbtft/fb_s6d1121.o 6498 1776 0 8274 2052 drivers/staging/fbtft/fb_ssd1289.o After: text data bss dec hex filename 5376 1584 64 7024 1b70 drivers/staging/fbtft/fb_hx8340bn.o 5276 1328 0 6604 19cc drivers/staging/fbtft/fb_hx8347d.o 3581 1360 0 4941 134d drivers/staging/fbtft/fb_ili9163.o 6905 1616 0 8521 2149 drivers/staging/fbtft/fb_ili9320.o 7229 2608 0 9837 266d drivers/staging/fbtft/fb_ili9325.o 6030 1488 0 7518 1d5e drivers/staging/fbtft/fb_s6d1121.o 6249 1872 0 8121 1fb9 drivers/staging/fbtft/fb_ssd1289.o (gcc version 9.2.1, amd64) Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20190906153052.31846-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_hx8340bn.c | 2 +- drivers/staging/fbtft/fb_hx8347d.c | 2 +- drivers/staging/fbtft/fb_ili9163.c | 2 +- drivers/staging/fbtft/fb_ili9320.c | 2 +- drivers/staging/fbtft/fb_ili9325.c | 2 +- drivers/staging/fbtft/fb_s6d1121.c | 2 +- drivers/staging/fbtft/fb_ssd1289.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c index d47dcf31fffb..2fd7b87ea0ce 100644 --- a/drivers/staging/fbtft/fb_hx8340bn.c +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -151,7 +151,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x0f, 0x0f, 0x1f, 0x0f, 0x0f, 0x0f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c index 3427a858d17c..37eaf0862c5b 100644 --- a/drivers/staging/fbtft/fb_hx8347d.c +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -95,7 +95,7 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x7f, 0x7f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x0f, }; diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index fd32376700e2..05648c3ffe47 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -195,7 +195,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int gamma_adj(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1f, 0x3f, 0x0f, 0x0f, 0x7f, 0x1f, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F}; diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index ea6e001288ce..f2e72d14431d 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -214,7 +214,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, }; diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index 85e54a10ed72..c9aa4cb43123 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -208,7 +208,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, }; diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c index 5a129b1352cc..8c7de3290343 100644 --- a/drivers/staging/fbtft/fb_s6d1121.c +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -123,7 +123,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x1f, 0x1f, diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 88a5b6925901..7a3fe022cc69 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -129,7 +129,7 @@ static int set_var(struct fbtft_par *par) #define CURVE(num, idx) curves[(num) * par->gamma.num_values + (idx)] static int set_gamma(struct fbtft_par *par, u32 *curves) { - unsigned long mask[] = { + static const unsigned long mask[] = { 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x1f, 0x1f, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, }; -- cgit v1.2.3-59-g8ed1b From a76e712a5a09977354498bb842b3807a499c76fa Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 10 Sep 2019 07:46:04 +0000 Subject: staging: wilc1000: remove unused interrupt status handling code Remove interrupt handling for unused interrupt status(PLL update and Sleep). The firmware only initiates the interrupt for the data transfer to host and rest are not used anymore. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20190910074514.3073-1-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 26 -------------------------- drivers/staging/wilc1000/wilc_wlan.h | 10 ++-------- 2 files changed, 2 insertions(+), 34 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 2bbb359d2119..771d8cb68dc1 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -758,26 +758,6 @@ static void wilc_unknown_isr_ext(struct wilc *wilc) wilc->hif_func->hif_clear_int_ext(wilc, 0); } -static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) -{ - int trials = 10; - - wilc->hif_func->hif_clear_int_ext(wilc, PLL_INT_CLR); - - if (wilc->io_type == WILC_HIF_SDIO) - mdelay(WILC_PLL_TO_SDIO); - else - mdelay(WILC_PLL_TO_SPI); - - while (!(is_wilc1000(wilc_get_chipid(wilc, true)) && --trials)) - mdelay(1); -} - -static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) -{ - wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR); -} - static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) { u32 offset = wilc->rx_buffer_offset; @@ -827,15 +807,9 @@ void wilc_handle_isr(struct wilc *wilc) acquire_bus(wilc, WILC_BUS_ACQUIRE_AND_WAKEUP); wilc->hif_func->hif_read_int(wilc, &int_status); - if (int_status & PLL_INT_EXT) - wilc_pllupdate_isr_ext(wilc, int_status); - if (int_status & DATA_INT_EXT) wilc_wlan_handle_isr_ext(wilc, int_status); - if (int_status & SLEEP_INT_EXT) - wilc_sleeptimer_isr_ext(wilc, int_status); - if (!(int_status & (ALL_INT_EXT))) wilc_unknown_isr_ext(wilc); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index f566d040bb72..7469fa47d588 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -128,8 +128,6 @@ #define WILC_CFG_RSP_STATUS 2 #define WILC_CFG_RSP_SCAN 3 -#define WILC_PLL_TO_SDIO 4 -#define WILC_PLL_TO_SPI 2 #define WILC_ABORT_REQ_BIT BIT(31) #define WILC_RX_BUFF_SIZE (96 * 1024) @@ -185,14 +183,10 @@ #define EN_VMM BIT(8) #define DATA_INT_EXT INT_0 -#define PLL_INT_EXT INT_1 -#define SLEEP_INT_EXT INT_2 -#define ALL_INT_EXT (DATA_INT_EXT | PLL_INT_EXT | SLEEP_INT_EXT) -#define NUM_INT_EXT 3 +#define ALL_INT_EXT DATA_INT_EXT +#define NUM_INT_EXT 1 #define DATA_INT_CLR CLR_INT0 -#define PLL_INT_CLR CLR_INT1 -#define SLEEP_INT_CLR CLR_INT2 #define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) #define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) -- cgit v1.2.3-59-g8ed1b From 9a4c56be67f8153d8f8459c4c7bbbbc360d5fe9e Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 10 Sep 2019 07:46:07 +0000 Subject: staging: wilc1000: avoid twice IRQ handler execution for each single interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IRQ handler(isr_bh_routine()) was called twice for each interrupt from firmware. The data was read completely during the first call and the second call was doing nothing. Now changed the IRQ flag from ‘level’ to ‘edge’ trigger i.e IRQF_TRIGGER_LOW to IRQF_TRIGGER_FALLING to avoid extra interrupt trigger. Signed-off-by: Ajay Singh Link: https://lore.kernel.org/r/20190910074514.3073-2-ajay.kathat@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging') diff --git a/drivers/staging/wilc1000/wilc_netdev.c b/drivers/staging/wilc1000/wilc_netdev.c index cd11c35adcfe..508acb8bb089 100644 --- a/drivers/staging/wilc1000/wilc_netdev.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -60,7 +60,7 @@ static int init_irq(struct net_device *dev) ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine, isr_bh_routine, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "WILC_IRQ", dev); if (ret < 0) netdev_err(dev, "Failed to request IRQ\n"); -- cgit v1.2.3-59-g8ed1b From 63350bdb384543e2fcfd007b9da8239f03c56860 Mon Sep 17 00:00:00 2001 From: Rohit Sarkar Date: Wed, 11 Sep 2019 19:21:13 +0530 Subject: staging: vhciq_core: replace snprintf with scnprintf When the number of bytes to be printed exceeds the limit snprintf returns the number of bytes that would have been printed (if there was no truncation). This might cause issues, hence use scnprintf which returns the actual number of bytes printed to buffer always Signed-off-by: Rohit Sarkar Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190911135112.GA5569@SARKAR Signed-off-by: Greg Kroah-Hartman --- .../vc04_services/interface/vchiq_arm/vchiq_core.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 183f5cf887e0..56a23a297fa4 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -3322,13 +3322,13 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, char buf[80]; int len; - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " %s: slots %d-%d tx_pos=%x recycle=%x", label, shared->slot_first, shared->slot_last, shared->tx_pos, shared->slot_queue_recycle); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Slots claimed:"); vchiq_dump(dump_context, buf, len + 1); @@ -3336,7 +3336,7 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, struct vchiq_slot_info slot_info = *SLOT_INFO_FROM_INDEX(state, i); if (slot_info.use_count != slot_info.release_count) { - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " %d: %d/%d", i, slot_info.use_count, slot_info.release_count); vchiq_dump(dump_context, buf, len + 1); @@ -3344,7 +3344,7 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, } for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { - len = snprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", + len = scnprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", debug_names[i], shared->debug[i], shared->debug[i]); vchiq_dump(dump_context, buf, len + 1); } @@ -3357,11 +3357,11 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state) int len; int i; - len = snprintf(buf, sizeof(buf), "State %d: %s", state->id, + len = scnprintf(buf, sizeof(buf), "State %d: %s", state->id, conn_state_names[state->conn_state]); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " tx_pos=%x(@%pK), rx_pos=%x(@%pK)", state->local->tx_pos, state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK), @@ -3369,13 +3369,13 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state) state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK)); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Version: %d (min %d)", VCHIQ_VERSION, VCHIQ_VERSION_MIN); vchiq_dump(dump_context, buf, len + 1); if (VCHIQ_ENABLE_STATS) { - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, " "error_count=%d", state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, @@ -3383,7 +3383,7 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state) vchiq_dump(dump_context, buf, len + 1); } - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Slots: %d available (%d data), %d recyclable, %d stalls " "(%d data)", ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - @@ -3416,7 +3416,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) char buf[80]; int len; - len = snprintf(buf, sizeof(buf), "Service %u: %s (ref %u)", + len = scnprintf(buf, sizeof(buf), "Service %u: %s (ref %u)", service->localport, srvstate_names[service->srvstate], service->ref_count - 1); /*Don't include the lock just taken*/ @@ -3428,17 +3428,17 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) int tx_pending, rx_pending; if (service->remoteport != VCHIQ_PORT_FREE) { - int len2 = snprintf(remoteport, sizeof(remoteport), + int len2 = scnprintf(remoteport, sizeof(remoteport), "%u", service->remoteport); if (service->public_fourcc != VCHIQ_FOURCC_INVALID) - snprintf(remoteport + len2, + scnprintf(remoteport + len2, sizeof(remoteport) - len2, " (client %x)", service->client_id); } else strcpy(remoteport, "n/a"); - len += snprintf(buf + len, sizeof(buf) - len, + len += scnprintf(buf + len, sizeof(buf) - len, " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)", VCHIQ_FOURCC_AS_4CHARS(fourcc), remoteport, @@ -3455,7 +3455,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) rx_pending = service->bulk_rx.local_insert - service->bulk_rx.remote_insert; - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Bulk: tx_pending=%d (size %d)," " rx_pending=%d (size %d)", tx_pending, @@ -3468,7 +3468,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) if (VCHIQ_ENABLE_STATS) { vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Ctrl: tx_count=%d, tx_bytes=%llu, " "rx_count=%d, rx_bytes=%llu", service->stats.ctrl_tx_count, @@ -3477,7 +3477,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) service->stats.ctrl_rx_bytes); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " Bulk: tx_count=%d, tx_bytes=%llu, " "rx_count=%d, rx_bytes=%llu", service->stats.bulk_tx_count, @@ -3486,7 +3486,7 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) service->stats.bulk_rx_bytes); vchiq_dump(dump_context, buf, len + 1); - len = snprintf(buf, sizeof(buf), + len = scnprintf(buf, sizeof(buf), " %d quota stalls, %d slot stalls, " "%d bulk stalls, %d aborted, %d errors", service->stats.quota_stalls, @@ -3562,9 +3562,9 @@ void vchiq_log_dump_mem(const char *label, u32 addr, const void *void_mem, for (offset = 0; offset < 16; offset++) { if (offset < num_bytes) - s += snprintf(s, 4, "%02x ", mem[offset]); + s += scnprintf(s, 4, "%02x ", mem[offset]); else - s += snprintf(s, 4, " "); + s += scnprintf(s, 4, " "); } for (offset = 0; offset < 16; offset++) { -- cgit v1.2.3-59-g8ed1b From 129dac370096ab8eded1d6367f8b539df0e28737 Mon Sep 17 00:00:00 2001 From: Sandro Volery Date: Wed, 11 Sep 2019 08:23:59 +0200 Subject: Staging: octeon: Avoid several usecases of strcpy strcpy was used multiple times in strcpy to write into dev->name. I replaced them with strscpy. Signed-off-by: Sandro Volery Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190911062359.GA14886@volery Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 8847a11c212f..33762f2e9a44 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -794,7 +794,7 @@ static int cvm_oct_probe(struct platform_device *pdev) priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; priv->port = CVMX_PIP_NUM_INPUT_PORTS; priv->queue = -1; - strcpy(dev->name, "pow%d"); + strscpy(dev->name, "pow%d", sizeof(dev->name)); for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; @@ -866,39 +866,39 @@ static int cvm_oct_probe(struct platform_device *pdev) case CVMX_HELPER_INTERFACE_MODE_NPI: dev->netdev_ops = &cvm_oct_npi_netdev_ops; - strcpy(dev->name, "npi%d"); + strscpy(dev->name, "npi%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_XAUI: dev->netdev_ops = &cvm_oct_xaui_netdev_ops; - strcpy(dev->name, "xaui%d"); + strscpy(dev->name, "xaui%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_LOOP: dev->netdev_ops = &cvm_oct_npi_netdev_ops; - strcpy(dev->name, "loop%d"); + strscpy(dev->name, "loop%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_SGMII: priv->phy_mode = PHY_INTERFACE_MODE_SGMII; dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; - strcpy(dev->name, "eth%d"); + strscpy(dev->name, "eth%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_SPI: dev->netdev_ops = &cvm_oct_spi_netdev_ops; - strcpy(dev->name, "spi%d"); + strscpy(dev->name, "spi%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_GMII: priv->phy_mode = PHY_INTERFACE_MODE_GMII; dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; - strcpy(dev->name, "eth%d"); + strscpy(dev->name, "eth%d", sizeof(dev->name)); break; case CVMX_HELPER_INTERFACE_MODE_RGMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; - strcpy(dev->name, "eth%d"); + strscpy(dev->name, "eth%d", sizeof(dev->name)); cvm_set_rgmii_delay(priv, interface, port_index); break; -- cgit v1.2.3-59-g8ed1b From 3fb73eddba106ad2a265a5c5c29d14b0ed6aaee1 Mon Sep 17 00:00:00 2001 From: Sandro Volery Date: Tue, 10 Sep 2019 08:19:28 +0200 Subject: Staging: gasket: Use temporaries to reduce line length. Using temporaries for gasket_page_table entries to remove scnprintf() statements and reduce line length, as suggested by Joe Perches. Thanks! Signed-off-by: Sandro Volery Reviewed-by: Dan Carpenter Link: https://lore.kernel.org/r/20190910061928.GA9623@volery Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gasket/apex_driver.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/gasket/apex_driver.c b/drivers/staging/gasket/apex_driver.c index 2973bb920a26..46199c8ca441 100644 --- a/drivers/staging/gasket/apex_driver.c +++ b/drivers/staging/gasket/apex_driver.c @@ -509,6 +509,8 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr, struct gasket_dev *gasket_dev; struct gasket_sysfs_attribute *gasket_attr; enum sysfs_attribute_type type; + struct gasket_page_table *gpt; + uint val; gasket_dev = gasket_sysfs_get_device_data(device); if (!gasket_dev) { @@ -524,29 +526,25 @@ static ssize_t sysfs_show(struct device *device, struct device_attribute *attr, } type = (enum sysfs_attribute_type)gasket_attr->data.attr_type; + gpt = gasket_dev->page_table[0]; switch (type) { case ATTR_KERNEL_HIB_PAGE_TABLE_SIZE: - ret = scnprintf(buf, PAGE_SIZE, "%u\n", - gasket_page_table_num_entries( - gasket_dev->page_table[0])); + val = gasket_page_table_num_entries(gpt); break; case ATTR_KERNEL_HIB_SIMPLE_PAGE_TABLE_SIZE: - ret = scnprintf(buf, PAGE_SIZE, "%u\n", - gasket_page_table_num_simple_entries( - gasket_dev->page_table[0])); + val = gasket_page_table_num_simple_entries(gpt); break; case ATTR_KERNEL_HIB_NUM_ACTIVE_PAGES: - ret = scnprintf(buf, PAGE_SIZE, "%u\n", - gasket_page_table_num_active_pages( - gasket_dev->page_table[0])); + val = gasket_page_table_num_active_pages(gpt); break; default: dev_dbg(gasket_dev->dev, "Unknown attribute: %s\n", attr->attr.name); ret = 0; - break; + goto exit; } - + ret = scnprintf(buf, PAGE_SIZE, "%u\n", val); +exit: gasket_sysfs_put_attr(device, gasket_attr); gasket_sysfs_put_device_data(device, gasket_dev); return ret; -- cgit v1.2.3-59-g8ed1b