mmc: support background operation
RFC PATCH 1/1 mmc: support background operation
Hi mailing.
This RFC patch is supported background operation(BKOPS).
And if you want to test this patch, must apply "[PATCH v3] mmc: support HPI send command"
This patch is based on Hanumath Prasad's patch "mmc: enable background operations for emmc4.41 with HPI support" Hanumath's patch is implemented before applied per forlin's patch "use nonblock mmc request...". This patch is based on 3.1.0-rc1 in mmc-next.
Background operations is run when set the URGENT_BKOPS in response.
if set the URGENT_BKOPS in response, we can notify that card need the BKOPS. (URGENT_BKOPS is used in eMMC4.41 spec, but in eMMC4.5 changed to EXCEPTION_EVENT bit.
maybe, we need to change this point).
And all request is done, then run background operation.
if request read/write operation when running BKOPS, issue HPI interrupt
This patch is just RFC patch (not to merge), because i want to use BKOPS in userspace. (using ioctl).
I want to get mailing's review for this patch.
--- drivers/mmc/card/block.c | 4 ++++ drivers/mmc/card/queue.c | 10 ++++++++++ drivers/mmc/core/core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mmc/core/mmc.c | 28 ++++++++++++++++++++++++++++ drivers/mmc/core/mmc_ops.c | 3 +++ include/linux/mmc/card.h | 11 +++++++++++ include/linux/mmc/core.h | 1 + include/linux/mmc/mmc.h | 4 ++++ 8 files changed, 96 insertions(+), 0 deletions(-)
drivers/mmc/card/block.c +4 -0
@@ -1078,6 +1078,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)switch (status) {case MMC_BLK_SUCCESS :case MMC_BLK_PARTIAL : +if (mmc_card_mmc (card) && + (brq->cmd.resp[0 ] &R1_URGENT_BKOPS )) { +mmc_card_set_need_bkops (card); + }/* * A block was successfully transferred. */
drivers/mmc/card/queue.c +10 -0
@@ -46,6 +46,8 @@ static int mmc_queue_thread(void *d) {struct mmc_queue *mq = d;struct request_queue *q = mq->queue; +struct mmc_card *card = mq->card; +unsigned long flags; current->flags |=PF_MEMALLOC ;
@@ -61,6 +63,13 @@ static int mmc_queue_thread(void *d)spin_unlock_irq (q->queue_lock);if (req || mq->mqrq_prev->req) { +if (mmc_card_doing_bkops (card)) { +mmc_interrupt_hpi (card); +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, + flags); + }set_current_state (TASK_RUNNING ); mq->issue_fn (mq, req); }else {
@@ -68,6 +77,7 @@ static int mmc_queue_thread(void *d)set_current_state (TASK_RUNNING );break ; } +mmc_start_bkops (mq->card);up (&mq->thread_sem);schedule ();down (&mq->thread_sem);
drivers/mmc/core/core.c +35 -0
@@ -347,6 +347,41 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retriesEXPORT_SYMBOL (mmc_wait_for_cmd); +/* Start background operation */ +void mmc_start_bkops (struct mmc_card *card) +{ +int err; +unsigned long flags; + +BUG_ON (!card); + +if (!card->ext_csd.bkops_en) { +printk (KERN_INFO "Didn't set BKOPS enable bit!\n" ); +return ; + } + +if (mmc_card_doing_bkops (card) || + !mmc_card_need_bkops (card)) { +return ; + } + +mmc_claim_host (card->host); + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_BKOPS_START ,1 ,0 ); +if (err) { +mmc_card_clr_need_bkops (card); + goto out; + } + +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_need_bkops (card); +mmc_card_set_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, flags); +out: +mmc_release_host (card->host); +} +EXPORT_SYMBOL (mmc_start_bkops); +/** * mmc_interrupt_hpi - Issue for High priority Interrupt * @card: the MMC card associated with the HPI transfer
drivers/mmc/core/mmc.c +28 -0
@@ -421,6 +421,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME ] *10 ; } +/* +* check whether the eMMC card support BKOPS. +* if set BKOPS_SUPPORT bit, +* BKOPS_STATUS, BKOPS_EN,,BKOPS_START and +* URGENT_BKOPS are supported.(default) +*/ +if (ext_csd[EXT_CSD_BKOPS_SUPPORT ] &0x1 ) { + card->ext_csd.bkops =1 ; + card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN ]; + } + card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM ]; }
@@ -762,6 +773,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, }/* +* Enable HPI feature (if supported) +*/ +if (card->ext_csd.hpi) { + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_HPI_MGMT ,1 ,0 ); +if (err && err != -EBADMSG ) + goto free_card; + +if (err) { +printk (KERN_WARNING "%s: Enabling HPI failed\n" , +mmc_hostname (card->host)); + err =0 ; + }else + card->ext_csd.hpi_en =1 ; + } + +/* * Compute bus speed. */ max_dtr = (unsigned int )-1 ;
drivers/mmc/core/mmc_ops.c +3 -0
@@ -398,6 +398,9 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,if (err)return err; +if (index ==EXT_CSD_BKOPS_START ) +return 0 ; +/* Must check status to be sure of no errors */ do { err = mmc_send_status(card, &status);
include/linux/mmc/card.h +11 -0
@@ -67,6 +67,8 @@ struct mmc_ext_csd {bool hpi_en;/* HPI enablebit */ bool hpi;/* HPI support bit */ unsigned int hpi_cmd;/* cmd used as HPI */ +bool bkops;/* BKOPS support bit */ +bool bkops_en;/* BKOPS enable bit */ u8 raw_partition_support;/* 160 */ u8 raw_erased_mem_count;/* 181 */ u8 raw_ext_csd_structure;/* 194 */
@@ -192,6 +194,8 @@ struct mmc_card {#define MMC_QUIRK_DISABLE_CD (1<<5)/* disconnect CD/DAT[3] resistor */ #define MMC_QUIRK_INAND_CMD38 (1<<6)/* iNAND devices have broken CMD38 */ #define MMC_QUIRK_BLK_NO_CMD23 (1<<7)/* Avoid CMD23 for regular multiblock */ +#define MMC_STATE_NEED_BKOPS (1<<7)/* Need background operation */ +#define MMC_STATE_DOING_BKOPS (1<<8)/* Do running background operation */ unsigned int erase_size;/* erase size in sectors */ unsigned int erase_shift;/* if erase unit is power 2 */
@@ -318,6 +322,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)#define mmc_card_ddr_mode (c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)#define mmc_sd_card_uhs (c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)#define mmc_card_ext_capacity (c) ((c)->state & MMC_CARD_SDXC) +#define mmc_card_need_bkops (c) ((c)->state & MMC_STATE_NEED_BKOPS) +#define mmc_card_doing_bkops (c) ((c)->state & MMC_STATE_DOING_BKOPS)#define mmc_card_set_present (c) ((c)->state |= MMC_STATE_PRESENT)#define mmc_card_set_readonly (c) ((c)->state |= MMC_STATE_READONLY)
@@ -326,6 +332,11 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)#define mmc_card_set_ddr_mode (c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)#define mmc_sd_card_set_uhs (c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)#define mmc_card_set_ext_capacity (c) ((c)->state |= MMC_CARD_SDXC) +#define mmc_card_set_need_bkops (c) ((c)->state |= MMC_STATE_NEED_BKOPS) +#define mmc_card_set_doing_bkops (c) ((c)->state |= MMC_STATE_DOING_BKOPS) + +#define mmc_card_clr_need_bkops (c) ((c)->state &= ~MMC_STATE_NEED_BKOPS) +#define mmc_card_clr_doing_bkops (c) ((c)->state &= ~MMC_STATE_DOING_BKOPS)/* * Quirk add/remove for MMC products.
include/linux/mmc/core.h +1 -0
@@ -162,6 +162,7 @@ extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, unsigned int nr);extern unsigned int mmc_calc_max_discard (struct mmc_card *card); +extern void mmc_start_bkops (struct mmc_card *card);extern int mmc_set_blocklen (struct mmc_card *card,unsigned int blocklen);extern void mmc_set_data_timeout (struct mmc_data *,const struct mmc_card *);
include/linux/mmc/mmc.h +4 -0
@@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode)#define R1_READY_FOR_DATA (1 << 8)/* sx, a */ #define R1_SWITCH_ERROR (1 << 7)/* sx, c */ #define R1_APP_CMD (1 << 5)/* sr, c */ +#define R1_URGENT_BKOPS (1 << 6)/* sr, a */ #define R1_STATE_IDLE 0#define R1_STATE_READY 1
@@ -273,6 +274,8 @@ struct _mmc_csd {#define EXT_CSD_PARTITION_ATTRIBUTE 156/* R/W */ #define EXT_CSD_PARTITION_SUPPORT 160/* RO */ #define EXT_CSD_HPI_MGMT 161/* R/W */ +#define EXT_CSD_BKOPS_EN 163/* R/W */ +#define EXT_CSD_BKOPS_START 164/* R/W */ #define EXT_CSD_WR_REL_PARAM 166/* RO */ #define EXT_CSD_ERASE_GROUP_DEF 175/* R/W */ #define EXT_CSD_PART_CONFIG 179/* R/W */
@@ -295,6 +298,7 @@ struct _mmc_csd {#define EXT_CSD_SEC_ERASE_MULT 230/* RO */ #define EXT_CSD_SEC_FEATURE_SUPPORT 231/* RO */ #define EXT_CSD_TRIM_MULT 232/* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502/* RO */ #define EXT_CSD_HPI_FEATURES 503/* RO */ /*
Quoted 8 lines · Jaehoon Chung
Hi mailing.
This RFC patch is supported background operation(BKOPS).
And if you want to test this patch, must apply "[PATCH v3] mmc: support HPI send command"This patch is based on Hanumath Prasad's patch "mmc: enable background operations for emmc4.41 with HPI support" Hanumath's patch is implemented before applied per forlin's patch "use nonblock mmc request...". This patch is based on 3.1.0-rc1 in mmc-next.
I'm a little confused by this statement. Was this patch done before Per Forlin's work, or is this patch the implementation of the infrastructure Per Forlin worked on to do non-blocking requests to the host controller?
Quoted 86 lines
Background operations is run when set the
URGENT_BKOPSin response.if set the
URGENT_BKOPSin response, we can notify that card need the BKOPS. (URGENT_BKOPSis used in eMMC4.41 spec, but in eMMC4.5 changed toEXCEPTION_EVENTbit.
maybe, we need to change this point).And all request is done, then run background operation.
if request read/write operation when running BKOPS, issue HPI interruptThis patch is just RFC patch (not to merge), because i want to use BKOPS in userspace. (using ioctl).
I want to get mailing's review for this patch.
Signed-off-by Jaehoon Chung<[email protected]>Signed-off-by Kyungmin Park<[email protected]>CC Hanumath Prasad<[email protected]>--- drivers/mmc/card/block.c | 4 ++++ drivers/mmc/card/queue.c | 10 ++++++++++ drivers/mmc/core/core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mmc/core/mmc.c | 28 ++++++++++++++++++++++++++++ drivers/mmc/core/mmc_ops.c | 3 +++ include/linux/mmc/card.h | 11 +++++++++++ include/linux/mmc/core.h | 1 + include/linux/mmc/mmc.h | 4 ++++ 8 files changed, 96 insertions(+), 0 deletions(-)drivers/mmc/card/block.c +4
-0@@ -1078,6 +1078,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)switch (status) {case MMC_BLK_SUCCESS :case MMC_BLK_PARTIAL : +if (mmc_card_mmc (card)&& + (brq->cmd.resp[0 ]&R1_URGENT_BKOPS )) { +mmc_card_set_need_bkops (card); + }/* * A block was successfully transferred. */ drivers/mmc/card/queue.c +10
-0@@ -46,6 +46,8 @@ static int mmc_queue_thread(void *d) {struct mmc_queue *mq = d;struct request_queue *q = mq->queue; +struct mmc_card *card = mq->card; +unsigned long flags; current->flags |=PF_MEMALLOC ;@@ -61,6 +63,13 @@ static int mmc_queue_thread(void *d)spin_unlock_irq (q->queue_lock);if (req || mq->mqrq_prev->req) { +if (mmc_card_doing_bkops (card)) { +mmc_interrupt_hpi (card); +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, + flags); + }set_current_state (TASK_RUNNING ); mq->issue_fn (mq, req); }else {@@ -68,6 +77,7 @@ static int mmc_queue_thread(void *d)set_current_state (TASK_RUNNING );break ; } +mmc_start_bkops (mq->card);up (&mq->thread_sem);schedule ();down (&mq->thread_sem);drivers/mmc/core/core.c +0
-0
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 351
Quoted 5 lines
drivers/mmc/core/core.c +2
-0@@ -347,6 +347,41 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retriesEXPORT_SYMBOL (mmc_wait_for_cmd); +/* Start background operation */ +void mmc_start_bkops (struct mmc_card *card)
Is it possible to follow the kernel documentation standard for comment function headers (I believe Randy Dunlap has given links to this in the past)? You can see in this patch that after this function the next function is using a function comment header per kernel guidelines.
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 359
Quoted 8 lines
drivers/mmc/core/core.c +8
-0+{ +int err; +unsigned long flags; + +BUG_ON (!card); + +if (!card->ext_csd.bkops_en) { +printk (KERN_INFO "Didn't set BKOPS enable bit!\n" );
I know that if new drivers are added to the kernel, maintainers will reject the work if it's using printk()'s. If this code is getting new functions, is it a good idea to start using the more modern, accepted coding functions like pr_info()?
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 364
Quoted 5 lines
drivers/mmc/core/core.c +5
-0+return ; + } + +if (mmc_card_doing_bkops (card) || + !mmc_card_need_bkops (card)) {
This code wouldn't pass the checkpatch.pl tool; I've been burned by the Linux community of having brackets around a single line of code.
Quoted 28 lines
drivers/mmc/core/core.c +20
-0+return ; + } + +mmc_claim_host (card->host); + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_BKOPS_START ,1 ,0 ); +if (err) { +mmc_card_clr_need_bkops (card); + goto out; + } + +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_need_bkops (card); +mmc_card_set_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, flags); +out: +mmc_release_host (card->host); +} +EXPORT_SYMBOL (mmc_start_bkops); +/** * mmc_interrupt_hpi - Issue for High priority Interrupt * @card: the MMC card associated with the HPI transfer drivers/mmc/core/mmc.c +0
-0
drivers/mmc/core/mmc.c static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) · line 430
Quoted 10 lines
drivers/mmc/core/mmc.c +7
-0@@ -421,6 +421,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME ] *10 ; } +/* +* check whether the eMMC card support BKOPS. +* if set BKOPS_SUPPORT bit, +* BKOPS_STATUS, BKOPS_EN,,BKOPS_START and +* URGENT_BKOPS are supported.(default) +*/ +if (ext_csd[EXT_CSD_BKOPS_SUPPORT ]&0x1 ) {
That is kind of an ugly if() statement; a bit further down I explain my reasons for making if() statements like this more readable.
Quoted 8 lines
drivers/mmc/core/mmc.c +4
-0+ card->ext_csd.bkops =1 ; + card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN ]; + } + card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM ]; }
drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 778
Quoted 6 lines
drivers/mmc/core/mmc.c +3
-0@@ -762,6 +773,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, }/* +* Enable HPI feature (if supported) +*/ +if (card->ext_csd.hpi) {
I know some people prefer doing things like
A.'if (x)'
instead of
B.'if (x != NULL)
because A. is supposed to be some type of 'expert way' of doing things.
However, B. is a whole lot more readable and easier for people to decipher precisely what is going on, especially newer people that may not be as familiar with this part of the Linux kernel as others. Just looking at this patch, I can't tell if 'card->ext_csd.hpi' is supposed to be a number value or a pointer. And if you use Linus's tool 'sparse' to check your kernel code before submitting, there is a difference between statements like 'if (x == 0)' and 'if (x == NULL)', even though they could evaluate to the same result in this if() statement.
So I suggest adding the equality or inequality sign to this if() as well as any other if() to make the code a bit easier to understand.
Quoted 119 lines
drivers/mmc/core/mmc.c +14
-0+ err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_HPI_MGMT ,1 ,0 ); +if (err&& err != -EBADMSG ) + goto free_card; + +if (err) { +printk (KERN_WARNING "%s: Enabling HPI failed\n" , +mmc_hostname (card->host)); + err =0 ; + }else + card->ext_csd.hpi_en =1 ; + } + +/* * Compute bus speed. */ max_dtr = (unsigned int )-1 ;drivers/mmc/core/mmc_ops.c +3
-0@@ -398,6 +398,9 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,if (err)return err; +if (index ==EXT_CSD_BKOPS_START ) +return 0 ; +/* Must check status to be sure of no errors */ do { err = mmc_send_status(card,&status);include/linux/mmc/card.h +11
-0@@ -67,6 +67,8 @@ struct mmc_ext_csd {bool hpi_en;/* HPI enablebit */ bool hpi;/* HPI support bit */ unsigned int hpi_cmd;/* cmd used as HPI */ +bool bkops;/* BKOPS support bit */ +bool bkops_en;/* BKOPS enable bit */ u8 raw_partition_support;/* 160 */ u8 raw_erased_mem_count;/* 181 */ u8 raw_ext_csd_structure;/* 194 */ @@ -192,6 +194,8 @@ struct mmc_card {#define MMC_QUIRK_DISABLE_CD (1<<5)/* disconnect CD/DAT[3] resistor */ #define MMC_QUIRK_INAND_CMD38 (1<<6)/* iNAND devices have broken CMD38 */ #define MMC_QUIRK_BLK_NO_CMD23 (1<<7)/* Avoid CMD23 for regular multiblock */ +#define MMC_STATE_NEED_BKOPS (1<<7)/* Need background operation */ +#define MMC_STATE_DOING_BKOPS (1<<8)/* Do running background operation */ unsigned int erase_size;/* erase size in sectors */ unsigned int erase_shift;/* if erase unit is power 2 */ @@ -318,6 +322,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)#define mmc_card_ddr_mode (c) ((c)->state& MMC_STATE_HIGHSPEED_DDR)#define mmc_sd_card_uhs (c) ((c)->state& MMC_STATE_ULTRAHIGHSPEED)#define mmc_card_ext_capacity (c) ((c)->state& MMC_CARD_SDXC) +#define mmc_card_need_bkops (c) ((c)->state& MMC_STATE_NEED_BKOPS) +#define mmc_card_doing_bkops (c) ((c)->state& MMC_STATE_DOING_BKOPS)#define mmc_card_set_present (c) ((c)->state |= MMC_STATE_PRESENT)#define mmc_card_set_readonly (c) ((c)->state |= MMC_STATE_READONLY)@@ -326,6 +332,11 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)#define mmc_card_set_ddr_mode (c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)#define mmc_sd_card_set_uhs (c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)#define mmc_card_set_ext_capacity (c) ((c)->state |= MMC_CARD_SDXC) +#define mmc_card_set_need_bkops (c) ((c)->state |= MMC_STATE_NEED_BKOPS) +#define mmc_card_set_doing_bkops (c) ((c)->state |= MMC_STATE_DOING_BKOPS) + +#define mmc_card_clr_need_bkops (c) ((c)->state&= ~MMC_STATE_NEED_BKOPS) +#define mmc_card_clr_doing_bkops (c) ((c)->state&= ~MMC_STATE_DOING_BKOPS)/* * Quirk add/remove for MMC products. include/linux/mmc/core.h +1
-0@@ -162,6 +162,7 @@ extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, unsigned int nr);extern unsigned int mmc_calc_max_discard (struct mmc_card *card); +extern void mmc_start_bkops (struct mmc_card *card);extern int mmc_set_blocklen (struct mmc_card *card,unsigned int blocklen);extern void mmc_set_data_timeout (struct mmc_data *,const struct mmc_card *);include/linux/mmc/mmc.h +4
-1@@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode)#define R1_READY_FOR_DATA (1<< 8)/* sx, a */ #define R1_SWITCH_ERROR (1<< 7)/* sx, c */ #define R1_APP_CMD (1<< 5)/* sr, c */ +#define R1_URGENT_BKOPS (1<< 6)/* sr, a */ #define R1_STATE_IDLE 0#define R1_STATE_READY 1@@ -273,6 +274,8 @@ struct _mmc_csd {#define EXT_CSD_PARTITION_ATTRIBUTE 156/* R/W */ #define EXT_CSD_PARTITION_SUPPORT 160/* RO */ #define EXT_CSD_HPI_MGMT 161/* R/W */ +#define EXT_CSD_BKOPS_EN 163/* R/W */ +#define EXT_CSD_BKOPS_START 164/* R/W */ #define EXT_CSD_WR_REL_PARAM 166/* RO */ #define EXT_CSD_ERASE_GROUP_DEF 175/* R/W */ #define EXT_CSD_PART_CONFIG 179/* R/W */ @@ -295,6 +298,7 @@ struct _mmc_csd {#define EXT_CSD_SEC_ERASE_MULT 230/* RO */ #define EXT_CSD_SEC_FEATURE_SUPPORT 231/* RO */ #define EXT_CSD_TRIM_MULT 232/* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502/* RO */ #define EXT_CSD_HPI_FEATURES 503/* RO */ /* -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
J (James/Jay) Freyensee Storage Technology Group Intel Corporation
Hi,
Quoted 13 lines · J Freyensee
Quoted 11 lines · Jaehoon Chung
Hi mailing.
This RFC patch is supported background operation(BKOPS). And if you want to test this patch, must apply "[PATCH v3] mmc:
support HPI send command"This patch is based on Hanumath Prasad's patch "mmc: enable background operations for emmc4.41 with HPI support" Hanumath's patch is implemented before applied per forlin's patch "use nonblock mmc request...".
This patch is based on 3.1.0-rc1 in mmc-next.
Quoted 4 lines
I'm a little confused by this statement. Was this patch done before Per Forlin's work, or is this patch the implementation of the infrastructure Per Forlin worked on to do non-blocking requests to the host controller?
As I understand it, the background operations referred to by this patch are a feature of the spec/card, whereas the background operations in Per Forlin's nonblocking patch are merely a feature of the DMA preparation being done in the kernel (invisibly to the card).
- Chris.
Signature · 2 lines
Chris Ball <[email protected]> <http://printf.net/> One Laptop Per Child
Hi,
Quoted 13 lines · J Freyensee
Quoted 11 lines · Jaehoon Chung
Hi mailing.
This RFC patch is supported background operation(BKOPS). And if you want to test this patch, must apply "[PATCH v3] mmc:
support HPI send command"This patch is based on Hanumath Prasad's patch "mmc: enable background operations for emmc4.41 with HPI support"
Hanumath's patch is implemented before applied per forlin's patch "use nonblock mmc request...".
This patch is based on 3.1.0-rc1 in mmc-next.
Quoted 4 lines
I'm a little confused by this statement. Was this patch done before Per Forlin's work, or is this patch the implementation of the infrastructure Per Forlin worked on to do non-blocking requests to the host controller?
This feature(BKOPS) is defined in eMMC4.41 spec.(differ with Per Forlins's non-blocking patch) Hanumath Prasad's patch is sent before Per Forlin's patch.
so need to rebase for applied patch.
Quoted 94 lines
Quoted 94 lines
Background operations is run when set the
URGENT_BKOPSin response.if set the
URGENT_BKOPSin response, we can notify that card need the BKOPS.
(URGENT_BKOPSis used in eMMC4.41 spec, but in eMMC4.5 changed toEXCEPTION_EVENTbit.
maybe, we need to change this point).And all request is done, then run background operation.
if request read/write operation when running BKOPS, issue HPI interruptThis patch is just RFC patch (not to merge), because i want to use BKOPS in userspace.
(using ioctl).I want to get mailing's review for this patch.
Signed-off-by Jaehoon Chung<[email protected]>Signed-off-by Kyungmin Park<[email protected]>CC Hanumath Prasad<[email protected]>--- drivers/mmc/card/block.c | 4 ++++ drivers/mmc/card/queue.c | 10 ++++++++++ drivers/mmc/core/core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mmc/core/mmc.c | 28 ++++++++++++++++++++++++++++ drivers/mmc/core/mmc_ops.c | 3 +++ include/linux/mmc/card.h | 11 +++++++++++ include/linux/mmc/core.h | 1 + include/linux/mmc/mmc.h | 4 ++++ 8 files changed, 96 insertions(+), 0 deletions(-)drivers/mmc/card/block.c +4
-0@@ -1078,6 +1078,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)switch (status) {case MMC_BLK_SUCCESS :case MMC_BLK_PARTIAL : +if (mmc_card_mmc (card)&& + (brq->cmd.resp[0 ]&R1_URGENT_BKOPS )) { +mmc_card_set_need_bkops (card); + }/* * A block was successfully transferred. */drivers/mmc/card/queue.c +10
-0@@ -46,6 +46,8 @@ static int mmc_queue_thread(void *d) {struct mmc_queue *mq = d;struct request_queue *q = mq->queue; +struct mmc_card *card = mq->card; +unsigned long flags; current->flags |=PF_MEMALLOC ;@@ -61,6 +63,13 @@ static int mmc_queue_thread(void *d)spin_unlock_irq (q->queue_lock);if (req || mq->mqrq_prev->req) { +if (mmc_card_doing_bkops (card)) { +mmc_interrupt_hpi (card); +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, + flags); + }set_current_state (TASK_RUNNING ); mq->issue_fn (mq, req); }else {@@ -68,6 +77,7 @@ static int mmc_queue_thread(void *d)set_current_state (TASK_RUNNING );break ; } +mmc_start_bkops (mq->card);up (&mq->thread_sem);schedule ();down (&mq->thread_sem);drivers/mmc/core/core.c +0
-0@@ -347,6 +347,41 @@ int mmc_wait_for_cmd(struct mmc_host *host,struct
mmc_command*cmd, int retriesEXPORT_SYMBOL(mmc_wait_for_cmd);
Quoted 7 lines
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 351
Quoted 2 lines
drivers/mmc/core/core.c +2
-0+/* Start background operation */ +void mmc_start_bkops (struct mmc_card *card)Is it possible to follow the kernel documentation standard for comment function headers (I believe Randy Dunlap has given links to this in the past)? You can see in this patch that after this function the next function is using a function comment header per kernel guidelines.
You're right.
But this patch is the RFC patch (i mentioned this patch is not to merge). So i didn't add the comment for this function.
If this patch should be merge, i will add the comment for function. (at next time, if i send the other RFC patch, i will also add the comment)
Quoted 14 lines
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 359
Quoted 9 lines
drivers/mmc/core/core.c +8
-0+{ +int err; +unsigned long flags; + +BUG_ON (!card); + +if (!card->ext_csd.bkops_en) { +printk (KERN_INFO "Didn't set BKOPS enable bit!\n" );I know that if new drivers are added to the kernel, maintainers will reject the work if it's using printk()'s. If this code is getting new functions, is it a good idea to start using the more modern, accepted coding functions like
pr_info()?
No problem..using pr_info or pr_debug..
Quoted 9 lines
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 364
Quoted 6 lines
drivers/mmc/core/core.c +5
-0+return ; + } + +if (mmc_card_doing_bkops (card) || + !mmc_card_need_bkops (card)) {This code wouldn't pass the checkpatch.pl tool; I've been burned by the Linux community of having brackets around a single line of code.
I used the checkpatch.pl tool..but i didn't find message about this line. If you point out the brackets {}, i will removed that and make a single line.
Quoted 33 lines
Quoted 33 lines
drivers/mmc/core/core.c +20
-0+return ; + } + +mmc_claim_host (card->host); + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_BKOPS_START ,1 ,0 ); +if (err) { +mmc_card_clr_need_bkops (card); + goto out; + } + +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_need_bkops (card); +mmc_card_set_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, flags); +out: +mmc_release_host (card->host); +} +EXPORT_SYMBOL (mmc_start_bkops); +/** * mmc_interrupt_hpi - Issue for High priority Interrupt * @card: the MMC card associated with the HPI transfer drivers/mmc/core/mmc.c +0
-0@@ -421,6 +421,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME ] *10 ; }
Quoted 10 lines
drivers/mmc/core/mmc.c static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
Quoted 7 lines
drivers/mmc/core/mmc.c +7
-0+/* +* check whether the eMMC card support BKOPS. +* if set BKOPS_SUPPORT bit, +* BKOPS_STATUS, BKOPS_EN,,BKOPS_START and +* URGENT_BKOPS are supported.(default) +*/ +if (ext_csd[EXT_CSD_BKOPS_SUPPORT ]&0x1 ) {That is kind of an ugly
if()statement; a bit further down I explain my reasons for makingif()statements like this more readable.
I didn't understand this comment...how do you change this statement?
Quoted 33 lines
Quoted 9 lines
drivers/mmc/core/mmc.c +4
-0+ card->ext_csd.bkops =1 ; + card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN ]; + } + card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM ]; }drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, · line 779
Quoted 7 lines
drivers/mmc/core/mmc.c +3
-0@@ -762,6 +773,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, }/* +* Enable HPI feature (if supported) +*/ +if (card->ext_csd.hpi) {I know some people prefer doing things like
A.'if (x)'
instead of
B.'if (x != NULL)because A. is supposed to be some type of 'expert way' of doing things. However, B. is a whole lot more readable and easier for people to decipher precisely what is going on, especially newer people that may not be as familiar with this part of the Linux kernel as others. Just looking at this patch, I can't tell if '
card->ext_csd.hpi' is supposed to be a number value or a pointer. And if you use Linus's tool 'sparse' to check your kernel code before submitting, there is a difference between statements like 'if (x == 0)' and 'if (x == NULL)', even though they could evaluate to the same result in thisif()statement.
Quoted 2 lines
So I suggest adding the equality or inequality sign to this
if()as well as any otherif()to make the code a bit easier to understand.
Right..i will modify this point..
Thanks for your comments..
Any other opinion about this feature (BKOPS)..??
Regards,
Jaehoon Chung
Quoted 242 lines · Jaehoon Chung
Hi,
Quoted 13 lines · J Freyensee
Quoted 11 lines · Jaehoon Chung
Hi mailing.
This RFC patch is supported background operation(BKOPS). And if you want to test this patch, must apply "[PATCH v3] mmc:
support HPI send command"This patch is based on Hanumath Prasad's patch "mmc: enable background operations for emmc4.41 with HPI support"
Hanumath's patch is implemented before applied per forlin's patch "use nonblock mmc request...".
This patch is based on 3.1.0-rc1 in mmc-next.Quoted 4 lines
I'm a little confused by this statement. Was this patch done before Per Forlin's work, or is this patch the implementation of the infrastructure Per Forlin worked on to do non-blocking requests to the host controller?
This feature(BKOPS) is defined in eMMC4.41 spec.(differ with Per Forlins's non-blocking patch) Hanumath Prasad's patch is sent before Per Forlin's patch.
so need to rebase for applied patch.Quoted 94 lines
Quoted 94 lines
Background operations is run when set the
URGENT_BKOPSin response.if set the
URGENT_BKOPSin response, we can notify that card need the BKOPS.
(URGENT_BKOPSis used in eMMC4.41 spec, but in eMMC4.5 changed toEXCEPTION_EVENTbit.
maybe, we need to change this point).And all request is done, then run background operation.
if request read/write operation when running BKOPS, issue HPI interruptThis patch is just RFC patch (not to merge), because i want to use BKOPS in userspace.
(using ioctl).I want to get mailing's review for this patch.
Signed-off-by Jaehoon Chung<[email protected]>Signed-off-by Kyungmin Park<[email protected]>CC Hanumath Prasad<[email protected]>--- drivers/mmc/card/block.c | 4 ++++ drivers/mmc/card/queue.c | 10 ++++++++++ drivers/mmc/core/core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mmc/core/mmc.c | 28 ++++++++++++++++++++++++++++ drivers/mmc/core/mmc_ops.c | 3 +++ include/linux/mmc/card.h | 11 +++++++++++ include/linux/mmc/core.h | 1 + include/linux/mmc/mmc.h | 4 ++++ 8 files changed, 96 insertions(+), 0 deletions(-)drivers/mmc/card/block.c +4
-0@@ -1078,6 +1078,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)switch (status) {case MMC_BLK_SUCCESS :case MMC_BLK_PARTIAL : +if (mmc_card_mmc (card)&& + (brq->cmd.resp[0 ]&R1_URGENT_BKOPS )) { +mmc_card_set_need_bkops (card); + }/* * A block was successfully transferred. */drivers/mmc/card/queue.c +10
-0@@ -46,6 +46,8 @@ static int mmc_queue_thread(void *d) {struct mmc_queue *mq = d;struct request_queue *q = mq->queue; +struct mmc_card *card = mq->card; +unsigned long flags; current->flags |=PF_MEMALLOC ;@@ -61,6 +63,13 @@ static int mmc_queue_thread(void *d)spin_unlock_irq (q->queue_lock);if (req || mq->mqrq_prev->req) { +if (mmc_card_doing_bkops (card)) { +mmc_interrupt_hpi (card); +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, + flags); + }set_current_state (TASK_RUNNING ); mq->issue_fn (mq, req); }else {@@ -68,6 +77,7 @@ static int mmc_queue_thread(void *d)set_current_state (TASK_RUNNING );break ; } +mmc_start_bkops (mq->card);up (&mq->thread_sem);schedule ();down (&mq->thread_sem);drivers/mmc/core/core.c +0
-0@@ -347,6 +347,41 @@ int mmc_wait_for_cmd(struct mmc_host *host,struct
mmc_command*cmd, int retriesEXPORT_SYMBOL(mmc_wait_for_cmd);Quoted 7 lines
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 351
Quoted 2 lines
drivers/mmc/core/core.c +2
-0+/* Start background operation */ +void mmc_start_bkops (struct mmc_card *card)Is it possible to follow the kernel documentation standard for comment function headers (I believe Randy Dunlap has given links to this in the past)? You can see in this patch that after this function the next function is using a function comment header per kernel guidelines.
You're right.
But this patch is the RFC patch (i mentioned this patch is not to merge). So i didn't add the comment for this function.
If this patch should be merge, i will add the comment for function. (at next time, if i send the other RFC patch, i will also add the comment)Quoted 14 lines
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 359
Quoted 9 lines
drivers/mmc/core/core.c +8
-0+{ +int err; +unsigned long flags; + +BUG_ON (!card); + +if (!card->ext_csd.bkops_en) { +printk (KERN_INFO "Didn't set BKOPS enable bit!\n" );I know that if new drivers are added to the kernel, maintainers will reject the work if it's using printk()'s. If this code is getting new functions, is it a good idea to start using the more modern, accepted coding functions like
pr_info()?No problem..using
pr_infoorpr_debug..Quoted 9 lines
drivers/mmc/core/core.c int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries · line 364
Quoted 6 lines
drivers/mmc/core/core.c +5
-0+return ; + } + +if (mmc_card_doing_bkops (card) || + !mmc_card_need_bkops (card)) {This code wouldn't pass the checkpatch.pl tool; I've been burned by the Linux community of having brackets around a single line of code.
I used the checkpatch.pl tool..but i didn't find message about this line. If you point out the brackets {}, i will removed that and make a single line.
Quoted 33 lines
Quoted 33 lines
drivers/mmc/core/core.c +20
-0+return ; + } + +mmc_claim_host (card->host); + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_BKOPS_START ,1 ,0 ); +if (err) { +mmc_card_clr_need_bkops (card); + goto out; + } + +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_need_bkops (card); +mmc_card_set_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, flags); +out: +mmc_release_host (card->host); +} +EXPORT_SYMBOL (mmc_start_bkops); +/** * mmc_interrupt_hpi - Issue for High priority Interrupt * @card: the MMC card associated with the HPI transfer drivers/mmc/core/mmc.c +0
-0@@ -421,6 +421,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME ] *10 ; }Quoted 10 lines
drivers/mmc/core/mmc.c static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
Quoted 7 lines
drivers/mmc/core/mmc.c +7
-0+/* +* check whether the eMMC card support BKOPS. +* if set BKOPS_SUPPORT bit, +* BKOPS_STATUS, BKOPS_EN,,BKOPS_START and +* URGENT_BKOPS are supported.(default) +*/ +if (ext_csd[EXT_CSD_BKOPS_SUPPORT ]&0x1 ) {That is kind of an ugly
if()statement; a bit further down I explain my reasons for makingif()statements like this more readable.I didn't understand this comment...how do you change this statement?
Quoted 33 lines
Quoted 9 lines
drivers/mmc/core/mmc.c +4
-0+ card->ext_csd.bkops =1 ; + card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN ]; + } + card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM ]; }drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, · line 779
Quoted 7 lines
drivers/mmc/core/mmc.c +3
-0@@ -762,6 +773,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, }/* +* Enable HPI feature (if supported) +*/ +if (card->ext_csd.hpi) {I know some people prefer doing things like
A.'if (x)'
instead of
B.'if (x != NULL)because A. is supposed to be some type of 'expert way' of doing things. However, B. is a whole lot more readable and easier for people to decipher precisely what is going on, especially newer people that may not be as familiar with this part of the Linux kernel as others. Just looking at this patch, I can't tell if '
card->ext_csd.hpi' is supposed to be a number value or a pointer. And if you use Linus's tool 'sparse' to check your kernel code before submitting, there is a difference between statements like 'if (x == 0)' and 'if (x == NULL)', even though they could evaluate to the same result in thisif()statement.
Quoted 7 lines
Quoted 2 lines
So I suggest adding the equality or inequality sign to this
if()as well as any otherif()to make the code a bit easier to understand.Right..i will modify this point..
Thanks for your comments..
Any other opinion about this feature (BKOPS)..??
Unfortunately, I am still a little new to this area of the Linux kernel so I don't quite have the background to give an intelligent answer w/respect to eMMC 4.41 and BKOPS. I just have 3 device driver accepts in the TTY space, so my contributions to patches are mainly basic code functionality and Linux kernel/device-driver gotchas.
Do you know the tool 'sparse'? It's a good thing to try once, before submitting upstream, if you haven't done it.
Quoted 6 lines
Regards,
Jaehoon Chung
Signature · 3 lines
J (James/Jay) Freyensee Storage Technology Group Intel Corporation
Hi Jay..
I didn't know the tool 'sparse'. i will check the tool for your advice. Thank you a lot for your help.. :)
Quoted 17 lines
Unfortunately, I am still a little new to this area of the Linux kernel so I don't quite have the background to give an intelligent answer w/respect to eMMC 4.41 and BKOPS. I just have 3 device driver accepts in the TTY space, so my contributions to patches are mainly basic code functionality and Linux
kernel/device-drivergotchas.Do you know the tool 'sparse'? It's a good thing to try once, before submitting upstream, if you haven't done it.
Quoted 6 lines
Regards,
Jaehoon Chung
Quoted 4 lines · Jaehoon Chung
Hi Jay..
I didn't know the tool 'sparse'. i will check the tool for your advice. Thank you a lot for your help.. :)
here, I'll provide it from a write-up I did within my department. Unfortunately, finding documentation how to use it is pretty hard because very little is provided.
-------------------------------------------------
Step 9 in SubmitChecklist documentation in preparing to submit a device driver upstream to Linus's kernel is:
9: Check cleanly with sparse.
Sparse is a tool written by Linus that contains built-in checks for known problematic and a set of annotations in the Linux kernel designed to convey semantic information about types, such as what address space pointers point to, or what locks a function acquires or releases. It does appear to be a useful tool to make your code that much more tight.
The #1 problem with this tool is there is little documentation how to use it. I think I figured it out how to use it, basic-wise, with the help of searching on-line forums.
To set up and use for the first time:
1. git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git
2. cd to the sparse directory
3. make; sudo make install
4. cd to your linux kernel
5. 'make C=1 >& sparse.log' if you have not built your kernel, OR
'make C=2 >& sparse.log' if you have already built your kernel
I HIGHLY recommend the file redirection operator because a LOT OF STUFF GETS SPIT OUT.
6. To use other macros, do something like:
make C=1 CF=
example:
make C=2 CF="-D__CHECK_ENDIAN__" (to check endianess)
Further info:
http://en.wikipedia.org/wiki/Sparse
-------------------------------------------------
Quoted 19 lines
Quoted 18 lines
Unfortunately, I am still a little new to this area of the Linux kernel so I don't quite have the background to give an intelligent answer w/respect to eMMC 4.41 and BKOPS. I just have 3 device driver accepts in the TTY space, so my contributions to patches are mainly basic code functionality and Linux
kernel/device-drivergotchas.Do you know the tool 'sparse'? It's a good thing to try once, before submitting upstream, if you haven't done it.
Quoted 6 lines
Regards,
Jaehoon Chung
Signature · 3 lines
J (James/Jay) Freyensee Storage Technology Group Intel Corporation
Hi Jaehoon Chung,
Quoted 178 lines · Jaehoon Chung
Hi mailing.
This RFC patch is supported background operation(BKOPS).
And if you want to test this patch, must apply "[PATCH v3] mmc: support HPI send command"This patch is based on Hanumath Prasad's patch "mmc: enable background operations for emmc4.41 with HPI support"
Hanumath's patch is implemented before applied per forlin's patch "use nonblock mmc request...".
This patch is based on 3.1.0-rc1 in mmc-next.Background operations is run when set the
URGENT_BKOPSin response.if set the
URGENT_BKOPSin response, we can notify that card need the BKOPS.
(URGENT_BKOPSis used in eMMC4.41 spec, but in eMMC4.5 changed toEXCEPTION_EVENTbit.
maybe, we need to change this point).And all request is done, then run background operation.
if request read/write operation when running BKOPS, issue HPI interruptThis patch is just RFC patch (not to merge), because i want to use BKOPS in userspace.
(using ioctl).I want to get mailing's review for this patch.
Signed-off-by Jaehoon Chung <[email protected]>Signed-off-by Kyungmin Park <[email protected]>CC Hanumath Prasad <[email protected]>--- drivers/mmc/card/block.c | 4 ++++ drivers/mmc/card/queue.c | 10 ++++++++++ drivers/mmc/core/core.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mmc/core/mmc.c | 28 ++++++++++++++++++++++++++++ drivers/mmc/core/mmc_ops.c | 3 +++ include/linux/mmc/card.h | 11 +++++++++++ include/linux/mmc/core.h | 1 + include/linux/mmc/mmc.h | 4 ++++ 8 files changed, 96 insertions(+), 0 deletions(-)drivers/mmc/card/block.c +4
-0@@ -1078,6 +1078,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) switch (status) {case MMC_BLK_SUCCESS :case MMC_BLK_PARTIAL : +if (mmc_card_mmc (card) && + (brq->cmd.resp[0 ] &R1_URGENT_BKOPS )) { +mmc_card_set_need_bkops (card); + }/* * A block was successfully transferred. drivers/mmc/card/block.c +0
-0*/ drivers/mmc/card/queue.c +10
-0@@ -46,6 +46,8 @@ static int mmc_queue_thread(void *d) {struct mmc_queue *mq = d;struct request_queue *q = mq->queue; +struct mmc_card *card = mq->card; +unsigned long flags; current->flags |=PF_MEMALLOC ;@@ -61,6 +63,13 @@ static int mmc_queue_thread(void *d)spin_unlock_irq (q->queue_lock);if (req || mq->mqrq_prev->req) { +if (mmc_card_doing_bkops (card)) { +mmc_interrupt_hpi (card); +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, + flags); + }set_current_state (TASK_RUNNING ); mq->issue_fn (mq, req); }else {@@ -68,6 +77,7 @@ static int mmc_queue_thread(void *d)set_current_state (TASK_RUNNING );break ; } +mmc_start_bkops (mq->card);up (&mq->thread_sem);schedule ();down (&mq->thread_sem);drivers/mmc/core/core.c +0
-0@@ -347,6 +347,41 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct
mmc_command*cmd, int retries
EXPORT_SYMBOL(mmc_wait_for_cmd);drivers/mmc/core/core.c +35
-0+/* Start background operation */ +void mmc_start_bkops (struct mmc_card *card) +{ +int err; +unsigned long flags; + +BUG_ON (!card); + +if (!card->ext_csd.bkops_en) { +printk (KERN_INFO "Didn't set BKOPS enable bit!\n" ); +return ; + } + +if (mmc_card_doing_bkops (card) || + !mmc_card_need_bkops (card)) { +return ; + } + +mmc_claim_host (card->host); + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_BKOPS_START ,1 ,0 ); +if (err) { +mmc_card_clr_need_bkops (card); + goto out; + } + +spin_lock_irqsave (&card->host->lock, flags); +mmc_card_clr_need_bkops (card); +mmc_card_set_doing_bkops (card); +spin_unlock_irqrestore (&card->host->lock, flags); +out: +mmc_release_host (card->host); +} +EXPORT_SYMBOL (mmc_start_bkops); +/** * mmc_interrupt_hpi - Issue for High priority Interrupt * @card: the MMC card associated with the HPI transfer drivers/mmc/core/mmc.c +17
-0@@ -421,6 +421,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME ] *10 ; } +/* +* check whether the eMMC card support BKOPS. +* if set BKOPS_SUPPORT bit, +* BKOPS_STATUS, BKOPS_EN,,BKOPS_START and +* URGENT_BKOPS are supported.(default) +*/ +if (ext_csd[EXT_CSD_BKOPS_SUPPORT ] &0x1 ) { + card->ext_csd.bkops =1 ; + card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN ]; + } + card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM ]; }@@ -762,6 +773,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, }/* +* Enable HPI feature (if supported) +*/ +if (card->ext_csd.hpi) { + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_HPI_MGMT ,1 ,0 ); +if (err && err != -EBADMSG )
drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 · line 792
Quoted 10 lines
drivers/mmc/core/mmc.c +10
-0+ goto free_card; + +if (err) { +printk (KERN_WARNING "%s: Enabling HPI failed\n" , +mmc_hostname (card->host)); + err =0 ; + }else + card->ext_csd.hpi_en =1 ; + } +
There is no code for enabling BKOPS_EN?
If host want to handle background operation manually, it needs.
Quoted 116 lines
drivers/mmc/core/mmc.c +1
-0+/* * Compute bus speed. */ drivers/mmc/core/mmc.c +0
-0max_dtr = (unsigned int )-1 ;drivers/mmc/core/mmc_ops.c +3
-0@@ -398,6 +398,9 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, if (err) return err; +if (index ==EXT_CSD_BKOPS_START ) +return 0 ; +/* Must check status to be sure of no errors */ do {drivers/mmc/core/mmc_ops.c +0
-0err =mmc_send_status (card, &status);include/linux/mmc/card.h +2
-0@@ -67,6 +67,8 @@ struct mmc_ext_csd {bool hpi_en;/* HPI enablebit */ bool hpi;/* HPI support bit */ unsigned int hpi_cmd;/* cmd used as HPI */ +bool bkops;/* BKOPS support bit */ +bool bkops_en;/* BKOPS enable bit */ u8 raw_partition_support;/* 160 */ u8 raw_erased_mem_count;/* 181 */ u8 raw_ext_csd_structure;/* 194 */ @@ -192,6 +194,8 @@ struct mmc_card {#define MMC_QUIRK_DISABLE_CD (1<<5)/* disconnect CD/DAT[3] resistor */
#defineMMC_QUIRK_INAND_CMD38(1<<6) /* iNAND devices have
broken CMD38 */
#defineMMC_QUIRK_BLK_NO_CMD23(1<<7) /* Avoid CMD23 for regular
multiblock */
+#defineMMC_STATE_NEED_BKOPS(1<<7) /* Need background
operation */
+#defineMMC_STATE_DOING_BKOPS(1<<8) /* Do running background
operation */include/linux/mmc/card.h +2
-0unsigned int erase_size;/* erase size in sectors */ unsigned int erase_shift;/* if erase unit is power 2 */ @@ -318,6 +322,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR) #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) +#define mmc_card_need_bkops(c) ((c)->state & MMC_STATE_NEED_BKOPS) +#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)#define
mmc_card_set_readonly(c)((c)->state |=MMC_STATE_READONLY)include/linux/mmc/card.h +5
-0@@ -326,6 +332,11 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR) #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) +#define mmc_card_set_need_bkops(c) ((c)->state |= MMC_STATE_NEED_BKOPS) +#define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS) + +#define mmc_card_clr_need_bkops(c) ((c)->state &= ~MMC_STATE_NEED_BKOPS) +#define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS)/* * Quirk add/remove for MMC products.
include/linux/mmc/core.h +1
-0@@ -162,6 +162,7 @@ extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, unsigned int nr);extern unsigned int mmc_calc_max_discard (struct mmc_card *card); +extern void mmc_start_bkops (struct mmc_card *card);extern int mmc_set_blocklen (struct mmc_card *card,unsigned int blocklen);extern void mmc_set_data_timeout(struct
mmc_data*, const structmmc_card
*);include/linux/mmc/mmc.h +4
-1@@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode)#define R1_READY_FOR_DATA (1 << 8)/* sx, a */ #define R1_SWITCH_ERROR (1 << 7)/* sx, c */ #define R1_APP_CMD (1 << 5)/* sr, c */ +#define R1_URGENT_BKOPS (1 << 6)/* sr, a */ #define R1_STATE_IDLE 0#define R1_STATE_READY 1@@ -273,6 +274,8 @@ struct _mmc_csd {#define EXT_CSD_PARTITION_ATTRIBUTE 156/* R/W */ #define EXT_CSD_PARTITION_SUPPORT 160/* RO */ #define EXT_CSD_HPI_MGMT 161/* R/W */ +#define EXT_CSD_BKOPS_EN 163/* R/W */ +#define EXT_CSD_BKOPS_START 164/* R/W */ #define EXT_CSD_WR_REL_PARAM 166/* RO */ #define EXT_CSD_ERASE_GROUP_DEF 175/* R/W */ #define EXT_CSD_PART_CONFIG 179/* R/W */ @@ -295,6 +298,7 @@ struct _mmc_csd {#define EXT_CSD_SEC_ERASE_MULT 230/* RO */ #define EXT_CSD_SEC_FEATURE_SUPPORT 231/* RO */ #define EXT_CSD_TRIM_MULT 232/* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502/* RO */ #define EXT_CSD_HPI_FEATURES 503/* RO */ /* -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Seungwon.
Quoted 17 lines · Seungwon Jeon
Hi Jaehoon Chung,
Quoted 15 lines
drivers/mmc/core/mmc.c +10
-0@@ -762,6 +773,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, }/* +* Enable HPI feature (if supported) +*/ +if (card->ext_csd.hpi) { + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_HPI_MGMT ,1 ,0 ); +if (err && err != -EBADMSG ) + goto free_card; + +if (err) { + printk(KERN_WARNING "%s: Enabling HPI failed\n",
Quoted 8 lines
drivers/mmc/core/mmc.c static int mmc_init_card(struct mmc_host *host, u32 ocr, · line 791
Quoted 6 lines
drivers/mmc/core/mmc.c +6
-0+ mmc_hostname(card->host)); + err =0 ; + }else + card->ext_csd.hpi_en =1 ; + } +There is no code for enabling
BKOPS_EN?
If host want to handle background operation manually, it needs.
Sorry, this code is my mistake...maybe duplicated the HPI patch.. You means maybe need this code..
/*
+ * Enable BKOPS feature (if supported)
+ */
+ if (card->ext_csd.bkops != NULL) {
+ /*
+ * If card supported BKOPS, default set BKOPS_EN bit.
+ * But ensure to enable bkops, need to check enable bit
+ */
+ if (!card->ext_csd.bkops_en) {+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BKOPS_EN, 1, 0);
+ if (err && err != -EBADMSG)
+ goto free_card;
+
+ if (err) {
+ printk(KERN_ERR "%s: Enabling BKOPS failed\n",
+ mmc_hostname(card->host));
+ err = 0;
+ } else
+ card->ext_csd.bkops_en = 1;
+ }
+ }
+
I will resend the RFC patch..
Thank you for comment.
Best Regards,
Jaehoon Chung
Hi
In eMMC spec, if set BKOPS_SUPPORT bit in ext_csd,BKOPS_EN, BKOPS_STATUS, BKOPS_START and URGENT_BKOPS are supported for default.
So need not to send switch-command for BKOPS_EN when set BKOPS_SUPPORT bit.
Thanks,
Jaehoon Chung
Quoted 40 lines
Quoted 2 lines
There is no code for enabling
BKOPS_EN?
If host want to handle background operation manually, it needs.Sorry, this code is my mistake...maybe duplicated the HPI patch.. You means maybe need this code..
/*drivers/mmc/core/mmc.c +22
-0+* Enable BKOPS feature (if supported) +*/ +if (card->ext_csd.bkops !=NULL ) { +/* +* If card supported BKOPS, default set BKOPS_EN bit. +* But ensure to enable bkops, need to check enable bit +*/ +if (!card->ext_csd.bkops_en) { + err =mmc_switch (card,EXT_CSD_CMD_SET_NORMAL , +EXT_CSD_BKOPS_EN ,1 ,0 ); +if (err && err != -EBADMSG ) + goto free_card; + +if (err) { +printk (KERN_ERR "%s: Enabling BKOPS failed\n" , +mmc_hostname (card->host)); + err =0 ; + }else + card->ext_csd.bkops_en =1 ; + } + } +I will resend the RFC patch..
Thank you for comment.
Best Regards,
Jaehoon Chung
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html