On 06/08/2015 06:24 PM, Manoj Kumar wrote:
> On 6/8/2015 5:56 PM, Brian King wrote:
>>> +retry:
>>> + newval = atomic64_dec_if_positive(&afu->room);
>>> + if (!newval) {
>>> + do {
>>> + room = readq_be(&afu->host_map->cmd_room);
>>> + atomic64_set(&afu->room, room);
>>> + if (room)
>>> + goto write_ioarrin;
>>> + } while (nretry++ < MC_ROOM_RETRY_CNT);
>>
>> It looks like you removed the udelay here. Was that intentional?
>
> Pulled out going to sleep in the queuecommand path.
udelay doesn't sleep, its a busy wait, so you can still use it in queuecommand,
just don't spend too much time, and its probably better to udelay then to
just re-read in a tight loop.
>
>>> +
>>> + pr_err("%s: no cmd_room to send 0x%X\n",
>>> + __func__, cmd->rcb.cdb[0]);
>>> + rc = SCSI_MLQUEUE_HOST_BUSY;
>>
>> If you actually get here, how do you get out of this state? Since now
>> afu->room is
>> zero and anyone that comes through here will go to the else if leg.
>
> This was the optimization to avoid the MMIO for both threads. The other
> thread that raced should do the atomic set of afu->room to a positive value.
Let's take the simpler scenario of just one thread.
Let's start with afu->room = 1
We call atomic64_dec_if_positive, which results in afu->room going to zero and
0 being returned,
so we go into the if leg.
If afu->room is zero every time we read it from the adapter and we exhaust our
retries,
we return SCSI_MLQUEUE_HOST_BUSY. However, the next time we enter
cxlflash_send_cmd,
since afu->cmd is now 0, it will no longer get decremented, but the return
value will
be -1, so we'll go down the else if leg. We'll never get into the if leg again
to
re-read afu->room from the AFU. The simplest fix might just be to set afu->room
= 1
if you ever leave the if leg without having room.
+ newval = atomic64_dec_if_positive(&afu->room);
+ if (!newval) {
+ do {
+ room = readq_be(&afu->host_map->cmd_room);
+ atomic64_set(&afu->room, room);
+ if (room)
+ goto write_ioarrin;
+ } while (nretry++ < MC_ROOM_RETRY_CNT);
+
+ pr_err("%s: no cmd_room to send 0x%X\n",
+ __func__, cmd->rcb.cdb[0]);
+ rc = SCSI_MLQUEUE_HOST_BUSY;
+ goto out;
+ } else if (unlikely(newval < 0)) {
+ /* This should be rare. i.e. Only if two threads race and
+ * decrement before the MMIO read is done. In this case
+ * just benefit from the other thread having updated
+ * afu->room.
+ */
+ if (nretry++ < MC_ROOM_RETRY_CNT)
+ goto retry;
+ else {
+ rc = SCSI_MLQUEUE_HOST_BUSY;
+ goto out;
+ }
+ }
>
>>> + goto out;
>>> + } else if (unlikely(newval < 0)) {
>>> + /* This should be rare. i.e. Only if two threads race and
>>> + * decrement before the MMIO read is done. In this case
>>> + * just benefit from the other thread having updated
>>> + * afu->room.
>>> + */
>>> + if (nretry++ < MC_ROOM_RETRY_CNT)
>>
--
Brian King
Power Linux I/O
IBM Linux Technology Center
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html