#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/pci-bridge.h>
#include <net/checksum.h>
MODULE_DESCRIPTION("Spider Southbridge Gigabit Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(VERSION);
+MODULE_FIRMWARE(SPIDER_NET_FIRMWARE_NAME);
static int rx_descriptors = SPIDER_NET_RX_DESCRIPTORS_DEFAULT;
static int tx_descriptors = SPIDER_NET_TX_DESCRIPTORS_DEFAULT;
* @card: card structure
* @descr: descriptor to re-init
*
- * Return 0 on succes, <0 on failure.
+ * Return 0 on success, <0 on failure.
*
* Allocates a new rx skb, iommu-maps it and attaches it to the
* descriptor. Mark the descriptor as activated, ready-to-use.
/* iommu-map the skb */
buf = pci_map_single(card->pdev, descr->skb->data,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(buf)) {
+ if (pci_dma_mapping_error(card->pdev, buf)) {
dev_kfree_skb_any(descr->skb);
descr->skb = NULL;
if (netif_msg_rx_err(card) && net_ratelimit())
/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
- * @descr: descriptor structure to fill out
* @skb: packet to use
*
* returns 0 on success, <0 on failure.
unsigned long flags;
buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(buf)) {
+ if (pci_dma_mapping_error(card->pdev, buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
* spider_net_release_tx_chain releases the tx descriptors that spider has
* finished with (if non-brutal) or simply release tx descriptors (if brutal).
* If some other context is calling this function, we return 1 so that we're
- * scheduled again (if we were scheduled) and will not loose initiative.
+ * scheduled again (if we were scheduled) and will not lose initiative.
*/
static int
spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
{
+ struct net_device *dev = card->netdev;
struct spider_net_descr_chain *chain = &card->tx_chain;
struct spider_net_descr *descr;
struct spider_net_hw_descr *hwdescr;
status = spider_net_get_descr_status(hwdescr);
switch (status) {
case SPIDER_NET_DESCR_COMPLETE:
- card->netdev_stats.tx_packets++;
- card->netdev_stats.tx_bytes += descr->skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += descr->skb->len;
break;
case SPIDER_NET_DESCR_CARDOWNED:
if (netif_msg_tx_err(card))
dev_err(&card->netdev->dev, "forcing end of tx descriptor "
"with status x%02x\n", status);
- card->netdev_stats.tx_errors++;
+ dev->stats.tx_errors++;
break;
default:
- card->netdev_stats.tx_dropped++;
+ dev->stats.tx_dropped++;
if (!brutal) {
spin_unlock_irqrestore(&chain->lock, flags);
return 1;
/**
* spider_net_kick_tx_dma - enables TX DMA processing
* @card: card structure
- * @descr: descriptor address to enable TX processing at
*
* This routine will start the transmit DMA running if
* it is not already running. This routine ned only be
spider_net_release_tx_chain(card, 0);
if (spider_net_prepare_tx_descr(card, skb) != 0) {
- card->netdev_stats.tx_dropped++;
+ netdev->stats.tx_dropped++;
netif_stop_queue(netdev);
return NETDEV_TX_BUSY;
}
spider_net_pass_skb_up(struct spider_net_descr *descr,
struct spider_net_card *card)
{
- struct spider_net_hw_descr *hwdescr= descr->hwdescr;
- struct sk_buff *skb;
- struct net_device *netdev;
- u32 data_status, data_error;
-
- data_status = hwdescr->data_status;
- data_error = hwdescr->data_error;
- netdev = card->netdev;
+ struct spider_net_hw_descr *hwdescr = descr->hwdescr;
+ struct sk_buff *skb = descr->skb;
+ struct net_device *netdev = card->netdev;
+ u32 data_status = hwdescr->data_status;
+ u32 data_error = hwdescr->data_error;
- skb = descr->skb;
skb_put(skb, hwdescr->valid_size);
/* the card seems to add 2 bytes of junk in front
}
/* update netdevice statistics */
- card->netdev_stats.rx_packets++;
- card->netdev_stats.rx_bytes += skb->len;
+ netdev->stats.rx_packets++;
+ netdev->stats.rx_bytes += skb->len;
/* pass skb up to stack */
netif_receive_skb(skb);
static int
spider_net_decode_one_descr(struct spider_net_card *card)
{
+ struct net_device *dev = card->netdev;
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr = chain->tail;
struct spider_net_hw_descr *hwdescr = descr->hwdescr;
(status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
(status == SPIDER_NET_DESCR_FORCE_END) ) {
if (netif_msg_rx_err(card))
- dev_err(&card->netdev->dev,
+ dev_err(&dev->dev,
"dropping RX descriptor with state %d\n", status);
- card->netdev_stats.rx_dropped++;
+ dev->stats.rx_dropped++;
goto bad_desc;
}
static int spider_net_poll(struct napi_struct *napi, int budget)
{
struct spider_net_card *card = container_of(napi, struct spider_net_card, napi);
- struct net_device *netdev = card->netdev;
int packets_done = 0;
while (packets_done < budget) {
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
if (packets_done < budget) {
- netif_rx_complete(netdev, napi);
+ napi_complete(napi);
spider_net_rx_irq_on(card);
card->ignore_rx_ramfull = 0;
}
}
/**
- * spider_net_get_stats - get interface statistics
- * @netdev: interface device structure
- *
- * returns the interface statistics residing in the spider_net_card struct
- */
-static struct net_device_stats *
-spider_net_get_stats(struct net_device *netdev)
-{
- struct spider_net_card *card = netdev_priv(netdev);
- struct net_device_stats *stats = &card->netdev_stats;
- return stats;
-}
-
-/**
* spider_net_change_mtu - changes the MTU of an interface
* @netdev: interface device structure
* @new_mtu: new MTU value
spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
/* reset phy and setup aneg */
+ card->aneg_count = 0;
+ card->medium = BCM54XX_COPPER;
spider_net_setup_aneg(card);
mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
* found when an interrupt is presented
*/
static void
-spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
+spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
+ u32 error_reg1, u32 error_reg2)
{
- u32 error_reg1, error_reg2;
u32 i;
int show_error = 1;
- error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
- error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
-
- error_reg1 &= SPIDER_NET_INT1_MASK_VALUE;
- error_reg2 &= SPIDER_NET_INT2_MASK_VALUE;
-
/* check GHIINT0STS ************************************/
if (status_reg)
for (i = 0; i < 32; i++)
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
- netif_rx_schedule(card->netdev,
- &card->napi);
+ napi_schedule(&card->napi);
}
show_error = 0;
break;
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
- netif_rx_schedule(card->netdev,
- &card->napi);
+ napi_schedule(&card->napi);
show_error = 0;
break;
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
- netif_rx_schedule(card->netdev,
- &card->napi);
+ napi_schedule(&card->napi);
show_error = 0;
break;
/**
* spider_net_interrupt - interrupt handler for spider_net
- * @irq: interupt number
+ * @irq: interrupt number
* @ptr: pointer to net_device
- * @regs: PU registers
*
* returns IRQ_HANDLED, if interrupt was for driver, or IRQ_NONE, if no
* interrupt found raised by card.
{
struct net_device *netdev = ptr;
struct spider_net_card *card = netdev_priv(netdev);
- u32 status_reg;
+ u32 status_reg, error_reg1, error_reg2;
status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
- status_reg &= SPIDER_NET_INT0_MASK_VALUE;
+ error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
+ error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
- if (!status_reg)
+ if (!(status_reg & SPIDER_NET_INT0_MASK_VALUE) &&
+ !(error_reg1 & SPIDER_NET_INT1_MASK_VALUE) &&
+ !(error_reg2 & SPIDER_NET_INT2_MASK_VALUE))
return IRQ_NONE;
if (status_reg & SPIDER_NET_RXINT ) {
spider_net_rx_irq_off(card);
- netif_rx_schedule(netdev, &card->napi);
+ napi_schedule(&card->napi);
card->num_rx_ints ++;
}
if (status_reg & SPIDER_NET_TXINT)
- netif_rx_schedule(netdev, &card->napi);
+ napi_schedule(&card->napi);
if (status_reg & SPIDER_NET_LINKINT)
spider_net_link_reset(netdev);
if (status_reg & SPIDER_NET_ERRINT )
- spider_net_handle_error_irq(card, status_reg);
+ spider_net_handle_error_irq(card, status_reg,
+ error_reg1, error_reg2);
/* clear interrupt sources */
spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
*
* spider_net_enable_interrupt enables several interrupts
*/
-static void
+static void
spider_net_enable_interrupts(struct spider_net_card *card)
{
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
*
* spider_net_disable_interrupts disables all the interrupts
*/
-static void
+static void
spider_net_disable_interrupts(struct spider_net_card *card)
{
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
goto init_firmware_failed;
/* start probing with copper */
+ card->aneg_count = 0;
+ card->medium = BCM54XX_COPPER;
spider_net_setup_aneg(card);
if (card->phy.def->phy_id)
mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);
/* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */
if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) {
- pr_info("%s: link is down trying to bring it up\n", card->netdev->name);
+ pr_debug("%s: link is down trying to bring it up\n",
+ card->netdev->name);
switch (card->medium) {
case BCM54XX_COPPER:
card->aneg_count = 0;
- pr_debug("Found %s with %i Mbps, %s-duplex %sautoneg.\n",
- phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half",
- phy->autoneg==1 ? "" : "no ");
+ pr_info("%s: link up, %i Mbps, %s-duplex %sautoneg.\n",
+ card->netdev->name, phy->speed,
+ phy->duplex == 1 ? "Full" : "Half",
+ phy->autoneg == 1 ? "" : "no ");
return;
}
card->spider_stats.tx_timeouts++;
}
+static const struct net_device_ops spider_net_ops = {
+ .ndo_open = spider_net_open,
+ .ndo_stop = spider_net_stop,
+ .ndo_start_xmit = spider_net_xmit,
+ .ndo_set_multicast_list = spider_net_set_multi,
+ .ndo_set_mac_address = spider_net_set_mac,
+ .ndo_change_mtu = spider_net_change_mtu,
+ .ndo_do_ioctl = spider_net_do_ioctl,
+ .ndo_tx_timeout = spider_net_tx_timeout,
+ .ndo_validate_addr = eth_validate_addr,
+ /* HW VLAN */
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ /* poll controller */
+ .ndo_poll_controller = spider_net_poll_controller,
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+};
+
/**
* spider_net_setup_netdev_ops - initialization of net_device operations
* @netdev: net_device structure
static void
spider_net_setup_netdev_ops(struct net_device *netdev)
{
- netdev->open = &spider_net_open;
- netdev->stop = &spider_net_stop;
- netdev->hard_start_xmit = &spider_net_xmit;
- netdev->get_stats = &spider_net_get_stats;
- netdev->set_multicast_list = &spider_net_set_multi;
- netdev->set_mac_address = &spider_net_set_mac;
- netdev->change_mtu = &spider_net_change_mtu;
- netdev->do_ioctl = &spider_net_do_ioctl;
- /* tx watchdog */
- netdev->tx_timeout = &spider_net_tx_timeout;
+ netdev->netdev_ops = &spider_net_ops;
netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT;
- /* HW VLAN */
-#ifdef CONFIG_NET_POLL_CONTROLLER
- /* poll controller */
- netdev->poll_controller = &spider_net_poll_controller;
-#endif /* CONFIG_NET_POLL_CONTROLLER */
/* ethtool ops */
netdev->ethtool_ops = &spider_net_ethtool_ops;
}
/**
* spider_net_setup_pci_dev - sets up the device in terms of PCI operations
- * @card: card structure
* @pdev: PCI device
*
* Returns the card structure or NULL if any errors occur