* for-5.9/drivers: (38 commits) block: add max_active_zones to blk-sysfs block: add max_open_zones to blk-sysfs s390/dasd: Use struct_size() helper s390/dasd: fix inability to use DASD with DIAG driver md-cluster: fix wild pointer of unlock_all_bitmaps() md/raid5-cache: clear MD_SB_CHANGE_PENDING before flushing stripes md: fix deadlock causing by sysfs_notify md: improve io stats accounting md: raid0/linear: fix dereference before null check on pointer mddev rsxx: switch from 'pci_free_consistent()' to 'dma_free_coherent()' nvme: remove ns->disk checks nvme-pci: use standard block status symbolic names nvme-pci: use the consistent return type of nvme_pci_iod_alloc_size() nvme-pci: add a blank line after declarations nvme-pci: fix some comments issues nvme-pci: remove redundant segment validation nvme: document quirked Intel models nvme: expose reconnect_delay and ctrl_loss_tmo via sysfs nvme: support for zoned namespaces nvme: support for multiple Command Sets Supported and Effects log pages ...
Showing the changes to include/linux (2 of 39 files). Show all
Unified · Split
| @@ -513,6 +513,8 @@ struct request_queue { · 512 unmodified lines | |||
| 513 | unsigned int nr_zones; | 513 | unsigned int nr_zones; |
| 514 | unsigned long *conv_zones_bitmap; | 514 | unsigned long *conv_zones_bitmap; |
| 515 | unsigned long *seq_zones_wlock; | 515 | unsigned long *seq_zones_wlock; |
| 516 | unsigned int max_open_zones; | ||
| 517 | unsigned int max_active_zones; | ||
| 516 | #endif /* CONFIG_BLK_DEV_ZONED */ | 518 | #endif /* CONFIG_BLK_DEV_ZONED */ |
| 517 | 519 | ||
| 518 | /* | 520 | /* |
| @@ -722,6 +724,28 @@ static inline bool blk_queue_zone_is_seq(struct request_queue *q, · 203 unmodified lines | |||
| 722 | return true; | 724 | return true; |
| 723 | return !test_bit(blk_queue_zone_no(q, sector), q->conv_zones_bitmap); | 725 | return !test_bit(blk_queue_zone_no(q, sector), q->conv_zones_bitmap); |
| 724 | } | 726 | } |
| 727 | |||
| 728 | static inline void blk_queue_max_open_zones(struct request_queue *q, | ||
| 729 | unsigned int max_open_zones) | ||
| 730 | { | ||
| 731 | q->max_open_zones = max_open_zones; | ||
| 732 | } | ||
| 733 | |||
| 734 | static inline unsigned int queue_max_open_zones(const struct request_queue *q) | ||
| 735 | { | ||
| 736 | return q->max_open_zones; | ||
| 737 | } | ||
| 738 | |||
| 739 | static inline void blk_queue_max_active_zones(struct request_queue *q, | ||
| 740 | unsigned int max_active_zones) | ||
| 741 | { | ||
| 742 | q->max_active_zones = max_active_zones; | ||
| 743 | } | ||
| 744 | |||
| 745 | static inline unsigned int queue_max_active_zones(const struct request_queue *q) | ||
| 746 | { | ||
| 747 | return q->max_active_zones; | ||
| 748 | } | ||
| 725 | #else /* CONFIG_BLK_DEV_ZONED */ | 749 | #else /* CONFIG_BLK_DEV_ZONED */ |
| 726 | static inline unsigned int blk_queue_nr_zones(struct request_queue *q) | 750 | static inline unsigned int blk_queue_nr_zones(struct request_queue *q) |
| 727 | { | 751 | { |
| @@ -737,6 +761,14 @@ static inline unsigned int blk_queue_zone_no(struct request_queue *q, · 9 unmodified lines | |||
| 737 | { | 761 | { |
| 738 | return 0; | 762 | return 0; |
| 739 | } | 763 | } |
| 764 | static inline unsigned int queue_max_open_zones(const struct request_queue *q) | ||
| 765 | { | ||
| 766 | return 0; | ||
| 767 | } | ||
| 768 | static inline unsigned int queue_max_active_zones(const struct request_queue *q) | ||
| 769 | { | ||
| 770 | return 0; | ||
| 771 | } | ||
| 740 | #endif /* CONFIG_BLK_DEV_ZONED */ | 772 | #endif /* CONFIG_BLK_DEV_ZONED */ |
| 741 | 773 | ||
| 742 | static inline bool rq_is_sync(struct request *rq) | 774 | static inline bool rq_is_sync(struct request *rq) |
| @@ -1519,6 +1551,24 @@ static inline sector_t bdev_zone_sectors(struct block_device *bdev) · 776 unmodified lines | |||
| 1519 | return 0; | 1551 | return 0; |
| 1520 | } | 1552 | } |
| 1521 | 1553 | ||
| 1554 | static inline unsigned int bdev_max_open_zones(struct block_device *bdev) | ||
| 1555 | { | ||
| 1556 | struct request_queue *q = bdev_get_queue(bdev); | ||
| 1557 | |||
| 1558 | if (q) | ||
| 1559 | return queue_max_open_zones(q); | ||
| 1560 | return 0; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | static inline unsigned int bdev_max_active_zones(struct block_device *bdev) | ||
| 1564 | { | ||
| 1565 | struct request_queue *q = bdev_get_queue(bdev); | ||
| 1566 | |||
| 1567 | if (q) | ||
| 1568 | return queue_max_active_zones(q); | ||
| 1569 | return 0; | ||
| 1570 | } | ||
| 1571 | |||
| 1522 | static inline int queue_dma_alignment(const struct request_queue *q) | 1572 | static inline int queue_dma_alignment(const struct request_queue *q) |
| 1523 | { | 1573 | { |
| 1524 | return q ? q->dma_alignment : 511; | 1574 | return q ? q->dma_alignment : 511; |
| @@ -132,6 +132,7 @@ enum { · 131 unmodified lines | |||
| 132 | #define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) | 132 | #define NVME_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff) |
| 133 | #define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) | 133 | #define NVME_CAP_STRIDE(cap) (((cap) >> 32) & 0xf) |
| 134 | #define NVME_CAP_NSSRC(cap) (((cap) >> 36) & 0x1) | 134 | #define NVME_CAP_NSSRC(cap) (((cap) >> 36) & 0x1) |
| 135 | #define NVME_CAP_CSS(cap) (((cap) >> 37) & 0xff) | ||
| 135 | #define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf) | 136 | #define NVME_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf) |
| 136 | #define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf) | 137 | #define NVME_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf) |
| 137 | 138 | ||
| @@ -162,7 +163,6 @@ enum { · 24 unmodified lines | |||
| 162 | 163 | ||
| 163 | enum { | 164 | enum { |
| 164 | NVME_CC_ENABLE = 1 << 0, | 165 | NVME_CC_ENABLE = 1 << 0, |
| 165 | NVME_CC_CSS_NVM = 0 << 4, | ||
| 166 | NVME_CC_EN_SHIFT = 0, | 166 | NVME_CC_EN_SHIFT = 0, |
| 167 | NVME_CC_CSS_SHIFT = 4, | 167 | NVME_CC_CSS_SHIFT = 4, |
| 168 | NVME_CC_MPS_SHIFT = 7, | 168 | NVME_CC_MPS_SHIFT = 7, |
| @@ -170,6 +170,9 @@ enum { · 1 unmodified line | |||
| 170 | NVME_CC_SHN_SHIFT = 14, | 170 | NVME_CC_SHN_SHIFT = 14, |
| 171 | NVME_CC_IOSQES_SHIFT = 16, | 171 | NVME_CC_IOSQES_SHIFT = 16, |
| 172 | NVME_CC_IOCQES_SHIFT = 20, | 172 | NVME_CC_IOCQES_SHIFT = 20, |
| 173 | NVME_CC_CSS_NVM = 0 << NVME_CC_CSS_SHIFT, | ||
| 174 | NVME_CC_CSS_CSI = 6 << NVME_CC_CSS_SHIFT, | ||
| 175 | NVME_CC_CSS_MASK = 7 << NVME_CC_CSS_SHIFT, | ||
| 173 | NVME_CC_AMS_RR = 0 << NVME_CC_AMS_SHIFT, | 176 | NVME_CC_AMS_RR = 0 << NVME_CC_AMS_SHIFT, |
| 174 | NVME_CC_AMS_WRRU = 1 << NVME_CC_AMS_SHIFT, | 177 | NVME_CC_AMS_WRRU = 1 << NVME_CC_AMS_SHIFT, |
| 175 | NVME_CC_AMS_VS = 7 << NVME_CC_AMS_SHIFT, | 178 | NVME_CC_AMS_VS = 7 << NVME_CC_AMS_SHIFT, |
| @@ -179,6 +182,8 @@ enum { · 3 unmodified lines | |||
| 179 | NVME_CC_SHN_MASK = 3 << NVME_CC_SHN_SHIFT, | 182 | NVME_CC_SHN_MASK = 3 << NVME_CC_SHN_SHIFT, |
| 180 | NVME_CC_IOSQES = NVME_NVM_IOSQES << NVME_CC_IOSQES_SHIFT, | 183 | NVME_CC_IOSQES = NVME_NVM_IOSQES << NVME_CC_IOSQES_SHIFT, |
| 181 | NVME_CC_IOCQES = NVME_NVM_IOCQES << NVME_CC_IOCQES_SHIFT, | 184 | NVME_CC_IOCQES = NVME_NVM_IOCQES << NVME_CC_IOCQES_SHIFT, |
| 185 | NVME_CAP_CSS_NVM = 1 << 0, | ||
| 186 | NVME_CAP_CSS_CSI = 1 << 6, | ||
| 182 | NVME_CSTS_RDY = 1 << 0, | 187 | NVME_CSTS_RDY = 1 << 0, |
| 183 | NVME_CSTS_CFS = 1 << 1, | 188 | NVME_CSTS_CFS = 1 << 1, |
| 184 | NVME_CSTS_NSSRO = 1 << 4, | 189 | NVME_CSTS_NSSRO = 1 << 4, |
| @@ -369,11 +374,37 @@ struct nvme_id_ns { · 184 unmodified lines | |||
| 369 | __u8 vs[3712]; | 374 | __u8 vs[3712]; |
| 370 | }; | 375 | }; |
| 371 | 376 | ||
| 377 | struct nvme_zns_lbafe { | ||
| 378 | __le64 zsze; | ||
| 379 | __u8 zdes; | ||
| 380 | __u8 rsvd9[7]; | ||
| 381 | }; | ||
| 382 | |||
| 383 | struct nvme_id_ns_zns { | ||
| 384 | __le16 zoc; | ||
| 385 | __le16 ozcs; | ||
| 386 | __le32 mar; | ||
| 387 | __le32 mor; | ||
| 388 | __le32 rrl; | ||
| 389 | __le32 frl; | ||
| 390 | __u8 rsvd20[2796]; | ||
| 391 | struct nvme_zns_lbafe lbafe[16]; | ||
| 392 | __u8 rsvd3072[768]; | ||
| 393 | __u8 vs[256]; | ||
| 394 | }; | ||
| 395 | |||
| 396 | struct nvme_id_ctrl_zns { | ||
| 397 | __u8 zasl; | ||
| 398 | __u8 rsvd1[4095]; | ||
| 399 | }; | ||
| 400 | |||
| 372 | enum { | 401 | enum { |
| 373 | NVME_ID_CNS_NS = 0x00, | 402 | NVME_ID_CNS_NS = 0x00, |
| 374 | NVME_ID_CNS_CTRL = 0x01, | 403 | NVME_ID_CNS_CTRL = 0x01, |
| 375 | NVME_ID_CNS_NS_ACTIVE_LIST = 0x02, | 404 | NVME_ID_CNS_NS_ACTIVE_LIST = 0x02, |
| 376 | NVME_ID_CNS_NS_DESC_LIST = 0x03, | 405 | NVME_ID_CNS_NS_DESC_LIST = 0x03, |
| 406 | NVME_ID_CNS_CS_NS = 0x05, | ||
| 407 | NVME_ID_CNS_CS_CTRL = 0x06, | ||
| 377 | NVME_ID_CNS_NS_PRESENT_LIST = 0x10, | 408 | NVME_ID_CNS_NS_PRESENT_LIST = 0x10, |
| 378 | NVME_ID_CNS_NS_PRESENT = 0x11, | 409 | NVME_ID_CNS_NS_PRESENT = 0x11, |
| 379 | NVME_ID_CNS_CTRL_NS_LIST = 0x12, | 410 | NVME_ID_CNS_CTRL_NS_LIST = 0x12, |
| @@ -383,6 +414,11 @@ enum { · 3 unmodified lines | |||
| 383 | NVME_ID_CNS_UUID_LIST = 0x17, | 414 | NVME_ID_CNS_UUID_LIST = 0x17, |
| 384 | }; | 415 | }; |
| 385 | 416 | ||
| 417 | enum { | ||
| 418 | NVME_CSI_NVM = 0, | ||
| 419 | NVME_CSI_ZNS = 2, | ||
| 420 | }; | ||
| 421 | |||
| 386 | enum { | 422 | enum { |
| 387 | NVME_DIR_IDENTIFY = 0x00, | 423 | NVME_DIR_IDENTIFY = 0x00, |
| 388 | NVME_DIR_STREAMS = 0x01, | 424 | NVME_DIR_STREAMS = 0x01, |
| @@ -435,11 +471,13 @@ struct nvme_ns_id_desc { · 46 unmodified lines | |||
| 435 | #define NVME_NIDT_EUI64_LEN 8 | 471 | #define NVME_NIDT_EUI64_LEN 8 |
| 436 | #define NVME_NIDT_NGUID_LEN 16 | 472 | #define NVME_NIDT_NGUID_LEN 16 |
| 437 | #define NVME_NIDT_UUID_LEN 16 | 473 | #define NVME_NIDT_UUID_LEN 16 |
| 474 | #define NVME_NIDT_CSI_LEN 1 | ||
| 438 | 475 | ||
| 439 | enum { | 476 | enum { |
| 440 | NVME_NIDT_EUI64 = 0x01, | 477 | NVME_NIDT_EUI64 = 0x01, |
| 441 | NVME_NIDT_NGUID = 0x02, | 478 | NVME_NIDT_NGUID = 0x02, |
| 442 | NVME_NIDT_UUID = 0x03, | 479 | NVME_NIDT_UUID = 0x03, |
| 480 | NVME_NIDT_CSI = 0x04, | ||
| 443 | }; | 481 | }; |
| 444 | 482 | ||
| 445 | struct nvme_smart_log { | 483 | struct nvme_smart_log { |
| @@ -519,6 +557,27 @@ struct nvme_ana_rsp_hdr { · 73 unmodified lines | |||
| 519 | __le16 rsvd10[3]; | 557 | __le16 rsvd10[3]; |
| 520 | }; | 558 | }; |
| 521 | 559 | ||
| 560 | struct nvme_zone_descriptor { | ||
| 561 | __u8 zt; | ||
| 562 | __u8 zs; | ||
| 563 | __u8 za; | ||
| 564 | __u8 rsvd3[5]; | ||
| 565 | __le64 zcap; | ||
| 566 | __le64 zslba; | ||
| 567 | __le64 wp; | ||
| 568 | __u8 rsvd32[32]; | ||
| 569 | }; | ||
| 570 | |||
| 571 | enum { | ||
| 572 | NVME_ZONE_TYPE_SEQWRITE_REQ = 0x2, | ||
| 573 | }; | ||
| 574 | |||
| 575 | struct nvme_zone_report { | ||
| 576 | __le64 nr_zones; | ||
| 577 | __u8 resv8[56]; | ||
| 578 | struct nvme_zone_descriptor entries[]; | ||
| 579 | }; | ||
| 580 | |||
| 522 | enum { | 581 | enum { |
| 523 | NVME_SMART_CRIT_SPARE = 1 << 0, | 582 | NVME_SMART_CRIT_SPARE = 1 << 0, |
| 524 | NVME_SMART_CRIT_TEMPERATURE = 1 << 1, | 583 | NVME_SMART_CRIT_TEMPERATURE = 1 << 1, |
| @@ -613,6 +672,9 @@ enum nvme_opcode { · 88 unmodified lines | |||
| 613 | nvme_cmd_resv_report = 0x0e, | 672 | nvme_cmd_resv_report = 0x0e, |
| 614 | nvme_cmd_resv_acquire = 0x11, | 673 | nvme_cmd_resv_acquire = 0x11, |
| 615 | nvme_cmd_resv_release = 0x15, | 674 | nvme_cmd_resv_release = 0x15, |
| 675 | nvme_cmd_zone_mgmt_send = 0x79, | ||
| 676 | nvme_cmd_zone_mgmt_recv = 0x7a, | ||
| 677 | nvme_cmd_zone_append = 0x7d, | ||
| 616 | }; | 678 | }; |
| 617 | 679 | ||
| 618 | #define nvme_opcode_name(opcode) { opcode, #opcode } | 680 | #define nvme_opcode_name(opcode) { opcode, #opcode } |
| @@ -751,6 +813,7 @@ struct nvme_rw_command { · 132 unmodified lines | |||
| 751 | enum { | 813 | enum { |
| 752 | NVME_RW_LR = 1 << 15, | 814 | NVME_RW_LR = 1 << 15, |
| 753 | NVME_RW_FUA = 1 << 14, | 815 | NVME_RW_FUA = 1 << 14, |
| 816 | NVME_RW_APPEND_PIREMAP = 1 << 9, | ||
| 754 | NVME_RW_DSM_FREQ_UNSPEC = 0, | 817 | NVME_RW_DSM_FREQ_UNSPEC = 0, |
| 755 | NVME_RW_DSM_FREQ_TYPICAL = 1, | 818 | NVME_RW_DSM_FREQ_TYPICAL = 1, |
| 756 | NVME_RW_DSM_FREQ_RARE = 2, | 819 | NVME_RW_DSM_FREQ_RARE = 2, |
| @@ -816,6 +879,53 @@ struct nvme_write_zeroes_cmd { · 59 unmodified lines | |||
| 816 | __le16 appmask; | 879 | __le16 appmask; |
| 817 | }; | 880 | }; |
| 818 | 881 | ||
| 882 | enum nvme_zone_mgmt_action { | ||
| 883 | NVME_ZONE_CLOSE = 0x1, | ||
| 884 | NVME_ZONE_FINISH = 0x2, | ||
| 885 | NVME_ZONE_OPEN = 0x3, | ||
| 886 | NVME_ZONE_RESET = 0x4, | ||
| 887 | NVME_ZONE_OFFLINE = 0x5, | ||
| 888 | NVME_ZONE_SET_DESC_EXT = 0x10, | ||
| 889 | }; | ||
| 890 | |||
| 891 | struct nvme_zone_mgmt_send_cmd { | ||
| 892 | __u8 opcode; | ||
| 893 | __u8 flags; | ||
| 894 | __u16 command_id; | ||
| 895 | __le32 nsid; | ||
| 896 | __le32 cdw2[2]; | ||
| 897 | __le64 metadata; | ||
| 898 | union nvme_data_ptr dptr; | ||
| 899 | __le64 slba; | ||
| 900 | __le32 cdw12; | ||
| 901 | __u8 zsa; | ||
| 902 | __u8 select_all; | ||
| 903 | __u8 rsvd13[2]; | ||
| 904 | __le32 cdw14[2]; | ||
| 905 | }; | ||
| 906 | |||
| 907 | struct nvme_zone_mgmt_recv_cmd { | ||
| 908 | __u8 opcode; | ||
| 909 | __u8 flags; | ||
| 910 | __u16 command_id; | ||
| 911 | __le32 nsid; | ||
| 912 | __le64 rsvd2[2]; | ||
| 913 | union nvme_data_ptr dptr; | ||
| 914 | __le64 slba; | ||
| 915 | __le32 numd; | ||
| 916 | __u8 zra; | ||
| 917 | __u8 zrasf; | ||
| 918 | __u8 pr; | ||
| 919 | __u8 rsvd13; | ||
| 920 | __le32 cdw14[2]; | ||
| 921 | }; | ||
| 922 | |||
| 923 | enum { | ||
| 924 | NVME_ZRA_ZONE_REPORT = 0, | ||
| 925 | NVME_ZRASF_ZONE_REPORT_ALL = 0, | ||
| 926 | NVME_REPORT_ZONE_PARTIAL = 1, | ||
| 927 | }; | ||
| 928 | |||
| 819 | /* Features */ | 929 | /* Features */ |
| 820 | 930 | ||
| 821 | enum { | 931 | enum { |
| @@ -972,7 +1082,9 @@ struct nvme_identify { · 150 unmodified lines | |||
| 972 | __u8 cns; | 1082 | __u8 cns; |
| 973 | __u8 rsvd3; | 1083 | __u8 rsvd3; |
| 974 | __le16 ctrlid; | 1084 | __le16 ctrlid; |
| 975 | __u32 rsvd11[5]; | 1085 | __u8 rsvd11[3]; |
| 1086 | __u8 csi; | ||
| 1087 | __u32 rsvd12[4]; | ||
| 976 | }; | 1088 | }; |
| 977 | 1089 | ||
| 978 | #define NVME_IDENTIFY_DATA_SIZE 4096 | 1090 | #define NVME_IDENTIFY_DATA_SIZE 4096 |
| @@ -1086,7 +1198,9 @@ struct nvme_get_log_page_command { · 107 unmodified lines | |||
| 1086 | }; | 1198 | }; |
| 1087 | __le64 lpo; | 1199 | __le64 lpo; |
| 1088 | }; | 1200 | }; |
| 1089 | __u32 rsvd14[2]; | 1201 | __u8 rsvd14[3]; |
| 1202 | __u8 csi; | ||
| 1203 | __u32 rsvd15; | ||
| 1090 | }; | 1204 | }; |
| 1091 | 1205 | ||
| 1092 | struct nvme_directive_cmd { | 1206 | struct nvme_directive_cmd { |
| @@ -1283,6 +1397,8 @@ struct nvme_command { · 190 unmodified lines | |||
| 1283 | struct nvme_format_cmd format; | 1397 | struct nvme_format_cmd format; |
| 1284 | struct nvme_dsm_cmd dsm; | 1398 | struct nvme_dsm_cmd dsm; |
| 1285 | struct nvme_write_zeroes_cmd write_zeroes; | 1399 | struct nvme_write_zeroes_cmd write_zeroes; |
| 1400 | struct nvme_zone_mgmt_send_cmd zms; | ||
| 1401 | struct nvme_zone_mgmt_recv_cmd zmr; | ||
| 1286 | struct nvme_abort_cmd abort; | 1402 | struct nvme_abort_cmd abort; |
| 1287 | struct nvme_get_log_page_command get_log_page; | 1403 | struct nvme_get_log_page_command get_log_page; |
| 1288 | struct nvmf_common_command fabrics; | 1404 | struct nvmf_common_command fabrics; |
| @@ -1416,6 +1532,18 @@ enum { · 127 unmodified lines | |||
| 1416 | NVME_SC_DISCOVERY_RESTART = 0x190, | 1532 | NVME_SC_DISCOVERY_RESTART = 0x190, |
| 1417 | NVME_SC_AUTH_REQUIRED = 0x191, | 1533 | NVME_SC_AUTH_REQUIRED = 0x191, |
| 1418 | 1534 | ||
| 1535 | /* | ||
| 1536 | * I/O Command Set Specific - Zoned commands: | ||
| 1537 | */ | ||
| 1538 | NVME_SC_ZONE_BOUNDARY_ERROR = 0x1b8, | ||
| 1539 | NVME_SC_ZONE_FULL = 0x1b9, | ||
| 1540 | NVME_SC_ZONE_READ_ONLY = 0x1ba, | ||
| 1541 | NVME_SC_ZONE_OFFLINE = 0x1bb, | ||
| 1542 | NVME_SC_ZONE_INVALID_WRITE = 0x1bc, | ||
| 1543 | NVME_SC_ZONE_TOO_MANY_ACTIVE = 0x1bd, | ||
| 1544 | NVME_SC_ZONE_TOO_MANY_OPEN = 0x1be, | ||
| 1545 | NVME_SC_ZONE_INVALID_TRANSITION = 0x1bf, | ||
| 1546 | |||
| 1419 | /* | 1547 | /* |
| 1420 | * Media and Data Integrity Errors: | 1548 | * Media and Data Integrity Errors: |
| 1421 | */ | 1549 | */ |