6.17.5-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainerPATCH 142/159 xfs: fix log CRC mismatches between i386 and other architectures
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <[email protected]>
[ Upstream commit e747883c7d7306acb4d683038d881528fbfbe749 ]
When mounting file systems with a log that was dirtied on i386 on other architectures or vice versa, log recovery is unhappy:
[ 11.068052] XFS (vdb): Torn write (CRC failure) detected at log block 0x2. Truncating head block from 0xc.
This is because the CRCs generated by i386 and other architectures always diff. The reason for that is that sizeof(struct xlog_rec_header) returns different values for i386 vs the rest (324 vs 328), because the struct is not sizeof(uint64_t) aligned, and i386 has odd struct size alignment rules.
This issue goes back to commit 13cdc853c519 ("Add log versioning, and new super block field for the log stripe") in the xfs-import tree, which adds log v2 support and the h_size field that causes the unaligned size. At that time it only mattered for the crude debug only log header checksum, but with commit 0e446be44806 ("xfs: add CRC checks to the log") it became a real issue for v5 file system, because now there is a proper CRC, and regular builds actually expect it match.
Fix this by allowing checksums with and without the padding.
--- fs/xfs/libxfs/xfs_log_format.h | 30 +++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_ondisk.h | 2 ++ fs/xfs/xfs_log.c | 8 ++++---- fs/xfs/xfs_log_priv.h | 4 ++-- fs/xfs/xfs_log_recover.c | 19 +++++++++++++++++-- 5 files changed, 54 insertions(+), 9 deletions(-)
fs/xfs/libxfs/xfs_log_format.h +29 -1
@@ -174,12 +174,40 @@ typedef struct xlog_rec_header {__be32 h_prev_block;/* block number to previous LR : 4 */ __be32 h_num_logops;/* number of log operations in this LR : 4 */ __be32 h_cycle_data[XLOG_HEADER_CYCLE_SIZE /BBSIZE ]; -/* new fields */ + +/* fields added by the Linux port: */ __be32 h_fmt;/* format of log record : 4 */ uuid_t h_fs_uuid;/* uuid of FS : 16 */ + +/* fields added for log v2: */ __be32 h_size;/* iclog size : 4 */ + +/* +* When h_size added for log v2 support, it caused structure to have +* a different size on i386 vs all other architectures because the +* sum of the size ofthe member is not aligned by that of the largest +* __be64-sized member, and i386 has really odd struct alignment rules. +* +* Due to the way the log headers are placed out on-disk that alone is +* not a problem becaue the xlog_rec_header always sits alone in a +* BBSIZEs area, and the rest of that area is padded with zeroes. +* But xlog_cksum used to calculate the checksum based on the structure +* size, and thus gives different checksums for i386 vs the rest. +* We now do two checksum validation passes for both sizes to allow +* moving v5 file systems with unclean logs between i386 and other +* (little-endian) architectures. +*/ +__u32 h_pad0; } xlog_rec_header_t; +#ifdef __i386__ +#define XLOG_REC_SIZE offsetofend(struct xlog_rec_header, h_size) +#define XLOG_REC_SIZE_OTHER sizeof(struct xlog_rec_header) +#else +#define XLOG_REC_SIZE sizeof(struct xlog_rec_header) +#define XLOG_REC_SIZE_OTHER offsetofend(struct xlog_rec_header, h_size) +#endif /* __i386__ */ + typedef struct xlog_rec_ext_header { __be32 xh_cycle; /* write cycle of log : 4 */ __be32 xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /* : 256 */
fs/xfs/libxfs/xfs_ondisk.h +2 -0
@@ -174,6 +174,8 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_rud_log_format, 16); XFS_CHECK_STRUCT_SIZE(struct xfs_map_extent, 32); XFS_CHECK_STRUCT_SIZE(struct xfs_phys_extent, 16); + XFS_CHECK_STRUCT_SIZE(struct xlog_rec_header, 328); + XFS_CHECK_STRUCT_SIZE(struct xlog_rec_ext_header, 260); XFS_CHECK_OFFSET(struct xfs_bui_log_format, bui_extents, 16); XFS_CHECK_OFFSET(struct xfs_cui_log_format, cui_extents, 16);
fs/xfs/xfs_log.c +4 -4
@@ -1568,13 +1568,13 @@ xlog_cksum(struct xlog *log, struct xlog_rec_header *rhead, char *dp, - int size) + unsigned int hdrsize, + unsigned int size) { uint32_t crc;/* first generate the crc for the record header ... */ - crc =xfs_start_cksum_update ((char *)rhead, -sizeof (struct xlog_rec_header ), + crc =xfs_start_cksum_update ((char *)rhead, hdrsize, offsetof(struct xlog_rec_header , h_crc));/* ... then for additional cycle data for v2 logs ... */
@@ -1818,7 +1818,7 @@ xlog_sync(/* calculcate the checksum */ iclog->ic_header.h_crc =xlog_cksum (log, &iclog->ic_header, - iclog->ic_datap, size); + iclog->ic_datap,XLOG_REC_SIZE , size);/* * Intentionally corrupt the log record CRC based on the error injection * frequency, if defined. This facilitates testing log recovery in the
fs/xfs/xfs_log_priv.h +2 -2
@@ -499,8 +499,8 @@ xlog_recover_finish(extern void xlog_recover_cancel (struct xlog *); -extern __le32 xlog_cksum (struct xlog *log,struct xlog_rec_header *rhead, -char *dp,int size); +__le32 xlog_cksum (struct xlog *log,struct xlog_rec_header *rhead, +char *dp,unsigned int hdrsize,unsigned int size);extern struct kmem_cache *xfs_log_ticket_cache; struct xlog_ticket *xlog_ticket_alloc(struct xlog *log, int unit_bytes,
fs/xfs/xfs_log_recover.c +17 -2
@@ -2894,9 +2894,24 @@ xlog_recover_process(int pass, struct list_head *buffer_list) { - __le32 expected_crc = rhead->h_crc, crc; + __le32 expected_crc = rhead->h_crc, crc, other_crc; - crc =xlog_cksum (log, rhead, dp,be32_to_cpu (rhead->h_len)); + crc =xlog_cksum (log, rhead, dp,XLOG_REC_SIZE , +be32_to_cpu (rhead->h_len)); + +/* +* Look at the end of the struct xlog_rec_header definition in +* xfs_log_format.h for the glory details. +*/ +if (expected_crc && crc != expected_crc) { + other_crc =xlog_cksum (log, rhead, dp,XLOG_REC_SIZE_OTHER , +be32_to_cpu (rhead->h_len)); +if (other_crc == expected_crc) { +xfs_notice_once (log->l_mp, +"Fixing up incorrect CRC due to padding." ); + crc = other_crc; + } + }/* * Nothing else to do if this is a CRC verification pass. Just return
Greg Kroah-Hartman
maintainerPATCH 143/159 NFSD: Rework encoding and decoding of nfsd4_deviceid
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit 832738e4b325b742940761e10487403f9aad13e8 ]
Compilers may optimize the layout of C structures, so we should not rely on sizeof struct and memcpy to encode and decode XDR structures. The byte order of the fields should also be taken into account.
This patch adds the correct functions to handle the deviceid4 structure and removes the pad field, which is currently not used by NFSD, from the runtime state. The server's byte order is preserved because the deviceid4 blob on the wire is only used as a cookie by the client.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/blocklayoutxdr.c | 7 ++----- fs/nfsd/flexfilelayoutxdr.c | 3 +-- fs/nfsd/nfs4layouts.c | 1 - fs/nfsd/nfs4xdr.c | 14 +------------- fs/nfsd/xdr4.h | 36 +++++++++++++++++++++++++++++++++++- 5 files changed, 39 insertions(+), 22 deletions(-)
fs/nfsd/blocklayoutxdr.c +2 -5
@@ -29,8 +29,7 @@ nfsd4_block_encode_layoutget(struct xdr_ *p++ =cpu_to_be32 (len); *p++ =cpu_to_be32 (1 );/* we always return a single extent */ - p =xdr_encode_opaque_fixed (p, &b->vol_id, -sizeof (struct nfsd4_deviceid )); + p =svcxdr_encode_deviceid4 (p, &b->vol_id); p =xdr_encode_hyper (p, b->foff); p =xdr_encode_hyper (p, b->len); p =xdr_encode_hyper (p, b->soff);
@@ -156,9 +155,7 @@ nfsd4_block_decode_layoutupdate(__be32 *for (i =0 ; i < nr_iomaps; i++) {struct pnfs_block_extent bex; -memcpy (&bex.vol_id, p,sizeof (struct nfsd4_deviceid )); - p +=XDR_QUADLEN (sizeof (struct nfsd4_deviceid )); - + p =svcxdr_decode_deviceid4 (p, &bex.vol_id); p =xdr_decode_hyper (p, &bex.foff);if (bex.foff & (block_size -1 )) { goto fail;
fs/nfsd/flexfilelayoutxdr.c +1 -2
@@ -54,8 +54,7 @@ nfsd4_ff_encode_layoutget(struct xdr_str *p++ =cpu_to_be32 (1 );/* single mirror */ *p++ =cpu_to_be32 (1 );/* single data server */ - p =xdr_encode_opaque_fixed (p, &fl->deviceid, -sizeof (struct nfsd4_deviceid )); + p =svcxdr_encode_deviceid4 (p, &fl->deviceid); *p++ =cpu_to_be32 (1 );/* efficiency */
fs/nfsd/nfs4layouts.c +0 -1
@@ -120,7 +120,6 @@ nfsd4_set_deviceid(struct nfsd4_deviceid id->fsid_idx = fhp->fh_export->ex_devid_map->idx; id->generation = device_generation; - id->pad =0 ;return 0 ; }
fs/nfsd/nfs4xdr.c +1 -13
@@ -588,18 +588,6 @@ nfsd4_decode_state_owner4(struct nfsd4_c }#ifdef CONFIG_NFSD_PNFS -static __be32 -nfsd4_decode_deviceid4 (struct nfsd4_compoundargs *argp, -struct nfsd4_deviceid *devid) -{ -__be32 *p; - - p =xdr_inline_decode (argp->xdr,NFS4_DEVICEID4_SIZE ); -if (!p) -return nfserr_bad_xdr; -memcpy (devid, p,sizeof (*devid)); -return nfs_ok; -} static __be32 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp,
@@ -1784,7 +1772,7 @@ nfsd4_decode_getdeviceinfo(struct nfsd4___be32 status;memset (gdev,0 ,sizeof (*gdev)); - status =nfsd4_decode_deviceid4 (argp, &gdev->gd_devid); + status =nfsd4_decode_deviceid4 (argp->xdr, &gdev->gd_devid);if (status)return status;if (xdr_stream_decode_u32 (argp->xdr, &gdev->gd_layout_type) <0 )
fs/nfsd/xdr4.h +35 -1
@@ -595,9 +595,43 @@ struct nfsd4_reclaim_complete {struct nfsd4_deviceid {u64 fsid_idx;u32 generation; -u32 pad; }; +static inline __be32 * +svcxdr_encode_deviceid4 (__be32 *p,const struct nfsd4_deviceid *devid) +{ +__be64 *q = (__be64 *)p; + + *q = (__force __be64 )devid->fsid_idx; + p +=2 ; + *p++ = (__force __be32 )devid->generation; + *p++ = xdr_zero; +return p; +} + +static inline __be32 * +svcxdr_decode_deviceid4 (__be32 *p,struct nfsd4_deviceid *devid) +{ +__be64 *q = (__be64 *)p; + + devid->fsid_idx = (__force u64)(*q); + p +=2 ; + devid->generation = (__force u32)(*p++); + p++;/* NFSD does not use the remaining octets */ +return p; +} + +static inline __be32 +nfsd4_decode_deviceid4 (struct xdr_stream *xdr,struct nfsd4_deviceid *devid) +{ +__be32 *p =xdr_inline_decode (xdr,NFS4_DEVICEID4_SIZE ); + +if (unlikely (!p)) +return nfserr_bad_xdr; +svcxdr_decode_deviceid4 (p, devid); +return nfs_ok; +} +struct nfsd4_layout_seg {u32 iomode;u64 offset;
Greg Kroah-Hartman
maintainerPATCH 144/159 NFSD: Minor cleanup in layoutcommit processing
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit 274365a51d88658fb51cca637ba579034e90a799 ]
Remove dprintk in nfsd4_layoutcommit. These are not needed in day to day usage, and the information is also available in Wireshark when capturing NFS traffic.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/nfs4proc.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
fs/nfsd/nfs4proc.c +3 -9
@@ -2521,18 +2521,12 @@ nfsd4_layoutcommit(struct svc_rqst *rqst inode =d_inode (current_fh->fh_dentry); nfserr = nfserr_inval; -if (new_size <= seg->offset) { -dprintk ("pnfsd: last write before layout segment\n" ); +if (new_size <= seg->offset) goto out; - } -if (new_size > seg->offset + seg->length) { -dprintk ("pnfsd: last write beyond layout segment\n" ); +if (new_size > seg->offset + seg->length) goto out; - } -if (!lcp->lc_newoffset && new_size >i_size_read (inode)) { -dprintk ("pnfsd: layoutcommit beyond EOF\n" ); +if (!lcp->lc_newoffset && new_size >i_size_read (inode)) goto out; - } nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid, false, lcp->lc_layout_type,
Greg Kroah-Hartman
maintainerPATCH 145/159 NFSD: Implement large extent array support in pNFS
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit f963cf2b91a30b5614c514f3ad53ca124cb65280 ]
When pNFS client in the block or scsi layout mode sends layoutcommit to MDS, a variable length array of modified extents is supplied within the request. This patch allows the server to accept such extent arrays if they do not fit within single memory page.
The issue can be reproduced when writing to a 1GB file using FIO with O_DIRECT, 4K block and large I/O depth without preallocation of the file. In this case, the server returns NFSERR_BADXDR to the client.
Stable-dep-of: d68886bae76a ("NFSD: Fix last write offset handling in layoutcommit")
--- fs/nfsd/blocklayout.c | 20 ++++++----- fs/nfsd/blocklayoutxdr.c | 83 +++++++++++++++++++++++++++++++---------------- fs/nfsd/blocklayoutxdr.h | 4 +- fs/nfsd/nfs4proc.c | 2 - fs/nfsd/nfs4xdr.c | 11 ++---- fs/nfsd/pnfs.h | 1 fs/nfsd/xdr4.h | 3 - 7 files changed, 78 insertions(+), 46 deletions(-)
fs/nfsd/blocklayout.c +12 -8
@@ -173,16 +173,18 @@ nfsd4_block_proc_getdeviceinfo(struct su }static __be32 -nfsd4_block_proc_layoutcommit (struct inode *inode, +nfsd4_block_proc_layoutcommit (struct inode *inode,struct svc_rqst *rqstp,struct nfsd4_layoutcommit *lcp) {struct iomap *iomaps;int nr_iomaps;__be32 nfserr; - nfserr =nfsd4_block_decode_layoutupdate (lcp->lc_up_layout, - lcp->lc_up_len, &iomaps, &nr_iomaps, -i_blocksize (inode)); + rqstp->rq_arg = lcp->lc_up_layout; +svcxdr_init_decode (rqstp); + + nfserr =nfsd4_block_decode_layoutupdate (&rqstp->rq_arg_stream, + &iomaps, &nr_iomaps,i_blocksize (inode));if (nfserr != nfs_ok)return nfserr;
@@ -313,16 +315,18 @@ nfsd4_scsi_proc_getdeviceinfo(struct supreturn nfserrno (nfsd4_block_get_device_info_scsi (sb, clp, gdp)); }static __be32 -nfsd4_scsi_proc_layoutcommit (struct inode *inode, +nfsd4_scsi_proc_layoutcommit (struct inode *inode,struct svc_rqst *rqstp,struct nfsd4_layoutcommit *lcp) {struct iomap *iomaps;int nr_iomaps;__be32 nfserr; - nfserr =nfsd4_scsi_decode_layoutupdate (lcp->lc_up_layout, - lcp->lc_up_len, &iomaps, &nr_iomaps, -i_blocksize (inode)); + rqstp->rq_arg = lcp->lc_up_layout; +svcxdr_init_decode (rqstp); + + nfserr =nfsd4_scsi_decode_layoutupdate (&rqstp->rq_arg_stream, + &iomaps, &nr_iomaps,i_blocksize (inode));if (nfserr != nfs_ok)return nfserr;
fs/nfsd/blocklayoutxdr.c +56 -27
163 lines not on this page · raw message
fs/nfsd/blocklayoutxdr.h +2 -2
@@ -54,9 +54,9 @@ __be32 nfsd4_block_encode_getdeviceinfo( const struct nfsd4_getdeviceinfo *gdp);__be32 nfsd4_block_encode_layoutget (struct xdr_stream *xdr,const struct nfsd4_layoutget *lgp); -__be32 nfsd4_block_decode_layoutupdate (__be32 *p,u32 len, +__be32 nfsd4_block_decode_layoutupdate (struct xdr_stream *xdr,struct iomap **iomapp,int *nr_iomapsp,u32 block_size); -__be32 nfsd4_scsi_decode_layoutupdate (__be32 *p,u32 len, +__be32 nfsd4_scsi_decode_layoutupdate (struct xdr_stream *xdr,struct iomap **iomapp,int *nr_iomapsp,u32 block_size);#endif /* _NFSD_BLOCKLAYOUTXDR_H */
fs/nfsd/nfs4proc.c +1 -1
@@ -2549,7 +2549,7 @@ nfsd4_layoutcommit(struct svc_rqst *rqst lcp->lc_size_chg = false; } - nfserr = ops->proc_layoutcommit (inode, lcp); + nfserr = ops->proc_layoutcommit (inode, rqstp, lcp);nfs4_put_stid (&ls->ls_stid); out:return nfserr;
fs/nfsd/nfs4xdr.c +5 -6
@@ -593,6 +593,8 @@ static __be32 nfsd4_decode_layoutupdate4(struct nfsd4_compoundargs *argp, struct nfsd4_layoutcommit *lcp) { + u32 len; +if (xdr_stream_decode_u32 (argp->xdr, &lcp->lc_layout_type) <0 )return nfserr_bad_xdr;if (lcp->lc_layout_type <LAYOUT_NFSV4_1_FILES )
@@ -600,13 +602,10 @@ nfsd4_decode_layoutupdate4(struct nfsd4_if (lcp->lc_layout_type >=LAYOUT_TYPE_MAX )return nfserr_bad_xdr; -if (xdr_stream_decode_u32 (argp->xdr, &lcp->lc_up_len) <0 ) +if (xdr_stream_decode_u32 (argp->xdr, &len) <0 ) +return nfserr_bad_xdr; +if (!xdr_stream_subsegment (argp->xdr, &lcp->lc_up_layout, len))return nfserr_bad_xdr; -if (lcp->lc_up_len >0 ) { - lcp->lc_up_layout =xdr_inline_decode (argp->xdr, lcp->lc_up_len); -if (!lcp->lc_up_layout) -return nfserr_bad_xdr; - }return nfs_ok; }
fs/nfsd/pnfs.h +1 -0
@@ -35,6 +35,7 @@ struct nfsd4_layout_ops { const struct nfsd4_layoutget *lgp);__be32 (*proc_layoutcommit)(struct inode *inode, +struct svc_rqst *rqstp,struct nfsd4_layoutcommit *lcp); void (*fence_client)(struct nfs4_layout_stateid *ls,
fs/nfsd/xdr4.h +1 -2
@@ -664,8 +664,7 @@ struct nfsd4_layoutcommit {u64 lc_last_wr;/* request */ struct timespec64 lc_mtime;/* request */ u32 lc_layout_type;/* request */ -u32 lc_up_len;/* layout length */ -void *lc_up_layout;/* decoded by callback */ +struct xdr_buf lc_up_layout;/* decoded by callback */ bool lc_size_chg;/* response */ u64 lc_newsize;/* response */ };
Greg Kroah-Hartman
maintainerPATCH 146/159 NFSD: Fix last write offset handling in layoutcommit
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Bashirov <[email protected]>
[ Upstream commit d68886bae76a4b9b3484d23e5b7df086f940fa38 ]
The data type of loca_last_write_offset is newoffset4 and is switched on a boolean value, no_newoffset, that indicates if a previous write occurred or not. If no_newoffset is FALSE, an offset is not given. This means that client does not try to update the file size. Thus, server should not try to calculate new file size and check if it fits into the segment range. See RFC 8881, section 12.5.4.2.
Sometimes the current incorrect logic may cause clients to hang when trying to sync an inode. If layoutcommit fails, the client marks the inode as dirty again.
--- fs/nfsd/blocklayout.c | 5 ++--- fs/nfsd/nfs4proc.c | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 18 deletions(-)
fs/nfsd/blocklayout.c +2 -3
@@ -118,7 +118,6 @@ nfsd4_block_commit_blocks(struct inode * struct iomap *iomaps, int nr_iomaps) {struct timespec64 mtime =inode_get_mtime (inode); -loff_t new_size = lcp->lc_last_wr +1 ;struct iattr iattr = { .ia_valid =0 };int error;
@@ -128,9 +127,9 @@ nfsd4_block_commit_blocks(struct inode * iattr.ia_valid |=ATTR_ATIME |ATTR_CTIME |ATTR_MTIME ; iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime; -if (new_size >i_size_read (inode)) { +if (lcp->lc_size_chg) { iattr.ia_valid |=ATTR_SIZE ; - iattr.ia_size = new_size; + iattr.ia_size = lcp->lc_newsize; } error = inode->i_sb->s_export_op->commit_blocks(inode, iomaps,
fs/nfsd/nfs4proc.c +15 -15
@@ -2504,7 +2504,6 @@ nfsd4_layoutcommit(struct svc_rqst *rqstconst struct nfsd4_layout_seg *seg = &lcp->lc_seg;struct svc_fh *current_fh = &cstate->current_fh;const struct nfsd4_layout_ops *ops; -loff_t new_size = lcp->lc_last_wr +1 ;struct inode *inode;struct nfs4_layout_stateid *ls;__be32 nfserr;
@@ -2520,13 +2519,21 @@ nfsd4_layoutcommit(struct svc_rqst *rqst goto out; inode =d_inode (current_fh->fh_dentry); - nfserr = nfserr_inval; -if (new_size <= seg->offset) - goto out; -if (new_size > seg->offset + seg->length) - goto out; -if (!lcp->lc_newoffset && new_size >i_size_read (inode)) - goto out; + lcp->lc_size_chg = false; +if (lcp->lc_newoffset) { +loff_t new_size = lcp->lc_last_wr +1 ; + + nfserr = nfserr_inval; +if (new_size <= seg->offset) + goto out; +if (new_size > seg->offset + seg->length) + goto out; + +if (new_size >i_size_read (inode)) { + lcp->lc_size_chg = true; + lcp->lc_newsize = new_size; + } + } nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid, false, lcp->lc_layout_type,
@@ -2542,13 +2549,6 @@ nfsd4_layoutcommit(struct svc_rqst *rqst/* LAYOUTCOMMIT does not require any serialization */ mutex_unlock (&ls->ls_mutex); -if (new_size >i_size_read (inode)) { - lcp->lc_size_chg = true; - lcp->lc_newsize = new_size; - }else { - lcp->lc_size_chg = false; - } - nfserr = ops->proc_layoutcommit (inode, rqstp, lcp);nfs4_put_stid (&ls->ls_stid); out:
Greg Kroah-Hartman
maintainerPATCH 147/159 phy: cdns-dphy: Store hs_clk_rate and return it
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomi Valkeinen <[email protected]>
[ Upstream commit 689a54acb56858c85de8c7285db82b8ae6dbf683 ]
The DPHY driver does not return the actual hs_clk_rate, so the DSI driver has no idea what clock was actually achieved. Set the realized hs_clk_rate to the opts struct, so that the DSI driver gets it back.
Stable-dep-of: 284fb19a3ffb ("phy: cadence: cdns-dphy: Fix PLL lock and O_CMN_READY polling")
--- drivers/phy/cadence/cdns-dphy.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/phy/cadence/cdns-dphy.c +5 -0
@@ -79,6 +79,7 @@ struct cdns_dphy_cfg {u8 pll_ipdiv;u8 pll_opdiv;u16 pll_fbdiv; +u32 hs_clk_rate;unsigned int nlanes; };
@@ -154,6 +155,9 @@ static int cdns_dsi_get_dphy_pll_cfg(str cfg->pll_ipdiv, pll_ref_hz); + cfg->hs_clk_rate =div_u64 ((u64 )pll_ref_hz * cfg->pll_fbdiv, +2 * cfg->pll_opdiv * cfg->pll_ipdiv); +return 0 ; }
@@ -297,6 +301,7 @@ static int cdns_dphy_config_from_opts(stif (ret)return ret; + opts->hs_clk_rate = cfg->hs_clk_rate; opts->wakeup =cdns_dphy_get_wakeup_time_ns (dphy) /1000 ;return 0 ;
Greg Kroah-Hartman
maintainerPATCH 148/159 phy: cadence: cdns-dphy: Fix PLL lock and O_CMN_READY polling
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devarsh Thakkar <[email protected]>
[ Upstream commit 284fb19a3ffb1083c3ad9c00d29749d09dddb99c ]
PLL lockup and O_CMN_READY assertion can only happen after common state machine gets enabled by programming DPHY_CMN_SSM register, but driver was polling them before the common state machine was enabled which is incorrect. This is as per the DPHY initialization sequence as mentioned in J721E TRM [1] at section "12.7.2.4.1.2.1 Start-up Sequence Timing Diagram". It shows O_CMN_READY polling at the end after common configuration pin setup where the common configuration pin setup step enables state machine as referenced in "Table 12-1533. Common Configuration-Related Setup mentions state machine"
To fix this :
- Add new function callbacks for polling on PLL lock and O_CMN_READY assertion.
- As state machine and clocks get enabled in power_on callback only, move the clock related programming part from configure callback to power_on
callback and poll for the PLL lockup and O_CMN_READY assertion after state machine gets enabled.
- The configure callback only saves the PLL configuration received from the client driver which will be applied later on in power_on callback.
- Add checks to ensure configure is called before power_on and state machine is in disabled state before power_on callback is called.
- Disable state machine in power_off so that client driver can re-configure the PLL by following up a power_off, configure, power_on sequence.
[1]: https://www.ti.com/lit/zip/spruil1
--- drivers/phy/cadence/cdns-dphy.c | 124 +++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 32 deletions(-)
drivers/phy/cadence/cdns-dphy.c +92 -32
@@ -100,6 +100,8 @@ struct cdns_dphy_ops {void (*set_pll_cfg)(struct cdns_dphy *dphy,const struct cdns_dphy_cfg *cfg);unsigned long (*get_wakeup_time_ns)(struct cdns_dphy *dphy); +int (*wait_for_pll_lock)(struct cdns_dphy *dphy); +int (*wait_for_cmn_ready)(struct cdns_dphy *dphy); };struct cdns_dphy {
@@ -109,6 +111,8 @@ struct cdns_dphy {struct clk *pll_ref_clk;const struct cdns_dphy_ops *ops;struct phy *phy; +bool is_configured; +bool is_powered; };/* Order of bands is important since the index is the band number. */
@@ -195,6 +199,16 @@ static unsigned long cdns_dphy_get_wakeureturn dphy->ops->get_wakeup_time_ns (dphy); } +static int cdns_dphy_wait_for_pll_lock (struct cdns_dphy *dphy) +{ +return dphy->ops->wait_for_pll_lock ? dphy->ops->wait_for_pll_lock (dphy) :0 ; +} + +static int cdns_dphy_wait_for_cmn_ready (struct cdns_dphy *dphy) +{ +return dphy->ops->wait_for_cmn_ready ? dphy->ops->wait_for_cmn_ready (dphy) :0 ; +} +static unsigned long cdns_dphy_ref_get_wakeup_time_ns (struct cdns_dphy *dphy) {/* Default wakeup time is 800 ns (in a simulated environment). */
@@ -236,7 +250,6 @@ static unsigned long cdns_dphy_j721e_getstatic void cdns_dphy_j721e_set_pll_cfg (struct cdns_dphy *dphy,const struct cdns_dphy_cfg *cfg) { -u32 status;/* * set the PWM and PLL Byteclk divider settings to recommended values
@@ -253,13 +266,6 @@ static void cdns_dphy_j721e_set_pll_cfg(writel (DPHY_TX_J721E_WIZ_LANE_RSTB , dphy->regs +DPHY_TX_J721E_WIZ_RST_CTRL ); - -readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_PLL_CTRL , status, - (status &DPHY_TX_WIZ_PLL_LOCK ),0 ,POLL_TIMEOUT_US ); - -readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_STATUS , status, - (status &DPHY_TX_WIZ_O_CMN_READY ),0 , -POLL_TIMEOUT_US ); }static void cdns_dphy_j721e_set_psm_div (struct cdns_dphy *dphy,u8 div)
@@ -267,6 +273,23 @@ static void cdns_dphy_j721e_set_psm_div(writel (div, dphy->regs +DPHY_TX_J721E_WIZ_PSM_FREQ ); } +static int cdns_dphy_j721e_wait_for_pll_lock (struct cdns_dphy *dphy) +{ +u32 status; + +return readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_PLL_CTRL , status, + status &DPHY_TX_WIZ_PLL_LOCK ,0 ,POLL_TIMEOUT_US ); +} + +static int cdns_dphy_j721e_wait_for_cmn_ready (struct cdns_dphy *dphy) +{ +u32 status; + +return readl_poll_timeout (dphy->regs +DPHY_TX_J721E_WIZ_STATUS , status, + status &DPHY_TX_WIZ_O_CMN_READY ,0 , +POLL_TIMEOUT_US ); +} +/* * This is the reference implementation of DPHY hooks. Specific integration of * this IP may have to re-implement some of them depending on how they decided
@@ -282,6 +305,8 @@ static const struct cdns_dphy_ops j721e_ .get_wakeup_time_ns = cdns_dphy_j721e_get_wakeup_time_ns, .set_pll_cfg = cdns_dphy_j721e_set_pll_cfg, .set_psm_div = cdns_dphy_j721e_set_psm_div, + .wait_for_pll_lock = cdns_dphy_j721e_wait_for_pll_lock, + .wait_for_cmn_ready = cdns_dphy_j721e_wait_for_cmn_ready, }; static int cdns_dphy_config_from_opts(struct phy *phy,
@@ -339,21 +364,36 @@ static int cdns_dphy_validate(struct phystatic int cdns_dphy_configure (struct phy *phy,union phy_configure_opts *opts) {struct cdns_dphy *dphy =phy_get_drvdata (phy); -struct cdns_dphy_cfg cfg = {0 }; -int ret, band_ctrl; -unsigned int reg; +int ret; - ret =cdns_dphy_config_from_opts (phy, &opts->mipi_dphy, &cfg); -if (ret) -return ret; + ret =cdns_dphy_config_from_opts (phy, &opts->mipi_dphy, &dphy->cfg); +if (!ret) + dphy->is_configured = true; + +return ret; +} + +static int cdns_dphy_power_on (struct phy *phy) +{ +struct cdns_dphy *dphy =phy_get_drvdata (phy); +int ret; +u32 reg; + +if (!dphy->is_configured || dphy->is_powered) +return -EINVAL ; + +clk_prepare_enable (dphy->psm_clk); +clk_prepare_enable (dphy->pll_ref_clk);/* * Configure the internal PSM clk divider so that the DPHY has a * 1MHz clk (or something close). */ ret =cdns_dphy_setup_psm (dphy); -if (ret) -return ret; +if (ret) { +dev_err (&dphy->phy->dev,"Failed to setup PSM with error %d\n" , ret); + goto err_power_on; + }/* * Configure attach clk lanes to data lanes: the DPHY has 2 clk lanes
@@ -368,40 +408,60 @@ static int cdns_dphy_configure(struct ph* Configure the DPHY PLL that will be used to generate the TX byte * clk. */ -cdns_dphy_set_pll_cfg (dphy, &cfg); +cdns_dphy_set_pll_cfg (dphy, &dphy->cfg); - band_ctrl =cdns_dphy_tx_get_band_ctrl (opts->mipi_dphy.hs_clk_rate); -if (band_ctrl <0 ) -return band_ctrl; + ret =cdns_dphy_tx_get_band_ctrl (dphy->cfg.hs_clk_rate); +if (ret <0 ) { +dev_err (&dphy->phy->dev,"Failed to get band control value with error %d\n" , ret); + goto err_power_on; + } - reg =FIELD_PREP (DPHY_BAND_CFG_LEFT_BAND , band_ctrl) | -FIELD_PREP (DPHY_BAND_CFG_RIGHT_BAND , band_ctrl); + reg =FIELD_PREP (DPHY_BAND_CFG_LEFT_BAND , ret) | +FIELD_PREP (DPHY_BAND_CFG_RIGHT_BAND , ret);writel (reg, dphy->regs +DPHY_BAND_CFG ); -return 0 ; -} - -static int cdns_dphy_power_on (struct phy *phy) -{ -struct cdns_dphy *dphy =phy_get_drvdata (phy); - -clk_prepare_enable (dphy->psm_clk); -clk_prepare_enable (dphy->pll_ref_clk); -/* Start TX state machine. */ writel (DPHY_CMN_SSM_EN |DPHY_CMN_TX_MODE_EN , dphy->regs +DPHY_CMN_SSM ); + ret =cdns_dphy_wait_for_pll_lock (dphy); +if (ret) { +dev_err (&dphy->phy->dev,"Failed to lock PLL with error %d\n" , ret); + goto err_power_on; + } + + ret =cdns_dphy_wait_for_cmn_ready (dphy); +if (ret) { +dev_err (&dphy->phy->dev,"O_CMN_READY signal failed to assert with error %d\n" , + ret); + goto err_power_on; + } + + dphy->is_powered = true; +return 0 ; + +err_power_on: +clk_disable_unprepare (dphy->pll_ref_clk); +clk_disable_unprepare (dphy->psm_clk); + +return ret; }static int cdns_dphy_power_off (struct phy *phy) {struct cdns_dphy *dphy =phy_get_drvdata (phy); +u32 reg;clk_disable_unprepare (dphy->pll_ref_clk);clk_disable_unprepare (dphy->psm_clk); +/* Stop TX state machine. */ + reg =readl (dphy->regs +DPHY_CMN_SSM ); +writel (reg & ~DPHY_CMN_SSM_EN , dphy->regs +DPHY_CMN_SSM ); + + dphy->is_powered = false; +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 149/159 NFSD: Define a proc_layoutcommit for the FlexFiles layout type
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 4b47a8601b71ad98833b447d465592d847b4dc77 ]
Avoid a crash if a pNFS client should happen to send a LAYOUTCOMMIT operation on a FlexFiles layout.
--- fs/nfsd/flexfilelayout.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/nfsd/flexfilelayout.c +8 -0
@@ -125,6 +125,13 @@ nfsd4_ff_proc_getdeviceinfo(struct superreturn 0 ; } +static __be32 +nfsd4_ff_proc_layoutcommit (struct inode *inode,struct svc_rqst *rqstp, +struct nfsd4_layoutcommit *lcp) +{ +return nfs_ok; +} +const struct nfsd4_layout_ops ff_layout_ops = { .notify_types =NOTIFY_DEVICEID4_DELETE |NOTIFY_DEVICEID4_CHANGE ,
@@ -133,4 +140,5 @@ const struct nfsd4_layout_ops ff_layout_ .encode_getdeviceinfo = nfsd4_ff_encode_getdeviceinfo, .proc_layoutget = nfsd4_ff_proc_layoutget, .encode_layoutget = nfsd4_ff_encode_layoutget, + .proc_layoutcommit = nfsd4_ff_proc_layoutcommit, };
Greg Kroah-Hartman
maintainerPATCH 150/159 x86/resctrl: Refactor resctrl_arch_rmid_read()
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babu Moger <[email protected]>
[ Upstream commit 7c9ac605e202c4668e441fc8146a993577131ca1 ]
resctrl_arch_rmid_read() adjusts the value obtained from MSR_IA32_QM_CTR to account for the overflow for MBM events and apply counter scaling for all the events. This logic is common to both reading an RMID and reading a hardware counter directly.
Refactor the hardware value adjustment logic into get_corrected_val() to prepare for support of reading a hardware counter.
Stable-dep-of: 15292f1b4c55 ("x86/resctrl: Fix miscount of bandwidth event when reactivating previously unavailable RMID")
--- arch/x86/kernel/cpu/resctrl/monitor.c | 38 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-)
arch/x86/kernel/cpu/resctrl/monitor.c +23 -15
@@ -224,24 +224,13 @@ static u64 mbm_overflow_count(u64 prev_mreturn chunks >> shift; } -int resctrl_arch_rmid_read (struct rdt_resource *r,struct rdt_mon_domain *d, -u32 unused,u32 rmid,enum resctrl_event_id eventid, -u64 *val,void *ignored) +static u64 get_corrected_val (struct rdt_resource *r,struct rdt_mon_domain *d, +u32 rmid,enum resctrl_event_id eventid,u64 msr_val) {struct rdt_hw_mon_domain *hw_dom =resctrl_to_arch_mon_dom (d);struct rdt_hw_resource *hw_res =resctrl_to_arch_res (r); -int cpu =cpumask_any (&d->hdr.cpu_mask);struct arch_mbm_state *am; -u64 msr_val, chunks; -u32 prmid; -int ret; - -resctrl_arch_rmid_read_context_check (); - - prmid =logical_rmid_to_physical_rmid (cpu, rmid); - ret =__rmid_read_phys (prmid, eventid, &msr_val); -if (ret) -return ret; +u64 chunks; am =get_arch_mbm_state (hw_dom, rmid, eventid);if (am) {
@@ -253,7 +242,26 @@ int resctrl_arch_rmid_read(struct rdt_re chunks = msr_val; } - *val = chunks * hw_res->mon_scale; +return chunks * hw_res->mon_scale; +} + +int resctrl_arch_rmid_read (struct rdt_resource *r,struct rdt_mon_domain *d, +u32 unused,u32 rmid,enum resctrl_event_id eventid, +u64 *val,void *ignored) +{ +int cpu =cpumask_any (&d->hdr.cpu_mask); +u64 msr_val; +u32 prmid; +int ret; + +resctrl_arch_rmid_read_context_check (); + + prmid =logical_rmid_to_physical_rmid (cpu, rmid); + ret =__rmid_read_phys (prmid, eventid, &msr_val); +if (ret) +return ret; + + *val =get_corrected_val (r, d, rmid, eventid, msr_val);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 151/159 x86/resctrl: Fix miscount of bandwidth event when reactivating previously unavailable RMID
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Babu Moger <[email protected]>
[ Upstream commit 15292f1b4c55a3a7c940dbcb6cb8793871ed3d92 ]
Users can create as many monitoring groups as the number of RMIDs supported by the hardware. However, on AMD systems, only a limited number of RMIDs are guaranteed to be actively tracked by the hardware. RMIDs that exceed this limit are placed in an "Unavailable" state.
When a bandwidth counter is read for such an RMID, the hardware sets MSR_IA32_QM_CTR.Unavailable (bit 62). When such an RMID starts being tracked again the hardware counter is reset to zero. MSR_IA32_QM_CTR.Unavailable remains set on first read after tracking re-starts and is clear on all subsequent reads as long as the RMID is tracked.
resctrl miscounts the bandwidth events after an RMID transitions from the "Unavailable" state back to being tracked. This happens because when the hardware starts counting again after resetting the counter to zero, resctrl in turn compares the new count against the counter value stored from the previous time the RMID was tracked.
This results in resctrl computing an event value that is either undercounting (when new counter is more than stored counter) or a mistaken overflow (when new counter is less than stored counter).
Reset the stored value (arch_mbm_state::prev_msr) of MSR_IA32_QM_CTR to zero whenever the RMID is in the "Unavailable" state to ensure accurate counting after the RMID resets to zero when it starts to be tracked again.
Example scenario that results in mistaken overflow
==================================================
1. The resctrl filesystem is mounted, and a task is assigned to a monitoring group.
$mount -t resctrl resctrl /sys/fs/resctrl $mkdir /sys/fs/resctrl/mon_groups/test1/ $echo 1234 > /sys/fs/resctrl/mon_groups/test1/tasks
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes
21323 <- Total bytes on domain 0
"Unavailable" <- Total bytes on domain 1
Task is running on domain 0. Counter on domain 1 is "Unavailable".
2. The task runs on domain 0 for a while and then moves to domain 1. The counter starts incrementing on domain 1.
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes
7345357 <- Total bytes on domain 0
4545 <- Total bytes on domain 1
3. At some point, the RMID in domain 0 transitions to the "Unavailable" state because the task is no longer executing in that domain.
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes
"Unavailable" <- Total bytes on domain 0
434341 <- Total bytes on domain 1
4. Since the task continues to migrate between domains, it may eventually return to domain 0.
$cat /sys/fs/resctrl/mon_groups/test1/mon_data/mon_L3_*/mbm_total_bytes 17592178699059 <- Overflow on domain 0
3232332 <- Total bytes on domain 1
In this case, the RMID on domain 0 transitions from "Unavailable" state to active state. The hardware sets MSR_IA32_QM_CTR.Unavailable (bit 62) when the counter is read and begins tracking the RMID counting from 0.
Subsequent reads succeed but return a value smaller than the previously saved MSR value (7345357). Consequently, the resctrl's overflow logic is triggered, it compares the previous value (7345357) with the new, smaller value and incorrectly interprets this as a counter overflow, adding a large delta.
In reality, this is a false positive: the counter did not overflow but was simply reset when the RMID transitioned from "Unavailable" back to active state.
Here is the text from APM [1] available from [2].
"In PQOS Version 2.0 or higher, the MBM hardware will set the U bit on the first QM_CTR read when it begins tracking an RMID that it was not previously tracking. The U bit will be zero for all subsequent reads from that RMID while it is still tracked by the hardware. Therefore, a QM_CTR read with the U bit set when that RMID is in use by a processor can be considered 0 when calculating the difference with a subsequent read."
[1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.3.3 Monitoring L3 Memory Bandwidth (MBM).
[ bp: Split commit message into smaller paragraph chunks for better
consumption. ]
--- arch/x86/kernel/cpu/resctrl/monitor.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
arch/x86/kernel/cpu/resctrl/monitor.c +10 -4
@@ -249,7 +249,9 @@ int resctrl_arch_rmid_read(struct rdt_re u32 unused, u32 rmid, enum resctrl_event_id eventid, u64 *val, void *ignored) { + struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d);int cpu =cpumask_any (&d->hdr.cpu_mask); +struct arch_mbm_state *am;u64 msr_val;u32 prmid;int ret;
@@ -258,12 +260,16 @@ int resctrl_arch_rmid_read(struct rdt_re prmid =logical_rmid_to_physical_rmid (cpu, rmid); ret =__rmid_read_phys (prmid, eventid, &msr_val); -if (ret) -return ret; - *val =get_corrected_val (r, d, rmid, eventid, msr_val); +if (!ret) { + *val =get_corrected_val (r, d, rmid, eventid, msr_val); + }else if (ret == -EINVAL ) { + am =get_arch_mbm_state (hw_dom, rmid, eventid); +if (am) + am->prev_msr =0 ; + } -return 0 ; +return ret; }/*
Greg Kroah-Hartman
maintainerPATCH 152/159 cxl: Fix match_region_by_range() to use region_res_match_cxl_range()
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit f4d027921c811ff7fc16e4d03c6bbbf4347cf37a ]
match_region_by_range() is not using the helper function that also takes extended linear cache size into account when comparing regions. This causes a x2 region to show up as 2 partial incomplete regions rather than a single CXL region with extended linear cache support. Replace the open coded compare logic with the proper helper function for comparison. User visible impact is that when 'cxl list' is issued, no activa CXL region(s) are shown. There may be multiple idle regions present. No actual active CXL region is present in the kernel.
[dj: Fix stable address]
--- drivers/cxl/core/region.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/cxl/core/region.c +2 -5
@@ -831,7 +831,7 @@ static int match_free_decoder(struct dev }static bool region_res_match_cxl_range (const struct cxl_region_params *p, -struct range *range) +const struct range *range) {if (!p->res)return false;
@@ -3287,10 +3287,7 @@ static int match_region_by_range(struct p = &cxlr->params;guard (rwsem_read)(&cxl_rwsem.region); -if (p->res && p->res->start == r->start && p->res->end == r->end) -return 1 ; - -return 0 ; +return region_res_match_cxl_range (p, r); } static int cxl_extended_linear_cache_resize(struct cxl_region *cxlr,
Greg Kroah-Hartman
maintainerPATCH 153/159 phy: cadence: cdns-dphy: Update calibration wait time for startup state machine
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devarsh Thakkar <[email protected]>
[ Upstream commit 2c27aaee934a1b5229152fe33a14f1fdf50da143 ]
Do read-modify-write so that we re-use the characterized reset value as specified in TRM [1] to program calibration wait time which defines number of cycles to wait for after startup state machine is in bandgap enable state.
This fixes PLL lock timeout error faced while using RPi DSI Panel on TI's AM62L and J721E SoC since earlier calibration wait time was getting overwritten to zero value thus failing the PLL to lockup and causing timeout.
[1] AM62P TRM (Section 14.8.6.3.2.1.1 DPHY_TX_DPHYTX_CMN0_CMN_DIG_TBIT2):
--- drivers/phy/cadence/cdns-dphy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/phy/cadence/cdns-dphy.c +3 -1
@@ -30,6 +30,7 @@#define DPHY_CMN_SSM DPHY_PMA_CMN(0x20)#define DPHY_CMN_SSM_EN BIT(0) +#define DPHY_CMN_SSM_CAL_WAIT_TIME GENMASK(8, 1)#define DPHY_CMN_TX_MODE_EN BIT(9)#define DPHY_CMN_PWM DPHY_PMA_CMN(0x40)
@@ -421,7 +422,8 @@ static int cdns_dphy_power_on(struct phywritel (reg, dphy->regs +DPHY_BAND_CFG );/* Start TX state machine. */ -writel (DPHY_CMN_SSM_EN |DPHY_CMN_TX_MODE_EN , + reg =readl (dphy->regs +DPHY_CMN_SSM ); +writel ((reg &DPHY_CMN_SSM_CAL_WAIT_TIME ) |DPHY_CMN_SSM_EN |DPHY_CMN_TX_MODE_EN , dphy->regs +DPHY_CMN_SSM ); ret =cdns_dphy_wait_for_pll_lock (dphy);
Greg Kroah-Hartman
maintainerPATCH 154/159 drm/xe: Use devm_ioremap_wc for VRAM mapping and drop manual unmap
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski <[email protected]>
[ Upstream commit 922ae875230be91c7f05f2aa90d176b6693e2601 ]
Let's replace the manual call to ioremap_wc function with devm_ioremap_wc function, ensuring that VRAM mappings are automatically released when the driver is detached.
Since devm_ioremap_wc registers the mapping with the device's managed resources, the explicit iounmap call in vram_fini is no longer needed, so let's remove it.
Stable-dep-of: d30203739be7 ("drm/xe: Move rebar to be done earlier")
--- drivers/gpu/drm/xe/xe_vram.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_vram.c +2 -4
@@ -156,7 +156,8 @@ static int determine_lmem_bar_size(struc xe->mem.vram.dpa_base =0 ;/* set up a map to the total memory area. */ - xe->mem.vram.mapping =ioremap_wc (xe->mem.vram.io_start, xe->mem.vram.io_size); + xe->mem.vram.mapping =devm_ioremap_wc (&pdev->dev, xe->mem.vram.io_start, + xe->mem.vram.io_size);return 0 ; }
@@ -278,9 +279,6 @@ static void vram_fini(void *arg)struct xe_tile *tile;int id; -if (xe->mem.vram.mapping) -iounmap (xe->mem.vram.mapping); - xe->mem.vram.mapping =NULL ;for_each_tile (tile, xe, id)
Greg Kroah-Hartman
maintainerPATCH 155/159 drm/xe: Use dynamic allocation for tile and device VRAM region structures
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski <[email protected]>
[ Upstream commit f92cfd72d9a650f90260c54accd840c6500c4c3a ]
In future platforms, we will need to represent the device and tile VRAM regions in a more dynamic way, so let's abandon the static allocation of these structures and start use a dynamic allocation.
v2:
- Add a helpers for accessing fields of the xe_vram_region structure
v3:
- Add missing EXPORT_SYMBOL_IF_KUNIT for xe_vram_region_actual_physical_size
Stable-dep-of: d30203739be7 ("drm/xe: Move rebar to be done earlier")
--- drivers/gpu/drm/xe/display/xe_fb_pin.c | 4 drivers/gpu/drm/xe/display/xe_plane_initial.c | 2 drivers/gpu/drm/xe/xe_assert.h | 4 drivers/gpu/drm/xe/xe_device.c | 19 ++++ drivers/gpu/drm/xe/xe_device_types.h | 6 - drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 2 drivers/gpu/drm/xe/xe_migrate.c | 25 +++-- drivers/gpu/drm/xe/xe_pci.c | 6 + drivers/gpu/drm/xe/xe_query.c | 2 drivers/gpu/drm/xe/xe_svm.c | 24 +---- drivers/gpu/drm/xe/xe_tile.c | 34 ++++++- drivers/gpu/drm/xe/xe_tile.h | 4 drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c | 10 +- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 7 - drivers/gpu/drm/xe/xe_vram.c | 121 +++++++++++++++++++------- drivers/gpu/drm/xe/xe_vram.h | 9 + 16 files changed, 202 insertions(+), 77 deletions(-)
drivers/gpu/drm/xe/display/xe_fb_pin.c +2 -2
@@ -289,7 +289,7 @@ static struct i915_vma *__xe_pin_fb_vma(if (IS_DGFX (to_xe_device (bo->ttm.base.dev)) &&intel_fb_rc_ccs_cc_plane (&fb->base) >=0 && !(bo->flags &XE_BO_FLAG_NEEDS_CPU_ACCESS )) { -struct xe_tile *tile =xe_device_get_root_tile (xe); +struct xe_vram_region *vram =xe_device_get_root_tile (xe)->mem.vram;/* * If we need to able to access the clear-color value stored in
@@ -297,7 +297,7 @@ static struct i915_vma *__xe_pin_fb_vma(* accessible. This is important on small-bar systems where * only some subset of VRAM is CPU accessible. */ -if (tile->mem.vram.io_size < tile->mem.vram.usable_size) { +if (xe_vram_region_io_size (vram) <xe_vram_region_usable_size (vram)) { ret = -EINVAL ; goto err; }
drivers/gpu/drm/xe/display/xe_plane_initial.c +1 -1
@@ -103,7 +103,7 @@ initial_plane_bo(struct xe_device *xe,* We don't currently expect this to ever be placed in the * stolen portion. */ -if (phys_base >= tile0->mem.vram.usable_size) { +if (phys_base >=xe_vram_region_usable_size (tile0->mem.vram)) {drm_err (&xe->drm,"Initial plane programming using invalid range, phys_base=%pa\n" , &phys_base);
drivers/gpu/drm/xe/xe_assert.h +3 -1
@@ -12,6 +12,7 @@#include "xe_gt_types.h" #include "xe_step.h" +#include "xe_vram.h" /** * DOC: Xe Asserts
@@ -145,7 +146,8 @@const struct xe_tile *__tile = (tile); \ char __buf[10] __maybe_unused; \xe_assert_msg (tile_to_xe (__tile), condition,"tile: %u VRAM %s\n" msg, \ - __tile->id, ({string_get_size (__tile->mem.vram.actual_physical_size,1 , \ + __tile->id, ({string_get_size ( \ +xe_vram_region_actual_physical_size (__tile->mem.vram),1 , \ STRING_UNITS_2, __buf, sizeof(__buf)); __buf; }), ## arg); \ })
drivers/gpu/drm/xe/xe_device.c +19 -0
@@ -688,6 +688,21 @@ static void sriov_update_device_info(str } } +static int xe_device_vram_alloc (struct xe_device *xe) +{ +struct xe_vram_region *vram; + +if (!IS_DGFX (xe)) +return 0 ; + + vram =drmm_kzalloc (&xe->drm,sizeof (*vram),GFP_KERNEL ); +if (!vram) +return -ENOMEM ; + + xe->mem.vram = vram; +return 0 ; +} +/** * xe_device_probe_early: Device early probe * @xe: xe device instance
@@ -735,6 +750,10 @@ int xe_device_probe_early(struct xe_devi xe->wedged.mode = xe_modparam.wedged_mode; + err =xe_device_vram_alloc (xe); +if (err) +return err; +return 0 ; }ALLOW_ERROR_INJECTION (xe_device_probe_early,ERRNO );/* See xe_pci_probe() */
drivers/gpu/drm/xe/xe_device_types.h +4 -2
@@ -77,6 +77,8 @@ struct xe_pxp;* device, such as HBM memory or CXL extension memory. */ struct xe_vram_region { +/** @tile: Back pointer to tile */ +struct xe_tile *tile;/** @io_start: IO start address of this VRAM instance */ resource_size_t io_start;/**
@@ -216,7 +218,7 @@ struct xe_tile {* Although VRAM is associated with a specific tile, it can * still be accessed by all tiles' GTs. */ -struct xe_vram_region vram; +struct xe_vram_region *vram;/** @mem.ggtt: Global graphics translation table */ struct xe_ggtt *ggtt;
@@ -412,7 +414,7 @@ struct xe_device {/** @mem: memory info for device */ struct {/** @mem.vram: VRAM info for device */ -struct xe_vram_region vram; +struct xe_vram_region *vram;/** @mem.sys_mgr: system TTM manager */ struct ttm_resource_manager sys_mgr;/** @mem.sys_mgr: system memory shrinker. */
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +1 -1
@@ -1604,7 +1604,7 @@ static u64 pf_query_free_lmem(struct xe_ {struct xe_tile *tile = gt->tile; -return xe_ttm_vram_get_avail (&tile->mem.vram.ttm.manager); +return xe_ttm_vram_get_avail (&tile->mem.vram->ttm.manager); }static u64 pf_query_max_lmem (struct xe_gt *gt)
drivers/gpu/drm/xe/xe_migrate.c +14 -11
@@ -34,6 +34,7 @@#include "xe_sync.h" #include "xe_trace_bo.h" #include "xe_vm.h" +#include "xe_vram.h" /** * struct xe_migrate - migrate context.
@@ -130,34 +131,36 @@ static u64 xe_migrate_vram_ofs(struct xeu64 identity_offset =IDENTITY_OFFSET ;if (GRAPHICS_VER (xe) >=20 && is_comp_pte) - identity_offset +=DIV_ROUND_UP_ULL (xe->mem.vram.actual_physical_size,SZ_1G ); + identity_offset +=DIV_ROUND_UP_ULL (xe_vram_region_actual_physical_size + (xe->mem.vram),SZ_1G ); - addr -= xe->mem.vram.dpa_base; + addr -=xe_vram_region_dpa_base (xe->mem.vram);return addr + (identity_offset <<xe_pt_shift (2 )); }static void xe_migrate_program_identity (struct xe_device *xe,struct xe_vm *vm,struct xe_bo *bo,u64 map_ofs,u64 vram_offset,u16 pat_index,u64 pt_2m_ofs) { +struct xe_vram_region *vram = xe->mem.vram; +resource_size_t dpa_base =xe_vram_region_dpa_base (vram);u64 pos, ofs, flags;u64 entry;/* XXX: Unclear if this should be usable_size? */ -u64 vram_limit = xe->mem.vram.actual_physical_size + - xe->mem.vram.dpa_base; +u64 vram_limit =xe_vram_region_actual_physical_size (vram) + dpa_base;u32 level =2 ; ofs = map_ofs +XE_PAGE_SIZE * level + vram_offset *8 ; flags = vm->pt_ops->pte_encode_addr (xe,0 , pat_index, level, true,0 ); -xe_assert (xe,IS_ALIGNED (xe->mem.vram.usable_size,SZ_2M )); +xe_assert (xe,IS_ALIGNED (xe_vram_region_usable_size (vram),SZ_2M ));/* * Use 1GB pages when possible, last chunk always use 2M * pages as mixing reserved memory (stolen, WOCPM) with a single * mapping is not allowed on certain platforms. */ -for (pos = xe->mem.vram.dpa_base; pos < vram_limit; +for (pos = dpa_base; pos < vram_limit; pos +=SZ_1G , ofs +=8 ) {if (pos +SZ_1G >= vram_limit) { entry = vm->pt_ops->pde_encode_bo(bo, pt_2m_ofs,
@@ -307,11 +310,11 @@ static int xe_migrate_prepare_vm(struct/* Identity map the entire vram at 256GiB offset */ if (IS_DGFX (xe)) {u64 pt30_ofs =xe_bo_size (bo) -2 *XE_PAGE_SIZE ; +resource_size_t actual_phy_size =xe_vram_region_actual_physical_size (xe->mem.vram);xe_migrate_program_identity (xe, vm, bo, map_ofs,IDENTITY_OFFSET , pat_index, pt30_ofs); -xe_assert (xe, xe->mem.vram.actual_physical_size <= - (MAX_NUM_PTE -IDENTITY_OFFSET ) *SZ_1G ); +xe_assert (xe, actual_phy_size <= (MAX_NUM_PTE -IDENTITY_OFFSET ) *SZ_1G );/* * Identity map the entire vram for compressed pat_index for xe2+
@@ -320,11 +323,11 @@ static int xe_migrate_prepare_vm(structif (GRAPHICS_VER (xe) >=20 &&xe_device_has_flat_ccs (xe)) {u16 comp_pat_index = xe->pat.idx[XE_CACHE_NONE_COMPRESSION ];u64 vram_offset =IDENTITY_OFFSET + -DIV_ROUND_UP_ULL (xe->mem.vram.actual_physical_size,SZ_1G ); +DIV_ROUND_UP_ULL (actual_phy_size,SZ_1G );u64 pt31_ofs =xe_bo_size (bo) -XE_PAGE_SIZE ; -xe_assert (xe, xe->mem.vram.actual_physical_size <= (MAX_NUM_PTE - -IDENTITY_OFFSET -IDENTITY_OFFSET /2 ) *SZ_1G ); +xe_assert (xe, actual_phy_size <= (MAX_NUM_PTE -IDENTITY_OFFSET - +IDENTITY_OFFSET /2 ) *SZ_1G );xe_migrate_program_identity (xe, vm, bo, map_ofs, vram_offset, comp_pat_index, pt31_ofs); }
drivers/gpu/drm/xe/xe_pci.c +6 -0
@@ -687,6 +687,8 @@ static int xe_info_init(struct xe_device* All of these together determine the overall GT count. */ for_each_tile (tile, xe, id) { +int err; + gt = tile->primary_gt; gt->info.type =XE_GT_TYPE_MAIN ; gt->info.id = tile->id * xe->info.max_gt_per_tile;
@@ -694,6 +696,10 @@ static int xe_info_init(struct xe_device gt->info.engine_mask = graphics_desc->hw_engine_mask; xe->info.gt_count++; + err =xe_tile_alloc_vram (tile); +if (err) +return err; +if (MEDIA_VER (xe) <13 && media_desc) gt->info.engine_mask |= media_desc->hw_engine_mask;
drivers/gpu/drm/xe/xe_query.c +1 -1
@@ -334,7 +334,7 @@ static int query_config(struct xe_device config->num_params = num_params; config->info[DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID ] = xe->info.devid | (xe->info.revid <<16 ); -if (xe_device_get_root_tile (xe)->mem.vram.usable_size) +if (xe->mem.vram) config->info[DRM_XE_QUERY_CONFIG_FLAGS ] |=DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM ;if (xe->info.has_usm &&IS_ENABLED (CONFIG_DRM_XE_GPUSVM ))
drivers/gpu/drm/xe/xe_svm.c +7 -17
@@ -306,16 +306,11 @@ static struct xe_vram_region *page_to_vr return container_of(page_pgmap(page), struct xe_vram_region, pagemap); } -static struct xe_tile *vr_to_tile (struct xe_vram_region *vr) -{ - return container_of(vr, struct xe_tile, mem.vram); -} -static u64 xe_vram_region_page_to_dpa (struct xe_vram_region *vr,struct page *page) {u64 dpa; -struct xe_tile *tile =vr_to_tile (vr); +struct xe_tile *tile = vr->tile;u64 pfn =page_to_pfn (page);u64 offset;
@@ -370,7 +365,7 @@ static int xe_svm_copy(struct page **pagif (!vr && spage) { vr =page_to_vr (spage); - tile =vr_to_tile (vr); + tile = vr->tile; }XE_WARN_ON (spage &&page_to_vr (spage) != vr);
@@ -508,7 +503,7 @@ static u64 block_offset_to_pfn(struct xestatic struct drm_buddy *tile_to_buddy (struct xe_tile *tile) { -return &tile->mem.vram.ttm.mm; +return &tile->mem.vram->ttm.mm; } static int xe_svm_populate_devmem_pfn(struct drm_pagemap_devmem *devmem_allocation,
@@ -522,7 +517,7 @@ static int xe_svm_populate_devmem_pfn(stlist_for_each_entry (block, blocks, link) {struct xe_vram_region *vr = block->private; -struct xe_tile *tile =vr_to_tile (vr); +struct xe_tile *tile = vr->tile;struct drm_buddy *buddy =tile_to_buddy (tile);u64 block_pfn =block_offset_to_pfn (vr,drm_buddy_block_offset (block));int i;
@@ -683,20 +678,15 @@ u64 xe_svm_find_vma_start(struct xe_vm * }#if IS_ENABLED (CONFIG_DRM_XE_PAGEMAP ) -static struct xe_vram_region *tile_to_vr (struct xe_tile *tile) -{ -return &tile->mem.vram; -} -static int xe_drm_pagemap_populate_mm (struct drm_pagemap *dpagemap,unsigned long start,unsigned long end,struct mm_struct *mm,unsigned long timeslice_ms) { -struct xe_tile *tile =container_of (dpagemap,typeof (*tile), mem.vram.dpagemap); +struct xe_vram_region *vr =container_of (dpagemap,typeof (*vr), dpagemap); +struct xe_tile *tile = vr->tile;struct xe_device *xe =tile_to_xe (tile);struct device *dev = xe->drm.dev; -struct xe_vram_region *vr =tile_to_vr (tile);struct drm_buddy_block *block;struct list_head *blocks;struct xe_bo *bo;
@@ -722,7 +712,7 @@ static int xe_drm_pagemap_populate_mm(stdrm_pagemap_devmem_init (&bo->devmem_allocation, dev, mm, &dpagemap_devmem_ops, - &tile->mem.vram.dpagemap, + &tile->mem.vram->dpagemap, end - start); blocks = &to_xe_ttm_vram_mgr_resource (bo->ttm.resource)->blocks;
drivers/gpu/drm/xe/xe_tile.c +31 -3
@@ -19,6 +19,7 @@#include "xe_tile_sysfs.h" #include "xe_ttm_vram_mgr.h" #include "xe_wa.h" +#include "xe_vram.h" /** * DOC: Multi-tile Design
@@ -96,6 +97,33 @@ static int xe_tile_alloc(struct xe_tile }/** +* xe_tile_alloc_vram - Perform per-tile VRAM structs allocation +* @tile: Tile to perform allocations for +* +* Allocates VRAM per-tile data structures using DRM-managed allocations. +* Does not touch the hardware. +* +* Returns -ENOMEM if allocations fail, otherwise 0. +*/ +int xe_tile_alloc_vram (struct xe_tile *tile) +{ +struct xe_device *xe =tile_to_xe (tile); +struct xe_vram_region *vram; + +if (!IS_DGFX (xe)) +return 0 ; + + vram =drmm_kzalloc (&xe->drm,sizeof (*vram),GFP_KERNEL ); +if (!vram) +return -ENOMEM ; + + vram->tile = tile; + tile->mem.vram = vram; + +return 0 ; +} + +/** * xe_tile_init_early - Initialize the tile and primary GT * @tile: Tile to initialize * @xe: Parent Xe device
@@ -132,8 +160,8 @@ static int tile_ttm_mgr_init(struct xe_tstruct xe_device *xe =tile_to_xe (tile);int err; -if (tile->mem.vram.usable_size) { - err =xe_ttm_vram_mgr_init (tile, &tile->mem.vram.ttm); +if (tile->mem.vram) { + err =xe_ttm_vram_mgr_init (tile, &tile->mem.vram->ttm);if (err)return err; xe->info.mem_region_mask |=BIT (tile->id) <<1 ;
@@ -168,7 +196,7 @@ int xe_tile_init_noalloc(struct xe_tilexe_wa_apply_tile_workarounds (tile);if (xe->info.has_usm &&IS_DGFX (xe)) -xe_devm_add (tile, &tile->mem.vram); +xe_devm_add (tile, tile->mem.vram);return xe_tile_sysfs_init (tile); }
drivers/gpu/drm/xe/xe_tile.h +3 -1
@@ -14,12 +14,14 @@ int xe_tile_init_early(struct xe_tile *tint xe_tile_init_noalloc (struct xe_tile *tile);int xe_tile_init (struct xe_tile *tile); +int xe_tile_alloc_vram (struct xe_tile *tile); +void xe_tile_migrate_wait (struct xe_tile *tile);#if IS_ENABLED (CONFIG_DRM_XE_PAGEMAP )static inline struct drm_pagemap *xe_tile_local_pagemap (struct xe_tile *tile) { -return &tile->mem.vram.dpagemap; +return &tile->mem.vram->dpagemap; }#else static inline struct drm_pagemap *xe_tile_local_pagemap (struct xe_tile *tile)
drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c +6 -4
@@ -25,6 +25,7 @@#include "xe_ttm_stolen_mgr.h" #include "xe_ttm_vram_mgr.h" #include "xe_wa.h" +#include "xe_vram.h" struct xe_ttm_stolen_mgr {struct xe_ttm_vram_mgr base;
@@ -82,15 +83,16 @@ static u32 get_wopcm_size(struct xe_devistatic s64 detect_bar2_dgfx (struct xe_device *xe,struct xe_ttm_stolen_mgr *mgr) { -struct xe_tile *tile =xe_device_get_root_tile (xe); +struct xe_vram_region *tile_vram =xe_device_get_root_tile (xe)->mem.vram; +resource_size_t tile_io_start =xe_vram_region_io_start (tile_vram);struct xe_mmio *mmio =xe_root_tile_mmio (xe);struct pci_dev *pdev =to_pci_dev (xe->drm.dev);u64 stolen_size, wopcm_size;u64 tile_offset;u64 tile_size; - tile_offset = tile->mem.vram.io_start - xe->mem.vram.io_start; - tile_size = tile->mem.vram.actual_physical_size; + tile_offset = tile_io_start -xe_vram_region_io_start (xe->mem.vram); + tile_size =xe_vram_region_actual_physical_size (tile_vram);/* Use DSM base address instead for stolen memory */ mgr->stolen_base = (xe_mmio_read64_2x32 (mmio,DSMBASE ) &BDSM_MASK ) - tile_offset;
@@ -107,7 +109,7 @@ static s64 detect_bar2_dgfx(struct xe_de/* Verify usage fits in the actual resource available */ if (mgr->stolen_base + stolen_size <=pci_resource_len (pdev,LMEM_BAR )) - mgr->io_base = tile->mem.vram.io_start + mgr->stolen_base; + mgr->io_base = tile_io_start + mgr->stolen_base;/* * There may be few KB of platform dependent reserved memory at the end
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +4 -3
@@ -340,10 +340,11 @@ int __xe_ttm_vram_mgr_init(struct xe_devint xe_ttm_vram_mgr_init (struct xe_tile *tile,struct xe_ttm_vram_mgr *mgr) {struct xe_device *xe =tile_to_xe (tile); -struct xe_vram_region *vram = &tile->mem.vram; +struct xe_vram_region *vram = tile->mem.vram;return __xe_ttm_vram_mgr_init (xe, mgr,XE_PL_VRAM0 + tile->id, - vram->usable_size, vram->io_size, +xe_vram_region_usable_size (vram), +xe_vram_region_io_size (vram),PAGE_SIZE ); }
@@ -392,7 +393,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_*/ xe_res_first (res, offset, length, &cursor);for_each_sgtable_sg ((*sgt), sg, i) { -phys_addr_t phys = cursor.start + tile->mem.vram.io_start; +phys_addr_t phys = cursor.start +xe_vram_region_io_start (tile->mem.vram);size_t size =min_t (u64, cursor.size,SZ_2G );dma_addr_t addr;
drivers/gpu/drm/xe/xe_vram.c +91 -30
179 lines not on this page · raw message
drivers/gpu/drm/xe/xe_vram.h +9 -0
@@ -6,8 +6,17 @@#ifndef _XE_VRAM_H_#define _XE_VRAM_H_ +#include <linux/types.h> +struct xe_device ; +struct xe_vram_region ;int xe_vram_probe (struct xe_device *xe); +resource_size_t xe_vram_region_io_start (const struct xe_vram_region *vram); +resource_size_t xe_vram_region_io_size (const struct xe_vram_region *vram); +resource_size_t xe_vram_region_dpa_base (const struct xe_vram_region *vram); +resource_size_t xe_vram_region_usable_size (const struct xe_vram_region *vram); +resource_size_t xe_vram_region_actual_physical_size (const struct xe_vram_region *vram); +#endif
Greg Kroah-Hartman
maintainerPATCH 156/159 drm/xe: Move struct xe_vram_region to a dedicated header
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski <[email protected]>
[ Upstream commit 7a20b4f558f4291161f71a5b7384262db9ccd6b0 ]
Let's move the xe_vram_region structure to a new header dedicated to VRAM to improve modularity and avoid unnecessary dependencies when only VRAM-related structures are needed.
v2: Fix build if CONFIG_DRM_XE_DEVMEM_MIRROR is enabled
v3: Fix build if CONFIG_DRM_XE_DISPLAY is enabled
v4: Move helper to get tile dpagemap to xe_svm.c
Stable-dep-of: d30203739be7 ("drm/xe: Move rebar to be done earlier")
--- drivers/gpu/drm/xe/display/xe_fb_pin.c | 1 drivers/gpu/drm/xe/display/xe_plane_initial.c | 1 drivers/gpu/drm/xe/xe_bo.c | 1 drivers/gpu/drm/xe/xe_bo_types.h | 1 drivers/gpu/drm/xe/xe_device.c | 1 drivers/gpu/drm/xe/xe_device_types.h | 60 --------------------- drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c | 1 drivers/gpu/drm/xe/xe_svm.c | 8 ++ drivers/gpu/drm/xe/xe_tile.c | 1 drivers/gpu/drm/xe/xe_tile.h | 12 ---- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 1 drivers/gpu/drm/xe/xe_vram.c | 1 drivers/gpu/drm/xe/xe_vram_types.h | 74 ++++++++++++++++++++++++++ 13 files changed, 91 insertions(+), 72 deletions(-) create mode 100644 drivers/gpu/drm/xe/xe_vram_types.h
drivers/gpu/drm/xe/display/xe_fb_pin.c +1 -0
@@ -16,6 +16,7 @@#include "xe_device.h" #include "xe_ggtt.h" #include "xe_pm.h" +#include "xe_vram_types.h" static void write_dpt_rotated(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, u32 bo_ofs,
drivers/gpu/drm/xe/display/xe_plane_initial.c +1 -0
@@ -21,6 +21,7 @@#include "intel_plane.h" #include "intel_plane_initial.h" #include "xe_bo.h" +#include "xe_vram_types.h" #include "xe_wa.h" #include <generated/xe_wa_oob.h>
drivers/gpu/drm/xe/xe_bo.c +1 -0
@@ -36,6 +36,7 @@#include "xe_trace_bo.h" #include "xe_ttm_stolen_mgr.h" #include "xe_vm.h" +#include "xe_vram_types.h" const char *const xe_mem_type_to_name[TTM_NUM_MEM_TYPES ] = { [XE_PL_SYSTEM ] ="system" ,
drivers/gpu/drm/xe/xe_bo_types.h +1 -0
@@ -9,6 +9,7 @@#include <linux/iosys-map.h> #include <drm/drm_gpusvm.h> +#include <drm/drm_pagemap.h> #include <drm/ttm/ttm_bo.h> #include <drm/ttm/ttm_device.h> #include <drm/ttm/ttm_placement.h>
drivers/gpu/drm/xe/xe_device.c +1 -0
@@ -64,6 +64,7 @@#include "xe_ttm_sys_mgr.h" #include "xe_vm.h" #include "xe_vram.h" +#include "xe_vram_types.h" #include "xe_vsec.h" #include "xe_wait_user_fence.h" #include "xe_wa.h"
drivers/gpu/drm/xe/xe_device_types.h +1 -59
84 lines not on this page · raw message
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +1 -0
@@ -33,6 +33,7 @@#include "xe_migrate.h" #include "xe_sriov.h" #include "xe_ttm_vram_mgr.h" +#include "xe_vram_types.h" #include "xe_wopcm.h" #define make_u64_from_u32 (hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo)))
drivers/gpu/drm/xe/xe_svm.c +7 -1
@@ -17,6 +17,7 @@#include "xe_ttm_vram_mgr.h" #include "xe_vm.h" #include "xe_vm_types.h" +#include "xe_vram_types.h" static bool xe_svm_range_in_vram (struct xe_svm_range *range) {
@@ -989,6 +990,11 @@ int xe_svm_range_get_pages(struct xe_vm#if IS_ENABLED (CONFIG_DRM_XE_PAGEMAP ) +static struct drm_pagemap *tile_local_pagemap (struct xe_tile *tile) +{ +return &tile->mem.vram->dpagemap; +} +/** * xe_svm_alloc_vram()- Allocate device memory pages for range, * migrating existing data.
@@ -1006,7 +1012,7 @@ int xe_svm_alloc_vram(struct xe_tile *tixe_assert (tile_to_xe (tile), range->base.flags.migrate_devmem);range_debug (range,"ALLOCATE VRAM" ); - dpagemap =xe_tile_local_pagemap (tile); + dpagemap =tile_local_pagemap (tile); return drm_pagemap_populate_mm(dpagemap, xe_svm_range_start(range), xe_svm_range_end(range), range->base.gpusvm->mm,
drivers/gpu/drm/xe/xe_tile.c +1 -0
@@ -20,6 +20,7 @@#include "xe_ttm_vram_mgr.h" #include "xe_wa.h" #include "xe_vram.h" +#include "xe_vram_types.h" /** * DOC: Multi-tile Design
drivers/gpu/drm/xe/xe_tile.h +0 -12
@@ -18,18 +18,6 @@ int xe_tile_alloc_vram(struct xe_tile *tvoid xe_tile_migrate_wait (struct xe_tile *tile); -#if IS_ENABLED (CONFIG_DRM_XE_PAGEMAP ) -static inline struct drm_pagemap *xe_tile_local_pagemap (struct xe_tile *tile) -{ -return &tile->mem.vram->dpagemap; -} -#else -static inline struct drm_pagemap *xe_tile_local_pagemap (struct xe_tile *tile) -{ -return NULL ; -} -#endif -static inline bool xe_tile_is_root (struct xe_tile *tile) {return tile->id ==0 ;
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +1 -0
@@ -15,6 +15,7 @@#include "xe_gt.h" #include "xe_res_cursor.h" #include "xe_ttm_vram_mgr.h" +#include "xe_vram_types.h" static inline struct drm_buddy_block *xe_ttm_vram_mgr_first_block (struct list_head *list)
drivers/gpu/drm/xe/xe_vram.c +1 -0
@@ -21,6 +21,7 @@#include "xe_module.h" #include "xe_sriov.h" #include "xe_vram.h" +#include "xe_vram_types.h" #define BAR_SIZE_SHIFT 20
drivers/gpu/drm/xe/xe_vram_types.h new file +74 -0
74 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 157/159 drm/xe: Unify the initialization of VRAM regions
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski <[email protected]>
[ Upstream commit 4b0a5f5ce7849aab7a67ba9f113ed75626f6de36 ]
Currently in the drivers we have defined VRAM regions per device and per tile. Initialization of these regions is done in two completely different ways. To simplify the logic of the code and make it easier to add new regions in the future, let's unify the way we initialize VRAM regions.
v2:
- fix doc comments in struct xe_vram_region
- remove unnecessary includes (Jani)
v3:
- move code from xe_vram_init_regions_managers to xe_tile_init_noalloc (Matthew)
- replace ioremap_wc to devm_ioremap_wc for mapping VRAM BAR (Matthew)
- Replace the tile id parameter with vram region in the xe_pf_begin function.
v4:
- remove tile back pointer from struct xe_vram_region
- add new back pointers: xe and migarte to xe_vram_region
Stable-dep-of: d30203739be7 ("drm/xe: Move rebar to be done earlier")
--- drivers/gpu/drm/xe/xe_bo.h | 4 drivers/gpu/drm/xe/xe_gt_pagefault.c | 13 +-- drivers/gpu/drm/xe/xe_query.c | 3 drivers/gpu/drm/xe/xe_svm.c | 43 ++++----- drivers/gpu/drm/xe/xe_tile.c | 37 ++------ drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 16 ++- drivers/gpu/drm/xe/xe_ttm_vram_mgr.h | 3 drivers/gpu/drm/xe/xe_vram.c | 151 +++++++++++++++++++++-------------- drivers/gpu/drm/xe/xe_vram.h | 2 drivers/gpu/drm/xe/xe_vram_types.h | 17 +++ 10 files changed, 164 insertions(+), 125 deletions(-)
drivers/gpu/drm/xe/xe_bo.h +3 -1
@@ -12,6 +12,7 @@#include "xe_macros.h" #include "xe_vm_types.h" #include "xe_vm.h" +#include "xe_vram_types.h" #define XE_DEFAULT_GTT_SIZE_MB 3072ULL/* 3GB by default */
@@ -23,8 +24,9 @@#define XE_BO_FLAG_VRAM_MASK (XE_BO_FLAG_VRAM0 | XE_BO_FLAG_VRAM1)/* -- */ #define XE_BO_FLAG_STOLEN BIT(4) +#define XE_BO_FLAG_VRAM (vram) (XE_BO_FLAG_VRAM0 << ((vram)->id))#define XE_BO_FLAG_VRAM_IF_DGFX (tile) (IS_DGFX(tile_to_xe(tile)) ? \ - XE_BO_FLAG_VRAM0 << (tile)->id : \ + XE_BO_FLAG_VRAM((tile)->mem.vram) : \ XE_BO_FLAG_SYSTEM)#define XE_BO_FLAG_GGTT BIT(5)#define XE_BO_FLAG_IGNORE_MIN_PAGE_SIZE BIT(6)
drivers/gpu/drm/xe/xe_gt_pagefault.c +8 -5
@@ -23,6 +23,7 @@#include "xe_svm.h" #include "xe_trace_bo.h" #include "xe_vm.h" +#include "xe_vram_types.h" struct pagefault {u64 page_addr;
@@ -74,7 +75,7 @@ static bool vma_is_valid(struct xe_tile }static int xe_pf_begin (struct drm_exec *exec,struct xe_vma *vma, -bool atomic,unsigned int id) +bool atomic,struct xe_vram_region *vram) {struct xe_bo *bo =xe_vma_bo (vma);struct xe_vm *vm =xe_vma_vm (vma);
@@ -84,14 +85,16 @@ static int xe_pf_begin(struct drm_exec *if (err)return err; -if (atomic &&IS_DGFX (vm->xe)) { +if (atomic && vram) { +xe_assert (vm->xe,IS_DGFX (vm->xe)); +if (xe_vma_is_userptr (vma)) { err = -EACCES ;return err; }/* Migrate to VRAM, move should invalidate the VMA first */ - err =xe_bo_migrate (bo,XE_PL_VRAM0 + id); + err =xe_bo_migrate (bo, vram->placement);if (err)return err; }else if (bo) {
@@ -138,7 +141,7 @@ retry_userptr:/* Lock VM and BOs dma-resv */ drm_exec_init (&exec,0 ,0 ); drm_exec_until_all_locked(&exec) { - err =xe_pf_begin (&exec, vma, atomic, tile->id); + err =xe_pf_begin (&exec, vma, atomic, tile->mem.vram);drm_exec_retry_on_contention (&exec);if (xe_vm_validate_should_retry (&exec, err, &end)) err = -EAGAIN ;
@@ -573,7 +576,7 @@ static int handle_acc(struct xe_gt *gt,/* Lock VM and BOs dma-resv */ drm_exec_init (&exec,0 ,0 ); drm_exec_until_all_locked(&exec) { - ret =xe_pf_begin (&exec, vma, true, tile->id); + ret =xe_pf_begin (&exec, vma, true, tile->mem.vram);drm_exec_retry_on_contention (&exec);if (ret)break ;
drivers/gpu/drm/xe/xe_query.c +2 -1
@@ -27,6 +27,7 @@#include "xe_oa.h" #include "xe_pxp.h" #include "xe_ttm_vram_mgr.h" +#include "xe_vram_types.h" #include "xe_wa.h" static const u16 xe_to_user_engine_class[] = {
@@ -407,7 +408,7 @@ static int query_gt_list(struct xe_devic gt_list->gt_list[iter].near_mem_regions =0x1 ; else gt_list->gt_list[iter].near_mem_regions = -BIT (gt_to_tile (gt)->id) <<1 ; +BIT (gt_to_tile (gt)->mem.vram->id) <<1 ; gt_list->gt_list[iter].far_mem_regions = xe->info.mem_region_mask ^ gt_list->gt_list[iter].near_mem_regions;
drivers/gpu/drm/xe/xe_svm.c +19 -24
123 lines not on this page · raw message
drivers/gpu/drm/xe/xe_tile.c +12 -25
@@ -7,6 +7,7 @@#include <drm/drm_managed.h> +#include "xe_bo.h" #include "xe_device.h" #include "xe_ggtt.h" #include "xe_gt.h"
@@ -114,11 +115,9 @@ int xe_tile_alloc_vram(struct xe_tile *tif (!IS_DGFX (xe))return 0 ; - vram =drmm_kzalloc (&xe->drm,sizeof (*vram),GFP_KERNEL ); -if (!vram) -return -ENOMEM ; - - vram->tile = tile; + vram =xe_vram_region_alloc (xe, tile->id,XE_PL_VRAM0 + tile->id); +if (IS_ERR (vram)) +return PTR_ERR (vram); tile->mem.vram = vram;return 0 ;
@@ -156,21 +155,6 @@ int xe_tile_init_early(struct xe_tile *t }ALLOW_ERROR_INJECTION (xe_tile_init_early,ERRNO );/* See xe_pci_probe() */ -static int tile_ttm_mgr_init (struct xe_tile *tile) -{ -struct xe_device *xe =tile_to_xe (tile); -int err; - -if (tile->mem.vram) { - err =xe_ttm_vram_mgr_init (tile, &tile->mem.vram->ttm); -if (err) -return err; - xe->info.mem_region_mask |=BIT (tile->id) <<1 ; - } - -return 0 ; -} -/** * xe_tile_init_noalloc - Init tile up to the point where allocations can happen. * @tile: The tile to initialize.
@@ -188,17 +172,20 @@ static int tile_ttm_mgr_init(struct xe_tint xe_tile_init_noalloc (struct xe_tile *tile) {struct xe_device *xe =tile_to_xe (tile); -int err; - - err =tile_ttm_mgr_init (tile); -if (err) -return err;xe_wa_apply_tile_workarounds (tile);if (xe->info.has_usm &&IS_DGFX (xe))xe_devm_add (tile, tile->mem.vram); +if (IS_DGFX (xe) && !ttm_resource_manager_used (&tile->mem.vram->ttm.manager)) { +int err =xe_ttm_vram_mgr_init (xe, tile->mem.vram); + +if (err) +return err; + xe->info.mem_region_mask |=BIT (tile->mem.vram->id) <<1 ; + } +return xe_tile_sysfs_init (tile); }
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +11 -5
@@ -338,12 +338,18 @@ int __xe_ttm_vram_mgr_init(struct xe_devreturn drmm_add_action_or_reset (&xe->drm, ttm_vram_mgr_fini, mgr); } -int xe_ttm_vram_mgr_init (struct xe_tile *tile,struct xe_ttm_vram_mgr *mgr) +/** +* xe_ttm_vram_mgr_init - initialize TTM VRAM region +* @xe: pointer to Xe device +* @vram: pointer to xe_vram_region that contains the memory region attributes +* +* Initialize the Xe TTM for given @vram region using the given parameters. +* +* Returns 0 for success, negative error code otherwise. +*/ +int xe_ttm_vram_mgr_init (struct xe_device *xe,struct xe_vram_region *vram) { -struct xe_device *xe =tile_to_xe (tile); -struct xe_vram_region *vram = tile->mem.vram; - -return __xe_ttm_vram_mgr_init (xe, mgr,XE_PL_VRAM0 + tile->id, +return __xe_ttm_vram_mgr_init (xe, &vram->ttm, vram->placement,xe_vram_region_usable_size (vram),xe_vram_region_io_size (vram),PAGE_SIZE );
drivers/gpu/drm/xe/xe_ttm_vram_mgr.h +2 -1
@@ -11,11 +11,12 @@enum dma_data_direction ;struct xe_device ;struct xe_tile ; +struct xe_vram_region ;int __xe_ttm_vram_mgr_init (struct xe_device *xe,struct xe_ttm_vram_mgr *mgr,u32 mem_type,u64 size,u64 io_size,u64 default_page_size); -int xe_ttm_vram_mgr_init (struct xe_tile *tile,struct xe_ttm_vram_mgr *mgr); +int xe_ttm_vram_mgr_init (struct xe_device *xe,struct xe_vram_region *vram); int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe, struct ttm_resource *res, u64 offset, u64 length,
drivers/gpu/drm/xe/xe_vram.c +91 -60
209 lines not on this page · raw message
drivers/gpu/drm/xe/xe_vram.h +2 -0
@@ -13,6 +13,8 @@ struct xe_vram_region;int xe_vram_probe (struct xe_device *xe); +struct xe_vram_region *xe_vram_region_alloc (struct xe_device *xe,u8 id,u32 placement); +resource_size_t xe_vram_region_io_start (const struct xe_vram_region *vram);resource_size_t xe_vram_region_io_size (const struct xe_vram_region *vram);resource_size_t xe_vram_region_dpa_base (const struct xe_vram_region *vram);
drivers/gpu/drm/xe/xe_vram_types.h +14 -3
@@ -12,7 +12,8 @@#include "xe_ttm_vram_mgr_types.h" -struct xe_tile ; +struct xe_device ; +struct xe_migrate ;/** * struct xe_vram_region - memory region structure
@@ -20,8 +21,14 @@ struct xe_tile;* device, such as HBM memory or CXL extension memory. */ struct xe_vram_region { -/** @tile: Back pointer to tile */ -struct xe_tile *tile; +/** @xe: Back pointer to xe device */ +struct xe_device *xe; +/** +* @id: VRAM region instance id +* +* The value should be unique for VRAM region. +*/ +u8 id;/** @io_start: IO start address of this VRAM instance */ resource_size_t io_start;/**
@@ -54,7 +61,11 @@ struct xe_vram_region {void __iomem *mapping;/** @ttm: VRAM TTM manager */ struct xe_ttm_vram_mgr ttm; +/** @placement: TTM placement dedicated for this region */ +u32 placement;#if IS_ENABLED (CONFIG_DRM_XE_PAGEMAP ) +/** @migrate: Back pointer to migrate */ +struct xe_migrate *migrate;/** @pagemap: Used to remap device memory as ZONE_DEVICE */ struct dev_pagemap pagemap;/**
Greg Kroah-Hartman
maintainerPATCH 158/159 drm/xe: Move rebar to be done earlier
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas De Marchi <[email protected]>
[ Upstream commit d30203739be798d3de5c84db3060e96f00c54e82 ]
There may be cases in which the BAR0 also needs to move to accommodate the bigger BAR2. However if it's not released, the BAR2 resize fails. During the vram probe it can't be released as it's already in use by xe_mmio for early register access.
Add a new function in xe_vram and let xe_pci call it directly before even early device probe. This allows the BAR2 to resize in cases BAR0 also needs to move, assuming there aren't other reasons to hold that move:
[] xe 0000:03:00.0: vgaarb: deactivate vga console [] xe 0000:03:00.0: [drm] Attempting to resize bar from 8192MiB -> 16384MiB [] xe 0000:03:00.0: BAR 0 [mem 0x83000000-0x83ffffff 64bit]: releasing [] xe 0000:03:00.0: BAR 2 [mem 0x4000000000-0x41ffffffff 64bit pref]: releasing [] pcieport 0000:02:01.0: bridge window [mem 0x4000000000-0x41ffffffff 64bit pref]: releasing [] pcieport 0000:01:00.0: bridge window [mem 0x4000000000-0x41ffffffff 64bit pref]: releasing [] pcieport 0000:01:00.0: bridge window [mem 0x4000000000-0x43ffffffff 64bit pref]: assigned [] pcieport 0000:02:01.0: bridge window [mem 0x4000000000-0x43ffffffff 64bit pref]: assigned [] xe 0000:03:00.0: BAR 2 [mem 0x4000000000-0x43ffffffff 64bit pref]: assigned [] xe 0000:03:00.0: BAR 0 [mem 0x83000000-0x83ffffff 64bit]: assigned [] pcieport 0000:00:01.0: PCI bridge to [bus 01-04] [] pcieport 0000:00:01.0: bridge window [mem 0x83000000-0x840fffff] [] pcieport 0000:00:01.0: bridge window [mem 0x4000000000-0x44007fffff 64bit pref] [] pcieport 0000:01:00.0: PCI bridge to [bus 02-04] [] pcieport 0000:01:00.0: bridge window [mem 0x83000000-0x840fffff] [] pcieport 0000:01:00.0: bridge window [mem 0x4000000000-0x43ffffffff 64bit pref] [] pcieport 0000:02:01.0: PCI bridge to [bus 03] [] pcieport 0000:02:01.0: bridge window [mem 0x83000000-0x83ffffff] [] pcieport 0000:02:01.0: bridge window [mem 0x4000000000-0x43ffffffff 64bit pref] [] xe 0000:03:00.0: [drm] BAR2 resized to 16384M [] xe 0000:03:00.0: [drm:xe_pci_probe [xe]] BATTLEMAGE e221:0000 dgfx:1 gfx:Xe2_HPG (20.02) ...
For BMG there are additional fix needed in the PCI side, but this helps getting it to a working resize.
All the rebar logic is more pci-specific than xe-specific and can be done very early in the probe sequence. In future it would be good to move it out of xe_vram.c, but this refactor is left for later.
--- drivers/gpu/drm/xe/xe_pci.c | 2 ++ drivers/gpu/drm/xe/xe_vram.c | 34 ++++++++++++++++++++++++++-------- drivers/gpu/drm/xe/xe_vram.h | 1 + 3 files changed, 29 insertions(+), 8 deletions(-)
drivers/gpu/drm/xe/xe_pci.c +2 -0
@@ -805,6 +805,8 @@ static int xe_pci_probe(struct pci_dev *if (err)return err; +xe_vram_resize_bar (xe); + err =xe_device_probe_early (xe);/* * In Boot Survivability mode, no drm card is exposed and driver
drivers/gpu/drm/xe/xe_vram.c +26 -8
@@ -26,15 +26,35 @@#define BAR_SIZE_SHIFT 20 -static void -_resize_bar (struct xe_device *xe,int resno,resource_size_t size) +/* +* Release all the BARs that could influence/block LMEMBAR resizing, i.e. +* assigned IORESOURCE_MEM_64 BARs +*/ +static void release_bars (struct pci_dev *pdev) +{ +struct resource *res; +int i; + +pci_dev_for_each_resource (pdev, res, i) { +/* Resource already un-assigned, do not reset it */ +if (!res->parent) +continue ; + +/* No need to release unrelated BARs */ +if (!(res->flags &IORESOURCE_MEM_64 )) +continue ; + +pci_release_resource (pdev, i); + } +} + +static void resize_bar (struct xe_device *xe,int resno,resource_size_t size) {struct pci_dev *pdev =to_pci_dev (xe->drm.dev);int bar_size =pci_rebar_bytes_to_size (size);int ret; -if (pci_resource_len (pdev, resno)) -pci_release_resource (pdev, resno); +release_bars (pdev); ret =pci_resize_resource (pdev, resno, bar_size);if (ret) {
@@ -50,7 +70,7 @@ _resize_bar(struct xe_device *xe, int re* if force_vram_bar_size is set, attempt to set to the requested size * else set to maximum possible size */ -static void resize_vram_bar (struct xe_device *xe) +void xe_vram_resize_bar (struct xe_device *xe) {int force_vram_bar_size = xe_modparam.force_vram_bar_size;struct pci_dev *pdev =to_pci_dev (xe->drm.dev);
@@ -119,7 +139,7 @@ static void resize_vram_bar(struct xe_depci_read_config_dword (pdev,PCI_COMMAND , &pci_cmd);pci_write_config_dword (pdev,PCI_COMMAND , pci_cmd & ~PCI_COMMAND_MEMORY ); -_resize_bar (xe,LMEM_BAR , rebar_size); +resize_bar (xe,LMEM_BAR , rebar_size);pci_assign_unassigned_bus_resources (pdev->bus);pci_write_config_dword (pdev,PCI_COMMAND , pci_cmd);
@@ -148,8 +168,6 @@ static int determine_lmem_bar_size(strucreturn -ENXIO ; } -resize_vram_bar (xe); - lmem_bar->io_start =pci_resource_start (pdev,LMEM_BAR ); lmem_bar->io_size =pci_resource_len (pdev,LMEM_BAR );if (!lmem_bar->io_size)
drivers/gpu/drm/xe/xe_vram.h +1 -0
@@ -11,6 +11,7 @@struct xe_device ;struct xe_vram_region ; +void xe_vram_resize_bar (struct xe_device *xe);int xe_vram_probe (struct xe_device *xe);struct xe_vram_region *xe_vram_region_alloc (struct xe_device *xe,u8 id,u32 placement);
Greg Kroah-Hartman
maintainerPATCH 159/159 drm/xe: Dont allow evicting of BOs in same VM in array of VM binds
In reply to Greg Kroah-Hartman6.17-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Brost <[email protected]>
[ Upstream commit 7ac74613e5f2ef3450f44fd2127198662c2563a9 ]
An array of VM binds can potentially evict other buffer objects (BOs) within the same VM under certain conditions, which may lead to NULL pointer dereferences later in the bind pipeline. To prevent this, clear the allow_res_evict flag in the xe_bo_validate call.
v2:
- Invert polarity of no_res_evict (Thomas)
- Add comment in code explaining issue (Thomas)
--- drivers/gpu/drm/xe/xe_vm.c | 32 +++++++++++++++++++++++--------- drivers/gpu/drm/xe/xe_vm_types.h | 2 ++ 2 files changed, 25 insertions(+), 9 deletions(-)
drivers/gpu/drm/xe/xe_vm.c +23 -9
@@ -2894,7 +2894,7 @@ static void vm_bind_ioctl_ops_unwind(str }static int vma_lock_and_validate (struct drm_exec *exec,struct xe_vma *vma, -bool validate) +bool res_evict,bool validate) {struct xe_bo *bo =xe_vma_bo (vma);struct xe_vm *vm =xe_vma_vm (vma);
@@ -2905,7 +2905,8 @@ static int vma_lock_and_validate(struct err =drm_exec_lock_obj (exec, &bo->ttm.base);if (!err && validate) err =xe_bo_validate (bo, vm, - !xe_vm_in_preempt_fence_mode (vm)); + !xe_vm_in_preempt_fence_mode (vm) && + res_evict); }return err;
@@ -2978,14 +2979,23 @@ static int prefetch_ranges(struct xe_vm }static int op_lock_and_prep (struct drm_exec *exec,struct xe_vm *vm, -struct xe_vma_op *op) +struct xe_vma_ops *vops,struct xe_vma_op *op) {int err =0 ; +bool res_evict; + +/* +* We only allow evicting a BO within the VM if it is not part of an +* array of binds, as an array of binds can evict another BO within the +* bind. +*/ + res_evict = !(vops->flags &XE_VMA_OPS_ARRAY_OF_BINDS );switch (op->base.op) {case DRM_GPUVA_OP_MAP :if (!op->map.invalidate_on_bind) err =vma_lock_and_validate (exec, op->map.vma, + res_evict, !xe_vm_in_fault_mode (vm) || op->map.immediate);break ;
@@ -2996,11 +3006,13 @@ static int op_lock_and_prep(struct drm_e err =vma_lock_and_validate (exec,gpuva_to_vma (op->base.remap.unmap->va), - false); + res_evict, false);if (!err && op->remap.prev) - err =vma_lock_and_validate (exec, op->remap.prev, true); + err =vma_lock_and_validate (exec, op->remap.prev, + res_evict, true);if (!err && op->remap.next) - err =vma_lock_and_validate (exec, op->remap.next, true); + err =vma_lock_and_validate (exec, op->remap.next, + res_evict, true);break ;case DRM_GPUVA_OP_UNMAP : err =check_ufence (gpuva_to_vma (op->base.unmap.va));
@@ -3009,7 +3021,7 @@ static int op_lock_and_prep(struct drm_e err =vma_lock_and_validate (exec,gpuva_to_vma (op->base.unmap.va), - false); + res_evict, false);break ;case DRM_GPUVA_OP_PREFETCH : {
@@ -3025,7 +3037,7 @@ static int op_lock_and_prep(struct drm_e err =vma_lock_and_validate (exec,gpuva_to_vma (op->base.prefetch.va), - false); + res_evict, false);if (!err && !xe_vma_has_no_bo (vma)) err =xe_bo_migrate (xe_vma_bo (vma), region_to_mem_type[region]);
@@ -3069,7 +3081,7 @@ static int vm_bind_ioctl_ops_lock_and_prreturn err;list_for_each_entry (op, &vops->list, link) { - err =op_lock_and_prep (exec, vm, op); + err =op_lock_and_prep (exec, vm, vops, op);if (err)return err; }
@@ -3698,6 +3710,8 @@ int xe_vm_bind_ioctl(struct drm_device * }xe_vma_ops_init (&vops, vm, q, syncs, num_syncs); +if (args->num_binds >1 ) + vops.flags |=XE_VMA_OPS_ARRAY_OF_BINDS ;for (i =0 ; i < args->num_binds; ++i) {u64 range = bind_ops[i].range;u64 addr = bind_ops[i].addr;
drivers/gpu/drm/xe/xe_vm_types.h +2 -0
@@ -467,6 +467,8 @@ struct xe_vma_ops {struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE ];/** @flag: signify the properties within xe_vma_ops*/ #define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0) +#define XE_VMA_OPS_FLAG_MADVISE BIT(1) +#define XE_VMA_OPS_ARRAY_OF_BINDS BIT(2)u32 flags;#ifdef TEST_VM_OPS_ERROR /** @inject_error: inject error to test error handling */
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release.
Hmm:
* LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o
* MODPOST Module.symvers
*ERROR: modpost: "pm_hibernation_mode_is_suspend" [drivers/gpu/drm/amd/amdgpu/amdgpu.ko] undefined!
Caused by drm-amd-fix-hybrid-sleep.patch
I have CONFIG_SUSPEND enabled, exactly same config as 6.17.4.
Looking at mainline it seems we also need parts of:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=495c8d35035edb66e3284113bef01f3b1b843832
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bbfe987c5a2854705393ad79813074e5eadcbde6
cheers
Holger
Quoted 11 lines · Holger Hoffstätte
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release.
Hmm:
* LD [M]
drivers/gpu/drm/amd/amdgpu/amdgpu.o
* MODPOST Module.symvers
*ERROR: modpost: "pm_hibernation_mode_is_suspend" [drivers/gpu/drm/amd/amdgpu/amdgpu.ko] undefined!Caused by drm-amd-fix-hybrid-sleep.patch
Quoted 8 lines
I have
CONFIG_SUSPENDenabled, exactly same config as 6.17.4.Looking at mainline it seems we also need parts of:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ commit/?id=495c8d35035edb66e3284113bef01f3b1b843832
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ commit/?id=bbfe987c5a2854705393ad79813074e5eadcbde6cheers
Holger
Can you please share your kconfig?
Specifically interesting are CONFIG_SUSPEND, CONFIG_HIBERNATION, CONFIG_HIBERNATE_CALLBACKS.
Quoted 20 lines · Mario Limonciello (AMD) (kernel.org)
Quoted 17 lines · Holger Hoffstätte
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release.
Hmm:
* LD [M]
drivers/gpu/drm/amd/amdgpu/amdgpu.o
* MODPOST Module.symvers
*ERROR: modpost: "pm_hibernation_mode_is_suspend" [drivers/gpu/drm/amd/amdgpu/amdgpu.ko] undefined!Caused by drm-amd-fix-hybrid-sleep.patch
I have
CONFIG_SUSPENDenabled, exactly same config as 6.17.4.Looking at mainline it seems we also need parts of:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ commit/?id=495c8d35035edb66e3284113bef01f3b1b843832
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ commit/?id=bbfe987c5a2854705393ad79813074e5eadcbde6
Quoted 6 lines
Quoted 2 lines
cheers
HolgerCan you please share your kconfig?
Specifically interesting are
CONFIG_SUSPEND,CONFIG_HIBERNATION,CONFIG_HIBERNATE_CALLBACKS.
$grep -e CONFIG_SUSPEND -e CONFIG_HIBERNATION -e CONFIG_HIBERNATE_CALLBACKS /etc/kernels/kernel-config-x86_64-6.17.5 CONFIG_SUSPEND=yCONFIG_SUSPEND_FREEZER=y
# CONFIG_SUSPEND_SKIP_SYNC is not set
# CONFIG_HIBERNATION is not set
This is intentional as I don't use hibernation, only suspend-to-ram.
thanks,
Holger
Quoted 34 lines · Holger Hoffstätte
Quoted 20 lines · Mario Limonciello (AMD) (kernel.org)
Quoted 17 lines · Holger Hoffstätte
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release.
Hmm:
* LD [M]
drivers/gpu/drm/amd/amdgpu/amdgpu.o
* MODPOST Module.symvers
*ERROR: modpost: "pm_hibernation_mode_is_suspend" [drivers/gpu/drm/amd/amdgpu/amdgpu.ko] undefined!Caused by drm-amd-fix-hybrid-sleep.patch
I have
CONFIG_SUSPENDenabled, exactly same config as 6.17.4.Looking at mainline it seems we also need parts of:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ commit/?id=495c8d35035edb66e3284113bef01f3b1b843832
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ commit/?id=bbfe987c5a2854705393ad79813074e5eadcbde6Quoted 6 lines
Quoted 2 lines
cheers
HolgerCan you please share your kconfig?
Specifically interesting are
CONFIG_SUSPEND,CONFIG_HIBERNATION,CONFIG_HIBERNATE_CALLBACKS.$grep -e
CONFIG_SUSPEND-eCONFIG_HIBERNATION-eCONFIG_HIBERNATE_CALLBACKS/etc/kernels/kernel-config-x86_64-6.17.5CONFIG_SUSPEND=yCONFIG_SUSPEND_FREEZER=y
#CONFIG_SUSPEND_SKIP_SYNCis not set
#CONFIG_HIBERNATIONis not set
Quoted 4 lines
This is intentional as I don't use hibernation, only suspend-to-ram.
thanks,
Holger
OK I think that we need those other commits you identified brought back too.
Greg Kroah-Hartman
maintainerQuoted 9 lines · Holger Hoffstätte
Quoted 1 line · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release.
Hmm:
* LD [M]
drivers/gpu/drm/amd/amdgpu/amdgpu.o
* MODPOST Module.symvers
*ERROR: modpost: "pm_hibernation_mode_is_suspend" [drivers/gpu/drm/amd/amdgpu/amdgpu.ko] undefined!
Quoted 7 lines
Caused by drm-amd-fix-hybrid-sleep.patch
I have
CONFIG_SUSPENDenabled, exactly same config as 6.17.4.Looking at mainline it seems we also need parts of:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=495c8d35035edb66e3284113bef01f3b1b843832
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bbfe987c5a2854705393ad79813074e5eadcbde6
Thanks, let me go fix this up and push out a -rc2.
greg k-h
Hi
no regressions here on x86_64 (RKL, Intel 11th Gen. CPU)
Thanks
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release. There are 159 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 23 Oct 2025 19:49:51 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.17.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.17.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
The kernel, bpf tool, perf tool, and kselftest builds fine for v6.17.5-rc1 on x86 and arm64 Azure VM.
Thanks,
Hardik
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.17.5 release. There are 159 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 23 Oct 2025 19:49:51 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.17.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.17.y
and the diffstat can be found below.
Quoted 9 lines
thanks,
greg k-h
Mario Limonciello <[email protected]>
drm/amd: Check whether secure display TA loaded successfully
Verified that the error messages are now gone with this patch.
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah