lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <8A42379416420646B9BFAC9682273B6D0EF11F8A@limkexm3.ad.analog.com>
Date:	Tue, 22 Dec 2009 11:46:39 +0000
From:	"Hennerich, Michael" <Michael.Hennerich@...log.com>
To:	"Ben Hutchings" <bhutchings@...arflare.com>,
	"Mike Frysinger" <vapier@...too.org>
CC:	<netdev@...r.kernel.org>, "David S. Miller" <davem@...emloft.net>,
	<uclinux-dist-devel@...ckfin.uclinux.org>
Subject: RE: [PATCH] wireless: adf702x: new driver for ADF7020/21 parts

Hi Ben,

Thanks for your feedback.
See comments below.

>From: Ben Hutchings
>On Mon, 2009-12-21 at 21:12 -0500, Mike Frysinger wrote:
>> From: Michael Hennerich <michael.hennerich@...log.com>
>>
>> This is a driver for Analog Devices series of ADF702x Narrow-Band
>> Short-Range Radio Transceiver chipsets, including the ADF7021 and
>> the ADF7025.  This Ethernet like driver implements a custom
>> software PHY.
>[...]
>> diff --git a/drivers/net/wireless/Kconfig
>b/drivers/net/wireless/Kconfig
>> index 56dd665..57974ac 100644
>> --- a/drivers/net/wireless/Kconfig
>> +++ b/drivers/net/wireless/Kconfig
>> @@ -44,6 +44,17 @@ config LIBERTAS_THINFIRM_USB
>>  	---help---
>>  	  A driver for Marvell Libertas 8388 USB devices using thinfirm.
>>
>> +config ADF702X
>> +	tristate "ADF702x Narrow-Band Short-Range Radio Transceiver"
>> +	depends on EXPERIMENTAL && SPI && BLACKFIN
>
>Any particular reason this should be EXPERIMENTAL?

No

>
>[...]
>> diff --git a/drivers/net/wireless/adf702x.c
>b/drivers/net/wireless/adf702x.c
>> new file mode 100644
>> index 0000000..ada0cb9
>> --- /dev/null
>> +++ b/drivers/net/wireless/adf702x.c
>[...]
>> +struct adf702x_priv {
>> +	struct spi_device *spi;
>> +	struct net_device *ndev;
>> +	struct sk_buff *tx_skb;
>> +	struct delayed_work tx_work;
>> +	struct work_struct tx_done_work;
>> +	wait_queue_head_t waitq;
>> +	dma_addr_t dma_handle;
>> +	spinlock_t lock;
>> +	unsigned rx_preample:1;
>
>Shouldn't this be named "rx_preamble" ("b" not "p")?

Right

>
>> +	unsigned rx:1;
>> +	unsigned rx_size;
>> +	u32 *rx_buf;
>> +	u32 *tx_buf;
>> +
>> +	/* Base reg base of SPORT controller */
>> +	volatile struct sport_register *sport;
>
>MMIO pointers should normally be declared like:
>
>	struct sport_register __iomem *sport;
>
>and used with readl, writel etc.

Well SPORT is a SoC peripheral it's mapped into Blackfin System MMR space.
Our versions of readX writeX are implemented for off-chip peripherals.
If you take a look at Blackfin io.h you will notice that we disable global interrupts, 
to avoid killed and reissued reads. This is not necessary for the System MMR space.   

Preferably I like to keep this as is, but I could also change it to use the 
Blackfin MMR accessor functions bfin_read{32,16} bfin_write{32,16}  

>
>[...]
>> +#define MAGIC		(0xA54662DA)
>
>You could choose a more meaningful name for this!

sure

>
>[...]
>> +/*
>> + * ONES: A instruction only DSPs feature
>> + * a XOR b -> return counted ONES (BIT Errors)
>> + */
>> +static inline unsigned short adf702x_xor_ones(unsigned int a,
>unsigned int b)
>> +{
>> +	unsigned short val;
>> +
>> +	__asm__ __volatile__ (
>> +				"%0 = %1 ^ %2;"
>> +				"%0.l = ONES %0;"
>> +				: "=d"(val) : "d"(a), "d"(b)
>> +				);
>> +	return val;
>> +}
>
>This could be written as hweight16(a ^ b).  I don't think the hweight
>functions have optimised implementations for Blackfin, but you can fix
>that.

This is what I was looking for - I wasn't aware of hweight{64,32,16,8}
Thanks!

>
>[...]
>> +/*
>> + * Get Packet size from header
>> + * Returns: size or 42 in case of an unrecoverable error
>> + */
>> +inline unsigned short adf702x_getrxsize(struct adf702x_priv *lp, int
>offset)
>
>Should be declared static inline, not just inline.

ok

>
>> +{
>> +	int size = adf702x_getsymbol(lp->rx_buf[offset + 1]) << 8 |
>> +			adf702x_getsymbol(lp->rx_buf[offset + 2]);
>> +
>> +	if (size > 0)
>> +		return size;
>> +
>> +	DBG(1, "%s :BITERR\n", __func__);
>> +	lp->ndev->stats.rx_errors++;
>> +	return 64;	/* Keep the Receiver busy for some time */
>
>64 != 42

I change the description

>
>[...]
>> +static int adf702x_net_xmit(struct sk_buff *skb, struct net_device
>*dev)
>> +{
>> +	struct adf702x_priv *lp = netdev_priv(dev);
>> +	unsigned char *buf_ptr = skb->data;
>> +	int i;
>> +	unsigned char delay;
>> +
>> +	DBG(2, "%s: %s(): transmitting %d bytes\n",
>> +		 dev->name, __func__, skb->len);
>> +
>> +	if (!skb->len)
>> +		return 0;
>
>I don't think this is possible.

Will remove

>
>> +	/* Only one packet at a time. Once TXDONE interrupt is serviced,
>the
>> +	 * queue will be restarted.
>> +	 */
>> +	netif_stop_queue(dev);
>> +	/* save the timestamp */
>> +	lp->ndev->trans_start = jiffies;
>
>Don't set trans_start; the networking core does this now.

ok

>
>> +	/* Remember the skb for deferred processing */
>> +	lp->tx_skb = skb;
>> +
>> +	BUG_ON(lp->tx_skb->len > 0xFFFF);
>
>If you're going to make assertions about the length, it would probably
>be more useful to check against the packet buffer size.

ok

>
>> +	lp->tx_buf[3] = adf702x_getchip(skb->len >> 8);
>> +	lp->tx_buf[4] = adf702x_getchip(skb->len & 0xFF);
>> +
>> +	DBG(3, "TX TX: ");
>> +	for (i = 0; i < skb->len; i++) {
>> +		lp->tx_buf[TX_HEADERSIZE + i] = adf702x_getchip(buf_ptr[i]);
>> +		DBG(3, "%x ", buf_ptr[i]);
>> +	}
>> +	DBG(3, "\n");
>> +
>> +	/* Avoid contentions
>> +	 * Schedule transmission randomly (0..64ms)
>> +	 * This allows other nodes to snip in
>> +	 */
>> +
>> +	get_random_bytes(&delay, sizeof(delay));
>> +	schedule_delayed_work(&lp->tx_work, msecs_to_jiffies(delay >> 2));
>
>get_random_bytes() uses up entropy that should be reserved for
>applications that really need it.  Instead of that, I think you should
>call random32() and use the most significant bits.

ok

>
>[...]
>> +static irqreturn_t adf702x_rx_interrupt(int irq, void *dev_id)
>> +{
>[...]
>> +			lp->rx_size = adf702x_getrxsize(lp, offset);
>> +			if (offset == 1) {
>> +				set_dma_x_count(lp->dma_ch_rx, lp->rx_size);
>> +				set_dma_start_addr(lp->dma_ch_rx,
>> +					(unsigned long)lp->rx_buf);
>> +			} else {
>> +				lp->rx_buf[0] = lp->rx_buf[3];
>> +				set_dma_x_count(lp->dma_ch_rx, lp->rx_size - 1);
>> +				set_dma_start_addr(lp->dma_ch_rx,
>> +					(unsigned long)&lp->rx_buf[1]);
>> +			}
>> +			enable_dma(lp->dma_ch_rx);
>> +			SSYNC();
>
>Is this some odd kind of memory barrier?

Well - it's an instruction that ensures that the write buffers are flushed and all instructions executed. 

>
>[...]
>> +static int __devinit adf702x_probe(struct spi_device *spi)
>> +{
>[...]
>> +	/*
>> +	 * MAC address? we use a
>> +	 * random one ...
>> +	 */
>> +
>> +	random_ether_addr(ndev->dev_addr);
>
>Assuming that the MAC address is not available in non-volatile memory or
>set directly by firmware, it should be provided in platform data.
>
>> +	ndev->mtu = 576;
>
>Even though you use Ethernet frames?

We could stick with the default MTU - but it would worsen the overall response time.

>
>> +	ndev->tx_queue_len = 10;
>> +	ndev->watchdog_timeo = 0;
>> +
>> +	err = register_netdev(ndev);
>> +	if (err) {
>> +		dev_err(&spi->dev, "failed to register netdev\n");
>> +		goto out1;
>> +	}
>
>Don't register the netdev yet!  It could be brought up immediately, even
>though your private structure is not initialised.

ups

>
>[...]
>> +	spin_lock_init(&lp->lock);
>> +	INIT_DELAYED_WORK(&lp->tx_work, adf702x_tx_work);
>> +	INIT_WORK(&lp->tx_done_work, adf702x_tx_done_work);
>> +	init_waitqueue_head(&lp->waitq);
>
>...and now you'll be ready to register the netdev.

ok

>
>> +static int __devexit adf702x_remove(struct spi_device *spi)
>> +{
>> +	struct adf702x_platform_data *pdata = spi->dev.platform_data;
>> +	struct net_device *dev = dev_get_drvdata(&spi->dev);
>> +	struct adf702x_priv *lp = netdev_priv(dev);
>
>First things first:
>
>	rtnl_lock();
>	dev_close(dev);
>	unregister_netdevice(dev);
>	rtnl_unlock();
>
>> +	dma_free_coherent(NULL, MAX_PACKET_SIZE, lp->rx_buf, lp-
>>dma_handle);
>> +	dma_free_coherent(NULL, MAX_PACKET_SIZE, lp->tx_buf, lp-
>>dma_handle);
>> +
>> +	if (lp->irq_sport_err)
>> +		free_irq(lp->irq_sport_err, dev);
>> +
>> +	gpio_free(lp->gpio_int_rfs);
>> +	free_dma(lp->dma_ch_rx);
>> +	free_dma(lp->dma_ch_tx);
>> +	peripheral_free_list(pdata->pin_req);
>> +
>> +	unregister_netdev(dev);
>[...]
>
>This unregister_netdev() should be replaced by the above additions.
>
>Ben.
>
>--
>Ben Hutchings, Senior Software Engineer, Solarflare Communications
>Not speaking for my employer; that's the marketing department's job.
>They asked us to note that Solarflare product names are trademarked.


Thanks and best regards,
Michael

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ