/* Per port (line or channel) information
*/
struct fst_port_info {
- hdlc_device hdlc; /* HDLC device struct - must be first */
+ struct net_device *dev;
struct fst_card_info *card; /* Card we're associated with */
int index; /* Port index on the card */
int hwif; /* Line hardware (lineInterface copy) */
};
/* Convert an HDLC device pointer into a port info pointer and similar */
-#define hdlc_to_port(H) ((struct fst_port_info *)(H))
-#define dev_to_port(D) hdlc_to_port(dev_to_hdlc(D))
-#define port_to_dev(P) hdlc_to_dev(&(P)->hdlc)
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+#define port_to_dev(P) ((P)->dev)
/*
int rxp;
unsigned short len;
struct sk_buff *skb;
+ struct net_device *dev = port_to_dev(port);
+ struct net_device_stats *stats = hdlc_stats(dev);
int i;
len );
if ( dmabits != ( RX_STP | RX_ENP ) || len > LEN_RX_BUFFER - 2 )
{
- port->hdlc.stats.rx_errors++;
+ stats->rx_errors++;
/* Update error stats and discard buffer */
if ( dmabits & RX_OFLO )
{
- port->hdlc.stats.rx_fifo_errors++;
+ stats->rx_fifo_errors++;
}
if ( dmabits & RX_CRC )
{
- port->hdlc.stats.rx_crc_errors++;
+ stats->rx_crc_errors++;
}
if ( dmabits & RX_FRAM )
{
- port->hdlc.stats.rx_frame_errors++;
+ stats->rx_frame_errors++;
}
if ( dmabits == ( RX_STP | RX_ENP ))
{
- port->hdlc.stats.rx_length_errors++;
+ stats->rx_length_errors++;
}
/* Discard buffer descriptors until we see the end of packet
{
dbg ( DBG_RX,"intr_rx: can't allocate buffer\n");
- port->hdlc.stats.rx_dropped++;
+ stats->rx_dropped++;
/* Return descriptor to card */
FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
port->rxpos = rxp;
/* Update stats */
- port->hdlc.stats.rx_packets++;
- port->hdlc.stats.rx_bytes += len;
+ stats->rx_packets++;
+ stats->rx_bytes += len;
/* Push upstream */
skb->mac.raw = skb->data;
- skb->dev = hdlc_to_dev ( &port->hdlc );
+ skb->dev = dev;
skb->protocol = hdlc_type_trans(skb, skb->dev);
netif_rx ( skb );
- port_to_dev ( port )->last_rx = jiffies;
+ dev->last_rx = jiffies;
}
* always load up the entire packet for DMA.
*/
dbg ( DBG_TX,"Tx underflow port %d\n", event & 0x03 );
- port->hdlc.stats.tx_errors++;
- port->hdlc.stats.tx_fifo_errors++;
+ hdlc_stats(port_to_dev(port))->tx_errors++;
+ hdlc_stats(port_to_dev(port))->tx_fifo_errors++;
break;
case INIT_CPLT:
{
int err;
- err = hdlc_open ( dev_to_hdlc ( dev ));
+ err = hdlc_open (dev);
if ( err )
return err;
{
netif_stop_queue ( dev );
fst_closeport ( dev_to_port ( dev ));
- hdlc_close ( dev_to_hdlc ( dev ));
+ hdlc_close ( dev );
return 0;
}
static int
-fst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity )
+fst_attach ( struct net_device *dev, unsigned short encoding, unsigned short parity )
{
/* Setting currently fixed in FarSync card so we check and forget */
if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT )
fst_tx_timeout ( struct net_device *dev )
{
struct fst_port_info *port;
+ struct net_device_stats *stats = hdlc_stats(dev);
dbg ( DBG_INTR | DBG_TX,"tx_timeout\n");
port = dev_to_port ( dev );
- port->hdlc.stats.tx_errors++;
- port->hdlc.stats.tx_aborted_errors++;
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
if ( port->txcnt > 0 )
fst_issue_cmd ( port, ABORTTX );
static int
fst_start_xmit ( struct sk_buff *skb, struct net_device *dev )
{
+ struct net_device_stats *stats = hdlc_stats(dev);
struct fst_card_info *card;
struct fst_port_info *port;
unsigned char dmabits;
if ( ! netif_carrier_ok ( dev ))
{
dev_kfree_skb ( skb );
- port->hdlc.stats.tx_errors++;
- port->hdlc.stats.tx_carrier_errors++;
+ stats->tx_errors++;
+ stats->tx_carrier_errors++;
return 0;
}
dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len,
LEN_TX_BUFFER );
dev_kfree_skb ( skb );
- port->hdlc.stats.tx_errors++;
+ stats->tx_errors++;
return 0;
}
spin_unlock_irqrestore ( &card->card_lock, flags );
dbg ( DBG_TX,"Out of Tx buffers\n");
dev_kfree_skb ( skb );
- port->hdlc.stats.tx_errors++;
+ stats->tx_errors++;
return 0;
}
if ( ++port->txpos >= NUM_TX_BUFFER )
FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len ));
FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP );
- port->hdlc.stats.tx_packets++;
- port->hdlc.stats.tx_bytes += skb->len;
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
dev_kfree_skb ( skb );
{
int i;
int err;
- struct net_device *dev;
/* We're working on a number of ports based on the card ID. If the
* firmware detects something different later (should never happen)
* we'll have to revise it in some way then.
*/
- for ( i = 0 ; i < card->nports ; i++ )
- {
- card->ports[i].card = card;
- card->ports[i].index = i;
- card->ports[i].run = 0;
-
- dev = hdlc_to_dev ( &card->ports[i].hdlc );
-
- /* Fill in the net device info */
- /* Since this is a PCI setup this is purely
- * informational. Give them the buffer addresses
- * and basic card I/O.
- */
- dev->mem_start = card->phys_mem
- + BUF_OFFSET ( txBuffer[i][0][0]);
- dev->mem_end = card->phys_mem
- + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]);
- dev->base_addr = card->pci_conf;
- dev->irq = card->irq;
-
- dev->tx_queue_len = FST_TX_QUEUE_LEN;
- dev->open = fst_open;
- dev->stop = fst_close;
- dev->do_ioctl = fst_ioctl;
- dev->watchdog_timeo = FST_TX_TIMEOUT;
- dev->tx_timeout = fst_tx_timeout;
- card->ports[i].hdlc.attach = fst_attach;
- card->ports[i].hdlc.xmit = fst_start_xmit;
-
- if (( err = register_hdlc_device ( &card->ports[i].hdlc )) < 0 )
- {
+ for ( i = 0 ; i < card->nports ; i++ ) {
+ err = register_hdlc_device(card->ports[i].dev);
+ if (err < 0) {
+ int j;
printk_err ("Cannot register HDLC device for port %d"
" (errno %d)\n", i, -err );
+ for (j = i; j < card->nports; j++) {
+ free_netdev(card->ports[j].dev);
+ card->ports[j].dev = NULL;
+ }
card->nports = i;
break;
}
}
- spin_lock_init ( &card->card_lock );
-
printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n",
- hdlc_to_dev(&card->ports[0].hdlc)->name,
- hdlc_to_dev(&card->ports[card->nports-1].hdlc)->name,
+ port_to_dev(&card->ports[0])->name,
+ port_to_dev(&card->ports[card->nports-1])->name,
type_strings[card->type], card->irq, card->nports );
}
static int firsttime_done = 0;
struct fst_card_info *card;
int err = 0;
+ int i;
if ( ! firsttime_done )
{
card->state = FST_UNINIT;
+ spin_lock_init ( &card->card_lock );
+
+ for ( i = 0 ; i < card->nports ; i++ ) {
+ struct net_device *dev = alloc_hdlcdev(&card->ports[i]);
+ hdlc_device *hdlc;
+ if (!dev) {
+ while (i--)
+ free_netdev(card->ports[i].dev);
+ printk_err ("FarSync: out of memory\n");
+ goto error_free_card;
+ }
+ card->ports[i].dev = dev;
+ card->ports[i].card = card;
+ card->ports[i].index = i;
+ card->ports[i].run = 0;
+
+ hdlc = dev_to_hdlc(dev);
+
+ /* Fill in the net device info */
+ /* Since this is a PCI setup this is purely
+ * informational. Give them the buffer addresses
+ * and basic card I/O.
+ */
+ dev->mem_start = card->phys_mem
+ + BUF_OFFSET ( txBuffer[i][0][0]);
+ dev->mem_end = card->phys_mem
+ + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]);
+ dev->base_addr = card->pci_conf;
+ dev->irq = card->irq;
+
+ dev->tx_queue_len = FST_TX_QUEUE_LEN;
+ dev->open = fst_open;
+ dev->stop = fst_close;
+ dev->do_ioctl = fst_ioctl;
+ dev->watchdog_timeo = FST_TX_TIMEOUT;
+ dev->tx_timeout = fst_tx_timeout;
+ hdlc->attach = fst_attach;
+ hdlc->xmit = fst_start_xmit;
+ }
+
dbg ( DBG_PCI,"type %d nports %d irq %d\n", card->type,
card->nports, card->irq );
dbg ( DBG_PCI,"conf %04x mem %08x ctlmem %08x\n",
printk_err ("Unable to get config I/O @ 0x%04X\n",
card->pci_conf );
err = -ENODEV;
- goto error_free_card;
+ goto error_free_ports;
}
if ( ! request_mem_region ( card->phys_mem, FST_MEMSIZE,"Shared RAM"))
{
error_release_io:
release_region ( card->pci_conf, 0x80 );
+error_free_ports:
+ for (i = 0; i < card->nports; i++)
+ free_netdev(card->ports[i].dev);
error_free_card:
kfree ( card );
return err;
for ( i = 0 ; i < card->nports ; i++ )
{
- unregister_hdlc_device ( &card->ports[i].hdlc );
+ struct net_device *dev = port_to_dev(&card->ports[i]);
+ unregister_hdlc_device(dev);
}
fst_disable_intr ( card );
release_mem_region ( card->phys_mem, FST_MEMSIZE );
release_region ( card->pci_conf, 0x80 );
+ for (i = 0; i < card->nports; i++)
+ free_netdev(card->ports[i].dev);
+
kfree ( card );
}