* [PATCH 1/4] b44: add wol and setup for later 4401
From: Gary Zambrano @ 2006-05-24 14:40 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
This patch adds set and get functions and support for the later 4401 revs.
Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 7b3dfc4..e42e0aa 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -75,6 +75,12 @@
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
+/* b44 internal pattern match filter info */
+#define B44_WOL_PATTERN_BASE 0x400
+#define B44_WOL_PATTERN_SIZE 0x80
+#define B44_WOL_MASK_BASE 0x600
+#define B44_WOL_MASK_SIZE 0x10
+
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -1442,6 +1448,43 @@ static void b44_poll_controller(struct n
}
#endif
+
+static void b44_setup_wol(struct b44 *bp)
+{
+ u32 val;
+ u16 pmval;
+
+ bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI);
+
+ if (bp->flags & B44_FLAG_B0_ANDLATER) {
+
+ bw32 (bp, B44_WKUP_LEN, WKUP_LEN_DISABLE);
+
+ val = bp->dev->dev_addr[2] << 24 |
+ bp->dev->dev_addr[3] << 16 |
+ bp->dev->dev_addr[4] << 8 |
+ bp->dev->dev_addr[5];
+ bw32(bp, B44_ADDR_LO, val);
+
+ val = bp->dev->dev_addr[0] << 8 |
+ bp->dev->dev_addr[1];
+ bw32(bp, B44_ADDR_HI, val);
+
+ val = br32(bp, B44_DEVCTRL);
+ bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE);
+
+ } else {
+ b44_setup_pseudo_magicp(bp);
+ }
+
+ val = br32(bp, B44_SBTMSLOW);
+ bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE);
+
+ pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval);
+ pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE);
+
+}
+
static int b44_close(struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
@@ -1467,6 +1510,11 @@ static int b44_close(struct net_device *
netif_poll_enable(dev);
+ if (bp->flags & B44_FLAG_WOL_ENABLE){
+ b44_init_hw(bp);
+ b44_setup_wol(bp);
+ }
+
b44_free_consistent(bp);
return 0;
@@ -1810,12 +1858,38 @@ static void b44_get_ethtool_stats(struct
spin_unlock_irq(&bp->lock);
}
+static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct b44 *bp = netdev_priv(dev);
+
+ wol->supported = WAKE_MAGIC;
+ if (bp->flags & B44_FLAG_WOL_ENABLE)
+ wol->wolopts = WAKE_MAGIC;
+ else
+ wol->wolopts = 0;
+ memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct b44 *bp = netdev_priv(dev);
+
+ if (wol->wolopts & WAKE_MAGIC)
+ bp->flags |= B44_FLAG_WOL_ENABLE;
+ else
+ bp->flags &= ~B44_FLAG_WOL_ENABLE;
+
+ return 0;
+}
+
static struct ethtool_ops b44_ethtool_ops = {
.get_drvinfo = b44_get_drvinfo,
.get_settings = b44_get_settings,
.set_settings = b44_set_settings,
.nway_reset = b44_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_wol = b44_get_wol,
+ .set_wol = b44_set_wol,
.get_ringparam = b44_get_ringparam,
.set_ringparam = b44_set_ringparam,
.get_pauseparam = b44_get_pauseparam,
@@ -1894,6 +1968,10 @@ static int __devinit b44_get_invariants(
/* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
*/
+
+ if (ssb_get_core_rev(bp) >= 7)
+ bp->flags |= B44_FLAG_B0_ANDLATER;
+
out:
return err;
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index b178662..18baa19 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -24,6 +24,8 @@
#define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */
#define WKUP_LEN_P3_SHIFT 24
#define WKUP_LEN_D3 0x80000000
+#define WKUP_LEN_DISABLE 0x80808080
+#define WKUP_LEN_ENABLE_TWO 0x80800000
#define B44_ISTAT 0x0020UL /* Interrupt Status */
#define ISTAT_LS 0x00000020 /* Link Change (B0 only) */
#define ISTAT_PME 0x00000040 /* Power Management Event */
@@ -264,6 +266,8 @@
#define SBIDHIGH_VC_SHIFT 16
/* SSB PCI config space registers. */
+#define SSB_PMCSR 0x44
+#define SSB_PE 0x100
#define SSB_BAR0_WIN 0x80
#define SSB_BAR1_WIN 0x84
#define SSB_SPROM_CONTROL 0x88
@@ -420,6 +424,7 @@ struct b44 {
u32 dma_offset;
u32 flags;
+#define B44_FLAG_B0_ANDLATER 0x00000001
#define B44_FLAG_BUGGY_TXPTR 0x00000002
#define B44_FLAG_REORDER_BUG 0x00000004
#define B44_FLAG_PAUSE_AUTO 0x00008000
@@ -435,6 +440,7 @@ struct b44 {
#define B44_FLAG_INTERNAL_PHY 0x10000000
#define B44_FLAG_RX_RING_HACK 0x20000000
#define B44_FLAG_TX_RING_HACK 0x40000000
+#define B44_FLAG_WOL_ENABLE 0x80000000
u32 rx_offset;
^ permalink raw reply related
* [PATCH 4/4] b44: update version to 1.01
From: Gary Zambrano @ 2006-05-24 14:40 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 6eea1fc..f72a591 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -29,8 +29,8 @@
#define DRV_MODULE_NAME "b44"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.00"
-#define DRV_MODULE_RELDATE "Apr 7, 2006"
+#define DRV_MODULE_VERSION "1.01"
+#define DRV_MODULE_RELDATE "May 24, 2006"
#define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \
^ permalink raw reply related
* [PATCH 0/4] b44: add wol to b44
From: Gary Zambrano @ 2006-05-24 14:40 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
Adding wol to b44 is included in these patches:
1/4 - add wol and setup for later 4401
2/4 - wol setup for older 4401
3/4 - add parameter to init_hw() for wol
4/4 - update version
^ permalink raw reply
* [PATCH 2/4] b44: wol setup for older 4401
From: Gary Zambrano @ 2006-05-24 14:40 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
This patch adds wol support for the older 4401 revs.
Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index b9e2462..6f4d1d4 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1448,6 +1448,93 @@ static void b44_poll_controller(struct n
}
#endif
+static inline void bwfilter_table(struct b44 *bp,
+ u32 *pattern,
+ u32 bytes,
+ u32 table_offset)
+{
+ u32 i;
+
+ for (i = 0; i < bytes; i += sizeof(u32)) {
+ bw32(bp, B44_FILT_ADDR, table_offset + i);
+ bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]);
+ }
+}
+
+/* Setup two common magic packet patterns in the b44 WOL
+ * pattern matching filter.
+ */
+static void b44_setup_pseudo_magicp(struct b44 *bp)
+{
+
+ u32 val;
+ int plen0, plen1, max, i, j;
+ u8 *pwol_pattern;
+ u8 *pwol_mask;
+
+ pwol_pattern = kmalloc(B44_WOL_PATTERN_SIZE, GFP_KERNEL);
+ pwol_mask = kmalloc(B44_WOL_MASK_SIZE, GFP_KERNEL);
+
+ /* UDP magic packet pattern */
+ memset(pwol_pattern, 0, B44_WOL_PATTERN_SIZE);
+ memset(pwol_pattern + 42, 0xff, 6); /* sync pattern */
+ max = ETH_ALEN;
+ for (i = 0; i < 14; ++i) {
+ if (i == 13)
+ max = 2;
+ for (j = 0; j < max; ++j) {
+ pwol_pattern[42 + 6 +
+ (i * ETH_ALEN) + j] =
+ bp->dev->dev_addr[j];
+ }
+ }
+
+ memset(pwol_mask, 0, B44_WOL_MASK_SIZE);
+ pwol_mask[5] = 0xfc;
+ memset(pwol_mask + 6, 0xff, 10);
+ plen0 = B44_WOL_PATTERN_SIZE - 1;
+
+ bwfilter_table(bp, (u32 *)pwol_pattern,
+ B44_WOL_PATTERN_SIZE, B44_WOL_PATTERN_BASE);
+
+ bwfilter_table(bp, (u32 *)pwol_mask,
+ B44_WOL_MASK_SIZE, B44_WOL_MASK_BASE);
+
+ /* raw ethernet II magic packet pattern */
+ memset(pwol_pattern, 0, B44_WOL_PATTERN_SIZE);
+ memset(pwol_pattern + 14, 0xff, 6); /* sync pattern */
+ max = ETH_ALEN;
+ for (i = 0; i < 16; ++i) {
+ for (j = 0; j < max; ++j) {
+ pwol_pattern[14 + 6 +
+ (i * ETH_ALEN) + j] =
+ bp->dev->dev_addr[j];
+ }
+ }
+
+ memset(pwol_mask, 0, B44_WOL_MASK_SIZE);
+ pwol_mask[2] = 0xf0;
+ memset(pwol_mask + 3, 0xff, 11);
+ pwol_mask[14] = 0xf;
+ plen1 = 14 + 6 + 96 - 1;
+
+ bwfilter_table(bp, (u32 *)pwol_pattern, B44_WOL_PATTERN_SIZE,
+ B44_WOL_PATTERN_BASE + B44_WOL_PATTERN_SIZE);
+ bwfilter_table(bp, (u32 *)pwol_mask, B44_WOL_MASK_SIZE,
+ B44_WOL_MASK_BASE + B44_WOL_MASK_SIZE);
+
+ /* set this pattern's length: one less than the real length */
+ val = plen0 | (plen1 << 8) | WKUP_LEN_ENABLE_TWO;
+ bw32(bp, B44_WKUP_LEN, val);
+
+ /* enable chip wakeup pattern matching */
+ val = br32(bp, B44_DEVCTRL);
+ bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE);
+
+ kfree(pwol_mask);
+ kfree(pwol_pattern);
+
+}
static void b44_setup_wol(struct b44 *bp)
{
^ permalink raw reply related
* [PATCH 3/4] b44: add parameter to init_hw for wol
From: Gary Zambrano @ 2006-05-24 14:40 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
This patch adds a parameter to init_hw() for wol.
Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 81d1f36..6eea1fc 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -107,7 +107,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
static void b44_halt(struct b44 *);
static void b44_init_rings(struct b44 *);
-static void b44_init_hw(struct b44 *);
+static void b44_init_hw(struct b44 *, int);
static int dma_desc_align_mask;
static int dma_desc_sync_size;
@@ -875,7 +875,7 @@ static int b44_poll(struct net_device *n
spin_lock_irq(&bp->lock);
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
netif_wake_queue(bp->dev);
spin_unlock_irq(&bp->lock);
done = 1;
@@ -944,7 +944,7 @@ static void b44_tx_timeout(struct net_de
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
spin_unlock_irq(&bp->lock);
@@ -1059,7 +1059,7 @@ static int b44_change_mtu(struct net_dev
b44_halt(bp);
dev->mtu = new_mtu;
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
@@ -1354,14 +1354,15 @@ static int b44_set_mac_addr(struct net_d
* packet processing. Invoked with bp->lock held.
*/
static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp)
+static void b44_init_hw(struct b44 *bp, int full)
{
u32 val;
b44_chip_reset(bp);
- b44_phy_reset(bp);
- b44_setup_phy(bp);
-
+ if (full) {
+ b44_phy_reset(bp);
+ b44_setup_phy(bp);
+ }
/* Enable CRC32, set proper LED modes and power on PHY */
bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
@@ -1374,16 +1375,21 @@ static void b44_init_hw(struct b44 *bp)
bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
- bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
- bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
- bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+ if (full){
+ bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+ bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
+ bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
(bp->rx_offset << DMARX_CTRL_ROSHIFT)));
- bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
+ bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
- bw32(bp, B44_DMARX_PTR, bp->rx_pending);
- bp->rx_prod = bp->rx_pending;
+ bw32(bp, B44_DMARX_PTR, bp->rx_pending);
+ bp->rx_prod = bp->rx_pending;
- bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+ bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+ }else{
+ bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+ (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ }
val = br32(bp, B44_ENET_CTRL);
bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
@@ -1399,7 +1405,7 @@ static int b44_open(struct net_device *d
goto out;
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
b44_check_phy(bp);
@@ -1598,7 +1604,7 @@ static int b44_close(struct net_device *
netif_poll_enable(dev);
if (bp->flags & B44_FLAG_WOL_ENABLE){
- b44_init_hw(bp);
+ b44_init_hw(bp, 0);
b44_setup_wol(bp);
}
@@ -1860,7 +1866,7 @@ static int b44_set_ringparam(struct net_
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
netif_wake_queue(bp->dev);
spin_unlock_irq(&bp->lock);
@@ -1903,7 +1909,7 @@ static int b44_set_pauseparam(struct net
if (bp->flags & B44_FLAG_PAUSE_AUTO) {
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
} else {
__b44_set_flow_ctrl(bp, bp->flags);
}
@@ -2281,7 +2287,7 @@ static int b44_resume(struct pci_dev *pd
spin_lock_irq(&bp->lock);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
^ permalink raw reply related
* Re: [PATCH 1/4] b44: add wol and setup for later 4401
From: Francois Romieu @ 2006-05-24 22:06 UTC (permalink / raw)
To: Gary Zambrano; +Cc: Jeff Garzik, netdev
In-Reply-To: <1148481644.2976.51.camel@dhcp-10-7-81-7.broadcom.com>
Gary Zambrano <zambrano@broadcom.com> :
>
> This patch adds set and get functions and support for the later 4401 revs.
>
> Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
>
> diff --git a/drivers/net/b44.c b/drivers/net/b44.c
> index 7b3dfc4..e42e0aa 100644
> --- a/drivers/net/b44.c
> +++ b/drivers/net/b44.c
[...]
> @@ -1467,6 +1510,11 @@ static int b44_close(struct net_device *
>
> netif_poll_enable(dev);
>
> + if (bp->flags & B44_FLAG_WOL_ENABLE){
> + b44_init_hw(bp);
> + b44_setup_wol(bp);
> + }
> +
> b44_free_consistent(bp);
>
> return 0;
Should b44_setup_wol() not be used in b44_suspend() as well ?
(nit: s/){/) {/)
--
Ueimor
^ permalink raw reply
* Re: [PATCH 2/4] b44: wol setup for older 4401
From: Francois Romieu @ 2006-05-24 22:13 UTC (permalink / raw)
To: Gary Zambrano; +Cc: Jeff Garzik, netdev
In-Reply-To: <1148481647.2976.52.camel@dhcp-10-7-81-7.broadcom.com>
Gary Zambrano <zambrano@broadcom.com> :
[...]
> diff --git a/drivers/net/b44.c b/drivers/net/b44.c
> index b9e2462..6f4d1d4 100644
> --- a/drivers/net/b44.c
> +++ b/drivers/net/b44.c
[...]
> +static void b44_setup_pseudo_magicp(struct b44 *bp)
> +{
> +
> + u32 val;
> + int plen0, plen1, max, i, j;
> + u8 *pwol_pattern;
> + u8 *pwol_mask;
> +
> + pwol_pattern = kmalloc(B44_WOL_PATTERN_SIZE, GFP_KERNEL);
> + pwol_mask = kmalloc(B44_WOL_MASK_SIZE, GFP_KERNEL);
> +
> + /* UDP magic packet pattern */
> + memset(pwol_pattern, 0, B44_WOL_PATTERN_SIZE);
> + memset(pwol_pattern + 42, 0xff, 6); /* sync pattern */
kmalloc can fail. It should be checked.
> + max = ETH_ALEN;
> + for (i = 0; i < 14; ++i) {
> + if (i == 13)
> + max = 2;
> + for (j = 0; j < max; ++j) {
> + pwol_pattern[42 + 6 +
> + (i * ETH_ALEN) + j] =
> + bp->dev->dev_addr[j];
Indentation went strange here.
--
Ueimor
^ permalink raw reply
* Re: [PATCH 1/4] b44: add wol and setup for later 4401
From: Gary Zambrano @ 2006-05-24 15:27 UTC (permalink / raw)
To: Francois Romieu; +Cc: Jeff Garzik, netdev
In-Reply-To: <20060524220658.GA2863@electric-eye.fr.zoreil.com>
On Thu, 2006-05-25 at 00:06 +0200, Francois Romieu wrote:
> Should b44_setup_wol() not be used in b44_suspend() as well ?
>
Yes. Thank you.
> (nit: s/){/) {/)
>
ok.
^ permalink raw reply
* Re: [PATCH 2/4] b44: wol setup for older 4401
From: Gary Zambrano @ 2006-05-24 15:33 UTC (permalink / raw)
To: Francois Romieu; +Cc: Jeff Garzik, netdev
In-Reply-To: <20060524221306.GB2863@electric-eye.fr.zoreil.com>
On Thu, 2006-05-25 at 00:13 +0200, Francois Romieu wrote:
> > + pwol_pattern = kmalloc(B44_WOL_PATTERN_SIZE, GFP_KERNEL);
> > + pwol_mask = kmalloc(B44_WOL_MASK_SIZE, GFP_KERNEL);
> > +
> kmalloc can fail. It should be checked.
Yep. Thanks.
> > + max = ETH_ALEN;
> > + for (i = 0; i < 14; ++i) {
> > + if (i == 13)
> > + max = 2;
> > + for (j = 0; j < max; ++j) {
> > + pwol_pattern[42 + 6 +
> > + (i * ETH_ALEN) + j] =
> > + bp->dev->dev_addr[j];
>
> Indentation went strange here.
>
Will adjust.
Thanks.
^ permalink raw reply
* [RFC] new qla3xxx NIC Driver v2.02.00k29
From: Ron Mercer @ 2006-05-24 23:06 UTC (permalink / raw)
To: netdev; +Cc: linux-driver, Ying Ping Lok
All,
Third submission for the upstream inclusion of the qla3xxx Ethernet
driver. This is a complementary network driver for our ISP4XXX parts.
There is a concurrent effort underway to get the iSCSI driver (qla4xxx)
integrated upstream as well.
The following files are included and have been posted to the link below:
LICENSE.qla3xxx
qla3xxxsrc-v2.02.00k29.tgz
ftp://ftp.qlogic.com/network/upstream/20.02.00k29/
Second submission:
http://marc.theaimsgroup.com/?l=linux-netdev&m=114780280407707&w=2
Comments from second submission:
http://marc.theaimsgroup.com/?l=linux-netdev&m=114782208808695&w=2
Changes in this release:
- Reordered code to remove forward declarations.
- Removed typedefs.
- Changed inter-driver hardware lock to use wait_event().
- Removed macros defined inside structure definitions.
- Removed volatile usage.
- Removed wrapper RD_REG_READ/WRITE macros for readl/writel
- Bug fix for msi logic.
- Removed unused debug print functions.
- probe now propagates error codes from api to caller.
- Removed internal send queue and lock dependency.
Looking forward to any and all feedback.
Regards,
Ron Mercer
Qlogic Corporation
^ permalink raw reply
* [PATCH 1/4] [IrDA] *_DONGLE should depend on IRTTY_SIR
From: Samuel Ortiz @ 2006-05-25 6:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, irda-users
If a SIR dongle is built in the kernel while IRTTY_SIR is built
as a module, kernel compilation will fail.
Thus, the SIR dongle config should depend on the IRTTY_SIR.
Closes kernel bug# 6512
(http://bugzilla.kernel.org/show_bug.cgi?id=6512)
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
---
drivers/net/irda/Kconfig | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
cf17d65eca0463ff3e078fab4db2caac57f5fa46
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 5e6d007..cff8598 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -33,7 +33,7 @@ config DONGLE
config ESI_DONGLE
tristate "ESI JetEye PC dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Extended Systems
JetEye PC dongle. To compile it as a module, choose M here. The ESI
@@ -44,7 +44,7 @@ config ESI_DONGLE
config ACTISYS_DONGLE
tristate "ACTiSYS IR-220L and IR220L+ dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-220L and
IR220L+ dongles. To compile it as a module, choose M here. The
@@ -55,7 +55,7 @@ config ACTISYS_DONGLE
config TEKRAM_DONGLE
tristate "Tekram IrMate 210B dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Tekram IrMate 210B
dongle. To compile it as a module, choose M here. The Tekram dongle
@@ -66,7 +66,7 @@ config TEKRAM_DONGLE
config TOIM3232_DONGLE
tristate "TOIM3232 IrDa dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Vishay/Temic
TOIM3232 and TOIM4232 based dongles.
@@ -74,7 +74,7 @@ config TOIM3232_DONGLE
config LITELINK_DONGLE
tristate "Parallax LiteLink dongle"
- depends on DONGLE && IRDA
+ depends on IRTTY_SIR && DONGLE && IRDA
help
Say Y here if you want to build support for the Parallax Litelink
dongle. To compile it as a module, choose M here. The Parallax
@@ -85,7 +85,7 @@ config LITELINK_DONGLE
config MA600_DONGLE
tristate "Mobile Action MA600 dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Mobile Action MA600
dongle. To compile it as a module, choose M here. The MA600 dongle
@@ -98,7 +98,7 @@ config MA600_DONGLE
config GIRBIL_DONGLE
tristate "Greenwich GIrBIL dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Greenwich GIrBIL
dongle. If you want to compile it as a module, choose M here.
@@ -109,7 +109,7 @@ config GIRBIL_DONGLE
config MCP2120_DONGLE
tristate "Microchip MCP2120"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Microchip MCP2120
dongle. If you want to compile it as a module, choose M here.
@@ -123,7 +123,7 @@ config MCP2120_DONGLE
config OLD_BELKIN_DONGLE
tristate "Old Belkin dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. If you want to compile it as a module, choose
@@ -132,7 +132,7 @@ config OLD_BELKIN_DONGLE
config ACT200L_DONGLE
tristate "ACTiSYS IR-200L dongle"
- depends on DONGLE && IRDA && EXPERIMENTAL
+ depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the ACTiSYS IR-200L
dongle. If you want to compile it as a module, choose M here.
--
1.3.2
^ permalink raw reply related
* [PATCH 2/4] [IrDA] Initial support for MCS7780 based dongles
From: Samuel Ortiz @ 2006-05-25 6:19 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, irda-users, bpugh
The MosChip MCS7780 chipset is an IrDA USB bridge that
doesn't conform with the IrDA-USB standard and thus needs
its separate driver.
Tested on an actual MCS7780 based dongle.
Original implementation by Brian Pugh <bpugh@cs.pdx.edu>
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
---
drivers/net/irda/Kconfig | 15 +
drivers/net/irda/Makefile | 1
drivers/net/irda/mcs7780.c | 1009 ++++++++++++++++++++++++++++++++++++++++++++
drivers/net/irda/mcs7780.h | 167 +++++++
4 files changed, 1192 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/irda/mcs7780.c
create mode 100644 drivers/net/irda/mcs7780.h
b85118a0356615f60897561812d020a252ee81d0
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index cff8598..d2ce489 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -417,5 +417,20 @@ config PXA_FICP
available capabilities may vary from one PXA2xx target to
another.
+config MCS_FIR
+ tristate "MosChip MCS7780 IrDA-USB dongle"
+ depends on IRDA && USB && EXPERIMENTAL
+ help
+ Say Y or M here if you want to build support for the MosChip
+ MCS7780 IrDA-USB bridge device driver.
+
+ USB bridge based on the MosChip MCS7780 don't conform to the
+ IrDA-USB device class specification, and therefore need their
+ own specific driver. Those dongles support SIR and FIR (4Mbps)
+ speeds.
+
+ To compile it as a module, choose M here: the module will be called
+ mcs7780.
+
endmenu
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index c1ce239..5be09f1 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
obj-$(CONFIG_VIA_FIR) += via-ircc.o
obj-$(CONFIG_PXA_FICP) += pxaficp_ir.o
+obj-$(CONFIG_MCS_FIR) += mcs7780.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_DONGLE_OLD) += esi.o
obj-$(CONFIG_TEKRAM_DONGLE_OLD) += tekram.o
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
new file mode 100644
index 0000000..efae2aa
--- /dev/null
+++ b/drivers/net/irda/mcs7780.c
@@ -0,0 +1,1009 @@
+/*****************************************************************************
+*
+* Filename: mcs7780.c
+* Version: 0.4-alpha
+* Description: Irda MosChip USB Dongle Driver
+* Authors: Lukasz Stelmach <stlman@poczta.fm>
+* Brian Pugh <bpugh@cs.pdx.edu>
+* Judy Fischbach <jfisch@cs.pdx.edu>
+*
+* Based on stir4200 driver, but some things done differently.
+* Based on earlier driver by Paul Stewart <stewart@parc.com>
+*
+* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+* Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+* Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+* Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+* Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+* Copyright (C) 2005, Judy Fischbach <jfisch@cs.pdx.edu>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither
+ * compatibile with irda-usb nor with stir4200. Although it is quite
+ * similar to the later as far as general idea of operation is concerned.
+ * That is it requires the software to do all the framing job at SIR speeds.
+ * The hardware does take care of the framing at MIR and FIR speeds.
+ * It supports all speeds from 2400 through 4Mbps
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+#include "mcs7780.h"
+
+#define MCS_VENDOR_ID 0x9710
+#define MCS_PRODUCT_ID 0x7780
+
+static struct usb_device_id mcs_table[] = {
+ /* MosChip Corp., MCS7780 FIR-USB Adapter */
+ {USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)},
+ {},
+};
+
+MODULE_AUTHOR("Brian Pugh <bpugh@cs.pdx.edu>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780");
+MODULE_VERSION("0.3alpha");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(usb, mcs_table);
+
+static int qos_mtt_bits = 0x07 /* > 1ms */ ;
+module_param(qos_mtt_bits, int, 0);
+MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
+
+static int receive_mode = 0x1;
+module_param(receive_mode, int, 0);
+MODULE_PARM_DESC(receive_mode,
+ "Receive mode of the device (1:fast, 0:slow, default:1)");
+
+static int sir_tweak = 1;
+module_param(sir_tweak, int, 0444);
+MODULE_PARM_DESC(sir_tweak,
+ "Default pulse width (1:1.6us, 0:3/16 bit, default:1).");
+
+static int transceiver_type = MCS_TSC_VISHAY;
+module_param(transceiver_type, int, 0444);
+MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h.");
+
+struct usb_driver mcs_driver = {
+ .name = "mcs7780",
+ .probe = mcs_probe,
+ .disconnect = mcs_disconnect,
+ .id_table = mcs_table,
+};
+
+/* speed flag selection by direct addressing.
+addr = (speed >> 8) & 0x0f
+
+0x1 57600 0x2 115200 0x4 1152000 0x5 9600
+0x6 38400 0x9 2400 0xa 576000 0xb 19200
+
+4Mbps (or 2400) must be checked separately. Since it also has
+to be programmed in a different manner that is not a big problem.
+*/
+static __u16 mcs_speed_set[16] = { 0,
+ MCS_SPEED_57600,
+ MCS_SPEED_115200,
+ 0,
+ MCS_SPEED_1152000,
+ MCS_SPEED_9600,
+ MCS_SPEED_38400,
+ 0, 0,
+ MCS_SPEED_2400,
+ MCS_SPEED_576000,
+ MCS_SPEED_19200,
+ 0, 0, 0,
+};
+
+/* Set given 16 bit register with a 16 bit value. Send control message
+ * to set dongle register. */
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val)
+{
+ struct usb_device *dev = mcs->usbdev;
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+ MCS_WR_RTYPE, val, reg, NULL, 0,
+ msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+}
+
+/* Get 16 bit register value. Send contol message to read dongle register. */
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val)
+{
+ struct usb_device *dev = mcs->usbdev;
+ int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+ MCS_RD_RTYPE, 0, reg, val, 2,
+ msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+
+ return ret;
+}
+
+/* Setup a communication between mcs7780 and TFDU chips. It is described
+ * in more detail in the data sheet. The setup sequence puts the the
+ * vishay tranceiver into high speed mode. It will also receive SIR speed
+ * packets but at reduced sensitivity.
+ */
+
+/* 0: OK 1:ERROR */
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs)
+{
+ int ret = 0;
+ __u16 rval;
+
+ /* mcs_get_reg should read exactly two bytes from the dongle */
+ ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+ if (unlikely(ret != 2)) {
+ ret = -EIO;
+ goto error;
+ }
+
+ /* The MCS_XCVR_CONF bit puts the transceiver into configuration
+ * mode. The MCS_MODE0 bit must start out high (1) and then
+ * transition to low and the MCS_STFIR and MCS_MODE1 bits must
+ * be low.
+ */
+ rval |= (MCS_MODE0 | MCS_XCVR_CONF);
+ rval &= ~MCS_STFIR;
+ rval &= ~MCS_MODE1;
+ ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+ if (unlikely(ret))
+ goto error;
+
+ rval &= ~MCS_MODE0;
+ ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+ if (unlikely(ret))
+ goto error;
+
+ rval &= ~MCS_XCVR_CONF;
+ ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+ if (unlikely(ret))
+ goto error;
+
+ ret = 0;
+ error:
+ return ret;
+}
+
+/* Setup a communication between mcs7780 and agilent chip. */
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs)
+{
+ IRDA_WARNING("This transceiver type is not supported yet.");
+ return 1;
+}
+
+/* Setup a communication between mcs7780 and sharp chip. */
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs)
+{
+ IRDA_WARNING("This transceiver type is not supported yet.");
+ return 1;
+}
+
+/* Common setup for all transceivers */
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs)
+{
+ int ret = 0;
+ __u16 rval;
+ char *msg;
+
+ msg = "Basic transceiver setup error.";
+
+ /* read value of MODE Register, set the DRIVER and RESET bits
+ * and write value back out to MODE Register
+ */
+ ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+ if(unlikely(ret != 2))
+ goto error;
+ rval |= MCS_DRIVER; /* put the mcs7780 into configuration mode. */
+ ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+ if(unlikely(ret))
+ goto error;
+
+ rval = 0; /* set min pulse width to 0 initially. */
+ ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval);
+ if(unlikely(ret))
+ goto error;
+
+ ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+ if(unlikely(ret != 2))
+ goto error;
+
+ rval &= ~MCS_FIR; /* turn off fir mode. */
+ if(mcs->sir_tweak)
+ rval |= MCS_SIR16US; /* 1.6us pulse width */
+ else
+ rval &= ~MCS_SIR16US; /* 3/16 bit time pulse width */
+
+ /* make sure ask mode and back to back packets are off. */
+ rval &= ~(MCS_BBTG | MCS_ASK);
+
+ rval &= ~MCS_SPEED_MASK;
+ rval |= MCS_SPEED_9600; /* make sure initial speed is 9600. */
+ mcs->speed = 9600;
+ mcs->new_speed = 0; /* new_speed is set to 0 */
+ rval &= ~MCS_PLLPWDN; /* disable power down. */
+
+ /* make sure device determines direction and that the auto send sip
+ * pulse are on.
+ */
+ rval |= MCS_DTD | MCS_SIPEN;
+
+ ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+ if(unlikely(ret))
+ goto error;
+
+ msg = "transceiver model specific setup error.";
+ switch (mcs->transceiver_type) {
+ case MCS_TSC_VISHAY:
+ ret = mcs_setup_transceiver_vishay(mcs);
+ break;
+
+ case MCS_TSC_SHARP:
+ ret = mcs_setup_transceiver_sharp(mcs);
+ break;
+
+ case MCS_TSC_AGILENT:
+ ret = mcs_setup_transceiver_agilent(mcs);
+ break;
+
+ default:
+ IRDA_WARNING("Unknown transceiver type: %d",
+ mcs->transceiver_type);
+ ret = 1;
+ }
+ if (unlikely(ret))
+ goto error;
+
+ /* If transceiver is not SHARP, then if receive mode set
+ * on the RXFAST bit in the XCVR Register otherwise unset it
+ */
+ if (mcs->transceiver_type != MCS_TSC_SHARP) {
+
+ ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+ if (unlikely(ret != 2))
+ goto error;
+ if (mcs->receive_mode)
+ rval |= MCS_RXFAST;
+ else
+ rval &= ~MCS_RXFAST;
+ ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+ if (unlikely(ret))
+ goto error;
+ }
+
+ msg = "transceiver reset.";
+
+ ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+ if (unlikely(ret != 2))
+ goto error;
+
+ /* reset the mcs7780 so all changes take effect. */
+ rval &= ~MCS_RESET;
+ ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+ if (unlikely(ret))
+ goto error;
+ else
+ return ret;
+
+error:
+ IRDA_ERROR("%s", msg);
+ return ret;
+}
+
+/* Wraps the data in format for SIR */
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf)
+{
+ int wraplen;
+
+ /* 2: full frame length, including "the length" */
+ wraplen = async_wrap_skb(skb, buf + 2, 4094);
+
+ wraplen += 2;
+ buf[0] = wraplen & 0xff;
+ buf[1] = (wraplen >> 8) & 0xff;
+
+ return wraplen;
+}
+
+/* Wraps the data in format for FIR */
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+ unsigned int len = 0;
+ __u32 fcs = ~(crc32_le(~0, skb->data, skb->len));
+
+ /* add 2 bytes for length value and 4 bytes for fcs. */
+ len = skb->len + 6;
+
+ /* The mcs7780 requires that the first two bytes are the packet
+ * length in little endian order. Note: the length value includes
+ * the two bytes for the length value itself.
+ */
+ buf[0] = len & 0xff;
+ buf[1] = (len >> 8) & 0xff;
+ /* copy the data into the tx buffer. */
+ memcpy(buf+2, skb->data, skb->len);
+ /* put the fcs in the last four bytes in little endian order. */
+ buf[len - 4] = fcs & 0xff;
+ buf[len - 3] = (fcs >> 8) & 0xff;
+ buf[len - 2] = (fcs >> 16) & 0xff;
+ buf[len - 1] = (fcs >> 24) & 0xff;
+
+ return len;
+}
+
+/* Wraps the data in format for MIR */
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+ __u16 fcs = 0;
+ int len = skb->len + 4;
+
+ fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len));
+ /* put the total packet length in first. Note: packet length
+ * value includes the two bytes that hold the packet length
+ * itself.
+ */
+ buf[0] = len & 0xff;
+ buf[1] = (len >> 8) & 0xff;
+ /* copy the data */
+ memcpy(buf+2, skb->data, skb->len);
+ /* put the fcs in last two bytes in little endian order. */
+ buf[len - 2] = fcs & 0xff;
+ buf[len - 1] = (fcs >> 8) & 0xff;
+
+ return len;
+}
+
+/* Unwrap received packets at MIR speed. A 16 bit crc_ccitt checksum is
+ * used for the fcs. When performed over the entire packet the result
+ * should be GOOD_FCS = 0xf0b8. Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+ __u16 fcs;
+ int new_len;
+ struct sk_buff *skb;
+
+ /* Assume that the frames are going to fill a single packet
+ * rather than span multiple packets.
+ */
+
+ new_len = len - 2;
+ if(unlikely(new_len <= 0)) {
+ IRDA_ERROR("%s short frame length %d\n",
+ mcs->netdev->name, new_len);
+ ++mcs->stats.rx_errors;
+ ++mcs->stats.rx_length_errors;
+ return;
+ }
+ fcs = 0;
+ fcs = irda_calc_crc16(~fcs, buf, len);
+
+ if(fcs != GOOD_FCS) {
+ IRDA_ERROR("crc error calc 0x%x len %d\n",
+ fcs, new_len);
+ mcs->stats.rx_errors++;
+ mcs->stats.rx_crc_errors++;
+ return;
+ }
+
+ skb = dev_alloc_skb(new_len + 1);
+ if(unlikely(!skb)) {
+ ++mcs->stats.rx_dropped;
+ return;
+ }
+
+ skb_reserve(skb, 1);
+ memcpy(skb->data, buf, new_len);
+ skb_put(skb, new_len);
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ skb->dev = mcs->netdev;
+
+ netif_rx(skb);
+
+ mcs->stats.rx_packets++;
+ mcs->stats.rx_bytes += new_len;
+
+ return;
+}
+
+/* Unwrap received packets at FIR speed. A 32 bit crc_ccitt checksum is
+ * used for the fcs. Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+ __u32 fcs;
+ int new_len;
+ struct sk_buff *skb;
+
+ /* Assume that the frames are going to fill a single packet
+ * rather than span multiple packets. This is most likely a false
+ * assumption.
+ */
+
+ new_len = len - 4;
+ if(unlikely(new_len <= 0)) {
+ IRDA_ERROR("%s short frame length %d\n",
+ mcs->netdev->name, new_len);
+ ++mcs->stats.rx_errors;
+ ++mcs->stats.rx_length_errors;
+ return;
+ }
+
+ fcs = ~(crc32_le(~0, buf, new_len));
+ if(fcs != le32_to_cpu(get_unaligned((u32 *)(buf+new_len)))) {
+ IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
+ mcs->stats.rx_errors++;
+ mcs->stats.rx_crc_errors++;
+ return;
+ }
+
+ skb = dev_alloc_skb(new_len + 1);
+ if(unlikely(!skb)) {
+ ++mcs->stats.rx_dropped;
+ return;
+ }
+
+ skb_reserve(skb, 1);
+ memcpy(skb->data, buf, new_len);
+ skb_put(skb, new_len);
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ skb->dev = mcs->netdev;
+
+ netif_rx(skb);
+
+ mcs->stats.rx_packets++;
+ mcs->stats.rx_bytes += new_len;
+
+ return;
+}
+
+
+/* Allocates urbs for both receive and transmit.
+ * If alloc fails return error code 0 (fail) otherwise
+ * return error code 1 (success).
+ */
+static inline int mcs_setup_urbs(struct mcs_cb *mcs)
+{
+ mcs->rx_urb = NULL;
+
+ mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!mcs->tx_urb)
+ return 0;
+
+ mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!mcs->rx_urb)
+ return 0;
+
+ return 1;
+}
+
+/* Sets up state to be initially outside frame, gets receive urb,
+ * sets status to successful and then submits the urb to start
+ * receiving the data.
+ */
+static inline int mcs_receive_start(struct mcs_cb *mcs)
+{
+ mcs->rx_buff.in_frame = FALSE;
+ mcs->rx_buff.state = OUTSIDE_FRAME;
+
+ usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev,
+ usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in),
+ mcs->in_buf, 4096, mcs_receive_irq, mcs);
+
+ mcs->rx_urb->status = 0;
+ return usb_submit_urb(mcs->rx_urb, GFP_KERNEL);
+}
+
+/* Finds the in and out endpoints for the mcs control block */
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+ struct usb_host_endpoint *ep, int epnum)
+{
+ int i;
+ int ret = 0;
+
+ /* If no place to store the endpoints just return */
+ if (!ep)
+ return ret;
+
+ /* cycle through all endpoints, find the first two that are DIR_IN */
+ for (i = 0; i < epnum; i++) {
+ if (ep[i].desc.bEndpointAddress & USB_DIR_IN)
+ mcs->ep_in = ep[i].desc.bEndpointAddress;
+ else
+ mcs->ep_out = ep[i].desc.bEndpointAddress;
+
+ /* MosChip says that the chip has only two bulk
+ * endpoints. Find one for each direction and move on.
+ */
+ if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) {
+ ret = 1;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void mcs_speed_work(void *arg)
+{
+ struct mcs_cb *mcs = arg;
+ struct net_device *netdev = mcs->netdev;
+
+ mcs_speed_change(mcs);
+ netif_wake_queue(netdev);
+}
+
+/* Function to change the speed of the mcs7780. Fully supports SIR,
+ * MIR, and FIR speeds.
+ */
+static int mcs_speed_change(struct mcs_cb *mcs)
+{
+ int ret = 0;
+ int rst = 0;
+ int cnt = 0;
+ __u16 nspeed;
+ __u16 rval;
+
+ nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f];
+
+ do {
+ mcs_get_reg(mcs, MCS_RESV_REG, &rval);
+ } while(cnt++ < 100 && (rval & MCS_IRINTX));
+
+ if(cnt >= 100) {
+ IRDA_ERROR("unable to change speed");
+ ret = -EIO;
+ goto error;
+ }
+
+ mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+
+ /* MINRXPW values recomended by MosChip */
+ if (mcs->new_speed <= 115200) {
+ rval &= ~MCS_FIR;
+
+ if ((rst = (mcs->speed > 115200)))
+ mcs_set_reg(mcs, MCS_MINRXPW_REG, 0);
+
+ } else if (mcs->new_speed <= 1152000) {
+ rval &= ~MCS_FIR;
+
+ if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000)))
+ mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+ } else {
+ rval |= MCS_FIR;
+
+ if ((rst = (mcs->speed != 4000000)))
+ mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+ }
+
+ rval &= ~MCS_SPEED_MASK;
+ rval |= nspeed;
+
+ ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+ if (unlikely(ret))
+ goto error;
+
+ if (rst)
+ switch (mcs->transceiver_type) {
+ case MCS_TSC_VISHAY:
+ ret = mcs_setup_transceiver_vishay(mcs);
+ break;
+
+ case MCS_TSC_SHARP:
+ ret = mcs_setup_transceiver_sharp(mcs);
+ break;
+
+ case MCS_TSC_AGILENT:
+ ret = mcs_setup_transceiver_agilent(mcs);
+ break;
+
+ default:
+ ret = 1;
+ IRDA_WARNING("Unknown transceiver type: %d",
+ mcs->transceiver_type);
+ }
+ if (unlikely(ret))
+ goto error;
+
+ mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+ rval &= ~MCS_RESET;
+ ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+
+ mcs->speed = mcs->new_speed;
+ error:
+ mcs->new_speed = 0;
+ return ret;
+}
+
+/* Ioctl calls not supported at this time. Can be an area of future work. */
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+ /* struct if_irda_req *irq = (struct if_irda_req *)rq; */
+ /* struct mcs_cb *mcs = netdev_priv(netdev); */
+ int ret = 0;
+
+ switch (cmd) {
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+/* Network device is taken down, done by "ifconfig irda0 down" */
+static int mcs_net_close(struct net_device *netdev)
+{
+ int ret = 0;
+ struct mcs_cb *mcs = netdev_priv(netdev);
+
+ /* Stop transmit processing */
+ netif_stop_queue(netdev);
+
+ /* kill and free the receive and transmit URBs */
+ usb_kill_urb(mcs->rx_urb);
+ usb_free_urb(mcs->rx_urb);
+ usb_kill_urb(mcs->tx_urb);
+ usb_free_urb(mcs->tx_urb);
+
+ /* Stop and remove instance of IrLAP */
+ if (mcs->irlap)
+ irlap_close(mcs->irlap);
+
+ mcs->irlap = NULL;
+ return ret;
+}
+
+/* Network device is taken up, done by "ifconfig irda0 up" */
+static int mcs_net_open(struct net_device *netdev)
+{
+ struct mcs_cb *mcs = netdev_priv(netdev);
+ char hwname[16];
+ int ret = 0;
+
+ ret = usb_clear_halt(mcs->usbdev,
+ usb_sndbulkpipe(mcs->usbdev, mcs->ep_in));
+ if (ret)
+ goto error1;
+ ret = usb_clear_halt(mcs->usbdev,
+ usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out));
+ if (ret)
+ goto error1;
+
+ ret = mcs_setup_transceiver(mcs);
+ if (ret)
+ goto error1;
+
+ ret = -ENOMEM;
+
+ /* Initialize for SIR/FIR to copy data directly into skb. */
+ mcs->receiving = 0;
+ mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+ mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+ if (!mcs->rx_buff.skb)
+ goto error1;
+
+ skb_reserve(mcs->rx_buff.skb, 1);
+ mcs->rx_buff.head = mcs->rx_buff.skb->data;
+ do_gettimeofday(&mcs->rx_time);
+
+ /*
+ * Now that everything should be initialized properly,
+ * Open new IrLAP layer instance to take care of us...
+ * Note : will send immediately a speed change...
+ */
+ sprintf(hwname, "usb#%d", mcs->usbdev->devnum);
+ mcs->irlap = irlap_open(netdev, &mcs->qos, hwname);
+ if (!mcs->irlap) {
+ IRDA_ERROR("mcs7780: irlap_open failed");
+ goto error2;
+ }
+
+ if (!mcs_setup_urbs(mcs))
+ goto error3;
+
+ ret = mcs_receive_start(mcs);
+ if (ret)
+ goto error3;
+
+ netif_start_queue(netdev);
+ return 0;
+
+ error3:
+ irlap_close(mcs->irlap);
+ error2:
+ kfree_skb(mcs->rx_buff.skb);
+ error1:
+ return ret;
+}
+
+
+/* Get device stats for /proc/net/dev and ifconfig */
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev)
+{
+ struct mcs_cb *mcs = netdev_priv(netdev);
+ return &mcs->stats;
+}
+
+/* Receive callback function. */
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs)
+{
+ __u8 *bytes;
+ struct mcs_cb *mcs = urb->context;
+ int i;
+ int ret;
+
+ if (!netif_running(mcs->netdev))
+ return;
+
+ if (urb->status)
+ return;
+
+ if (urb->actual_length > 0) {
+ bytes = urb->transfer_buffer;
+
+ /* MCS returns frames without BOF and EOF
+ * I assume it returns whole frames.
+ */
+ /* SIR speed */
+ if(mcs->speed < 576000) {
+ async_unwrap_char(mcs->netdev, &mcs->stats,
+ &mcs->rx_buff, 0xc0);
+
+ for (i = 0; i < urb->actual_length; i++)
+ async_unwrap_char(mcs->netdev, &mcs->stats,
+ &mcs->rx_buff, bytes[i]);
+
+ async_unwrap_char(mcs->netdev, &mcs->stats,
+ &mcs->rx_buff, 0xc1);
+ }
+ /* MIR speed */
+ else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+ mcs_unwrap_mir(mcs, urb->transfer_buffer,
+ urb->actual_length);
+ }
+ /* FIR speed */
+ else {
+ mcs_unwrap_fir(mcs, urb->transfer_buffer,
+ urb->actual_length);
+ }
+ mcs->netdev->last_rx = jiffies;
+ do_gettimeofday(&mcs->rx_time);
+ }
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/* Transmit callback funtion. */
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct mcs_cb *mcs = urb->context;
+ struct net_device *ndev = mcs->netdev;
+
+ if (unlikely(mcs->new_speed))
+ schedule_work(&mcs->work);
+ else
+ netif_wake_queue(ndev);
+}
+
+/* Transmit callback funtion. */
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ unsigned long flags;
+ struct mcs_cb *mcs;
+ int wraplen;
+ int ret = 0;
+
+
+ if (skb == NULL || ndev == NULL)
+ return -EINVAL;
+
+ netif_stop_queue(ndev);
+ mcs = netdev_priv(ndev);
+
+ spin_lock_irqsave(&mcs->lock, flags);
+
+ mcs->new_speed = irda_get_next_speed(skb);
+ if (likely(mcs->new_speed == mcs->speed))
+ mcs->new_speed = 0;
+
+ /* SIR speed */
+ if(mcs->speed < 576000) {
+ wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf);
+ }
+ /* MIR speed */
+ else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+ wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf);
+ }
+ /* FIR speed */
+ else {
+ wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf);
+ }
+ usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev,
+ usb_sndbulkpipe(mcs->usbdev, mcs->ep_out),
+ mcs->out_buf, wraplen, mcs_send_irq, mcs);
+
+ if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) {
+ IRDA_ERROR("failed tx_urb: %d", ret);
+ switch (ret) {
+ case -ENODEV:
+ case -EPIPE:
+ break;
+ default:
+ mcs->stats.tx_errors++;
+ netif_start_queue(ndev);
+ }
+ } else {
+ mcs->stats.tx_packets++;
+ mcs->stats.tx_bytes += skb->len;
+ }
+
+ dev_kfree_skb(skb);
+ spin_unlock_irqrestore(&mcs->lock, flags);
+ return ret;
+}
+
+/*
+ * This function is called by the USB subsystem for each new device in the
+ * system. Need to verify the device and if it is, then start handling it.
+ */
+static int mcs_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct net_device *ndev = NULL;
+ struct mcs_cb *mcs;
+ int ret = -ENOMEM;
+
+ ndev = alloc_irdadev(sizeof(*mcs));
+ if (!ndev)
+ goto error1;
+
+ IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.", udev->devnum);
+
+ /* what is it realy for? */
+ SET_MODULE_OWNER(ndev);
+ SET_NETDEV_DEV(ndev, &intf->dev);
+
+ ret = usb_reset_configuration(udev);
+ if (ret != 0) {
+ IRDA_ERROR("mcs7780: usb reset configuration failed");
+ goto error2;
+ }
+
+ mcs = netdev_priv(ndev);
+ mcs->usbdev = udev;
+ mcs->netdev = ndev;
+ spin_lock_init(&mcs->lock);
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies(&mcs->qos);
+
+ /* That's the Rx capability. */
+ mcs->qos.baud_rate.bits &=
+ IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200
+ | IR_576000 | IR_1152000 | (IR_4000000 << 8);
+
+
+ mcs->qos.min_turn_time.bits &= qos_mtt_bits;
+ irda_qos_bits_to_value(&mcs->qos);
+
+ /* Speed change work initialisation*/
+ INIT_WORK(&mcs->work, mcs_speed_work, mcs);
+
+ /* Override the network functions we need to use */
+ ndev->hard_start_xmit = mcs_hard_xmit;
+ ndev->open = mcs_net_open;
+ ndev->stop = mcs_net_close;
+ ndev->get_stats = mcs_net_get_stats;
+ ndev->do_ioctl = mcs_net_ioctl;
+
+ if (!intf->cur_altsetting)
+ goto error2;
+
+ ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint,
+ intf->cur_altsetting->desc.bNumEndpoints);
+ if (!ret) {
+ ret = -ENODEV;
+ goto error2;
+ }
+
+ ret = register_netdev(ndev);
+ if (ret != 0)
+ goto error2;
+
+ IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s",
+ ndev->name);
+
+ mcs->transceiver_type = transceiver_type;
+ mcs->sir_tweak = sir_tweak;
+ mcs->receive_mode = receive_mode;
+
+ usb_set_intfdata(intf, mcs);
+ return 0;
+
+ error2:
+ free_netdev(ndev);
+
+ error1:
+ return ret;
+}
+
+/* The current device is removed, the USB layer tells us to shut down. */
+static void mcs_disconnect(struct usb_interface *intf)
+{
+ struct mcs_cb *mcs = usb_get_intfdata(intf);
+
+ if (!mcs)
+ return;
+
+ flush_scheduled_work();
+
+ unregister_netdev(mcs->netdev);
+ free_netdev(mcs->netdev);
+
+ usb_set_intfdata(intf, NULL);
+ IRDA_DEBUG(0, "MCS7780 now disconnected.");
+}
+
+/* Module insertion */
+static int __init mcs_init(void)
+{
+ int result;
+
+ /* register this driver with the USB subsystem */
+ result = usb_register(&mcs_driver);
+ if (result)
+ IRDA_ERROR("usb_register failed. Error number %d", result);
+
+ return result;
+}
+module_init(mcs_init);
+
+/* Module removal */
+static void __exit mcs_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&mcs_driver);
+}
+module_exit(mcs_exit);
+
diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h
new file mode 100644
index 0000000..1a723d7
--- /dev/null
+++ b/drivers/net/irda/mcs7780.h
@@ -0,0 +1,167 @@
+/*****************************************************************************
+*
+* Filename: mcs7780.h
+* Version: 0.2-alpha
+* Description: Irda MosChip USB Dongle
+* Status: Experimental
+* Authors: Lukasz Stelmach <stlman@poczta.fm>
+* Brian Pugh <bpugh@cs.pdx.edu>
+*
+* Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+* Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+#ifndef _MCS7780_H
+#define _MCS7780_H
+
+#define MCS_MODE_SIR 0
+#define MCS_MODE_MIR 1
+#define MCS_MODE_FIR 2
+
+#define MCS_CTRL_TIMEOUT 500
+#define MCS_XMIT_TIMEOUT 500
+/* Possible transceiver types */
+#define MCS_TSC_VISHAY 0 /* Vishay TFD, default choice */
+#define MCS_TSC_AGILENT 1 /* Agilent 3602/3600 */
+#define MCS_TSC_SHARP 2 /* Sharp GP2W1000YP */
+
+/* Requests */
+#define MCS_RD_RTYPE 0xC0
+#define MCS_WR_RTYPE 0x40
+#define MCS_RDREQ 0x0F
+#define MCS_WRREQ 0x0E
+
+/* Register 0x00 */
+#define MCS_MODE_REG 0
+#define MCS_FIR ((__u16)0x0001)
+#define MCS_SIR16US ((__u16)0x0002)
+#define MCS_BBTG ((__u16)0x0004)
+#define MCS_ASK ((__u16)0x0008)
+#define MCS_PARITY ((__u16)0x0010)
+
+/* SIR/MIR speed constants */
+#define MCS_SPEED_SHIFT 5
+#define MCS_SPEED_MASK ((__u16)0x00E0)
+#define MCS_SPEED(x) ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT)
+#define MCS_SPEED_2400 ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_9600 ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_19200 ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_38400 ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_57600 ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_115200 ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_576000 ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_1152000 ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+
+#define MCS_PLLPWDN ((__u16)0x0100)
+#define MCS_DRIVER ((__u16)0x0200)
+#define MCS_DTD ((__u16)0x0400)
+#define MCS_DIR ((__u16)0x0800)
+#define MCS_SIPEN ((__u16)0x1000)
+#define MCS_SENDSIP ((__u16)0x2000)
+#define MCS_CHGDIR ((__u16)0x4000)
+#define MCS_RESET ((__u16)0x8000)
+
+/* Register 0x02 */
+#define MCS_XCVR_REG 2
+#define MCS_MODE0 ((__u16)0x0001)
+#define MCS_STFIR ((__u16)0x0002)
+#define MCS_XCVR_CONF ((__u16)0x0004)
+#define MCS_RXFAST ((__u16)0x0008)
+/* TXCUR [6:4] */
+#define MCS_TXCUR_SHIFT 4
+#define MCS_TXCUR_MASK ((__u16)0x0070)
+#define MCS_TXCUR(x) ((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT)
+#define MCS_SETTXCUR(x,y) \
+ ((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK)
+
+#define MCS_MODE1 ((__u16)0x0080)
+#define MCS_SMODE0 ((__u16)0x0100)
+#define MCS_SMODE1 ((__u16)0x0200)
+#define MCS_INVTX ((__u16)0x0400)
+#define MCS_INVRX ((__u16)0x0800)
+
+#define MCS_MINRXPW_REG 4
+
+#define MCS_RESV_REG 7
+#define MCS_IRINTX ((__u16)0x0001)
+#define MCS_IRINRX ((__u16)0x0002)
+
+struct mcs_cb {
+ struct usb_device *usbdev; /* init: probe_irda */
+ struct net_device *netdev; /* network layer */
+ struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct net_device_stats stats; /* network statistics */
+ struct qos_info qos;
+ unsigned int speed; /* Current speed */
+ unsigned int new_speed; /* new speed */
+
+ struct work_struct work; /* Change speed work */
+
+ struct sk_buff *tx_pending;
+ char in_buf[4096]; /* transmit/receive buffer */
+ char out_buf[4096]; /* transmit/receive buffer */
+ __u8 *fifo_status;
+
+ iobuff_t rx_buff; /* receive unwrap state machine */
+ struct timeval rx_time;
+ spinlock_t lock;
+ int receiving;
+
+ __u8 ep_in;
+ __u8 ep_out;
+
+ struct urb *rx_urb;
+ struct urb *tx_urb;
+
+ int transceiver_type;
+ int sir_tweak;
+ int receive_mode;
+};
+
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val);
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val);
+
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs);
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf);
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf);
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf);
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len);
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len);
+static inline int mcs_setup_urbs(struct mcs_cb *mcs);
+static inline int mcs_receive_start(struct mcs_cb *mcs);
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+ struct usb_host_endpoint *ep, int epnum);
+
+static int mcs_speed_change(struct mcs_cb *mcs);
+
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd);
+static int mcs_net_close(struct net_device *netdev);
+static int mcs_net_open(struct net_device *netdev);
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev);
+
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs);
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs);
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev);
+
+static int mcs_probe(struct usb_interface *intf,
+ const struct usb_device_id *id);
+static void mcs_disconnect(struct usb_interface *intf);
+
+#endif /* _MCS7780_H */
--
1.3.2
^ permalink raw reply related
* [PATCH 3/4] [IrDA] stir4200, switching to the kthread API
From: Samuel Ortiz @ 2006-05-25 6:19 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, irda-users, hch, shemminger
stir4200 uses a kernel thread for its TX/RX operations, and it is now
converted to the kernel kthread API.
Tested on an STIR4200 based dongle.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
---
drivers/net/irda/stir4200.c | 38 ++++++++++++++------------------------
1 files changed, 14 insertions(+), 24 deletions(-)
57a09954136abe1a184ff117f92cc7ebd8b93a49
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 31867e4..d61b208 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -50,6 +50,7 @@ #include <linux/slab.h>
#include <linux/delay.h>
#include <linux/usb.h>
#include <linux/crc32.h>
+#include <linux/kthread.h>
#include <net/irda/irda.h>
#include <net/irda/irlap.h>
#include <net/irda/irda_device.h>
@@ -173,9 +174,7 @@ struct stir_cb {
struct qos_info qos;
unsigned speed; /* Current speed */
- wait_queue_head_t thr_wait; /* transmit thread wakeup */
- struct completion thr_exited;
- pid_t thr_pid;
+ struct task_struct *thread; /* transmit thread */
struct sk_buff *tx_pending;
void *io_buf; /* transmit/receive buffer */
@@ -577,7 +576,7 @@ static int stir_hard_xmit(struct sk_buff
SKB_LINEAR_ASSERT(skb);
skb = xchg(&stir->tx_pending, skb);
- wake_up(&stir->thr_wait);
+ wake_up_process(stir->thread);
/* this should never happen unless stop/wakeup problem */
if (unlikely(skb)) {
@@ -753,13 +752,7 @@ static int stir_transmit_thread(void *ar
struct net_device *dev = stir->netdev;
struct sk_buff *skb;
- daemonize("%s", dev->name);
- allow_signal(SIGTERM);
-
- while (netif_running(dev)
- && netif_device_present(dev)
- && !signal_pending(current))
- {
+ while (!kthread_should_stop()) {
#ifdef CONFIG_PM
/* if suspending, then power off and wait */
if (unlikely(freezing(current))) {
@@ -813,10 +806,11 @@ #endif
}
/* sleep if nothing to send */
- wait_event_interruptible(stir->thr_wait, stir->tx_pending);
- }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
- complete_and_exit (&stir->thr_exited, 0);
+ }
+ return 0;
}
@@ -859,7 +853,7 @@ static void stir_rcv_irq(struct urb *urb
warn("%s: usb receive submit error: %d",
stir->netdev->name, err);
stir->receiving = 0;
- wake_up(&stir->thr_wait);
+ wake_up_process(stir->thread);
}
}
@@ -928,10 +922,10 @@ static int stir_net_open(struct net_devi
}
/** Start kernel thread for transmit. */
- stir->thr_pid = kernel_thread(stir_transmit_thread, stir,
- CLONE_FS|CLONE_FILES);
- if (stir->thr_pid < 0) {
- err = stir->thr_pid;
+ stir->thread = kthread_run(stir_transmit_thread, stir,
+ "%s", stir->netdev->name);
+ if (IS_ERR(stir->thread)) {
+ err = PTR_ERR(stir->thread);
err("stir4200: unable to start kernel thread");
goto err_out6;
}
@@ -968,8 +962,7 @@ static int stir_net_close(struct net_dev
netif_stop_queue(netdev);
/* Kill transmit thread */
- kill_proc(stir->thr_pid, SIGTERM, 1);
- wait_for_completion(&stir->thr_exited);
+ kthread_stop(stir->thread);
kfree(stir->fifo_status);
/* Mop up receive urb's */
@@ -1084,9 +1077,6 @@ static int stir_probe(struct usb_interfa
stir->qos.min_turn_time.bits &= qos_mtt_bits;
irda_qos_bits_to_value(&stir->qos);
- init_completion (&stir->thr_exited);
- init_waitqueue_head (&stir->thr_wait);
-
/* Override the network functions we need to use */
net->hard_start_xmit = stir_hard_xmit;
net->open = stir_net_open;
--
1.3.2
^ permalink raw reply related
* [PATCH 4/4] [IrDA] ali-ircc: using device model power management
From: Samuel Ortiz @ 2006-05-25 6:20 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, irda-users
This patch gets rid of the old power management code and now uses the
device model for the ali-ircc driver.
Signed-off-by: Samuel Ortiz <samuel@sortiz.org>
---
drivers/net/irda/ali-ircc.c | 106 +++++++++++++++++++++----------------------
1 files changed, 51 insertions(+), 55 deletions(-)
3e4b76aae7a8b088e1c8724aaedc1e63eae589a2
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 2e7882e..bf1fca5 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -34,14 +34,12 @@ #include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
@@ -51,7 +49,19 @@ #include "ali-ircc.h"
#define CHIP_IO_EXTENT 8
#define BROKEN_DONGLE_ID
-static char *driver_name = "ali-ircc";
+#define ALI_IRCC_DRIVER_NAME "ali-ircc"
+
+/* Power Management */
+static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state);
+static int ali_ircc_resume(struct platform_device *dev);
+
+static struct platform_driver ali_ircc_driver = {
+ .suspend = ali_ircc_suspend,
+ .resume = ali_ircc_resume,
+ .driver = {
+ .name = ALI_IRCC_DRIVER_NAME,
+ },
+};
/* Module parameters */
static int qos_mtt_bits = 0x07; /* 1 ms or more */
@@ -97,10 +107,7 @@ static int ali_ircc_is_receiving(struct
static int ali_ircc_net_open(struct net_device *dev);
static int ali_ircc_net_close(struct net_device *dev);
static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud);
-static void ali_ircc_suspend(struct ali_ircc_cb *self);
-static void ali_ircc_wakeup(struct ali_ircc_cb *self);
static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev);
/* SIR function */
@@ -145,6 +152,14 @@ static int __init ali_ircc_init(void)
int i = 0;
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
+
+ ret = platform_driver_register(&ali_ircc_driver);
+ if (ret) {
+ IRDA_ERROR("%s, Can't register driver!\n",
+ ALI_IRCC_DRIVER_NAME);
+ return ret;
+ }
+
/* Probe for all the ALi chipsets we know about */
for (chip= chips; chip->name; chip++, i++)
@@ -214,6 +229,10 @@ static int __init ali_ircc_init(void)
}
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
+
+ if (ret)
+ platform_driver_unregister(&ali_ircc_driver);
+
return ret;
}
@@ -228,14 +247,14 @@ static void __exit ali_ircc_cleanup(void
int i;
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
-
- pm_unregister_all(ali_ircc_pmproc);
for (i=0; i < 4; i++) {
if (dev_self[i])
ali_ircc_close(dev_self[i]);
}
+ platform_driver_unregister(&ali_ircc_driver);
+
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
}
@@ -249,7 +268,6 @@ static int ali_ircc_open(int i, chipio_t
{
struct net_device *dev;
struct ali_ircc_cb *self;
- struct pm_dev *pmdev;
int dongle_id;
int err;
@@ -284,7 +302,8 @@ static int ali_ircc_open(int i, chipio_t
self->io.fifo_size = 16; /* SIR: 16, FIR: 32 Benjamin 2000/11/1 */
/* Reserve the ioports that we need */
- if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
+ if (!request_region(self->io.fir_base, self->io.fir_ext,
+ ALI_IRCC_DRIVER_NAME)) {
IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
self->io.fir_base);
err = -ENODEV;
@@ -354,13 +373,10 @@ static int ali_ircc_open(int i, chipio_t
/* Check dongle id */
dongle_id = ali_ircc_read_dongle_id(i, info);
- IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
+ IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__,
+ ALI_IRCC_DRIVER_NAME, dongle_types[dongle_id]);
self->io.dongle_id = dongle_id;
-
- pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ali_ircc_pmproc);
- if (pmdev)
- pmdev->data = self;
IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
@@ -548,12 +564,11 @@ static int ali_ircc_setup(chipio_t *info
/* Should be 0x00 in the M1535/M1535D */
if(version != 0x00)
{
- IRDA_ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+ IRDA_ERROR("%s, Wrong chip version %02x\n",
+ ALI_IRCC_DRIVER_NAME, version);
return -1;
}
- // IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base);
-
/* Set FIR FIFO Threshold Register */
switch_bank(iobase, BANK1);
outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR);
@@ -583,7 +598,8 @@ static int ali_ircc_setup(chipio_t *info
/* Switch to SIR space */
FIR2SIR(iobase);
- IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", driver_name);
+ IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n",
+ ALI_IRCC_DRIVER_NAME);
/* Enable receive interrupts */
// outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM
@@ -647,7 +663,8 @@ static irqreturn_t ali_ircc_interrupt(in
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
if (!dev) {
- IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
+ IRDA_WARNING("%s: irq %d for unknown device.\n",
+ ALI_IRCC_DRIVER_NAME, irq);
return IRQ_NONE;
}
@@ -1328,7 +1345,8 @@ static int ali_ircc_net_open(struct net_
/* Request IRQ and install Interrupt Handler */
if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev))
{
- IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name,
+ IRDA_WARNING("%s, unable to allocate irq=%d\n",
+ ALI_IRCC_DRIVER_NAME,
self->io.irq);
return -EAGAIN;
}
@@ -1338,7 +1356,8 @@ static int ali_ircc_net_open(struct net_
* failure.
*/
if (request_dma(self->io.dma, dev->name)) {
- IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name,
+ IRDA_WARNING("%s, unable to allocate dma=%d\n",
+ ALI_IRCC_DRIVER_NAME,
self->io.dma);
free_irq(self->io.irq, self);
return -EAGAIN;
@@ -2108,61 +2127,38 @@ static struct net_device_stats *ali_ircc
return &self->stats;
}
-static void ali_ircc_suspend(struct ali_ircc_cb *self)
+static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state)
{
- IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
+ struct ali_ircc_cb *self = platform_get_drvdata(dev);
- IRDA_MESSAGE("%s, Suspending\n", driver_name);
+ IRDA_MESSAGE("%s, Suspending\n", ALI_IRCC_DRIVER_NAME);
if (self->io.suspended)
- return;
+ return 0;
ali_ircc_net_close(self->netdev);
self->io.suspended = 1;
- IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );
+ return 0;
}
-static void ali_ircc_wakeup(struct ali_ircc_cb *self)
+static int ali_ircc_resume(struct platform_device *dev)
{
- IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
+ struct ali_ircc_cb *self = platform_get_drvdata(dev);
if (!self->io.suspended)
- return;
+ return 0;
ali_ircc_net_open(self->netdev);
- IRDA_MESSAGE("%s, Waking up\n", driver_name);
+ IRDA_MESSAGE("%s, Waking up\n", ALI_IRCC_DRIVER_NAME);
self->io.suspended = 0;
-
- IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );
-}
-static int ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct ali_ircc_cb *self = (struct ali_ircc_cb*) dev->data;
-
- IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
-
- if (self) {
- switch (rqst) {
- case PM_SUSPEND:
- ali_ircc_suspend(self);
- break;
- case PM_RESUME:
- ali_ircc_wakeup(self);
- break;
- }
- }
-
- IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );
-
return 0;
}
-
/* ALi Chip Function */
static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable)
--
1.3.2
^ permalink raw reply related
* Re: [PATCH 2/3] pci: bcm43xx kill pci_find_device
From: Jeff Garzik @ 2006-05-25 0:45 UTC (permalink / raw)
To: Jiri Slaby; +Cc: Greg KH, Linux Kernel Mailing List, linux-pci, Netdev List
In-Reply-To: <20060525003040.A91E0C7BDC@atrey.karlin.mff.cuni.cz>
Jiri Slaby wrote:
> bcm43xx kill pci_find_device
>
> Change pci_find_device to safer pci_get_device.
>
> Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
>
> ---
> commit 75664d3c6fe1d8d00b87e42cc001cb5d90613dae
> tree ebcec31955a991f1661197c7e8bcdd682e030681
> parent 431ef31d431939bc9370f952d9510ab9e5b0ad47
> author Jiri Slaby <ku@bellona.localdomain> Thu, 25 May 2006 02:04:38 +0159
> committer Jiri Slaby <ku@bellona.localdomain> Thu, 25 May 2006 02:04:38 +0159
>
> drivers/net/wireless/bcm43xx/bcm43xx_main.c | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
> index b488f77..f770f59 100644
> --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
> +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
> @@ -2142,9 +2142,10 @@ #ifdef CONFIG_BCM947XX
> if (bcm->pci_dev->bus->number == 0) {
> struct pci_dev *d = NULL;
> /* FIXME: we will probably need more device IDs here... */
> - d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
> + d = pci_get_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
> if (d != NULL) {
> bcm->irq = d->irq;
> + pci_dev_put(d);
Given the FIXME, if you are going to touch this area, it seems logical
to add a PCI device match table.
Jeff
^ permalink raw reply
* Re: [RFC] new qla3xxx NIC Driver v2.02.00k29
From: Jeff Garzik @ 2006-05-25 0:58 UTC (permalink / raw)
To: Ron Mercer; +Cc: netdev, linux-driver, Ying Ping Lok
In-Reply-To: <0BB3E5E7462EEA4295BC02D49691DC070D3692@AVEXCH1.qlogic.org>
Ron Mercer wrote:
> All,
>
> Third submission for the upstream inclusion of the qla3xxx Ethernet
> driver. This is a complementary network driver for our ISP4XXX parts.
> There is a concurrent effort underway to get the iSCSI driver (qla4xxx)
> integrated upstream as well.
>
> The following files are included and have been posted to the link below:
>
> LICENSE.qla3xxx
> qla3xxxsrc-v2.02.00k29.tgz
>
> ftp://ftp.qlogic.com/network/upstream/20.02.00k29/
Two points:
1) the ftp:// URL doesn't work for me.
2) Why do we need another license?
Jeff
^ permalink raw reply
* [PATCH] r8169: add new PCI ID
From: Yoichi Yuasa @ 2006-05-25 1:24 UTC (permalink / raw)
To: romieu; +Cc: netdev
Hi,
This patch add new PCI ID for r8169 driver.
RTL8110SBL has this PCI ID.
Please aply.
Yoichi
Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
diff -pruN -X tb0287/Documentation/dontdiff tb0287-orig/drivers/net/r8169.c tb0287/drivers/net/r8169.c
--- tb0287-orig/drivers/net/r8169.c 2006-05-25 10:09:43.981416000 +0900
+++ tb0287/drivers/net/r8169.c 2006-05-25 09:58:45.932290500 +0900
@@ -184,6 +184,7 @@ static const struct {
static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), },
{ PCI_DEVICE(0x16ec, 0x0116), },
{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, },
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Phil Dibowitz @ 2006-05-25 5:01 UTC (permalink / raw)
To: Ben Greear; +Cc: Rick Jones, jamal, netdev, David Miller, Jeff Garzik
In-Reply-To: <4474CBAA.4040307@candelatech.com>
[-- Attachment #1: Type: text/plain, Size: 3183 bytes --]
Brian Haley wrote:
>
> I don't have any problem with Phil's changes.
Thanks Brian, and Andy, and Ben for your support and ideas.
> So how is this different than if an SNMP station probes my system,
> then I reboot, then they probe again. Things will seem to have gone
> backwards, but they deal with that just fine.
Right. Reboots, rmmod/modprobe's, etc. can all cause this. Most
management interfaces seem to handle such things.
> DEC/Compaq/HP has allowed this on Tru64 UNIX since 1999 because we had
> customers that wanted it, noone ever complained about complications
> with SNMP. We did save the last time the stats were zero'd in the
> struct for posterity, but that was never get-able via SNMP:
...
> Maybe saving a "ztime" would make people happier?
I could certainly do this. It would of course change the structure
making the patch slightly more invasive, but it people want this, I can
do it.
Andy wrote:
> On Wed, 2006-05-24 at 14:23 -0400, Jeff Garzik wrote:
>
>> I disagree that we should bother about clearing statistics. It
>> always adds more complication than necessary. Few (if any) other
>> statistics in Linux permit easy clearing,
>
> iptables -Z
Good call - I forgot about that.
Ben Greear wrote:
>> Are SNMP traps generated by going into single-user mode? Rather like
>> what I was saying to Brian earlier. I suspect though that an rmmod
>> doesn't generate an SNMP trap - unless perhaps that to do the rmmod
>> one has to first ifdown the interface and that might?
>
> If the interface comes back, it will (may?) have a different device id
> (if-index),
> even if the name is the same.
Right - but most GUI management interfaces I've seen key off of
interface name *not* ifindex. Certainly Cacti, which I use, does.
> Regardless, not everyone uses SNMP, so clearing stats can still be
> useful. Even
> if it is not implemented perfectly (ie, no locking, so it's possible
> that a clear
> will not totally clear some stats), it will still be right most of the
> time, and
> that will help the casual user who is trying to diagnose network errors
> with only
> console access to the system... (ie, ifconfig -a).
Right. I think the point here is that it does _NOT_ inherently break
things. If you don't like the behavior, don't run "ethtool -z eth0",
it's that simple.
A co-worker suggested today, that maybe it'd appease people if the final
ethtool patch made it a capitol option that you can only run by itself.
I.e. if you can't call it with anything else, it's more difficult to
call my accident. I'd be willing to this.
As for the clearing, in this case, the clearing is done by a command to
the hardware - and I believe the hardware does that atomically. However,
I could certainly add a spinlock around it if someone sees a need.
--
Phil Dibowitz phil@ipom.com
Freeware and Technical Pages Insanity Palace of Metallica
http://www.phildev.net/ http://www.ipom.com/
"Be who you are and say what you feel, because those who mind don't
matter and those who matter don't mind."
- Dr. Seuss
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]
^ permalink raw reply
* Re: [RFC] new qla3xxx NIC Driver v2.02.00k29
From: Andrew Vasquez @ 2006-05-25 5:13 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Ron Mercer, netdev, linux-driver, Ying Ping Lok
In-Reply-To: <44750130.6080103@garzik.org>
On Wed, 24 May 2006, Jeff Garzik wrote:
> >Third submission for the upstream inclusion of the qla3xxx Ethernet
> >driver. This is a complementary network driver for our ISP4XXX parts.
> >There is a concurrent effort underway to get the iSCSI driver (qla4xxx)
> >integrated upstream as well.
> >
> >The following files are included and have been posted to the link below:
> >
> >LICENSE.qla3xxx
> >qla3xxxsrc-v2.02.00k29.tgz
> >
> >ftp://ftp.qlogic.com/network/upstream/20.02.00k29/
>
> Two points:
>
> 1) the ftp:// URL doesn't work for me.
that should have read as:
ftp://ftp.qlogic.com/outgoing/linux/network/upstream/20.02.00k29/qla3xxxsrc-v2.02.00-k29.tgz
> 2) Why do we need another license?
I believe he is referring to this one:
ftp://ftp.qlogic.com/outgoing/linux/network/upstream/2.02.00k19/LICENSE.qla3xxx
which is QLogic's boiler-plate license for drivers which support
hardware that can potentially be programmed with an external firmware
blob. In this case, the QLA3xxx boards currently run with the
'onboard' firmware image. Above and beyond the standard GPL licencing
of the driver sources, the license goes further and states that any
firmware-blob will be licensed under the three-clause BSD license.
This is similar to QLogic's FC driver:
http://kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;h=9e15b4f9cd289f116a1448986847a6313d13bf5f;hb=a8bd60705aa17a998516837d9c1e503ad4cbd7fc;f=Documentation/scsi/LICENSE.qla2xxx
--
av
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Ben Greear @ 2006-05-25 7:18 UTC (permalink / raw)
To: Phil Dibowitz; +Cc: Rick Jones, jamal, netdev, David Miller, Jeff Garzik
In-Reply-To: <44753A3B.5010204@ipom.com>
Phil Dibowitz wrote:
> As for the clearing, in this case, the clearing is done by a command to
> the hardware - and I believe the hardware does that atomically. However,
> I could certainly add a spinlock around it if someone sees a need.
No, because then you'd also have to add the spin-lock in the hot path
to keep rx/tx threads from accessing counters at the same time. There is no
way a patch that hurts performance like this will be accepted, but I'm
still hopeful that a patch with zero or very near zero performance impact
will be accepted.
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Bill Fink @ 2006-05-25 7:23 UTC (permalink / raw)
To: Jeff Garzik; +Cc: bcook, phil, davem, netdev
In-Reply-To: <4474BD52.6020604@garzik.org>
On Wed, 24 May 2006, Jeff Garzik wrote:
> Brent Cook wrote:
> > Note that this is just clearing the hardware statistics on the interface, and
> > would not require any kind of atomic_increment addition for interfaces that
> > support that. It would be kind-of awkward to implement this on drivers that
> > increment stats in hardware though (lo, vlan, br, etc.) This also brings up
> > the question of resetting the stats for 'netstat -s'
>
> If you don't atomically clear the statistics, then you are leaving open
> a window where the stats could easily be corrupted, if the network
> interface is under load.
>
> This 'clearing' operation has implications on the rest of the statistics
> usage.
>
> More complexity, and breaking of apps, when we could just use the
> existing, working system? I'll take the "do nothing, break nothing,
> everything still works" route any day.
I'll admit to not knowing all the intricacies of the kernel coding involved,
but I don't offhand see how zeroing the stats would be significantly more
complex than updating the stats during normal usage. But I'll have to
leave that argument to the experts.
To me the main argument is that such a stat zeroing feature would be
extremely useful. When trying to track down nasty networking problems
that traverse a multitude of devices, it is often highly desirable to
zero the interface statistics on all the interfaces in the path (which
is available on all networking switches and routers I have worked with),
run some kind of stress test across the path, and then examine the packet
and error counters on all the involved interfaces. This makes it easy to
pinpoint where packets are getting lost or errors are being introduced,
especially when there are scores of stats per device and you may not even
know a priori exactly what you are looking for. Using such a scheme, the
human mind can quickly discern patterns in the data and focus in on any
likely problem areas. The human mind (at least speaking for myself) is
not nearly as adept when having to deal with deltas. Yes, you can record
the initial state of all the devices, run the stress test, record the new
state of all the devices, and then spend a large amount of time devising
a script to calculate all the deltas for all the scores of variables on
all the involved devices, and then finally try and figure out what is
wrong. But it would be so much better, easier, and more efficient, if
the kernel simply provided such a feature that almost all other networking
devices provide.
I also think the SNMP/mgt apps argument is specious. A) SNMP isn't even
an issue with all networks. B) As has been pointed out by others, there
is no requirement to have to use such a new stats zeroing feature. It
would simply be a tool in the network engineer's toolbelt, just like
possibly taking an interface down and back up to see if it corrects a
problem. The network engineer has to balance the potential benefit/harm
of any action he chooses to take, but let him have that choice. And C)
I don't think any decent SNMP/mgt app will be particularly bothered by
zeroing interface stats. I believe they are fairly decent about dealing
with such events (I don't recall our MRTG graphs getting any giant spikes
when I've zeroed interface stats on our GigE/10-GigE switches). I think
the main harm in such a case would be the loss of a sampling interval.
-Bill
^ permalink raw reply
* Re: reminder, 2.6.18 window...
From: Bill Fink @ 2006-05-25 7:55 UTC (permalink / raw)
To: Phil Dibowitz; +Cc: greearb, rick.jones2, hadi, netdev, davem, jeff
In-Reply-To: <44753A3B.5010204@ipom.com>
On Wed, 24 May 2006, Phil Dibowitz wrote:
> Right. I think the point here is that it does _NOT_ inherently break
> things. If you don't like the behavior, don't run "ethtool -z eth0",
> it's that simple.
>
> A co-worker suggested today, that maybe it'd appease people if the final
> ethtool patch made it a capitol option that you can only run by itself.
> I.e. if you can't call it with anything else, it's more difficult to
> call my accident. I'd be willing to this.
I think that's a good idea. Since it is changing (zeroing) the stats,
it probably should be a capitol option.
-Bill
^ permalink raw reply
* Re: [PATCH 3/4] myri10ge - Driver core
From: Benjamin Herrenschmidt @ 2006-05-25 7:56 UTC (permalink / raw)
To: Anton Blanchard; +Cc: Brice Goglin, netdev, gallatin, linux-kernel
In-Reply-To: <20060523153928.GB5938@krispykreme>
On Wed, 2006-05-24 at 01:39 +1000, Anton Blanchard wrote:
> > +#ifdef CONFIG_MTRR
> > + mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
> > + MTRR_TYPE_WRCOMB, 1);
> > +#endif
> ...
> > + mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
>
> Not sure how we are meant to specify write through in drivers. Any ideas Ben?
No proper interface exposed, he'll have to do an #ifdef powerpc here or
such and use __ioremap with explicit page attributes. I have a hack to
do that automatically for memory covered by prefetchable PCI BARs when
mmap'ing from userland but not for kernel ioremap.
Ben.
^ permalink raw reply
* Re: [PATCH 3/4] myri10ge - Driver core
From: Benjamin Herrenschmidt @ 2006-05-25 7:59 UTC (permalink / raw)
To: Brice Goglin; +Cc: Anton Blanchard, netdev, gallatin, linux-kernel
In-Reply-To: <4474138C.2050705@myri.com>
On Wed, 2006-05-24 at 10:04 +0200, Brice Goglin wrote:
> I am not sure what you mean.
> The only ppc64 with PCI-E that we have seen so far (a G5) couldn't do
> write combining according to Apple.
That is not 100% true.... I don't know what apple had in mind. It also
depends in what slot you are.
Do you have ways to measure the difference ?
Try doing __ioremap(mgp->iomem_base, mgp->board_span, _PAGE_NO_CACHE);
instead of using the normal ioremap for #ifdef powerpc and tell us if it
makes a difference.
Ben.
^ permalink raw reply
* RE: [PATCH] TCP Veno module for kernel 2.6.16.13
From: #ZHOU BIN# @ 2006-05-25 8:30 UTC (permalink / raw)
To: Stephen Hemminger, Baruch Even; +Cc: jmorris, netdev
Yes, I agree. Actually the main contribution of TCP Veno is not in this AI phase. No matter the ABC is added or not, TCP Veno can always improve the performance over wireless networks, according to our tests.
Best Regards,
Zhou Bin
-----Original Message-----
From: Stephen Hemminger [mailto:shemminger@osdl.org]
Sent: Thursday, May 25, 2006 12:47 AM
To: Baruch Even
Cc: #ZHOU BIN#; jmorris@namei.org; netdev@vger.kernel.org
Subject: Re: [PATCH] TCP Veno module for kernel 2.6.16.13
On Wed, 24 May 2006 17:16:52 +0100
Baruch Even <baruch@ev-en.org> wrote:
> #ZHOU BIN# wrote:
> > From: Bin Zhou <zhou0022@ntu.edu.sg>
> > + else if (sysctl_tcp_abc) {
> > + /* RFC3465: Apppriate Byte Count
> > + * increase once for each full cwnd acked.
> > + * Veno has no idear about it so far, so we keep
> > + * it as Reno.
> > + */
> > + if (tp->bytes_acked >= tp->snd_cwnd*tp->mss_cache) {
> > + tp->bytes_acked -= tp->snd_cwnd*tp->mss_cache;
> > + if (tp->snd_cwnd < tp->snd_cwnd_clamp)
> > + tp->snd_cwnd++;
> > + }
>
> You should prefer to ignore abc instead. At least that's what everyone
> else is doing, the only place where abc is active is in NewReno.
>
> Baruch
That was intentional. When ABC was added, the desire was to not change existing
behavior for other congestion control methods.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox