Commit 1f66c744 authored by Jeff Garzik's avatar Jeff Garzik

Merge http://typhoon.bkbits.net/typhoon-2.6

into pobox.com:/garz/repo/netdev-2.6/typhoon
parents 11ab9af3 a316e58f
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -50,6 +50,13 @@ ...@@ -50,6 +50,13 @@
*/ */
static int rx_copybreak = 200; static int rx_copybreak = 200;
/* Should we use MMIO or Port IO?
* 0: Port IO
* 1: MMIO
* 2: Try MMIO, fallback to Port IO
*/
static unsigned int use_mmio = 2;
/* end user-configurable values */ /* end user-configurable values */
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast). /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
...@@ -93,8 +100,8 @@ static const int multicast_filter_limit = 32; ...@@ -93,8 +100,8 @@ static const int multicast_filter_limit = 32;
#define PKT_BUF_SZ 1536 #define PKT_BUF_SZ 1536
#define DRV_MODULE_NAME "typhoon" #define DRV_MODULE_NAME "typhoon"
#define DRV_MODULE_VERSION "1.5.4" #define DRV_MODULE_VERSION "1.5.7"
#define DRV_MODULE_RELDATE "04/09/09" #define DRV_MODULE_RELDATE "05/01/07"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define ERR_PFX KERN_ERR PFX #define ERR_PFX KERN_ERR PFX
...@@ -131,9 +138,16 @@ static char version[] __devinitdata = ...@@ -131,9 +138,16 @@ static char version[] __devinitdata =
"typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David Dillow <dave@thedillows.org>"); MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
MODULE_VERSION(DRV_MODULE_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)"); MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
MODULE_PARM(rx_copybreak, "i"); MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
"the buffer given back to the NIC. Default "
"is 200.");
MODULE_PARM_DESC(use_mmio, "Use MMIO (1) or PIO(0) to access the NIC. "
"Default is to try MMIO and fallback to PIO.");
module_param(rx_copybreak, int, 0);
module_param(use_mmio, int, 0);
#if defined(NETIF_F_TSO) && MAX_SKB_FRAGS > 32 #if defined(NETIF_F_TSO) && MAX_SKB_FRAGS > 32
#warning Typhoon only supports 32 entries in its SG list for TSO, disabling TSO #warning Typhoon only supports 32 entries in its SG list for TSO, disabling TSO
...@@ -310,7 +324,7 @@ enum state_values { ...@@ -310,7 +324,7 @@ enum state_values {
* cannot pass a read, so this forces current writes to post. * cannot pass a read, so this forces current writes to post.
*/ */
#define typhoon_post_pci_writes(x) \ #define typhoon_post_pci_writes(x) \
do { readl(x + TYPHOON_REG_HEARTBEAT); } while(0) do { if(likely(use_mmio)) ioread32(x+TYPHOON_REG_HEARTBEAT); } while(0)
/* We'll wait up to six seconds for a reset, and half a second normally. /* We'll wait up to six seconds for a reset, and half a second normally.
*/ */
...@@ -391,17 +405,17 @@ typhoon_reset(void __iomem *ioaddr, int wait_type) ...@@ -391,17 +405,17 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
else else
timeout = TYPHOON_RESET_TIMEOUT_SLEEP; timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS); iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
writel(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET); iowrite32(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
udelay(1); udelay(1);
writel(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET); iowrite32(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET);
if(wait_type != NoWait) { if(wait_type != NoWait) {
for(i = 0; i < timeout; i++) { for(i = 0; i < timeout; i++) {
if(readl(ioaddr + TYPHOON_REG_STATUS) == if(ioread32(ioaddr + TYPHOON_REG_STATUS) ==
TYPHOON_STATUS_WAITING_FOR_HOST) TYPHOON_STATUS_WAITING_FOR_HOST)
goto out; goto out;
...@@ -416,8 +430,8 @@ typhoon_reset(void __iomem *ioaddr, int wait_type) ...@@ -416,8 +430,8 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
} }
out: out:
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS); iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
/* The 3XP seems to need a little extra time to complete the load /* The 3XP seems to need a little extra time to complete the load
* of the sleep image before we can reliably boot it. Failure to * of the sleep image before we can reliably boot it. Failure to
...@@ -442,7 +456,7 @@ typhoon_wait_status(void __iomem *ioaddr, u32 wait_value) ...@@ -442,7 +456,7 @@ typhoon_wait_status(void __iomem *ioaddr, u32 wait_value)
int i, err = 0; int i, err = 0;
for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) { for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
if(readl(ioaddr + TYPHOON_REG_STATUS) == wait_value) if(ioread32(ioaddr + TYPHOON_REG_STATUS) == wait_value)
goto out; goto out;
udelay(TYPHOON_UDELAY); udelay(TYPHOON_UDELAY);
} }
...@@ -478,7 +492,7 @@ typhoon_hello(struct typhoon *tp) ...@@ -478,7 +492,7 @@ typhoon_hello(struct typhoon *tp)
INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP); INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP);
smp_wmb(); smp_wmb();
writel(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY); iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
spin_unlock(&tp->command_lock); spin_unlock(&tp->command_lock);
} }
} }
...@@ -633,7 +647,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd, ...@@ -633,7 +647,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd,
/* "I feel a presence... another warrior is on the the mesa." /* "I feel a presence... another warrior is on the the mesa."
*/ */
wmb(); wmb();
writel(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY); iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
typhoon_post_pci_writes(tp->ioaddr); typhoon_post_pci_writes(tp->ioaddr);
if((cmd->flags & TYPHOON_CMD_RESPOND) == 0) if((cmd->flags & TYPHOON_CMD_RESPOND) == 0)
...@@ -687,7 +701,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd, ...@@ -687,7 +701,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd,
* is the case. * is the case.
*/ */
if(indexes->respCleared != indexes->respReady) if(indexes->respCleared != indexes->respReady)
writel(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT); iowrite32(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT);
} }
spin_unlock(&tp->command_lock); spin_unlock(&tp->command_lock);
...@@ -889,7 +903,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -889,7 +903,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
/* Kick the 3XP /* Kick the 3XP
*/ */
wmb(); wmb();
writel(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister); iowrite32(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister);
dev->trans_start = jiffies; dev->trans_start = jiffies;
...@@ -1058,8 +1072,10 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) ...@@ -1058,8 +1072,10 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) { if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
strcpy(info->fw_version, "Unknown runtime"); strcpy(info->fw_version, "Unknown runtime");
} else { } else {
strncpy(info->fw_version, (char *) &xp_resp[1], 32); u32 sleep_ver = xp_resp[0].parm2;
info->fw_version[31] = 0; snprintf(info->fw_version, 32, "%02x.%03x.%03x",
sleep_ver >> 24, (sleep_ver >> 12) & 0xfff,
sleep_ver & 0xfff);
} }
} }
...@@ -1251,7 +1267,7 @@ typhoon_wait_interrupt(void __iomem *ioaddr) ...@@ -1251,7 +1267,7 @@ typhoon_wait_interrupt(void __iomem *ioaddr)
int i, err = 0; int i, err = 0;
for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) { for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
if(readl(ioaddr + TYPHOON_REG_INTR_STATUS) & if(ioread32(ioaddr + TYPHOON_REG_INTR_STATUS) &
TYPHOON_INTR_BOOTCMD) TYPHOON_INTR_BOOTCMD)
goto out; goto out;
udelay(TYPHOON_UDELAY); udelay(TYPHOON_UDELAY);
...@@ -1260,7 +1276,7 @@ typhoon_wait_interrupt(void __iomem *ioaddr) ...@@ -1260,7 +1276,7 @@ typhoon_wait_interrupt(void __iomem *ioaddr)
err = -ETIMEDOUT; err = -ETIMEDOUT;
out: out:
writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS); iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
return err; return err;
} }
...@@ -1394,11 +1410,11 @@ typhoon_download_firmware(struct typhoon *tp) ...@@ -1394,11 +1410,11 @@ typhoon_download_firmware(struct typhoon *tp)
goto err_out; goto err_out;
} }
irqEnabled = readl(ioaddr + TYPHOON_REG_INTR_ENABLE); irqEnabled = ioread32(ioaddr + TYPHOON_REG_INTR_ENABLE);
writel(irqEnabled | TYPHOON_INTR_BOOTCMD, iowrite32(irqEnabled | TYPHOON_INTR_BOOTCMD,
ioaddr + TYPHOON_REG_INTR_ENABLE); ioaddr + TYPHOON_REG_INTR_ENABLE);
irqMasked = readl(ioaddr + TYPHOON_REG_INTR_MASK); irqMasked = ioread32(ioaddr + TYPHOON_REG_INTR_MASK);
writel(irqMasked | TYPHOON_INTR_BOOTCMD, iowrite32(irqMasked | TYPHOON_INTR_BOOTCMD,
ioaddr + TYPHOON_REG_INTR_MASK); ioaddr + TYPHOON_REG_INTR_MASK);
err = -ETIMEDOUT; err = -ETIMEDOUT;
...@@ -1410,24 +1426,24 @@ typhoon_download_firmware(struct typhoon *tp) ...@@ -1410,24 +1426,24 @@ typhoon_download_firmware(struct typhoon *tp)
numSections = le32_to_cpu(fHdr->numSections); numSections = le32_to_cpu(fHdr->numSections);
load_addr = le32_to_cpu(fHdr->startAddr); load_addr = le32_to_cpu(fHdr->startAddr);
writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS); iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
writel(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR); iowrite32(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
hmac = le32_to_cpu(fHdr->hmacDigest[0]); hmac = le32_to_cpu(fHdr->hmacDigest[0]);
writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0); iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
hmac = le32_to_cpu(fHdr->hmacDigest[1]); hmac = le32_to_cpu(fHdr->hmacDigest[1]);
writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1); iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
hmac = le32_to_cpu(fHdr->hmacDigest[2]); hmac = le32_to_cpu(fHdr->hmacDigest[2]);
writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2); iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
hmac = le32_to_cpu(fHdr->hmacDigest[3]); hmac = le32_to_cpu(fHdr->hmacDigest[3]);
writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3); iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
hmac = le32_to_cpu(fHdr->hmacDigest[4]); hmac = le32_to_cpu(fHdr->hmacDigest[4]);
writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4); iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
writel(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND); iowrite32(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
image_data += sizeof(struct typhoon_file_header); image_data += sizeof(struct typhoon_file_header);
/* The readl() in typhoon_wait_interrupt() will force the /* The ioread32() in typhoon_wait_interrupt() will force the
* last write to the command register to post, so * last write to the command register to post, so
* we don't need a typhoon_post_pci_writes() after it. * we don't need a typhoon_post_pci_writes() after it.
*/ */
...@@ -1441,7 +1457,7 @@ typhoon_download_firmware(struct typhoon *tp) ...@@ -1441,7 +1457,7 @@ typhoon_download_firmware(struct typhoon *tp)
len = min_t(u32, section_len, PAGE_SIZE); len = min_t(u32, section_len, PAGE_SIZE);
if(typhoon_wait_interrupt(ioaddr) < 0 || if(typhoon_wait_interrupt(ioaddr) < 0 ||
readl(ioaddr + TYPHOON_REG_STATUS) != ioread32(ioaddr + TYPHOON_REG_STATUS) !=
TYPHOON_STATUS_WAITING_FOR_SEGMENT) { TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
printk(KERN_ERR "%s: segment ready timeout\n", printk(KERN_ERR "%s: segment ready timeout\n",
tp->name); tp->name);
...@@ -1458,13 +1474,14 @@ typhoon_download_firmware(struct typhoon *tp) ...@@ -1458,13 +1474,14 @@ typhoon_download_firmware(struct typhoon *tp)
csum = csum_fold(csum); csum = csum_fold(csum);
csum = le16_to_cpu(csum); csum = le16_to_cpu(csum);
writel(len, ioaddr + TYPHOON_REG_BOOT_LENGTH); iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
writel(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM); iowrite32(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
writel(load_addr, ioaddr + TYPHOON_REG_BOOT_DEST_ADDR); iowrite32(load_addr,
writel(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI); ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
writel(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO); iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
iowrite32(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
writel(TYPHOON_BOOTCMD_SEG_AVAILABLE, iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
ioaddr + TYPHOON_REG_COMMAND); ioaddr + TYPHOON_REG_COMMAND);
image_data += len; image_data += len;
...@@ -1474,25 +1491,25 @@ typhoon_download_firmware(struct typhoon *tp) ...@@ -1474,25 +1491,25 @@ typhoon_download_firmware(struct typhoon *tp)
} }
if(typhoon_wait_interrupt(ioaddr) < 0 || if(typhoon_wait_interrupt(ioaddr) < 0 ||
readl(ioaddr + TYPHOON_REG_STATUS) != ioread32(ioaddr + TYPHOON_REG_STATUS) !=
TYPHOON_STATUS_WAITING_FOR_SEGMENT) { TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
printk(KERN_ERR "%s: final segment ready timeout\n", tp->name); printk(KERN_ERR "%s: final segment ready timeout\n", tp->name);
goto err_out_irq; goto err_out_irq;
} }
writel(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND); iowrite32(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) { if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) {
printk(KERN_ERR "%s: boot ready timeout, status 0x%0x\n", printk(KERN_ERR "%s: boot ready timeout, status 0x%0x\n",
tp->name, readl(ioaddr + TYPHOON_REG_STATUS)); tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS));
goto err_out_irq; goto err_out_irq;
} }
err = 0; err = 0;
err_out_irq: err_out_irq:
writel(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK); iowrite32(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK);
writel(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE); iowrite32(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE);
pci_free_consistent(pdev, PAGE_SIZE, dpage, dpage_dma); pci_free_consistent(pdev, PAGE_SIZE, dpage, dpage_dma);
...@@ -1510,24 +1527,25 @@ typhoon_boot_3XP(struct typhoon *tp, u32 initial_status) ...@@ -1510,24 +1527,25 @@ typhoon_boot_3XP(struct typhoon *tp, u32 initial_status)
goto out_timeout; goto out_timeout;
} }
writel(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI); iowrite32(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI);
writel(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO); iowrite32(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
writel(TYPHOON_BOOTCMD_REG_BOOT_RECORD, ioaddr + TYPHOON_REG_COMMAND); iowrite32(TYPHOON_BOOTCMD_REG_BOOT_RECORD,
ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_RUNNING) < 0) { if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_RUNNING) < 0) {
printk(KERN_ERR "%s: boot finish timeout (status 0x%x)\n", printk(KERN_ERR "%s: boot finish timeout (status 0x%x)\n",
tp->name, readl(ioaddr + TYPHOON_REG_STATUS)); tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS));
goto out_timeout; goto out_timeout;
} }
/* Clear the Transmit and Command ready registers /* Clear the Transmit and Command ready registers
*/ */
writel(0, ioaddr + TYPHOON_REG_TX_HI_READY); iowrite32(0, ioaddr + TYPHOON_REG_TX_HI_READY);
writel(0, ioaddr + TYPHOON_REG_CMD_READY); iowrite32(0, ioaddr + TYPHOON_REG_CMD_READY);
writel(0, ioaddr + TYPHOON_REG_TX_LO_READY); iowrite32(0, ioaddr + TYPHOON_REG_TX_LO_READY);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
writel(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND); iowrite32(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND);
return 0; return 0;
...@@ -1806,7 +1824,8 @@ typhoon_poll(struct net_device *dev, int *total_budget) ...@@ -1806,7 +1824,8 @@ typhoon_poll(struct net_device *dev, int *total_budget)
if(done) { if(done) {
netif_rx_complete(dev); netif_rx_complete(dev);
writel(TYPHOON_INTR_NONE, tp->ioaddr + TYPHOON_REG_INTR_MASK); iowrite32(TYPHOON_INTR_NONE,
tp->ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(tp->ioaddr); typhoon_post_pci_writes(tp->ioaddr);
} }
...@@ -1821,14 +1840,14 @@ typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs) ...@@ -1821,14 +1840,14 @@ typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
void __iomem *ioaddr = tp->ioaddr; void __iomem *ioaddr = tp->ioaddr;
u32 intr_status; u32 intr_status;
intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS); intr_status = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
if(!(intr_status & TYPHOON_INTR_HOST_INT)) if(!(intr_status & TYPHOON_INTR_HOST_INT))
return IRQ_NONE; return IRQ_NONE;
writel(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS); iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
if(netif_rx_schedule_prep(dev)) { if(netif_rx_schedule_prep(dev)) {
writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK); iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
__netif_rx_schedule(dev); __netif_rx_schedule(dev);
} else { } else {
...@@ -1905,7 +1924,7 @@ typhoon_wakeup(struct typhoon *tp, int wait_type) ...@@ -1905,7 +1924,7 @@ typhoon_wakeup(struct typhoon *tp, int wait_type)
* we can download the Runtime Image. But let's not make users of * we can download the Runtime Image. But let's not make users of
* the old firmware pay for the reset. * the old firmware pay for the reset.
*/ */
writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND); iowrite32(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 || if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET)) (tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
return typhoon_reset(ioaddr, wait_type); return typhoon_reset(ioaddr, wait_type);
...@@ -1994,8 +2013,8 @@ typhoon_start_runtime(struct typhoon *tp) ...@@ -1994,8 +2013,8 @@ typhoon_start_runtime(struct typhoon *tp)
tp->card_state = Running; tp->card_state = Running;
smp_wmb(); smp_wmb();
writel(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE); iowrite32(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
writel(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK); iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(ioaddr); typhoon_post_pci_writes(ioaddr);
return 0; return 0;
...@@ -2020,7 +2039,7 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type) ...@@ -2020,7 +2039,7 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type)
* when called with !netif_running(). This will be posted * when called with !netif_running(). This will be posted
* when we force the posting of the command. * when we force the posting of the command.
*/ */
writel(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE); iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_RX_DISABLE); INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_RX_DISABLE);
typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
...@@ -2274,6 +2293,52 @@ typhoon_enable_wake(struct pci_dev *pdev, u32 state, int enable) ...@@ -2274,6 +2293,52 @@ typhoon_enable_wake(struct pci_dev *pdev, u32 state, int enable)
} }
#endif #endif
static int __devinit
typhoon_test_mmio(struct pci_dev *pdev)
{
void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
int mode = 0;
u32 val;
if(!ioaddr)
goto out;
if(ioread32(ioaddr + TYPHOON_REG_STATUS) !=
TYPHOON_STATUS_WAITING_FOR_HOST)
goto out_unmap;
iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
/* Ok, see if we can change our interrupt status register by
* sending ourselves an interrupt. If so, then MMIO works.
* The 50usec delay is arbitrary -- it could probably be smaller.
*/
val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
if((val & TYPHOON_INTR_SELF) == 0) {
iowrite32(1, ioaddr + TYPHOON_REG_SELF_INTERRUPT);
ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
udelay(50);
val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
if(val & TYPHOON_INTR_SELF)
mode = 1;
}
iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
out_unmap:
pci_iounmap(pdev, ioaddr);
out:
if(!mode)
printk(KERN_INFO PFX "falling back to port IO\n");
return mode;
}
static int __devinit static int __devinit
typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
...@@ -2281,8 +2346,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2281,8 +2346,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct net_device *dev; struct net_device *dev;
struct typhoon *tp; struct typhoon *tp;
int card_id = (int) ent->driver_data; int card_id = (int) ent->driver_data;
unsigned long ioaddr; void __iomem *ioaddr;
void __iomem *ioaddr_mapped;
void *shared; void *shared;
dma_addr_t shared_dma; dma_addr_t shared_dma;
struct cmd_desc xp_cmd; struct cmd_desc xp_cmd;
...@@ -2323,8 +2387,21 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2323,8 +2387,21 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_out_mwi; goto error_out_mwi;
} }
/* sanity checks, resource #1 is our mmio area /* sanity checks on IO and MMIO BARs
*/ */
if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
printk(ERR_PFX
"%s: region #1 not a PCI IO resource, aborting\n",
pci_name(pdev));
err = -ENODEV;
goto error_out_mwi;
}
if(pci_resource_len(pdev, 0) < 128) {
printk(ERR_PFX "%s: Invalid PCI IO region size, aborting\n",
pci_name(pdev));
err = -ENODEV;
goto error_out_mwi;
}
if(!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { if(!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
printk(ERR_PFX printk(ERR_PFX
"%s: region #1 not a PCI MMIO resource, aborting\n", "%s: region #1 not a PCI MMIO resource, aborting\n",
...@@ -2346,12 +2423,14 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2346,12 +2423,14 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_out_mwi; goto error_out_mwi;
} }
/* map our MMIO region /* map our registers
*/ */
ioaddr = pci_resource_start(pdev, 1); if(use_mmio != 0 && use_mmio != 1)
ioaddr_mapped = ioremap(ioaddr, 128); use_mmio = typhoon_test_mmio(pdev);
if (!ioaddr_mapped) {
printk(ERR_PFX "%s: cannot remap MMIO, aborting\n", ioaddr = pci_iomap(pdev, use_mmio, 128);
if (!ioaddr) {
printk(ERR_PFX "%s: cannot remap registers, aborting\n",
pci_name(pdev)); pci_name(pdev));
err = -EIO; err = -EIO;
goto error_out_regions; goto error_out_regions;
...@@ -2374,13 +2453,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2374,13 +2453,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->shared_dma = shared_dma; tp->shared_dma = shared_dma;
tp->pdev = pdev; tp->pdev = pdev;
tp->tx_pdev = pdev; tp->tx_pdev = pdev;
tp->ioaddr = ioaddr_mapped; tp->ioaddr = ioaddr;
tp->tx_ioaddr = ioaddr_mapped; tp->tx_ioaddr = ioaddr;
tp->dev = dev; tp->dev = dev;
/* need to be able to restore PCI state after a suspend */
pci_save_state(pdev);
/* Init sequence: /* Init sequence:
* 1) Reset the adapter to clear any bad juju * 1) Reset the adapter to clear any bad juju
* 2) Reload the sleep image * 2) Reload the sleep image
...@@ -2388,16 +2464,18 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2388,16 +2464,18 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
* 4) Get the hardware address. * 4) Get the hardware address.
* 5) Put the card to sleep. * 5) Put the card to sleep.
*/ */
if (typhoon_reset(ioaddr_mapped, WaitSleep) < 0) { if (typhoon_reset(ioaddr, WaitSleep) < 0) {
printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev)); printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev));
err = -EIO; err = -EIO;
goto error_out_dma; goto error_out_dma;
} }
/* Now that we've reset the 3XP and are sure it's not going to /* Now that we've reset the 3XP and are sure it's not going to
* write all over memory, enable bus mastering. * write all over memory, enable bus mastering, and save our
* state for resuming after a suspend.
*/ */
pci_set_master(pdev); pci_set_master(pdev);
pci_save_state(pdev);
/* dev->name is not valid until we register, but we need to /* dev->name is not valid until we register, but we need to
* use some common routines to initialize the card. So that those * use some common routines to initialize the card. So that those
...@@ -2491,8 +2569,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2491,8 +2569,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
printk(KERN_INFO "%s: %s at 0x%lx, ", printk(KERN_INFO "%s: %s at %s 0x%lx, ",
dev->name, typhoon_card_info[card_id].name, ioaddr); dev->name, typhoon_card_info[card_id].name,
use_mmio ? "MMIO" : "IO", pci_resource_start(pdev, use_mmio));
for(i = 0; i < 5; i++) for(i = 0; i < 5; i++)
printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x\n", dev->dev_addr[i]); printk("%2.2x\n", dev->dev_addr[i]);
...@@ -2515,7 +2594,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2515,7 +2594,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 *ver_string = (u8 *) &xp_resp[1]; u8 *ver_string = (u8 *) &xp_resp[1];
ver_string[25] = 0; ver_string[25] = 0;
printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version " printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version "
"%u.%u.%u.%u %s\n", dev->name, HIPQUAD(sleep_ver), "%02x.%03x.%03x %s\n", dev->name, sleep_ver >> 24,
(sleep_ver >> 12) & 0xfff, sleep_ver & 0xfff,
ver_string); ver_string);
} else { } else {
printk(KERN_WARNING "%s: Unknown Sleep Image version " printk(KERN_WARNING "%s: Unknown Sleep Image version "
...@@ -2526,13 +2606,13 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2526,13 +2606,13 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0; return 0;
error_out_reset: error_out_reset:
typhoon_reset(ioaddr_mapped, NoWait); typhoon_reset(ioaddr, NoWait);
error_out_dma: error_out_dma:
pci_free_consistent(pdev, sizeof(struct typhoon_shared), pci_free_consistent(pdev, sizeof(struct typhoon_shared),
shared, shared_dma); shared, shared_dma);
error_out_remap: error_out_remap:
iounmap(ioaddr_mapped); pci_iounmap(pdev, ioaddr);
error_out_regions: error_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
error_out_mwi: error_out_mwi:
...@@ -2555,7 +2635,7 @@ typhoon_remove_one(struct pci_dev *pdev) ...@@ -2555,7 +2635,7 @@ typhoon_remove_one(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev); pci_restore_state(pdev);
typhoon_reset(tp->ioaddr, NoWait); typhoon_reset(tp->ioaddr, NoWait);
iounmap(tp->ioaddr); pci_iounmap(pdev, tp->ioaddr);
pci_free_consistent(pdev, sizeof(struct typhoon_shared), pci_free_consistent(pdev, sizeof(struct typhoon_shared),
tp->shared, tp->shared_dma); tp->shared, tp->shared_dma);
pci_release_regions(pdev); pci_release_regions(pdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment