PCIe says: »Tag[7:0] is a 8-bit field generated by each Requestor, and it must be unique for all outstanding Requests that require a Completion for that Requester«. Requester ID and Tag together form the Transaction ID. This Transaction ID must be unique for all outstanding requests in the system, not the Tag alone, just the Tags of a single Requester.
The Requester always knows which transactions, initiated by him, are not completed yet, so it must not use a tag of those unfinished requests. The Tags used by other Requesters, probably reading data from this device, are completely independent from that. In the process of completing such Requests, you have to return the Requester’s Transaction ID, irrespective of your own Tag housekeeping.
There are different strategies for keeping track of valid Tags to be used in Requests initiated by your device: Just use a single Tag if you can live with waiting for all returned data before you re-use this tag. For higher performance, one would issue interleaved requests, for which one might want to keep a pool of Tags. A Tag is consumed from this pool upon starting a request, and Tags are recycled when all Completions for it are have been received. Furthermore, one should keep track of outstanding Requests and recycle those Tags that didn’t get the expected completions within the Completion Timeout.