 So, we do see something, really. Yay, we do see something. Right. So. Can you increase the font size, please? The font size? Better? No, the thing is that originally, the original design of LibATA was that LibATA could be used standalone without ever recurring to discuss the subsystem. And, but then, as it was quite complicated, they added a SCSI layer in between, such that all commands are actually coming in via the SCSI layer. This was primarily due to facilitate the use of a TAPI device, meaning CD-ROMs, which essentially had been using SCSI CDBs internally already all the time. So, meaning that the sole user of LibATA really is SCSI. There is no other user. And it turns out that it's getting more and more cumbersome trying to separate those two out, especially due to the work that John Gary did for updating LibSauce, because LibSauce can also recur to LibATA. And so, it always gets into issues and some weird pointer usage to figure out, right, is this a SCSI command? Is this an ATI command? What is it now we're dealing with? So, the proposal is to give up the pretension that we could ever use LibATA without the SCSI interface, and more tightly couple both of them, such that we don't have the problem that we can't call SCSI functions within LibATA. Case in point here is that one, because if we were doing that, we could put the ATI-specific things, that's the ATI-Q command, as the payload of the SCSI command. That's what you see here, what this would entail to. So, we would always allocate a SCSI request, a structure request and a SCSI command for all ATI commands. So, that would be helpful, because that would mean that also the internal commands would show up as SCSI commands. Currently, the internal commands are allocated internally and will never ever show up in the tag map of the request, or of the request queue. With that, they will show up and we can use iterators when walking the list of outstanding commands. Again, quite helpful. So, the problem is this ominous internal tag. So, the LibATA has the notion of an internal tag, which is being used for sending internal commands. This tag is tag number 32 of 31 available tags. No, there are 32 available tags. It's number 33 or value 32. It's actually not a tag. So, to be precise, it's called a tag without being a tag. Yeah, exactly. So, essentially, you have a queue depth of 32, starting from zero, and you allocate tag number 32. So, meaning that one beyond the actual queue depth. The reason why this one works is that those internal commands are not queued. So, again, in ATA speciality, the ATA can use tag commands, but these are the commands themselves are distinct from the normal commands. So, there are commands and there are tag commands. And those commands which are non-tag, obviously don't require a tag, but also, for those we don't need to wait for any tag to become free, because they are the only commands which are outstanding on the queue at that time. And that is also why this one here works. It's got the alert request that's being called. It will be for an internal tag, which will be had to be checked, but the assumption is that they will be non-queued, and therefore, the queue always will be free by the time we're sending the command. And in case of error here, we need a big fat warning, because that should not happen. In case of an error, can we get into this situation when error happens and the queue is full? Well, the queue is full means that you send 32-NCQ commands. So, that all tags are busy, and we get an error, we can't. No, no, no. So, the queue is full means that you send 32-NCQ commands, and if one of them fails, you get them back on your lap because you get a queue abort on ATA. Whose queue is full? The drive queue. The ATA drive or the discussed? ATA drive. But that has a fixed number of queue slots. Yes, constant. That's what we're saying, 32 at most. I don't understand the question. So, the problem is that we don't want that Scasialloc request to fail for an internal command, which is a non-queued command. And the assumption, of course, is that when you issue that command, you don't have any NCQ command ongoing, so nothing queued on the drive. And that's the reason why that call to ATA request shouldn't fail because you don't have any command ongoing. The problem, though, is that most of the time we start issuing internal commands to either recover from a failed NCQ command or because we're scanning the drive. If we're scanning or revalidating the drive, we're reading a bunch of block pages and we are in an error recovery context to prevent NCQ commands in the BTA, so nothing is going on. The drive is essentially idle. That's going to work. The problem is the situation where you send 32 tack command to the drive, the drive queue is full. You can't send anything more. One of those fail. You get back, you get an ATA queue abort, so all the commands... You get back all 32 with a failure. Yeah, but the 32 commands are using a Scasialloc request. So now what happens to this one, when you want to unlock that internal command to go and get the sense that I had to know which one failed and get the drive out of her state, you need that internal command and that one can fail. Damien, this is what the reserve tax are for, right? No, specifically for Arihan. With the current implementation, yes, because we actually have 33 twosies. Right, I'm saying... But that one... No, but let me finish. So block and queue has a notion of a reserve tag. Yes. When you set up a tag set, you say my depth is 32 and I would like one reserve tag, right? You reserve this reserve tag for error handling purposes, right, that's why it exists. So you can never... This would need to dip into the reserve pool. Since you can't have these queued anyway, you can't have multiple error operations going at the same time, but if the drive and normal tag set is full, right, you still have your reserve tag and that's what you use it for. And for this case, it's fine, right, because you don't care about the actual tag, obviously, since it's outside of the bounds. You just need to be able to allocate a request that's specifically for error handling, which is what that is. Okay, so I can use reserve tag. Okay. Yeah, because... But that means... But you don't have any more outstanding commands in the drive. Once you get an error, every single command is failed out of the drive. Yes, it is. Logically, it's just failed. So, exactly. So, the thing is, logically, they are failed, but they're still marked busy, internal in the hostwares. Yeah, the... Meaning we can't allocate a new command because all the tags are still nominally busy in the host. And in order to recover anything, we would need to send whatever, read log page something like blah, blah, before we know the status of these commands. They all will be failed, clearly for the... In the ATA case. But we still would need to recover the data and would need to have an additional step for freeing up the tags. Am I correct, Jens? Yeah, no, then you're right. Yeah, yeah. So, you just need... The request is just a placeholder, right, to be able to talk to the platform. So, meaning I have your okay to have an... To update the SCSI layer to have internal tags. Oh, yeah. Okay. Right. Muted. Well, actually... I think, I mean, that's how you would do the error handling. And I fully support the notion of getting rid of this. I mean, I think that the idea of a de-separating or having Libby ATA be separate from SCSI, right, is maybe an old pipe dream these days that's so far from reality. Just embrace it and get rid of this private array of things and just set up your queue depth of 32 with one reserve tag. Okay. And if SCSI doesn't support that, yeah, then you would need to have a little bit of SCSI surgery. I can't speak to that, but for sure, this would be the canonical way of achieving this goal. Okay. That would be the way to do it. Good. Cool. John, but now the question to you. That would mean that... Can you show the... I think I can. Ah, well. So just, I don't mean to be pedantic, but you have a SCSI request, AP to SCSI queue, I regret. So... See if that is right. Sorry. What this does is that essentially it gets rid of one of the pointers in the SAS task. That's the ULDD task. With that, we can get rid of that pointer because then the ULDD task will always point to a SCSI command. It would also mean, unfortunately, that we would always allocate an ATA queue command even for real SAS commands. Okay. Just something I've run into a problem is that when you initially try to send ATA internal commands, you don't have a SCSI device available yet today. That is, and without that, you don't have a request queue. So you can't really allocate an internal command for a SCSI device which doesn't exist yet. For SAS, you mean? For all right for discovery? Yeah. Right, okay, so no. This is, so primarily this is, if you listen closely, is for the ATA stack. Right. So this is for QC issue type things. Yeah. Don't think you need QC issue for the initial SAS discovery, do you? Well, when it's sending the initial internal commands, you need, what you're doing here, you need a request queue and the obvious one would be the SCSI device request queue, which when you're doing the inquiry or discovery isn't available yet, which is a problem. Yeah, I mean, but this is, I think it's a different problem because this is, again, just for ATA now. Yeah. So we would always allocate the ATA structure for the SCSI command, even though it's a SAS. Say that again, you'll always allocate the what? Sorry? Sorry? You said you'll always allocate the SCSI. Yeah. What? So now the thing is that's for SAS tasks. Yeah. It would mean that all SAS tasks will always have a bit of additional space in the command structure, which refers to the ATA command, even though it might be a real SAS task which doesn't have an ATA one. Yeah. So it's slightly wasteful for SAS in this case. The point I'm just trying to make today is the problem that you've got an ordering issue that you don't have, if you wanna send an internal command, you don't have a SCSI device yet with the request queue. So, okay, that's all I'm saying. So yeah, but this is also something which I hope to resolve by more tightly integrating because that means I actually can refer to the SCSI device even from Lib ATA. Currently I can't because Lib ATA is not supposed to know that there is a SCSI device, which really is a bit bonkers. So, if we were able to refer directly to the SCSI device from Lib ATA, we would get rid of that one. Damien, anything to add? Yeah, no, I just need to see code. But I think, yeah, Jens' idea of the reserve tag is probably the easiest. Yeah. That matches what exists today with the internal QCCMD array which we can get rid of. Yeah. But it also means that if we need to send NCQ commands via internal NCQ commands, we will need to have a special flag such that we can use the tag allocated because for NCQ commands, we actually do need to use the tag allocated. So, read log, the classic one, read log, read log NCQ, that needs to go via... Right now, nobody's using that, so there's no such code. I actually need to add it for some stuff, but in that case, for command ration limits, for recovery, and then NCQ read log. I'm pretty sure I added the code at one point. No, read log doesn't go. I haven't seen the packing into NCQ commands for read log. Anywhere. So, I may have missed it, but I don't think it's there. So, if we only ever send non-NCQ command via the internal one, we have to check. Okay, so the next question really is then, which my work is stuck on, is what to do next with the internal command? Well, I just got the okay that I can do it. So, meaning that I can at least, I can add the Nessay infrastructure so that the SCSI layer can use internal commands. Currently, there is no infrastructure for you, allowing you even to allocate and to specify that. So, that would be the first step to getting the infrastructure such that the SCSI device can use internal tags, or the reserve tags. Okay, so what I was really saying was that normally once you allocate the internal tag, you call issue QC, which in the case of AHCI, I assume it sends directly to the hardware. But if you've got a SAS stack, that needs to be handled directly by the hardware as well. Exactly, in the SAS case, I really have to look that. It sounds a bit odd what SAS does there. So, I really have to check how this ties together. Because it's, for internal commands, they are being sent via SAS and then back to QC, and then I'm getting confused. What do you do if you send an ATA internal command with this, also go back wire? So, ugh, I have to survive. I was wondering if you answered any idea on that, because today, if you just allocate the SCSI request, all it just does is uses it as a placeholder. Yeah. And that's it. And as the work I was doing, the idea was to try and send that to the block layer, which is quite problematic. Yep. All right. Good, let's see where we end up when trying to do so. But at least, so the internal tags, the internal tag allocation will be the first step, and then we can build upon that, how we can update the one and other driver to actually use it. So, the first ATA will possibly be the first one, because that really makes sense to get rid of this internal tag stuff. And we also will be able to get rid of the tag pointer in the QC itself, because, well, we can just infer it from the SCSI command, as there's always no SCSI command attached to it. Well, yeah. You need to add the back pointer to the SCSI command from QC, or the story there. Well, then there's a back pointer. You just, it container off? I mean, it's embedded. Yeah. You don't need the back pointer anymore? Yes. Yes. So that's the good thing. So it actually shortens down on the structures. So, beneficial all around. Okay.