Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge patch series "UFS patches for kernel 6.11"

Bart Van Assche <bvanassche@acm.org> says:

Hi Martin,

Please consider this series of UFS driver patches for the next merge window.

Thank you,

Bart.

Link: https://lore.kernel.org/r/20240708211716.2827751-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+90 -87
+25 -6
drivers/ufs/core/ufs-mcq.c
··· 137 137 * 138 138 * MAC - Max. Active Command of the Host Controller (HC) 139 139 * HC wouldn't send more than this commands to the device. 140 - * It is mandatory to implement get_hba_mac() to enable MCQ mode. 141 140 * Calculates and adjusts the queue depth based on the depth 142 141 * supported by the HC and ufs device. 143 142 */ ··· 144 145 { 145 146 int mac; 146 147 147 - /* Mandatory to implement get_hba_mac() */ 148 - mac = ufshcd_mcq_vops_get_hba_mac(hba); 149 - if (mac < 0) { 150 - dev_err(hba->dev, "Failed to get mac, err=%d\n", mac); 151 - return mac; 148 + if (!hba->vops || !hba->vops->get_hba_mac) { 149 + /* 150 + * Extract the maximum number of active transfer tasks value 151 + * from the host controller capabilities register. This value is 152 + * 0-based. 153 + */ 154 + hba->capabilities = 155 + ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES); 156 + mac = hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS_MCQ; 157 + mac++; 158 + } else { 159 + mac = hba->vops->get_hba_mac(hba); 152 160 } 161 + if (mac < 0) 162 + goto err; 153 163 154 164 WARN_ON_ONCE(!hba->dev_info.bqueuedepth); 155 165 /* ··· 167 159 * shared queuing architecture is enabled. 168 160 */ 169 161 return min_t(int, mac, hba->dev_info.bqueuedepth); 162 + 163 + err: 164 + dev_err(hba->dev, "Failed to get mac, err=%d\n", mac); 165 + return mac; 170 166 } 171 167 172 168 static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) ··· 427 415 void ufshcd_mcq_enable(struct ufs_hba *hba) 428 416 { 429 417 ufshcd_rmwl(hba, MCQ_MODE_SELECT, MCQ_MODE_SELECT, REG_UFS_MEM_CFG); 418 + hba->mcq_enabled = true; 430 419 } 431 420 EXPORT_SYMBOL_GPL(ufshcd_mcq_enable); 421 + 422 + void ufshcd_mcq_disable(struct ufs_hba *hba) 423 + { 424 + ufshcd_rmwl(hba, MCQ_MODE_SELECT, 0, REG_UFS_MEM_CFG); 425 + hba->mcq_enabled = false; 426 + } 432 427 433 428 void ufshcd_mcq_config_esi(struct ufs_hba *hba, struct msi_msg *msg) 434 429 {
+1 -14
drivers/ufs/core/ufshcd-priv.h
··· 64 64 void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag, 65 65 struct cq_entry *cqe); 66 66 int ufshcd_mcq_init(struct ufs_hba *hba); 67 + void ufshcd_mcq_disable(struct ufs_hba *hba); 67 68 int ufshcd_mcq_decide_queue_depth(struct ufs_hba *hba); 68 69 int ufshcd_mcq_memory_alloc(struct ufs_hba *hba); 69 - void ufshcd_mcq_make_queues_operational(struct ufs_hba *hba); 70 - void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds); 71 - u32 ufshcd_mcq_read_cqis(struct ufs_hba *hba, int i); 72 - void ufshcd_mcq_write_cqis(struct ufs_hba *hba, u32 val, int i); 73 70 struct ufs_hw_queue *ufshcd_mcq_req_to_hwq(struct ufs_hba *hba, 74 71 struct request *req); 75 - unsigned long ufshcd_mcq_poll_cqe_lock(struct ufs_hba *hba, 76 - struct ufs_hw_queue *hwq); 77 72 void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba, 78 73 struct ufs_hw_queue *hwq); 79 74 bool ufshcd_cmd_inflight(struct scsi_cmnd *cmd); ··· 246 251 { 247 252 if (hba->vops && hba->vops->mcq_config_resource) 248 253 return hba->vops->mcq_config_resource(hba); 249 - 250 - return -EOPNOTSUPP; 251 - } 252 - 253 - static inline int ufshcd_mcq_vops_get_hba_mac(struct ufs_hba *hba) 254 - { 255 - if (hba->vops && hba->vops->get_hba_mac) 256 - return hba->vops->get_hba_mac(hba); 257 254 258 255 return -EOPNOTSUPP; 259 256 }
+54 -55
drivers/ufs/core/ufshcd.c
··· 164 164 enum { 165 165 UFSHCD_MAX_CHANNEL = 0, 166 166 UFSHCD_MAX_ID = 1, 167 - UFSHCD_CMD_PER_LUN = 32 - UFSHCD_NUM_RESERVED, 168 - UFSHCD_CAN_QUEUE = 32 - UFSHCD_NUM_RESERVED, 169 167 }; 170 168 171 169 static const char *const ufshcd_state_name[] = { ··· 453 455 454 456 intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); 455 457 456 - if (is_mcq_enabled(hba)) { 458 + if (hba->mcq_enabled) { 457 459 struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, rq); 458 460 459 461 hwq_id = hwq->id; ··· 2302 2304 if (unlikely(ufshcd_should_inform_monitor(hba, lrbp))) 2303 2305 ufshcd_start_monitor(hba, lrbp); 2304 2306 2305 - if (is_mcq_enabled(hba)) { 2307 + if (hba->mcq_enabled) { 2306 2308 int utrd_size = sizeof(struct utp_transfer_req_desc); 2307 2309 struct utp_transfer_req_desc *src = lrbp->utr_descriptor_ptr; 2308 2310 struct utp_transfer_req_desc *dest; ··· 2402 2404 hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; 2403 2405 2404 2406 /* nutrs and nutmrs are 0 based values */ 2405 - hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1; 2407 + hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS_SDB) + 1; 2406 2408 hba->nutmrs = 2407 2409 ((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1; 2408 2410 hba->reserved_slot = hba->nutrs - 1; ··· 3001 3003 goto out; 3002 3004 } 3003 3005 3004 - if (is_mcq_enabled(hba)) 3006 + if (hba->mcq_enabled) 3005 3007 hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(cmd)); 3006 3008 3007 3009 ufshcd_send_command(hba, tag, hwq); ··· 3060 3062 unsigned long flags; 3061 3063 int err; 3062 3064 3063 - if (is_mcq_enabled(hba)) { 3065 + if (hba->mcq_enabled) { 3064 3066 /* 3065 3067 * MCQ mode. Clean up the MCQ resources similar to 3066 3068 * what the ufshcd_utrl_clear() does for SDB mode. ··· 3170 3172 __func__, lrbp->task_tag); 3171 3173 3172 3174 /* MCQ mode */ 3173 - if (is_mcq_enabled(hba)) { 3175 + if (hba->mcq_enabled) { 3174 3176 /* successfully cleared the command, retry if needed */ 3175 3177 if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0) 3176 3178 err = -EAGAIN; ··· 3992 3994 */ 3993 3995 static int ufshcd_dme_link_startup(struct ufs_hba *hba) 3994 3996 { 3995 - struct uic_command uic_cmd = {0}; 3997 + struct uic_command uic_cmd = { 3998 + .command = UIC_CMD_DME_LINK_STARTUP, 3999 + }; 3996 4000 int ret; 3997 - 3998 - uic_cmd.command = UIC_CMD_DME_LINK_STARTUP; 3999 4001 4000 4002 ret = ufshcd_send_uic_cmd(hba, &uic_cmd); 4001 4003 if (ret) ··· 4014 4016 */ 4015 4017 static int ufshcd_dme_reset(struct ufs_hba *hba) 4016 4018 { 4017 - struct uic_command uic_cmd = {0}; 4019 + struct uic_command uic_cmd = { 4020 + .command = UIC_CMD_DME_RESET, 4021 + }; 4018 4022 int ret; 4019 - 4020 - uic_cmd.command = UIC_CMD_DME_RESET; 4021 4023 4022 4024 ret = ufshcd_send_uic_cmd(hba, &uic_cmd); 4023 4025 if (ret) ··· 4053 4055 */ 4054 4056 static int ufshcd_dme_enable(struct ufs_hba *hba) 4055 4057 { 4056 - struct uic_command uic_cmd = {0}; 4058 + struct uic_command uic_cmd = { 4059 + .command = UIC_CMD_DME_ENABLE, 4060 + }; 4057 4061 int ret; 4058 - 4059 - uic_cmd.command = UIC_CMD_DME_ENABLE; 4060 4062 4061 4063 ret = ufshcd_send_uic_cmd(hba, &uic_cmd); 4062 4064 if (ret) ··· 4110 4112 int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, 4111 4113 u8 attr_set, u32 mib_val, u8 peer) 4112 4114 { 4113 - struct uic_command uic_cmd = {0}; 4115 + struct uic_command uic_cmd = { 4116 + .command = peer ? UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET, 4117 + .argument1 = attr_sel, 4118 + .argument2 = UIC_ARG_ATTR_TYPE(attr_set), 4119 + .argument3 = mib_val, 4120 + }; 4114 4121 static const char *const action[] = { 4115 4122 "dme-set", 4116 4123 "dme-peer-set" ··· 4123 4120 const char *set = action[!!peer]; 4124 4121 int ret; 4125 4122 int retries = UFS_UIC_COMMAND_RETRIES; 4126 - 4127 - uic_cmd.command = peer ? 4128 - UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET; 4129 - uic_cmd.argument1 = attr_sel; 4130 - uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set); 4131 - uic_cmd.argument3 = mib_val; 4132 4123 4133 4124 do { 4134 4125 /* for peer attributes we retry upon failure */ ··· 4153 4156 int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, 4154 4157 u32 *mib_val, u8 peer) 4155 4158 { 4156 - struct uic_command uic_cmd = {0}; 4159 + struct uic_command uic_cmd = { 4160 + .command = peer ? UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET, 4161 + .argument1 = attr_sel, 4162 + }; 4157 4163 static const char *const action[] = { 4158 4164 "dme-get", 4159 4165 "dme-peer-get" ··· 4189 4189 goto out; 4190 4190 } 4191 4191 } 4192 - 4193 - uic_cmd.command = peer ? 4194 - UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET; 4195 - uic_cmd.argument1 = attr_sel; 4196 4192 4197 4193 do { 4198 4194 /* for peer attributes we retry upon failure */ ··· 4322 4326 */ 4323 4327 int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) 4324 4328 { 4325 - struct uic_command uic_cmd = {0}; 4329 + struct uic_command uic_cmd = { 4330 + .command = UIC_CMD_DME_SET, 4331 + .argument1 = UIC_ARG_MIB(PA_PWRMODE), 4332 + .argument3 = mode, 4333 + }; 4326 4334 int ret; 4327 4335 4328 4336 if (hba->quirks & UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP) { ··· 4339 4339 } 4340 4340 } 4341 4341 4342 - uic_cmd.command = UIC_CMD_DME_SET; 4343 - uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE); 4344 - uic_cmd.argument3 = mode; 4345 4342 ufshcd_hold(hba); 4346 4343 ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); 4347 4344 ufshcd_release(hba); ··· 4379 4382 4380 4383 int ufshcd_uic_hibern8_enter(struct ufs_hba *hba) 4381 4384 { 4382 - int ret; 4383 - struct uic_command uic_cmd = {0}; 4385 + struct uic_command uic_cmd = { 4386 + .command = UIC_CMD_DME_HIBER_ENTER, 4387 + }; 4384 4388 ktime_t start = ktime_get(); 4389 + int ret; 4385 4390 4386 4391 ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, PRE_CHANGE); 4387 4392 4388 - uic_cmd.command = UIC_CMD_DME_HIBER_ENTER; 4389 4393 ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); 4390 4394 trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter", 4391 4395 ktime_to_us(ktime_sub(ktime_get(), start)), ret); ··· 4404 4406 4405 4407 int ufshcd_uic_hibern8_exit(struct ufs_hba *hba) 4406 4408 { 4407 - struct uic_command uic_cmd = {0}; 4409 + struct uic_command uic_cmd = { 4410 + .command = UIC_CMD_DME_HIBER_EXIT, 4411 + }; 4408 4412 int ret; 4409 4413 ktime_t start = ktime_get(); 4410 4414 4411 4415 ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, PRE_CHANGE); 4412 4416 4413 - uic_cmd.command = UIC_CMD_DME_HIBER_EXIT; 4414 4417 ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd); 4415 4418 trace_ufshcd_profile_hibern8(dev_name(hba->dev), "exit", 4416 4419 ktime_to_us(ktime_sub(ktime_get(), start)), ret); ··· 5561 5562 u32 tr_doorbell; 5562 5563 struct ufs_hw_queue *hwq; 5563 5564 5564 - if (is_mcq_enabled(hba)) { 5565 + if (hba->mcq_enabled) { 5565 5566 hwq = &hba->uhq[queue_num]; 5566 5567 5567 5568 return ufshcd_mcq_poll_cqe_lock(hba, hwq); ··· 6202 6203 /* Complete requests that have door-bell cleared */ 6203 6204 static void ufshcd_complete_requests(struct ufs_hba *hba, bool force_compl) 6204 6205 { 6205 - if (is_mcq_enabled(hba)) 6206 + if (hba->mcq_enabled) 6206 6207 ufshcd_mcq_compl_pending_transfer(hba, force_compl); 6207 6208 else 6208 6209 ufshcd_transfer_req_compl(hba); ··· 6459 6460 *ret ? "failed" : "succeeded"); 6460 6461 6461 6462 /* Release cmd in MCQ mode if abort succeeds */ 6462 - if (is_mcq_enabled(hba) && (*ret == 0)) { 6463 + if (hba->mcq_enabled && (*ret == 0)) { 6463 6464 hwq = ufshcd_mcq_req_to_hwq(hba, scsi_cmd_to_rq(lrbp->cmd)); 6464 6465 if (!hwq) 6465 6466 return 0; ··· 7392 7393 goto out; 7393 7394 } 7394 7395 7395 - if (is_mcq_enabled(hba)) { 7396 + if (hba->mcq_enabled) { 7396 7397 for (pos = 0; pos < hba->nutrs; pos++) { 7397 7398 lrbp = &hba->lrb[pos]; 7398 7399 if (ufshcd_cmd_inflight(lrbp->cmd) && ··· 7488 7489 */ 7489 7490 dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n", 7490 7491 __func__, tag); 7491 - if (is_mcq_enabled(hba)) { 7492 + if (hba->mcq_enabled) { 7492 7493 /* MCQ mode */ 7493 7494 if (ufshcd_cmd_inflight(lrbp->cmd)) { 7494 7495 /* sleep for max. 200us same delay as in SDB mode */ ··· 7566 7567 7567 7568 ufshcd_hold(hba); 7568 7569 7569 - if (!is_mcq_enabled(hba)) { 7570 + if (!hba->mcq_enabled) { 7570 7571 reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); 7571 7572 if (!test_bit(tag, &hba->outstanding_reqs)) { 7572 7573 /* If command is already aborted/completed, return FAILED. */ ··· 7599 7600 } 7600 7601 hba->req_abort_count++; 7601 7602 7602 - if (!is_mcq_enabled(hba) && !(reg & (1 << tag))) { 7603 + if (!hba->mcq_enabled && !(reg & (1 << tag))) { 7603 7604 /* only execute this code in single doorbell mode */ 7604 7605 dev_err(hba->dev, 7605 7606 "%s: cmd was completed, but without a notifying intr, tag = %d", ··· 7626 7627 goto release; 7627 7628 } 7628 7629 7629 - if (is_mcq_enabled(hba)) { 7630 + if (hba->mcq_enabled) { 7630 7631 /* MCQ mode. Branch off to handle abort for mcq mode */ 7631 7632 err = ufshcd_mcq_abort(cmd); 7632 7633 goto release; ··· 8681 8682 if (ret) 8682 8683 goto err; 8683 8684 8685 + hba->host->can_queue = hba->nutrs - UFSHCD_NUM_RESERVED; 8686 + hba->reserved_slot = hba->nutrs - UFSHCD_NUM_RESERVED; 8687 + 8684 8688 return 0; 8685 8689 err: 8686 8690 hba->nutrs = old_nutrs; ··· 8704 8702 ufshcd_enable_intr(hba, intrs); 8705 8703 ufshcd_mcq_make_queues_operational(hba); 8706 8704 ufshcd_mcq_config_mac(hba, hba->nutrs); 8707 - 8708 - hba->host->can_queue = hba->nutrs - UFSHCD_NUM_RESERVED; 8709 - hba->reserved_slot = hba->nutrs - UFSHCD_NUM_RESERVED; 8710 - 8711 - ufshcd_mcq_enable(hba); 8712 - hba->mcq_enabled = true; 8713 8705 8714 8706 dev_info(hba->dev, "MCQ configured, nr_queues=%d, io_queues=%d, read_queue=%d, poll_queues=%d, queue_depth=%d\n", 8715 8707 hba->nr_hw_queues, hba->nr_queues[HCTX_TYPE_DEFAULT], ··· 8732 8736 ufshcd_set_link_active(hba); 8733 8737 8734 8738 /* Reconfigure MCQ upon reset */ 8735 - if (is_mcq_enabled(hba) && !init_dev_params) 8739 + if (hba->mcq_enabled && !init_dev_params) { 8736 8740 ufshcd_config_mcq(hba); 8741 + ufshcd_mcq_enable(hba); 8742 + } 8737 8743 8738 8744 /* Verify device initialization by sending NOP OUT UPIU */ 8739 8745 ret = ufshcd_verify_dev_init(hba); ··· 8756 8758 if (ret) 8757 8759 return ret; 8758 8760 if (is_mcq_supported(hba) && !hba->scsi_host_added) { 8761 + ufshcd_mcq_enable(hba); 8759 8762 ret = ufshcd_alloc_mcq(hba); 8760 8763 if (!ret) { 8761 8764 ufshcd_config_mcq(hba); 8762 8765 } else { 8763 8766 /* Continue with SDB mode */ 8767 + ufshcd_mcq_disable(hba); 8764 8768 use_mcq_mode = false; 8765 8769 dev_err(hba->dev, "MCQ mode is disabled, err=%d\n", 8766 8770 ret); ··· 8776 8776 } else if (is_mcq_supported(hba)) { 8777 8777 /* UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH is set */ 8778 8778 ufshcd_config_mcq(hba); 8779 + ufshcd_mcq_enable(hba); 8779 8780 } 8780 8781 } 8781 8782 ··· 8962 8961 .eh_timed_out = ufshcd_eh_timed_out, 8963 8962 .this_id = -1, 8964 8963 .sg_tablesize = SG_ALL, 8965 - .cmd_per_lun = UFSHCD_CMD_PER_LUN, 8966 - .can_queue = UFSHCD_CAN_QUEUE, 8967 8964 .max_segment_size = PRDT_DATA_BYTE_COUNT_MAX, 8968 8965 .max_sectors = SZ_1M / SECTOR_SIZE, 8969 8966 .max_host_blocked = 1,
+3 -3
drivers/ufs/host/ufs-mediatek.c
··· 693 693 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 694 694 u32 irq, i; 695 695 696 - if (!is_mcq_enabled(hba)) 696 + if (!hba->mcq_enabled) 697 697 return; 698 698 699 699 if (host->mcq_nr_intr == 0) ··· 711 711 struct ufs_mtk_host *host = ufshcd_get_variant(hba); 712 712 u32 irq, i; 713 713 714 - if (!is_mcq_enabled(hba)) 714 + if (!hba->mcq_enabled) 715 715 return; 716 716 717 717 if (host->mcq_nr_intr == 0) ··· 1308 1308 if (err) 1309 1309 return err; 1310 1310 1311 - if (is_mcq_enabled(hba)) { 1311 + if (hba->mcq_enabled) { 1312 1312 ufs_mtk_config_mcq(hba, false); 1313 1313 ufshcd_mcq_make_queues_operational(hba); 1314 1314 ufshcd_mcq_config_mac(hba, hba->nutrs);
+5 -8
include/ufs/ufshcd.h
··· 73 73 * @done: UIC command completion 74 74 */ 75 75 struct uic_command { 76 - u32 command; 77 - u32 argument1; 76 + const u32 command; 77 + const u32 argument1; 78 78 u32 argument2; 79 79 u32 argument3; 80 80 int cmd_active; ··· 325 325 * @event_notify: called to notify important events 326 326 * @reinit_notify: called to notify reinit of UFSHCD during max gear switch 327 327 * @mcq_config_resource: called to configure MCQ platform resources 328 - * @get_hba_mac: called to get vendor specific mac value, mandatory for mcq mode 328 + * @get_hba_mac: reports maximum number of outstanding commands supported by 329 + * the controller. Should be implemented for UFSHCI 4.0 or later 330 + * controllers that are not compliant with the UFSHCI 4.0 specification. 329 331 * @op_runtime_config: called to config Operation and runtime regs Pointers 330 332 * @get_outstanding_cqs: called to get outstanding completion queues 331 333 * @config_esi: called to config Event Specific Interrupt ··· 1134 1132 }; 1135 1133 1136 1134 #define MCQ_QCFG_SIZE 0x40 1137 - 1138 - static inline bool is_mcq_enabled(struct ufs_hba *hba) 1139 - { 1140 - return hba->mcq_enabled; 1141 - } 1142 1135 1143 1136 static inline unsigned int ufshcd_mcq_opr_offset(struct ufs_hba *hba, 1144 1137 enum ufshcd_mcq_opr opr, int idx)
+2 -1
include/ufs/ufshci.h
··· 67 67 68 68 /* Controller capability masks */ 69 69 enum { 70 - MASK_TRANSFER_REQUESTS_SLOTS = 0x0000001F, 70 + MASK_TRANSFER_REQUESTS_SLOTS_SDB = 0x0000001F, 71 + MASK_TRANSFER_REQUESTS_SLOTS_MCQ = 0x000000FF, 71 72 MASK_NUMBER_OUTSTANDING_RTT = 0x0000FF00, 72 73 MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000, 73 74 MASK_EHSLUTRD_SUPPORTED = 0x00400000,