Message ID | 20220119014459.3904-1-wei.huang@intel.com (mailing list archive) |
---|---|
State | Accepted, archived |
Delegated to: | Qi Zhang |
Headers | show |
Series | [v1] raw/ifpga/base: fix SPI transaction | expand |
Context | Check | Description |
---|---|---|
ci/intel-Testing | success | Testing PASS |
ci/Intel-compilation | success | Compilation OK |
ci/iol-x86_64-unit-testing | success | Testing PASS |
ci/iol-aarch64-compile-testing | success | Testing PASS |
ci/iol-x86_64-compile-testing | success | Testing PASS |
ci/iol-aarch64-unit-testing | success | Testing PASS |
ci/iol-abi-testing | success | Testing PASS |
ci/iol-intel-Performance | success | Performance Testing PASS |
ci/github-robot: build | success | github build: passed |
ci/iol-broadcom-Performance | success | Performance Testing PASS |
ci/iol-intel-Functional | success | Functional Testing PASS |
ci/iol-mellanox-Performance | success | Performance Testing PASS |
ci/iol-broadcom-Functional | success | Functional Testing PASS |
ci/checkpatch | success | coding style OK |
Hi, > -----Original Message----- > From: Huang, Wei <wei.huang@intel.com> > Sent: Wednesday, January 19, 2022 9:45 > To: dev@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Qi Z > <qi.z.zhang@intel.com> > Cc: stable@dpdk.org; Zhang, Tianfei <tianfei.zhang@intel.com>; Yigit, Ferruh > <ferruh.yigit@intel.com> > Subject: [PATCH v1] raw/ifpga/base: fix SPI transaction > > From: Tianfei Zhang <tianfei.zhang@intel.com> > > When EOP is detected, 2 more bytes should be received (may be a > SPI_PACKET_ESC before last valid byte) then rx should be finished. > > Fixes: 96ebfcf8 ("raw/ifpga/base: add SPI and MAX10 device driver") > Cc: stable@dpdk.org > > Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com> > --- > drivers/raw/ifpga/base/opae_spi.c | 12 ++ > drivers/raw/ifpga/base/opae_spi.h | 4 + > drivers/raw/ifpga/base/opae_spi_transaction.c | 215 +++++++++++++++------ > ----- > 3 files changed, 140 insertions(+), 91 deletions(-) > > diff --git a/drivers/raw/ifpga/base/opae_spi.c > b/drivers/raw/ifpga/base/opae_spi.c > index 9efeecb..ca3d41f 100644 > --- a/drivers/raw/ifpga/base/opae_spi.c > +++ b/drivers/raw/ifpga/base/opae_spi.c > @@ -239,6 +239,18 @@ int spi_command(struct altera_spi_device *dev, > unsigned int chip_select, > return 0; > } > > +int spi_write(struct altera_spi_device *dev, unsigned int chip_select, > + unsigned int wlen, void *wdata) > +{ > + return spi_command(dev, chip_select, wlen, wdata, 0, NULL); } > + > +int spi_read(struct altera_spi_device *dev, unsigned int chip_select, > + unsigned int rlen, void *rdata) > +{ > + return spi_command(dev, chip_select, 0, NULL, rlen, rdata); } > + > struct altera_spi_device *altera_spi_alloc(void *base, int type) { > struct altera_spi_device *spi_dev = > diff --git a/drivers/raw/ifpga/base/opae_spi.h > b/drivers/raw/ifpga/base/opae_spi.h > index af11656..bcff67d 100644 > --- a/drivers/raw/ifpga/base/opae_spi.h > +++ b/drivers/raw/ifpga/base/opae_spi.h > @@ -117,6 +117,10 @@ struct spi_tran_header { > u32 addr; > }; > > +int spi_read(struct altera_spi_device *dev, unsigned int chip_select, > + unsigned int rlen, void *rdata); > +int spi_write(struct altera_spi_device *dev, unsigned int chip_select, > + unsigned int wlen, void *wdata); > int spi_command(struct altera_spi_device *dev, unsigned int chip_select, > unsigned int wlen, void *wdata, unsigned int rlen, void > *rdata); void spi_cs_deactivate(struct altera_spi_device *dev); diff --git > a/drivers/raw/ifpga/base/opae_spi_transaction.c > b/drivers/raw/ifpga/base/opae_spi_transaction.c > index 006cdb4..cd50d40 100644 > --- a/drivers/raw/ifpga/base/opae_spi_transaction.c > +++ b/drivers/raw/ifpga/base/opae_spi_transaction.c > @@ -40,7 +40,7 @@ static void print_buffer(const char *string, void *buffer, > int len) > printf("%s print buffer, len=%d\n", string, len); > > for (i = 0; i < len; i++) > - printf("%x ", *(p+i)); > + printf("%02x ", *(p+i)); > printf("\n"); > } > #else > @@ -72,43 +72,6 @@ static void reorder_phy_data(u8 bits_per_word, > } > } > > -enum { > - SPI_FOUND_SOP, > - SPI_FOUND_EOP, > - SPI_NOT_FOUND, > -}; > - > -static int resp_find_sop_eop(unsigned char *resp, unsigned int len, > - int flags) > -{ > - int ret = SPI_NOT_FOUND; > - > - unsigned char *b = resp; > - > - /* find SOP */ > - if (flags != SPI_FOUND_SOP) { > - while (b < resp + len && *b != SPI_PACKET_SOP) > - b++; > - > - if (*b != SPI_PACKET_SOP) > - goto done; > - > - ret = SPI_FOUND_SOP; > - } > - > - /* find EOP */ > - while (b < resp + len && *b != SPI_PACKET_EOP) > - b++; > - > - if (*b != SPI_PACKET_EOP) > - goto done; > - > - ret = SPI_FOUND_EOP; > - > -done: > - return ret; > -} > - > static void phy_tx_pad(unsigned char *phy_buf, unsigned int phy_buf_len, > unsigned int *aligned_len) > { > @@ -137,6 +100,104 @@ static void phy_tx_pad(unsigned char *phy_buf, > unsigned int phy_buf_len, > *p++ = SPI_BYTE_IDLE; > } > > +#define RX_ALL_IDLE_DATA (SPI_BYTE_IDLE << 24 | SPI_BYTE_IDLE << 16 | > \ > + SPI_BYTE_IDLE << 8 | SPI_BYTE_IDLE) > + > +static bool all_idle_data(u8 *rxbuf) > +{ > + return *(u32 *)rxbuf == RX_ALL_IDLE_DATA; } > + > +static unsigned char *find_eop(u8 *rxbuf, u32 BPW) { > + return memchr(rxbuf, SPI_PACKET_EOP, BPW); } > + > +static int do_spi_txrx(struct spi_transaction_dev *dev, > + unsigned char *tx_buffer, > + unsigned int tx_len, unsigned char *rx_buffer, > + unsigned int rx_len, > + unsigned int *actual_rx) > +{ > + unsigned int rx_cnt = 0; > + int ret = 0; > + unsigned int BPW = 4; > + bool eop_found = false; > + unsigned char *eop; > + unsigned char *ptr; > + unsigned char *rxbuf = rx_buffer; > + int add_byte = 0; > + unsigned long ticks; > + unsigned long timeout; > + > + /* send command */ > + ret = spi_write(dev->dev, dev->chipselect, tx_len, tx_buffer); > + if (ret) > + return -EBUSY; > + > + timeout = rte_get_timer_cycles() + > + msecs_to_timer_cycles(2000); > + > + /* read out data */ > + while (rx_cnt < rx_len) { > + ret = spi_read(dev->dev, dev->chipselect, BPW, rxbuf); > + if (ret) > + return -EBUSY; > + > + /* skip all of invalid data */ > + if (!eop_found && all_idle_data(rxbuf)) { > + ticks = rte_get_timer_cycles(); > + if (!time_after(ticks, timeout)) { > + continue; > + } else { > + dev_err(dev, "read spi data timeout\n"); > + return -ETIMEDOUT; > + } > + } > + > + rx_cnt += BPW; > + if (!eop_found) { > + /* EOP is found, we read 2 more bytes and exit. */ > + eop = find_eop(rxbuf, BPW); > + if (eop) { > + if ((BPW + rxbuf - eop) > 2) { > + /* > + * check if the last 2 bytes are already > + * received in current word. > + */ > + break; > + } else if ((BPW + rxbuf - eop) == 2) { > + /* > + * skip if last byte is not SPI_BYTE_ESC > + * or SPI_PACKET_ESC. this is the valid > + * end of a response too. > + */ > + ptr = eop + 1; > + > + if (*ptr != SPI_BYTE_ESC && > + *ptr != > SPI_PACKET_ESC) > + break; > + > + add_byte = 1; > + } else { > + add_byte = 2; > + } > + > + rx_len = min(rx_len, > + IFPGA_ALIGN(rx_cnt + > + add_byte, BPW)); > + eop_found = true; > + } > + } > + rxbuf += BPW; > + } > + > + *actual_rx = rx_cnt; > + print_buffer("found valid data:", rx_buffer, rx_cnt); > + > + return ret; > +} > + > static int byte_to_core_convert(struct spi_transaction_dev *dev, > unsigned int send_len, unsigned char *send_data, > unsigned int resp_len, unsigned char *resp_data, @@ - > 148,15 +209,9 @@ static int byte_to_core_convert(struct > spi_transaction_dev *dev, > unsigned char *resp_packet = dev->buffer->bytes_resp; > unsigned char *p; > unsigned char current_byte; > - unsigned char *tx_buffer; > unsigned int tx_len = 0; > - unsigned char *rx_buffer; > - unsigned int rx_len = 0; > - int retry = 0; > - int spi_flags; > - unsigned long timeout = msecs_to_timer_cycles(1000); > - unsigned long ticks; > unsigned int resp_max_len = 2 * resp_len; > + unsigned int actual_rx; > > print_buffer("before bytes:", send_data, send_len); > > @@ -190,48 +245,15 @@ static int byte_to_core_convert(struct > spi_transaction_dev *dev, > > print_buffer("after order to spi:", send_packet, tx_len); > > - /* call spi */ > - tx_buffer = send_packet; > - rx_buffer = resp_packet; > - rx_len = resp_max_len; > - spi_flags = SPI_NOT_FOUND; > - > -read_again: > - ret = spi_command(dev->dev, dev->chipselect, tx_len, tx_buffer, > - rx_len, rx_buffer); > + ret = do_spi_txrx(dev, send_packet, tx_len, resp_packet, > + resp_max_len, &actual_rx); > if (ret) > - return -EBUSY; > - > - print_buffer("read from spi:", rx_buffer, rx_len); > - > - /* look for SOP firstly*/ > - ret = resp_find_sop_eop(rx_buffer, rx_len - 1, spi_flags); > - if (ret != SPI_FOUND_EOP) { > - tx_buffer = NULL; > - tx_len = 0; > - ticks = rte_get_timer_cycles(); > - if (time_after(ticks, timeout) && > - retry++ > SPI_MAX_RETRY) { > - dev_err(NULL, "Have retry %d, found invalid packet > data\n", > - retry); > - return -EBUSY; > - } > - > - if (ret == SPI_FOUND_SOP) { > - rx_buffer += rx_len; > - resp_max_len += rx_len; > - } > - > - spi_flags = ret; > - goto read_again; > - } > - > - print_buffer("found valid data:", resp_packet, resp_max_len); > + return ret; > > /* analyze response packet */ > i = 0; > p = resp_data; > - while (i < resp_max_len) { > + while (i < actual_rx) { > current_byte = resp_packet[i]; > switch (current_byte) { > case SPI_BYTE_IDLE: > @@ -337,9 +359,13 @@ static int packet_to_byte_conver(struct > spi_transaction_dev *dev, > current_byte = resp_packet[i]; > > switch (current_byte) { > - case SPI_PACKET_ESC: > - case SPI_PACKET_CHANNEL: > case SPI_PACKET_SOP: > + dev_err(dev, "error on get SOP after SOP\n"); > + return -EINVAL; > + case SPI_PACKET_CHANNEL: > + i += 2; > + break; > + case SPI_PACKET_ESC: > i++; > current_byte = resp_packet[i]; > *p++ = xor_20(current_byte); > @@ -348,23 +374,30 @@ static int packet_to_byte_conver(struct > spi_transaction_dev *dev, > case SPI_PACKET_EOP: > i++; > current_byte = resp_packet[i]; > - if (current_byte == SPI_PACKET_ESC || > - current_byte == > SPI_PACKET_CHANNEL || > - current_byte == SPI_PACKET_SOP) { > + switch (current_byte) { > + case SPI_PACKET_ESC: > i++; > current_byte = resp_packet[i]; > *p++ = xor_20(current_byte); > - } else > + break; > + case SPI_PACKET_CHANNEL: > + case SPI_PACKET_SOP: > + case SPI_PACKET_EOP: > + dev_err(dev, "error get SOP/EOP after > EOP\n"); > + return -EINVAL; > + default: > *p++ = current_byte; > - i = valid_resp_len; > - break; > + break; > + } > + goto done; > + > default: > *p++ = current_byte; > i++; > } > - > } > > +done: > *valid = p - resp_buf; > > print_buffer("after packet:", resp_buf, *valid); > -- > 1.8.3.1 Acked-by: Rosen Xu <rosen.xu@intel.com>
> -----Original Message----- > From: Xu, Rosen <rosen.xu@intel.com> > Sent: Wednesday, January 19, 2022 6:51 PM > To: Huang, Wei <wei.huang@intel.com>; dev@dpdk.org; Zhang, Qi Z > <qi.z.zhang@intel.com> > Cc: stable@dpdk.org; Zhang, Tianfei <tianfei.zhang@intel.com>; Yigit, Ferruh > <ferruh.yigit@intel.com> > Subject: RE: [PATCH v1] raw/ifpga/base: fix SPI transaction > > Hi, > > > -----Original Message----- > > From: Huang, Wei <wei.huang@intel.com> > > Sent: Wednesday, January 19, 2022 9:45 > > To: dev@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Qi Z > > <qi.z.zhang@intel.com> > > Cc: stable@dpdk.org; Zhang, Tianfei <tianfei.zhang@intel.com>; Yigit, > > Ferruh <ferruh.yigit@intel.com> > > Subject: [PATCH v1] raw/ifpga/base: fix SPI transaction > > > > From: Tianfei Zhang <tianfei.zhang@intel.com> > > > > When EOP is detected, 2 more bytes should be received (may be a > > SPI_PACKET_ESC before last valid byte) then rx should be finished. > > > > Fixes: 96ebfcf8 ("raw/ifpga/base: add SPI and MAX10 device driver") > > Cc: stable@dpdk.org > > > > Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com> > Acked-by: Rosen Xu <rosen.xu@intel.com> Applied to dpdk-next-net-intel. Thanks Qi
diff --git a/drivers/raw/ifpga/base/opae_spi.c b/drivers/raw/ifpga/base/opae_spi.c index 9efeecb..ca3d41f 100644 --- a/drivers/raw/ifpga/base/opae_spi.c +++ b/drivers/raw/ifpga/base/opae_spi.c @@ -239,6 +239,18 @@ int spi_command(struct altera_spi_device *dev, unsigned int chip_select, return 0; } +int spi_write(struct altera_spi_device *dev, unsigned int chip_select, + unsigned int wlen, void *wdata) +{ + return spi_command(dev, chip_select, wlen, wdata, 0, NULL); +} + +int spi_read(struct altera_spi_device *dev, unsigned int chip_select, + unsigned int rlen, void *rdata) +{ + return spi_command(dev, chip_select, 0, NULL, rlen, rdata); +} + struct altera_spi_device *altera_spi_alloc(void *base, int type) { struct altera_spi_device *spi_dev = diff --git a/drivers/raw/ifpga/base/opae_spi.h b/drivers/raw/ifpga/base/opae_spi.h index af11656..bcff67d 100644 --- a/drivers/raw/ifpga/base/opae_spi.h +++ b/drivers/raw/ifpga/base/opae_spi.h @@ -117,6 +117,10 @@ struct spi_tran_header { u32 addr; }; +int spi_read(struct altera_spi_device *dev, unsigned int chip_select, + unsigned int rlen, void *rdata); +int spi_write(struct altera_spi_device *dev, unsigned int chip_select, + unsigned int wlen, void *wdata); int spi_command(struct altera_spi_device *dev, unsigned int chip_select, unsigned int wlen, void *wdata, unsigned int rlen, void *rdata); void spi_cs_deactivate(struct altera_spi_device *dev); diff --git a/drivers/raw/ifpga/base/opae_spi_transaction.c b/drivers/raw/ifpga/base/opae_spi_transaction.c index 006cdb4..cd50d40 100644 --- a/drivers/raw/ifpga/base/opae_spi_transaction.c +++ b/drivers/raw/ifpga/base/opae_spi_transaction.c @@ -40,7 +40,7 @@ static void print_buffer(const char *string, void *buffer, int len) printf("%s print buffer, len=%d\n", string, len); for (i = 0; i < len; i++) - printf("%x ", *(p+i)); + printf("%02x ", *(p+i)); printf("\n"); } #else @@ -72,43 +72,6 @@ static void reorder_phy_data(u8 bits_per_word, } } -enum { - SPI_FOUND_SOP, - SPI_FOUND_EOP, - SPI_NOT_FOUND, -}; - -static int resp_find_sop_eop(unsigned char *resp, unsigned int len, - int flags) -{ - int ret = SPI_NOT_FOUND; - - unsigned char *b = resp; - - /* find SOP */ - if (flags != SPI_FOUND_SOP) { - while (b < resp + len && *b != SPI_PACKET_SOP) - b++; - - if (*b != SPI_PACKET_SOP) - goto done; - - ret = SPI_FOUND_SOP; - } - - /* find EOP */ - while (b < resp + len && *b != SPI_PACKET_EOP) - b++; - - if (*b != SPI_PACKET_EOP) - goto done; - - ret = SPI_FOUND_EOP; - -done: - return ret; -} - static void phy_tx_pad(unsigned char *phy_buf, unsigned int phy_buf_len, unsigned int *aligned_len) { @@ -137,6 +100,104 @@ static void phy_tx_pad(unsigned char *phy_buf, unsigned int phy_buf_len, *p++ = SPI_BYTE_IDLE; } +#define RX_ALL_IDLE_DATA (SPI_BYTE_IDLE << 24 | SPI_BYTE_IDLE << 16 | \ + SPI_BYTE_IDLE << 8 | SPI_BYTE_IDLE) + +static bool all_idle_data(u8 *rxbuf) +{ + return *(u32 *)rxbuf == RX_ALL_IDLE_DATA; +} + +static unsigned char *find_eop(u8 *rxbuf, u32 BPW) +{ + return memchr(rxbuf, SPI_PACKET_EOP, BPW); +} + +static int do_spi_txrx(struct spi_transaction_dev *dev, + unsigned char *tx_buffer, + unsigned int tx_len, unsigned char *rx_buffer, + unsigned int rx_len, + unsigned int *actual_rx) +{ + unsigned int rx_cnt = 0; + int ret = 0; + unsigned int BPW = 4; + bool eop_found = false; + unsigned char *eop; + unsigned char *ptr; + unsigned char *rxbuf = rx_buffer; + int add_byte = 0; + unsigned long ticks; + unsigned long timeout; + + /* send command */ + ret = spi_write(dev->dev, dev->chipselect, tx_len, tx_buffer); + if (ret) + return -EBUSY; + + timeout = rte_get_timer_cycles() + + msecs_to_timer_cycles(2000); + + /* read out data */ + while (rx_cnt < rx_len) { + ret = spi_read(dev->dev, dev->chipselect, BPW, rxbuf); + if (ret) + return -EBUSY; + + /* skip all of invalid data */ + if (!eop_found && all_idle_data(rxbuf)) { + ticks = rte_get_timer_cycles(); + if (!time_after(ticks, timeout)) { + continue; + } else { + dev_err(dev, "read spi data timeout\n"); + return -ETIMEDOUT; + } + } + + rx_cnt += BPW; + if (!eop_found) { + /* EOP is found, we read 2 more bytes and exit. */ + eop = find_eop(rxbuf, BPW); + if (eop) { + if ((BPW + rxbuf - eop) > 2) { + /* + * check if the last 2 bytes are already + * received in current word. + */ + break; + } else if ((BPW + rxbuf - eop) == 2) { + /* + * skip if last byte is not SPI_BYTE_ESC + * or SPI_PACKET_ESC. this is the valid + * end of a response too. + */ + ptr = eop + 1; + + if (*ptr != SPI_BYTE_ESC && + *ptr != SPI_PACKET_ESC) + break; + + add_byte = 1; + } else { + add_byte = 2; + } + + rx_len = min(rx_len, + IFPGA_ALIGN(rx_cnt + + add_byte, BPW)); + eop_found = true; + } + } + rxbuf += BPW; + } + + *actual_rx = rx_cnt; + print_buffer("found valid data:", rx_buffer, rx_cnt); + + return ret; +} + static int byte_to_core_convert(struct spi_transaction_dev *dev, unsigned int send_len, unsigned char *send_data, unsigned int resp_len, unsigned char *resp_data, @@ -148,15 +209,9 @@ static int byte_to_core_convert(struct spi_transaction_dev *dev, unsigned char *resp_packet = dev->buffer->bytes_resp; unsigned char *p; unsigned char current_byte; - unsigned char *tx_buffer; unsigned int tx_len = 0; - unsigned char *rx_buffer; - unsigned int rx_len = 0; - int retry = 0; - int spi_flags; - unsigned long timeout = msecs_to_timer_cycles(1000); - unsigned long ticks; unsigned int resp_max_len = 2 * resp_len; + unsigned int actual_rx; print_buffer("before bytes:", send_data, send_len); @@ -190,48 +245,15 @@ static int byte_to_core_convert(struct spi_transaction_dev *dev, print_buffer("after order to spi:", send_packet, tx_len); - /* call spi */ - tx_buffer = send_packet; - rx_buffer = resp_packet; - rx_len = resp_max_len; - spi_flags = SPI_NOT_FOUND; - -read_again: - ret = spi_command(dev->dev, dev->chipselect, tx_len, tx_buffer, - rx_len, rx_buffer); + ret = do_spi_txrx(dev, send_packet, tx_len, resp_packet, + resp_max_len, &actual_rx); if (ret) - return -EBUSY; - - print_buffer("read from spi:", rx_buffer, rx_len); - - /* look for SOP firstly*/ - ret = resp_find_sop_eop(rx_buffer, rx_len - 1, spi_flags); - if (ret != SPI_FOUND_EOP) { - tx_buffer = NULL; - tx_len = 0; - ticks = rte_get_timer_cycles(); - if (time_after(ticks, timeout) && - retry++ > SPI_MAX_RETRY) { - dev_err(NULL, "Have retry %d, found invalid packet data\n", - retry); - return -EBUSY; - } - - if (ret == SPI_FOUND_SOP) { - rx_buffer += rx_len; - resp_max_len += rx_len; - } - - spi_flags = ret; - goto read_again; - } - - print_buffer("found valid data:", resp_packet, resp_max_len); + return ret; /* analyze response packet */ i = 0; p = resp_data; - while (i < resp_max_len) { + while (i < actual_rx) { current_byte = resp_packet[i]; switch (current_byte) { case SPI_BYTE_IDLE: @@ -337,9 +359,13 @@ static int packet_to_byte_conver(struct spi_transaction_dev *dev, current_byte = resp_packet[i]; switch (current_byte) { - case SPI_PACKET_ESC: - case SPI_PACKET_CHANNEL: case SPI_PACKET_SOP: + dev_err(dev, "error on get SOP after SOP\n"); + return -EINVAL; + case SPI_PACKET_CHANNEL: + i += 2; + break; + case SPI_PACKET_ESC: i++; current_byte = resp_packet[i]; *p++ = xor_20(current_byte); @@ -348,23 +374,30 @@ static int packet_to_byte_conver(struct spi_transaction_dev *dev, case SPI_PACKET_EOP: i++; current_byte = resp_packet[i]; - if (current_byte == SPI_PACKET_ESC || - current_byte == SPI_PACKET_CHANNEL || - current_byte == SPI_PACKET_SOP) { + switch (current_byte) { + case SPI_PACKET_ESC: i++; current_byte = resp_packet[i]; *p++ = xor_20(current_byte); - } else + break; + case SPI_PACKET_CHANNEL: + case SPI_PACKET_SOP: + case SPI_PACKET_EOP: + dev_err(dev, "error get SOP/EOP after EOP\n"); + return -EINVAL; + default: *p++ = current_byte; - i = valid_resp_len; - break; + break; + } + goto done; + default: *p++ = current_byte; i++; } - } +done: *valid = p - resp_buf; print_buffer("after packet:", resp_buf, *valid);