FreeBSD Bugzilla – Attachment 228827 Details for
Bug 258994
iic(4): Panics on Nanopi Neo when using 16-bit device addressing width: panic: Assertion strlen(description) < MAX_W_NAME failed at ... sys/kern/subr_witness.c:1914
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Added some improvements.
twsi.c.patch (text/plain), 7.65 KB, created by
alydiomc
on 2021-10-19 07:39:47 UTC
(
hide
)
Description:
Added some improvements.
Filename:
MIME Type:
Creator:
alydiomc
Created:
2021-10-19 07:39:47 UTC
Size:
7.65 KB
patch
obsolete
>diff --git a/sys/dev/iicbus/twsi/twsi.c b/sys/dev/iicbus/twsi/twsi.c >index a606c2aef..591a829fc 100644 >--- a/sys/dev/iicbus/twsi/twsi.c >+++ b/sys/dev/iicbus/twsi/twsi.c >@@ -550,7 +550,6 @@ twsi_intr(void *arg) > case TWSI_STATUS_RPTD_START: > /* Transmit the address */ > debugf(sc->dev, "Send the address (%x)", sc->msgs[sc->msg_idx].slave); >- > if (sc->msgs[sc->msg_idx].flags & IIC_M_RD) > TWSI_WRITE(sc, sc->reg_data, > sc->msgs[sc->msg_idx].slave | LSB); >@@ -576,7 +575,19 @@ twsi_intr(void *arg) > debugf(sc->dev, "Ack received after transmitting the address (read)\n"); > sc->recv_bytes = 0; > >- TWSI_WRITE(sc, sc->reg_control, sc->control_val); >+ /* If we are expecting one byte, disable ACK now or else we will miss >+ * TWSI_STATUS_DATA_RD_NOACK event. Per I2C standard the last data received >+ * will not be acknowledged. */ >+ if (sc->msgs[sc->msg_idx].len - sc->recv_bytes == 1){ >+ debugf(sc->dev, "Expecting one byte to receive, disabling ACK bit...\n"); >+ sc->control_val &= ~TWSI_CONTROL_ACK; >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); >+ /* Else, set ACK bit to acknowledge incoming data. >+ * TWSI_STATUS_DATA_RD_ACK will handle succeeding received envents. */ >+ } else { >+ sc->control_val |= TWSI_CONTROL_ACK; >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); >+ } > break; > > case TWSI_STATUS_ADDR_W_NACK: >@@ -590,75 +601,90 @@ twsi_intr(void *arg) > > case TWSI_STATUS_DATA_WR_ACK: > debugf(sc->dev, "Ack received after transmitting data\n"); >- if (sc->sent_bytes == sc->msgs[sc->msg_idx].len) { >+ /* Check if all data have been sent already.*/ >+ if (sc->sent_bytes == sc->msgs[sc->msg_idx].len) { > debugf(sc->dev, "Done sending all the bytes for msg %d\n", sc->msg_idx); >- /* Send stop, no interrupts on stop */ >- if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) { >- debugf(sc->dev, "Done TX data, send stop\n"); >- TWSI_WRITE(sc, sc->reg_control, >- sc->control_val | TWSI_CONTROL_STOP); >- } else { >- debugf(sc->dev, "Done TX data with NO_STOP\n"); >- TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); >- } >+ >+ /* Move to next message and decide the next operation to perform. */ > sc->msg_idx++; >- if (sc->msg_idx == sc->nmsgs) { >- debugf(sc->dev, "transfer_done=1\n"); >- transfer_done = 1; >- sc->error = 0; >+ sc->sent_bytes=0; /* Reset sent counter */ >+ >+ if (sc->msg_idx == sc->nmsgs) { >+ /* If we are done with all the messages, end the transfer. */ >+ debugf(sc->dev, "Done all massages, sending STOP\n"); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_STOP); >+ transfer_done = 1; >+ sc->transfer = 0; >+ sc->error = 0; >+ /* Else, process the next messages */ >+ } else if (sc->msgs[sc->msg_idx].flags == IIC_M_RD) { >+ /* If flag is IIC_M_RD, perform repeat START */ >+ debugf(sc->dev, "Done with massages[%d], sending repeat START\n", sc->msg_idx-1 ); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); > } else { >- debugf(sc->dev, "Send repeated start\n"); >- TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); >- } >- } else { >- debugf(sc->dev, "Sending byte %d (of %d) = %x\n", >- sc->sent_bytes, >- sc->msgs[sc->msg_idx].len, >- sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); >- TWSI_WRITE(sc, sc->reg_data, >- sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); >- TWSI_WRITE(sc, sc->reg_control, >- sc->control_val); >- sc->sent_bytes++; >+ /* Otherwise, treat it as a continuation of write operation. >+ * Immediately send the first data of the next message. >+ * >+ * from i2c.c notes: >+ * If the transfer direction is write and we did a write of the offset >+ * above, then we need to elide the start; this transfer is just more >+ * writing that follows the one started above. */ >+ >+ debugf(sc->dev, "Sending data=%x of msg[%d]\n", >+ sc->msgs[sc->msg_idx].buf[sc->sent_bytes], sc->msg_idx); >+ TWSI_WRITE(sc, sc->reg_data, sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); >+ sc->sent_bytes++; >+ } >+ >+ /* Send remaining data */ >+ } else { >+ debugf(sc->dev, "Sending data=%x of msg[%d]\n", sc->msgs[sc->msg_idx].buf[sc->sent_bytes], sc->msg_idx); >+ TWSI_WRITE(sc, sc->reg_data, sc->msgs[sc->msg_idx].buf[sc->sent_bytes]); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); >+ sc->sent_bytes++; > } >- break; >+ break; >+ > > case TWSI_STATUS_DATA_RD_ACK: > debugf(sc->dev, "Ack received after receiving data\n"); > sc->msgs[sc->msg_idx].buf[sc->recv_bytes++] = TWSI_READ(sc, sc->reg_data); > debugf(sc->dev, "msg_len=%d recv_bytes=%d\n", sc->msgs[sc->msg_idx].len, sc->recv_bytes); > >- /* If we only have one byte left, disable ACK */ >- if (sc->msgs[sc->msg_idx].len - sc->recv_bytes == 1) >+ /* If we only have one byte left to receive , disable ACK bit now * >+ * so that TWSI_STATUS_DATA_RD_NOACK for will be triggered for next event. */ >+ if (sc->msgs[sc->msg_idx].len - sc->recv_bytes == 1){ >+ debugf(sc->dev, "Last byte, disabling ACK bit...\n"); > sc->control_val &= ~TWSI_CONTROL_ACK; >- if (sc->msgs[sc->msg_idx].len == sc->recv_bytes) { >- debugf(sc->dev, "Done with msg %d\n", sc->msg_idx); >- sc->msg_idx++; >- if (sc->msg_idx == sc->nmsgs - 1) { >- debugf(sc->dev, "No more msgs\n"); >- transfer_done = 1; >- sc->error = 0; >- } >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); >+ } else { >+ /* Ensure we ACK the next data we received */ >+ sc->control_val |=TWSI_CONTROL_ACK; >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); > } >- TWSI_WRITE(sc, sc->reg_control, sc->control_val); > break; > > case TWSI_STATUS_DATA_RD_NOACK: >- if (sc->msgs[sc->msg_idx].len - sc->recv_bytes == 1) { >- sc->msgs[sc->msg_idx].buf[sc->recv_bytes++] = TWSI_READ(sc, sc->reg_data); >- debugf(sc->dev, "Done RX data, send stop (2)\n"); >- if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) >- TWSI_WRITE(sc, sc->reg_control, >- sc->control_val | TWSI_CONTROL_STOP); >+ /* Put the data on the receive buffer. */ >+ sc->msgs[sc->msg_idx].buf[sc->recv_bytes++] = TWSI_READ(sc, sc->reg_data); >+ debugf(sc->dev, "Done receiving all the byte(s) for msg %d\n", sc->msg_idx); >+ >+ sc->msg_idx++; /* Ready for next message */ >+ sc->recv_bytes=0; /* Reset receive counter */ >+ if (sc->msg_idx == sc->nmsgs) { >+ debugf(sc->dev, "Done all massages, sending STOP\n"); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_STOP); >+ transfer_done = 1; >+ sc->transfer = 0; >+ sc->error = 0; > } else { >- debugf(sc->dev, "No ack when receiving data, sending stop anyway\n"); >- if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) >- TWSI_WRITE(sc, sc->reg_control, >- sc->control_val | TWSI_CONTROL_STOP); >+ /* If we have more messages, start over. */ >+ debugf(sc->dev, "Done with massages[%d], sending repeat START\n", sc->msg_idx-1 ); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); >+ TWSI_WRITE(sc, sc->reg_control, sc->control_val); > } >- sc->transfer = 0; >- transfer_done = 1; >- sc->error = 0; > break; > > default:
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 258994
:
228624
| 228827