struct smbdirect_recv_io *response;
struct smbdirect_socket *sc =
container_of(work, struct smbdirect_socket, recv_io.posted.refill_work);
+ int posted = 0;
if (sc->status != SMBDIRECT_SOCKET_CONNECTED) {
return;
}
atomic_inc(&sc->recv_io.posted.count);
+ posted += 1;
}
}
+ atomic_add(posted, &sc->recv_io.credits.available);
+
/* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
if (atomic_read(&sc->recv_io.credits.count) <
sc->recv_io.credits.target - 1) {
*/
static int manage_credits_prior_sending(struct smbdirect_socket *sc)
{
+ int missing;
+ int available;
int new_credits;
if (atomic_read(&sc->recv_io.credits.count) >= sc->recv_io.credits.target)
return 0;
- new_credits = atomic_read(&sc->recv_io.posted.count);
- if (new_credits == 0)
+ missing = (int)sc->recv_io.credits.target - atomic_read(&sc->recv_io.credits.count);
+ available = atomic_xchg(&sc->recv_io.credits.available, 0);
+ new_credits = (u16)min3(U16_MAX, missing, available);
+ if (new_credits <= 0) {
+ /*
+ * If credits are available, but not granted
+ * we need to re-add them again.
+ */
+ if (available)
+ atomic_add(available, &sc->recv_io.credits.available);
return 0;
+ }
- new_credits -= atomic_read(&sc->recv_io.credits.count);
- if (new_credits <= 0)
- return 0;
+ if (new_credits < available) {
+ /*
+ * Readd the remaining available again.
+ */
+ available -= new_credits;
+ atomic_add(available, &sc->recv_io.credits.available);
+ }
+ /*
+ * Remember we granted the credits
+ */
+ atomic_add(new_credits, &sc->recv_io.credits.count);
return new_credits;
}
packet->credits_requested = cpu_to_le16(sp->send_credit_target);
new_credits = manage_credits_prior_sending(sc);
- atomic_add(new_credits, &sc->recv_io.credits.count);
packet->credits_granted = cpu_to_le16(new_credits);
packet->flags = 0;