lkml.org 
[lkml]   [2010]   [Feb]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [PATCH] seastar - SeaStar Ethernet driver
    On 02/02/10 12:58, Kevin Pedretti wrote:
    > [PATCH] seastar - SeaStar Ethernet driver
    >
    > The following patch introduces the seastar driver for the
    > SeaStar network interface in Cray XT3/XT4/XT5 systems. The
    > driver is called 'seastar'. This patch is against 2.6.32.7.
    >
    > The driver uses a simple datagram interface exported by the
    > SeaStar network interface to encapsulate Ethernet frames
    > on the Cray XT high speed network. The driver has been tested
    > to function correctly and is in use on Cray XT4 development
    > systems at Sandia.
    >
    > Signed-off-by: Kevin Pedretti<ktpedre@sandia.gov>

    > obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
    > diff -uprN -X linux-2.6.32.7-vanilla/Documentation/dontdiff linux-2.6.32.7-vanilla/drivers/net/seastar/firmware.c linux-2.6.32.7/drivers/net/seastar/firmware.c
    > --- linux-2.6.32.7-vanilla/drivers/net/seastar/firmware.c 1969-12-31 17:00:00.000000000 -0700
    > +++ linux-2.6.32.7/drivers/net/seastar/firmware.c 2010-02-02 09:13:44.000000000 -0700
    > @@ -0,0 +1,236 @@

    > +
    > +/**
    > + * Maps a region of host memory into the SeaStar.
    > + */

    Please note that "/**" in Linux kernel sources means "beginning of a kernel-doc comment",
    and none of these is in kernel-doc notation (format), so please change all of them
    to a simple "/*".
    (throughout all .c/.h files)

    > +static void seastar_map_host_region(struct ss_priv *ssp, const void *addr)
    > +{
    > + /* Round addr to the nearest 128 MB */
    > + unsigned long raw_paddr = __pa(addr);
    > + unsigned long paddr = raw_paddr& ~((1<< 28) - 1);
    > +
    > + htb_map[8] = 0x8000 | ((paddr>> 28) + 0);
    > + htb_map[9] = 0x8000 | ((paddr>> 28) + 1);

    space before <<, &, and >>

    > +
    > + ssp->host_region_phys = paddr;
    > +}
    > +
    > +
    > +/**
    > + * Converts a kernel virtual address to a SeaStar address.
    > + */
    > +static uint32_t virt_to_fw(struct ss_priv *ssp, void *addr)
    > +{
    > + unsigned long saddr;
    > +
    > + saddr = __pa(addr) - ssp->host_region_phys;
    > + saddr&= (2<< 28) - 1;
    > + saddr += (8<< 28);

    space before << (2x)

    > +
    > + return saddr;
    > +}
    > +
    > +
    > +/**
    > + * Send a command to the Seastar.
    > + */
    > +static uint32_t seastar_cmd(struct ss_priv *ssp, const struct command *cmd,
    > + int wait_for_result)
    > +{
    > + struct mailbox *mbox = ssp->mailbox;
    > + unsigned int next_write;
    > + uint32_t tail, result;
    > +
    > + /* Copy the command into the mailbox */
    > + mbox->commandq[ssp->mailbox_cached_write] = *cmd;
    > + next_write = ssp->mailbox_cached_write + 1;
    > + if (next_write == COMMAND_Q_LENGTH)
    > + next_write = 0;
    > +
    > + /* Wait until it is safe to advance the write pointer */
    > + while (next_write == ssp->mailbox_cached_read)
    > + ssp->mailbox_cached_read = mbox->commandq_read;
    > +
    > + /* Advance the write pointer */
    > + mbox->commandq_write = next_write;
    > + ssp->mailbox_cached_write = next_write;
    > +
    > + if (!wait_for_result)
    > + return 0;
    > +
    > + /* Wait for the result to arrive */
    > + tail = mbox->resultq_read;
    > + while (tail == mbox->resultq_write)
    > + ;

    I would limit that while loop somehow (not allowing it to continue forever).

    > +
    > + /* Read the result */
    > + result = mbox->resultq[tail];
    > + mbox->resultq_read = (tail>= RESULT_Q_LENGTH - 1) ? 0 : tail + 1;
    > +
    > + return result;
    > +}
    > +
    > +
    > +/**
    > + * Sends a datagram transmit command to the SeaStar.
    > + */
    > +void seastar_ip_tx_cmd(struct ss_priv *ssp, uint16_t nid, uint16_t length,
    > + uint64_t address, uint16_t pending_index)
    > +{
    > + struct command_ip_tx tx_cmd = {
    > + .op = COMMAND_IP_TX,
    > + .nid = nid,
    > + .length = length,
    > + .address = address,
    > + .pending_index = pending_index,
    > + };
    > +
    > + seastar_cmd(ssp, (struct command *)&tx_cmd, 0);
    > +}
    > +
    > +
    > +/**
    > + * Programs the SeaStar's HTB_BI register.
    > + */
    > +void seastar_setup_htb_bi(uint32_t idr)
    > +{
    > + /* Mask the APIC dest setup by Linux, causes problems with SeaStar */
    > + idr&= 0xFFFF0000;

    space after '&'

    > +
    > + *htb_bi = 0xFD000000 | (idr>> 8);

    space before >>

    > +}
    > +
    > +
    > +/**
    > + * Brings up the low-level Seastar hardware.
    > + */
    > +int seastar_hw_init(struct ss_priv *ssp)
    > +{
    > + uint32_t lower_memory = SEASTAR_HOST_BASE;
    > + const int num_eq = 1;
    > + uint32_t lower_pending;
    > + uint32_t lower_eqcb;
    > + uint32_t result;
    > + struct command_init init_cmd;
    > + struct command_init_eqcb eqcb_cmd;
    > + struct command_mark_alive alive_cmd;
    > +
    > + /* Read our NID from SeaStar and write it to the NIC control block */
    > + niccb->local_nid = *tx_source;
    > +
    > + printk(KERN_INFO "%s: nid %d (0x%x) version %x built %x\n",
    > + __func__,
    > + niccb->local_nid,
    > + niccb->local_nid,
    > + niccb->version,
    > + niccb->build_time
    > + );
    > +
    > + /* Allocate the PPC memory */
    > + lower_pending = lower_memory;
    > + lower_memory += NUM_PENDINGS * FW_PENDING_SIZE;
    > +
    > + lower_eqcb = lower_memory;
    > + lower_memory = num_eq * FW_EQCB_SIZE;
    > +
    > + /* Initialize the HTB map so that the Seastar can see our memory.
    > + * Since we are only doing upper pendings, we just use the
    > + * upper_pending_phys instead of the host_phys area. */
    > + seastar_map_host_region(ssp, ssp);
    > +
    > + ssp->mailbox =&seastar_mailbox[0];

    space before '&'

    > + ssp->mailbox_cached_read = ssp->mailbox->commandq_read;
    > + ssp->mailbox_cached_write = ssp->mailbox->commandq_write;
    > +
    > + /* Attempt to send a setup command to the NIC */
    > + init_cmd.op = COMMAND_INIT;
    > + init_cmd.process_index = 1;
    > + init_cmd.uid = 0;
    > + init_cmd.jid = 0;
    > +
    > + init_cmd.num_pendings = NUM_PENDINGS;
    > + init_cmd.pending_tx_limit = NUM_TX_PENDINGS;
    > + init_cmd.pending_table_addr = lower_pending;
    > + init_cmd.up_pending_table_addr = virt_to_fw(ssp, ssp->pending_table);
    > + init_cmd.up_pending_table_ht_addr = 0;
    > +
    > + init_cmd.num_memds = 0;
    > + init_cmd.memd_table_addr = 0;
    > +
    > + init_cmd.num_eqcbs = num_eq;
    > + init_cmd.eqcb_table_addr = lower_eqcb;
    > + init_cmd.eqheap_addr = virt_to_fw(ssp, ssp->eq);
    > + init_cmd.eqheap_length = NUM_EQ_ENTRIES * sizeof(ssp->eq[0]);
    > +
    > + init_cmd.shdr_table_ht_addr = 0;
    > + init_cmd.result_block_addr = 0;
    > + init_cmd.smb_table_addr = 0;
    > +
    > + result = seastar_cmd(ssp, (struct command *)&init_cmd, 1);
    > + if (result != 0) {
    > + dev_err(&ssp->pdev->dev,
    > + "init command failed, result=%d.\n", result);
    > + return -1;
    > + }
    > +
    > + eqcb_cmd.op = COMMAND_INIT_EQCB;
    > + eqcb_cmd.eqcb_index = 0;
    > + eqcb_cmd.base = virt_to_fw(ssp, ssp->eq);
    > + eqcb_cmd.count = NUM_EQ_ENTRIES;
    > +
    > + result = seastar_cmd(ssp, (struct command *)&eqcb_cmd, 1);
    > + if (result != 1) {
    > + dev_err(&ssp->pdev->dev,
    > + "init_eqcb command failed, result=%d.\n", result);
    > + return -1;
    > + }
    > +
    > + alive_cmd.op = COMMAND_MARK_ALIVE;
    > + alive_cmd.index = 1;
    > +
    > + result = seastar_cmd(ssp, (struct command *)&alive_cmd, 1);
    > + if (result != 0) {
    > + dev_err(&ssp->pdev->dev,
    > + "mark_alive command failed, result=%d\n", result);
    > + return -1;
    > + }
    > +
    > + return 0;
    > +}
    > diff -uprN -X linux-2.6.32.7-vanilla/Documentation/dontdiff linux-2.6.32.7-vanilla/drivers/net/seastar/firmware.h linux-2.6.32.7/drivers/net/seastar/firmware.h
    > --- linux-2.6.32.7-vanilla/drivers/net/seastar/firmware.h 1969-12-31 17:00:00.000000000 -0700
    > +++ linux-2.6.32.7/drivers/net/seastar/firmware.h 2010-02-02 09:15:02.000000000 -0700
    > @@ -0,0 +1,329 @@
    > +
    > +#ifndef _SEASTAR_FIRMWARE_H
    > +#define _SEASTAR_FIRMWARE_H
    > +
    > +
    > +/**
    > + * Number of entries in Host -> SeaStar command queue.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define COMMAND_Q_LENGTH 63
    > +
    > +
    > +/**
    > + * Number of entries in SeaStar -> Host result queue.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define RESULT_Q_LENGTH 2
    > +
    > +
    > +/**
    > + * SeaStar -> Host event types.
    > + *
    > + * WARNING: These must match the definitions used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define EVENT_TX_END 125
    > +#define EVENT_RX 126
    > +#define EVENT_RX_EMPTY 127
    > +
    > +
    > +/**
    > + * Host -> SeaStar command types.
    > + *
    > + * WARNING: These must match the definitions used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define COMMAND_INIT 0
    > +#define COMMAND_MARK_ALIVE 1
    > +#define COMMAND_INIT_EQCB 2
    > +#define COMMAND_IP_TX 13
    > +
    > +
    > +/**
    > + * Number of entries in the incoming datagram buffer table.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define NUM_SKBS 64
    > +
    > +
    > +/**
    > + * Size of the pending structure used by the SeaStar firmware.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define FW_PENDING_SIZE 32
    > +
    > +
    > +/**
    > + * Size of the event queue control block structure used by the SeaStar firmware.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define FW_EQCB_SIZE 32
    > +
    > +
    > +/**
    > + * SeaStar addresses of important structures in SeaStar memory.
    > + *
    > + * WARNING: These must match the definitions used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +#define SEASTAR_SCRATCH_BASE 0xFFFA0000
    > +#define SEASTAR_TX_SOURCE 0xFFE00108
    > +#define SEASTAR_MAILBOX_BASE 0xFFFA0000
    > +#define SEASTAR_SKB_BASE 0xFFFA4000
    > +#define SEASTAR_HOST_BASE 0xFFFA5000
    > +#define SEASTAR_HTB_BASE 0xFFE20000
    > +#define SEASTAR_HTB_BI 0xFFE20048
    > +#define SEASTAR_NICCB_BASE 0xFFFFE000
    > +
    > +
    > +/**
    > + * Kernel virtual address where the SeaStar memory is mapped.
    > + */
    > +#define SEASTAR_VIRT_BASE (0xFFFFFFFFull<< 32)
    > +
    > +
    > +/**
    > + * Kernel virtual address of the SeaStar's NIC control block.
    > + */
    > +static volatile struct niccb * const niccb
    > + = (void *)(SEASTAR_VIRT_BASE + SEASTAR_NICCB_BASE);
    > +
    > +
    > +/**
    > + * Kernel virtual address of the SeaStar's HTB_BI register.
    > + */
    > +static volatile uint32_t * const htb_bi
    > + = (void *)(SEASTAR_VIRT_BASE + SEASTAR_HTB_BI);
    > +
    > +
    > +/**
    > + * Kernel virtual address of the SeaStar's HyperTransport map.
    > + */
    > +static volatile uint32_t * const htb_map
    > + = (void *)(SEASTAR_VIRT_BASE + SEASTAR_HTB_BASE);
    > +
    > +
    > +/**
    > + * Kernel virtual address of the Host<-> SeaStar mailbox.
    > + */
    > +static struct mailbox * const seastar_mailbox
    > + = (void *)(SEASTAR_VIRT_BASE + SEASTAR_MAILBOX_BASE);
    > +
    > +
    > +/**
    > + * Kernel virtual address of the incoming datagram buffer table.
    > + */
    > +static volatile uint64_t * const seastar_skb
    > + = (void *)(SEASTAR_VIRT_BASE + SEASTAR_SKB_BASE);
    > +
    > +
    > +/**
    > + * Kernel virtual address of the SeaStar TX Source register.
    > + */
    > +static volatile uint16_t * const tx_source
    > + = (void *)(SEASTAR_VIRT_BASE + SEASTAR_TX_SOURCE);
    > +
    > +
    > +/**
    > + * The SeaStar NIC Control Block.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct niccb {
    > + uint32_t version; /* 0 */
    > + uint8_t pad[24];
    > + uint32_t build_time; /* 28 */
    > + uint8_t pad2[68];
    > + uint32_t ip_tx; /* 100 */
    > + uint32_t ip_tx_drop; /* 104 */
    > + uint32_t ip_rx; /* 108 */
    > + uint32_t ip_rx_drop; /* 112 */
    > + uint8_t pad3[52];
    > + uint16_t local_nid; /* 168 */
    > +} __attribute__((packed, aligned));
    > +
    > +
    > +/**
    > + * SeaStar datagram packet wire header.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct sshdr {
    > + uint16_t length; /* 0 */
    > + uint8_t lo_macs; /* 2 */
    > + uint8_t hdr_type; /* 3 */
    > +} __attribute__((packed));
    > +
    > +
    > +/**
    > + * Generic Host -> SeaStar command structure.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct command {
    > + uint8_t op; /* 0 */
    > + uint8_t pad[63]; /* [1,63] */
    > +} __attribute__((packed));
    > +
    > +
    > +/**
    > + * Initialize firmware command.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct command_init {

    > +
    > +/**
    > + * Start firmware running command.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct command_mark_alive {
    > + uint8_t op; /* 0 */
    > + uint8_t index; /* 1 */
    > +} __attribute__((packed));
    > +
    > +
    > +/**
    > + * Initialize event queue command.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct command_init_eqcb {
    > + uint8_t op; /* 0 */
    > + uint8_t pad; /* 1 */
    > + uint16_t eqcb_index; /* 2 */
    > + uint32_t base; /* 4 */
    > + uint32_t count; /* 8 */
    > +} __attribute__((packed));
    > +
    > +
    > +/**
    > + * Send datagram command.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct command_ip_tx {
    > + uint8_t op; /* 0 */
    > + uint8_t pad; /* 1 */
    > + uint16_t nid; /* 2 */
    > + uint16_t length; /* 4 */
    > + uint16_t pad2; /* 6 */
    > + uint64_t address; /* 8 */
    > + uint16_t pending_index; /* 16 */
    > +} __attribute__((packed));
    > +
    > +
    > +/**
    > + * Host<-> SeaStar Mailbox structure.
    > + *
    > + * WARNING: This must match the definition used by the
    > + * closed-source SeaStar firmware.
    > + */
    > +struct mailbox {

    > diff -uprN -X linux-2.6.32.7-vanilla/Documentation/dontdiff linux-2.6.32.7-vanilla/drivers/net/seastar/main.c linux-2.6.32.7/drivers/net/seastar/main.c
    > --- linux-2.6.32.7-vanilla/drivers/net/seastar/main.c 1969-12-31 17:00:00.000000000 -0700
    > +++ linux-2.6.32.7/drivers/net/seastar/main.c 2010-02-02 12:49:20.000000000 -0700
    > @@ -0,0 +1,584 @@

    > +
    > +static void refill_skb(struct net_device *netdev, int i)
    > +{
    > + struct ss_priv *ssp = netdev_priv(netdev);
    > + struct sk_buff *skb;
    > +
    > + skb = dev_alloc_skb(netdev->mtu + SKB_PAD);
    > + if (!skb) {
    > + dev_err(&ssp->pdev->dev, "dev_alloc_skb() failed.\n");
    > + return;
    > + }
    > +
    > + skb->dev = netdev;
    > + skb_reserve(skb, SKB_PAD);
    > +
    > + /* Push it down to the PPC as a quadbyte address */
    > + ssp->skb_table_phys[i] = virt_to_phys(skb->data)>> 2;

    space before >>

    > + ssp->skb_table_virt[i] = skb;
    > +}
    > +
    > +
    > +static int ss_open(struct net_device *netdev)
    > +{
    > + struct ss_priv *ssp = netdev_priv(netdev);
    > + int i;
    > +
    > + netif_start_queue(netdev);
    > +
    > + for (i = 0; i< NUM_SKBS; i++) {

    space before '<'

    > + ssp->skb_table_phys[i] = 0;
    > + ssp->skb_table_virt[i] = 0;
    > + refill_skb(netdev, i);
    > + }
    > +
    > + return 0;
    > +}
    > +
    > +
    > +static int eth2ss(struct ss_priv *ssp, struct sk_buff *skb)
    > +{
    > + struct ethhdr *ethhdr;
    > + struct sshdr *sshdr;
    > + uint8_t source_lo_mac, dest_lo_mac;
    > + uint32_t qb_len;
    > +
    > + /* Read the "low" bytes of the source and destination MAC addresses */
    > + ethhdr = (struct ethhdr *)skb->data;
    > + source_lo_mac = ethhdr->h_source[5];
    > + dest_lo_mac = ethhdr->h_dest[5];
    > +
    > + /* Drop anything not IPv4 */
    > + if (ethhdr->h_proto != ntohs(ETH_P_IP)) {
    > + dev_err(&ssp->pdev->dev, "squashing non-IPv4 packet.");
    > + return -1;
    > + }
    > +
    > + /* Squash broadcast packets, SeaStar doesn't support broadcast */
    > + if (dest_lo_mac == 0xFF) {
    > + dev_err(&ssp->pdev->dev, "squashing broadcast packet.");
    > + return -1;
    > + }
    > +
    > + /* We only support 4 bits of virtual hosts per physical node */
    > + if ((source_lo_mac& ~0xF) || (dest_lo_mac& ~0xF)) {

    space before '&' (2x)

    > + dev_err(&ssp->pdev->dev, "lo_mac out of range.");
    > + return -1;
    > + }
    > +
    > + /* Move ahead to allow sshdr to be filled in overtop of the ethhdr */
    > + sshdr = (struct sshdr *)
    > + skb_pull(skb, (unsigned int)(ETH_HLEN - sizeof(struct sshdr)));
    > +
    > + /* The length in quad bytes, rounded up to the nearest quad byte.
    > + * SS header is already counted in skb->len as per skb_pull() above */

    Is that second line supposed to explain the "- 1" below?

    > + qb_len = (ROUNDUP4(skb->len)>> 2) - 1;

    space before >>

    > +
    > + /* Build the SeaStar header */
    > + sshdr->length = qb_len;
    > + sshdr->lo_macs = (source_lo_mac<< 4) | dest_lo_mac;
    > + sshdr->hdr_type = (2<< 5); /* Datagram 2, type 0 == IP */

    (2 << 5); ...

    > +
    > + return 0;
    > +}
    > +

    > +
    > +
    > +static int ss_tx(struct sk_buff *skb, struct net_device *netdev)
    > +{
    > + unsigned long flags;
    > + struct ss_priv *ssp = netdev_priv(netdev);
    > + struct ethhdr *eh = (struct ethhdr *)skb->data;
    > + struct sshdr *sshdr;
    > + uint32_t dest_nid = ntohl(*(uint32_t *)eh->h_dest);
    > + struct pending *pending = NULL;
    > + void *msg;
    > +
    > + spin_lock_irqsave(&ssp->lock, flags);
    > +
    > + if (netif_queue_stopped(netdev)) {
    > + spin_unlock_irqrestore(&ssp->lock, flags);
    > + return NETDEV_TX_BUSY;
    > + }
    > +
    > + /* Convert the SKB from an ethernet frame to a seastar frame */
    > + if (eth2ss(ssp, skb)) {
    > + netdev->stats.tx_errors++;
    > + goto drop;
    > + }
    > +
    > + sshdr = (struct sshdr *)skb->data;
    > +
    > + /* Get a tx_pending so that we can track the completion of this SKB */
    > + pending = alloc_tx_pending(ssp);
    > + if (!pending) {
    > + netif_stop_queue(netdev);
    > + spin_unlock_irqrestore(&ssp->lock, flags);
    > + return NETDEV_TX_BUSY;
    > + }
    > +
    > + /* Stash skb away in the pending, will be needed in ss_tx_end() */
    > + pending->skb = skb;
    > +
    > + /* Make sure buffer we pass to SeaStar is quad-byte aligned */
    > + if (((unsigned long)skb->data& 0x3) == 0) {
    > + pending->bounce = NULL;
    > + msg = skb->data;
    > + } else {
    > + /* Need to use bounce buffer to get quad-byte alignment */
    > + pending->bounce = kmalloc(skb->len, GFP_KERNEL);
    > + if (!pending->bounce) {
    > + dev_err(&ssp->pdev->dev, "dev_alloc_skb() failed.\n");
    > + goto drop;
    > + }
    > + memcpy(pending->bounce, skb->data, skb->len);
    > + msg = pending->bounce;
    > + }
    > +
    > + seastar_ip_tx_cmd(
    > + ssp,
    > + dest_nid,
    > + sshdr->length,
    > + virt_to_phys(msg)>> 2,

    (msg) >> 2,

    > + pending_to_index(ssp, pending)
    > + );
    > +
    > + netdev->stats.tx_packets++;
    > + netdev->stats.tx_bytes += skb->len;
    > +
    > + spin_unlock_irqrestore(&ssp->lock, flags);
    > + return 0;
    > +
    > +drop:
    > + dev_kfree_skb_any(skb);
    > + if (pending)
    > + free_tx_pending(ssp, pending);
    > + spin_unlock_irqrestore(&ssp->lock, flags);
    > + return 0;
    > +}
    > +

    > +
    > +
    > +static irqreturn_t ss_interrupt(int irq, void *dev)
    > +{
    > + struct net_device *netdev = (struct net_device *)dev;
    > + struct ss_priv *ssp = netdev_priv(netdev);
    > + uint32_t ev;
    > + unsigned int type, index;
    > +
    > + while (1) {
    > + ev = next_event(ssp);
    > + if (!ev)
    > + break;

    There is usually some condition that limits how long a while (1) can continue.
    Does this environment not need that?
    > +
    > + type = (ev>> 16)& 0xFFFF;
    > + index = (ev>> 0)& 0xFFFF;
    > +
    > + switch (type) {
    > +
    > + case EVENT_TX_END:
    > + ss_tx_end(netdev, index);
    > + break;
    > +
    > + case EVENT_RX:
    > + ss_rx(netdev, index);
    > + break;
    > +
    > + case EVENT_RX_EMPTY:
    > + ss_rx_refill(netdev);
    > + break;
    > +
    > + default:
    > + dev_err(&ssp->pdev->dev,
    > + "unknown event type (type=%u, index=%u).\n",
    > + type, index);
    > + }
    > + }
    > +
    > + return IRQ_HANDLED;
    > +}
    > +

    > +
    > +static int __devinit ss_probe(struct pci_dev *pdev,
    > + const struct pci_device_id *id)
    > +{
    > + struct net_device *netdev;
    > + struct ss_priv *ssp;
    > + int i, irq, err = 0;
    > +
    > + err = pci_enable_device(pdev);
    > + if (err != 0) {
    > + dev_err(&pdev->dev, "Could not enable PCI device.\n");
    > + return -ENODEV;
    > + }
    > +
    > + netdev = alloc_etherdev(sizeof(*ssp));
    > + if (netdev == NULL) {
    > + dev_err(&pdev->dev, "Could not allocate ethernet device.\n");
    > + return -ENOMEM;
    > + }
    > +
    > + SET_NETDEV_DEV(netdev,&pdev->dev);
    > +
    > + strcpy(netdev->name, "ss");
    > + netdev->netdev_ops =&ss_netdev_ops;
    > + netdev->header_ops =&ss_header_ops;

    = &ss...

    > + netdev->mtu = 16000;
    > + netdev->flags = IFF_NOARP;
    > +
    > + /* Setup private state */
    > + ssp = netdev_priv(netdev);
    > + memset(ssp, 0, sizeof(*ssp));
    > +
    > + spin_lock_init(&ssp->lock);
    > + ssp->skb_table_phys = seastar_skb;
    > + ssp->eq_read = 0;
    > + ssp->pdev = pdev;
    > +
    > + /* Build the TX pending free list */
    > + ssp->tx_pending_free_list = 0;
    > + for (i = 0; i< NUM_TX_PENDINGS; i++)

    ; i < NUM_TX...

    > + free_tx_pending(ssp, index_to_pending(ssp, i));
    > +
    > + irq = __ht_create_irq(pdev, 0, ss_ht_irq_update);
    > + if (irq< 0) {

    if (irq < 0) {
    > + dev_err(&pdev->dev, "__ht_create_irq() failed, err=%d.\n", err);
    > + goto err_out;
    > + }
    > +
    > + err = request_irq(irq, ss_interrupt, IRQF_NOBALANCING,
    > + "seastar", netdev);
    > + if (err != 0) {
    > + dev_err(&pdev->dev, "request_irq() failed, err=%d.\n", err);
    > + goto err_out;
    > + }
    > +
    > + err = seastar_hw_init(netdev_priv(netdev));
    > + if (err != 0) {
    > + dev_err(&pdev->dev, "seastar_hw_init() failed, err=%d.\n", err);
    > + goto err_out;
    > + }
    > +
    > + err = register_netdev(netdev);
    > + if (err != 0) {
    > + dev_err(&pdev->dev, "register_netdev() failed, err=%d.\n", err);
    > + goto err_out;
    > + }
    > +
    > + return 0;
    > +
    > +err_out:
    > + free_netdev(netdev);
    > + return err;
    > +}
    > +
    > +
    > +static void __devexit ss_remove(struct pci_dev *pdev)
    > +{
    > + struct net_device *netdev = pci_get_drvdata(pdev);
    > +
    > + unregister_netdev(netdev);
    > + free_netdev(netdev);
    > + pci_disable_device(pdev);
    > +}
    > +
    > +
    > +#define PCI_VENDOR_ID_CRAY 0x17DB
    > +#define PCI_DEVICE_ID_SEASTAR 0x0101
    > +
    > +
    > +static struct pci_device_id ss_pci_tbl[] = {
    > + {PCI_DEVICE(PCI_VENDOR_ID_CRAY, PCI_DEVICE_ID_SEASTAR)},
    > + {0},
    > +};
    > +
    > +

    > diff -uprN -X linux-2.6.32.7-vanilla/Documentation/dontdiff linux-2.6.32.7-vanilla/drivers/net/seastar/seastar.h linux-2.6.32.7/drivers/net/seastar/seastar.h
    > --- linux-2.6.32.7-vanilla/drivers/net/seastar/seastar.h 1969-12-31 17:00:00.000000000 -0700
    > +++ linux-2.6.32.7/drivers/net/seastar/seastar.h 2010-02-02 09:14:33.000000000 -0700
    > @@ -0,0 +1,104 @@
    > +
    > +#ifndef _SEASTAR_H
    > +#define _SEASTAR_H
    > +
    > +
    > +/**
    > + * Rounds up to the nearest quadbyte.
    > + */
    > +#define ROUNDUP4(val) ((val + (4-1))& ~(4-1))
    > +
    > +
    > +/**
    > + * SeaStar datagram packet maximum transfer unit size in bytes.
    > + */
    > +#define SEASTAR_MTU 8192
    > +
    > +
    > +/**
    > + * Number of transmit and receive pending structures.
    > + */
    > +#define NUM_TX_PENDINGS 64
    > +#define NUM_RX_PENDINGS 64
    > +#define NUM_PENDINGS (NUM_TX_PENDINGS + NUM_RX_PENDINGS)
    > +
    > +
    > +/**
    > + * Number of entries in the SeaStar -> Host event queue.
    > + */
    > +#define NUM_EQ_ENTRIES 1024
    > +
    > +
    > +/**
    > + * When allocating an SKB, allocate this many bytes extra.
    > + */
    > +#define SKB_PAD (16 - sizeof(struct sshdr))
    > +
    > +
    > +/**
    > + * Pending structure.
    > + * One of these is used to track each in progress transmit.
    > + */
    > +struct pending {
    > + struct sk_buff *skb;
    > + struct pending *next;
    > + void *bounce;
    > +};
    > +
    > +
    > +/**
    > + * SeaStar driver private data.
    > + */


    --
    ~Randy


    \
     
     \ /
      Last update: 2010-02-02 23:01    [W:0.080 / U:31.544 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site