diff --git a/[refs] b/[refs] index 739b170c75ba..23792ebccb16 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a7a81fc060f050ad4ba7f6ef5cdc583dad2f7b21 +refs/heads/master: a7db74f4be3835fd16c6c582d320f692ccccc622 diff --git a/trunk/drivers/isdn/hardware/mISDN/hfc_multi.h b/trunk/drivers/isdn/hardware/mISDN/hfc_multi.h index 7bbf7300593d..a33d87afc843 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfc_multi.h +++ b/trunk/drivers/isdn/hardware/mISDN/hfc_multi.h @@ -162,8 +162,8 @@ struct hfc_multi { void (*write_fifo)(struct hfc_multi *hc, u_char *data, int len); u_long pci_origmembase, plx_origmembase, dsp_origmembase; - void __iomem *pci_membase; /* PCI memory */ - void __iomem *plx_membase; /* PLX memory */ + u_char *pci_membase; /* PCI memory (MUST BE BYTE POINTER) */ + u_char *plx_membase; /* PLX memory */ u_char *dsp_membase; /* DSP on PLX */ u_long pci_iobase; /* PCI IO */ struct hfcm_hw hw; /* remember data of write-only-registers */ diff --git a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c index c63e2f49da8a..1eac03f39d00 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -171,8 +171,9 @@ static int (*unregister_interrupt)(void); static int interrupt_registered; static struct hfc_multi *syncmaster; -static int plxsd_master; /* if we have a master card (yet) */ +int plxsd_master; /* if we have a master card (yet) */ static spinlock_t plx_lock; /* may not acquire other lock inside */ +EXPORT_SYMBOL(plx_lock); #define TYP_E1 1 #define TYP_4S 4 @@ -421,7 +422,7 @@ HFC_wait_debug(struct hfc_multi *hc, const char *function, int line) #endif /* write fifo data (REGIO) */ -static void +void write_fifo_regio(struct hfc_multi *hc, u_char *data, int len) { outb(A_FIFO_DATA0, (hc->pci_iobase)+4); @@ -442,7 +443,7 @@ write_fifo_regio(struct hfc_multi *hc, u_char *data, int len) } } /* write fifo data (PCIMEM) */ -static void +void write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) { while (len>>2) { @@ -464,7 +465,7 @@ write_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) } } /* read fifo data (REGIO) */ -static void +void read_fifo_regio(struct hfc_multi *hc, u_char *data, int len) { outb(A_FIFO_DATA0, (hc->pci_iobase)+4); @@ -486,7 +487,7 @@ read_fifo_regio(struct hfc_multi *hc, u_char *data, int len) } /* read fifo data (PCIMEM) */ -static void +void read_fifo_pcimem(struct hfc_multi *hc, u_char *data, int len) { while (len>>2) { @@ -705,7 +706,7 @@ vpm_out(struct hfc_multi *c, int which, unsigned short addr, } -static void +void vpm_init(struct hfc_multi *wc) { unsigned char reg; @@ -788,8 +789,7 @@ vpm_init(struct hfc_multi *wc) } } -#ifdef UNUSED -static void +void vpm_check(struct hfc_multi *hctmp) { unsigned char gpi2; @@ -799,7 +799,6 @@ vpm_check(struct hfc_multi *hctmp) if ((gpi2 & 0x3) != 0x3) printk(KERN_DEBUG "Got interrupt 0x%x from VPM!\n", gpi2); } -#endif /* UNUSED */ /* @@ -813,7 +812,7 @@ vpm_check(struct hfc_multi *hctmp) * */ -static void +void vpm_echocan_on(struct hfc_multi *hc, int ch, int taps) { unsigned int timeslot; @@ -845,7 +844,7 @@ vpm_echocan_on(struct hfc_multi *hc, int ch, int taps) vpm_out(hc, unit, timeslot, 0x7e); } -static void +void vpm_echocan_off(struct hfc_multi *hc, int ch) { unsigned int timeslot; @@ -888,9 +887,8 @@ vpm_echocan_off(struct hfc_multi *hc, int ch) static inline void hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) { - struct hfc_multi *hc, *next, *pcmmaster = NULL; - void __iomem *plx_acc_32; - u_int pv; + struct hfc_multi *hc, *next, *pcmmaster = 0; + u_int *plx_acc_32, pv; u_long flags; spin_lock_irqsave(&HFClock, flags); @@ -918,7 +916,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) /* Disable sync of all cards */ list_for_each_entry_safe(hc, next, &HFClist, list) { if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); pv = readl(plx_acc_32); pv &= ~PLX_SYNC_O_EN; writel(pv, plx_acc_32); @@ -940,7 +938,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) printk(KERN_DEBUG "id=%d (0x%p) = syncronized with " "interface.\n", hc->id, hc); /* Enable new sync master */ - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); pv = readl(plx_acc_32); pv |= PLX_SYNC_O_EN; writel(pv, plx_acc_32); @@ -970,7 +968,7 @@ hfcmulti_resync(struct hfc_multi *locked, struct hfc_multi *newmaster, int rm) "QUARTZ is automatically " "enabled by HFC-%dS\n", hc->type); } - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); pv = readl(plx_acc_32); pv |= PLX_SYNC_O_EN; writel(pv, plx_acc_32); @@ -1015,8 +1013,7 @@ plxsd_checksync(struct hfc_multi *hc, int rm) static void release_io_hfcmulti(struct hfc_multi *hc) { - void __iomem *plx_acc_32; - u_int pv; + u_int *plx_acc_32, pv; u_long plx_flags; if (debug & DEBUG_HFCMULTI_INIT) @@ -1036,7 +1033,7 @@ release_io_hfcmulti(struct hfc_multi *hc) printk(KERN_DEBUG "%s: release PLXSD card %d\n", __func__, hc->id + 1); spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); writel(PLX_GPIOC_INIT, plx_acc_32); pv = readl(plx_acc_32); /* Termination off */ @@ -1058,9 +1055,9 @@ release_io_hfcmulti(struct hfc_multi *hc) test_and_clear_bit(HFC_CHIP_PLXSD, &hc->chip); /* prevent resync */ pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0); if (hc->pci_membase) - iounmap(hc->pci_membase); + iounmap((void *)hc->pci_membase); if (hc->plx_membase) - iounmap(hc->plx_membase); + iounmap((void *)hc->plx_membase); if (hc->pci_iobase) release_region(hc->pci_iobase, 8); @@ -1083,8 +1080,7 @@ init_chip(struct hfc_multi *hc) u_long flags, val, val2 = 0, rev; int i, err = 0; u_char r_conf_en, rval; - void __iomem *plx_acc_32; - u_int pv; + u_int *plx_acc_32, pv; u_long plx_flags, hfc_flags; int plx_count; struct hfc_multi *pos, *next, *plx_last_hc; @@ -1158,7 +1154,7 @@ init_chip(struct hfc_multi *hc) printk(KERN_DEBUG "%s: initializing PLXSD card %d\n", __func__, hc->id + 1); spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); writel(PLX_GPIOC_INIT, plx_acc_32); pv = readl(plx_acc_32); /* The first and the last cards are terminating the PCM bus */ @@ -1194,7 +1190,8 @@ init_chip(struct hfc_multi *hc) "we disable termination\n", __func__, plx_last_hc->id + 1); spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc_32 = plx_last_hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(plx_last_hc->plx_membase + + PLX_GPIOC); pv = readl(plx_acc_32); pv &= ~PLX_TERM_ON; writel(pv, plx_acc_32); @@ -1243,7 +1240,7 @@ init_chip(struct hfc_multi *hc) /* Speech Design PLX bridge pcm and sync mode */ if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); pv = readl(plx_acc_32); /* Connect PCM */ if (hc->hw.r_pcm_md0 & V_PCM_MD) { @@ -1355,7 +1352,8 @@ init_chip(struct hfc_multi *hc) /* retry with master clock */ if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase + + PLX_GPIOC); pv = readl(plx_acc_32); pv |= PLX_MASTER_EN | PLX_SLAVE_EN_N; pv |= PLX_SYNC_O_EN; @@ -1391,7 +1389,7 @@ init_chip(struct hfc_multi *hc) if (test_bit(HFC_CHIP_PCM_MASTER, &hc->chip)) plxsd_master = 1; spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc_32 = hc->plx_membase + PLX_GPIOC; + plx_acc_32 = (u_int *)(hc->plx_membase+PLX_GPIOC); pv = readl(plx_acc_32); pv |= PLX_DSP_RES_N; writel(pv, plx_acc_32); @@ -2588,8 +2586,7 @@ hfcmulti_interrupt(int intno, void *dev_id) struct dchannel *dch; u_char r_irq_statech, status, r_irq_misc, r_irq_oview; int i; - void __iomem *plx_acc; - u_short wval; + u_short *plx_acc, wval; u_char e1_syncsta, temp; u_long flags; @@ -2609,7 +2606,7 @@ hfcmulti_interrupt(int intno, void *dev_id) if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, flags); - plx_acc = hc->plx_membase + PLX_INTCSR; + plx_acc = (u_short *)(hc->plx_membase + PLX_INTCSR); wval = readw(plx_acc); spin_unlock_irqrestore(&plx_lock, flags); if (!(wval & PLX_INTCSR_LINTI1_STATUS)) @@ -4094,7 +4091,7 @@ init_card(struct hfc_multi *hc) { int err = -EIO; u_long flags; - void __iomem *plx_acc; + u_short *plx_acc; u_long plx_flags; if (debug & DEBUG_HFCMULTI_INIT) @@ -4116,7 +4113,7 @@ init_card(struct hfc_multi *hc) if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc = hc->plx_membase + PLX_INTCSR; + plx_acc = (u_short *)(hc->plx_membase+PLX_INTCSR); writew((PLX_INTCSR_PCIINT_ENABLE | PLX_INTCSR_LINTI1_ENABLE), plx_acc); /* enable PCI & LINT1 irq */ spin_unlock_irqrestore(&plx_lock, plx_flags); @@ -4165,7 +4162,7 @@ init_card(struct hfc_multi *hc) error: if (test_bit(HFC_CHIP_PLXSD, &hc->chip)) { spin_lock_irqsave(&plx_lock, plx_flags); - plx_acc = hc->plx_membase + PLX_INTCSR; + plx_acc = (u_short *)(hc->plx_membase+PLX_INTCSR); writew(0x00, plx_acc); /*disable IRQs*/ spin_unlock_irqrestore(&plx_lock, plx_flags); } diff --git a/trunk/drivers/isdn/mISDN/core.c b/trunk/drivers/isdn/mISDN/core.c index 751665c448d0..33068177b7c9 100644 --- a/trunk/drivers/isdn/mISDN/core.c +++ b/trunk/drivers/isdn/mISDN/core.c @@ -26,12 +26,12 @@ MODULE_LICENSE("GPL"); module_param(debug, uint, S_IRUGO | S_IWUSR); static LIST_HEAD(devices); -static DEFINE_RWLOCK(device_lock); +DEFINE_RWLOCK(device_lock); static u64 device_ids; #define MAX_DEVICE_ID 63 static LIST_HEAD(Bprotocols); -static DEFINE_RWLOCK(bp_lock); +DEFINE_RWLOCK(bp_lock); struct mISDNdevice *get_mdevice(u_int id) @@ -192,7 +192,7 @@ mISDN_unregister_Bprotocol(struct Bprotocol *bp) } EXPORT_SYMBOL(mISDN_unregister_Bprotocol); -static int +int mISDNInit(void) { int err; @@ -224,7 +224,7 @@ mISDNInit(void) return err; } -static void mISDN_cleanup(void) +void mISDN_cleanup(void) { misdn_sock_cleanup(); mISDN_timer_cleanup(); diff --git a/trunk/drivers/isdn/mISDN/dsp_audio.c b/trunk/drivers/isdn/mISDN/dsp_audio.c index de3795e3f432..1c2dd5694773 100644 --- a/trunk/drivers/isdn/mISDN/dsp_audio.c +++ b/trunk/drivers/isdn/mISDN/dsp_audio.c @@ -30,7 +30,7 @@ EXPORT_SYMBOL(dsp_audio_s16_to_law); /* alaw -> ulaw */ u8 dsp_audio_alaw_to_ulaw[256]; /* ulaw -> alaw */ -static u8 dsp_audio_ulaw_to_alaw[256]; +u8 dsp_audio_ulaw_to_alaw[256]; u8 dsp_silence; diff --git a/trunk/drivers/isdn/mISDN/dsp_cmx.c b/trunk/drivers/isdn/mISDN/dsp_cmx.c index c884511e2d49..c2f51cc50760 100644 --- a/trunk/drivers/isdn/mISDN/dsp_cmx.c +++ b/trunk/drivers/isdn/mISDN/dsp_cmx.c @@ -1540,13 +1540,11 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members) schedule_work(&dsp->workq); } -static u32 samplecount; +u32 samplecount; struct timer_list dsp_spl_tl; u32 dsp_spl_jiffies; /* calculate the next time to fire */ -#ifdef UNUSED -static u32 dsp_start_jiffies; /* jiffies at the time, the calculation begins */ -#endif /* UNUSED */ -static struct timeval dsp_start_tv; /* time at start of calculation */ +u32 dsp_start_jiffies; /* jiffies at the time, the calculation begins */ +struct timeval dsp_start_tv; /* time at start of calculation */ void dsp_cmx_send(void *arg) diff --git a/trunk/drivers/isdn/mISDN/dsp_core.c b/trunk/drivers/isdn/mISDN/dsp_core.c index 1dc21d803410..2f10ed82c0db 100644 --- a/trunk/drivers/isdn/mISDN/dsp_core.c +++ b/trunk/drivers/isdn/mISDN/dsp_core.c @@ -161,7 +161,7 @@ #include "core.h" #include "dsp.h" -static const char *mISDN_dsp_revision = "2.0"; +const char *mISDN_dsp_revision = "2.0"; static int debug; static int options; @@ -631,6 +631,7 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) int ret = 0; u8 *digits; int cont; + struct sk_buff *nskb; u_long flags; hh = mISDN_HEAD_P(skb); @@ -689,7 +690,6 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb) digits = dsp_dtmf_goertzel_decode(dsp, skb->data, skb->len, (dsp_options&DSP_OPT_ULAW)?1:0); while (*digits) { - struct sk_buff *nskb; if (dsp_debug & DEBUG_DSP_DTMF) printk(KERN_DEBUG "%s: digit" "(%c) to layer %s\n", diff --git a/trunk/drivers/isdn/mISDN/dsp_pipeline.c b/trunk/drivers/isdn/mISDN/dsp_pipeline.c index 5ee6651b45b9..850260ab57d0 100644 --- a/trunk/drivers/isdn/mISDN/dsp_pipeline.c +++ b/trunk/drivers/isdn/mISDN/dsp_pipeline.c @@ -249,7 +249,7 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg) name = strsep(&tok, "("); args = strsep(&tok, ")"); if (args && !*args) - args = NULL; + args = 0; list_for_each_entry_safe(entry, n, &dsp_elements, list) if (!strcmp(entry->elem->name, name)) { diff --git a/trunk/drivers/isdn/mISDN/dsp_tones.c b/trunk/drivers/isdn/mISDN/dsp_tones.c index 7a9af66f4b19..23dd0dd21524 100644 --- a/trunk/drivers/isdn/mISDN/dsp_tones.c +++ b/trunk/drivers/isdn/mISDN/dsp_tones.c @@ -231,120 +231,120 @@ dsp_audio_generate_ulaw_samples(void) * tone sequence definition * ****************************/ -static struct pattern { +struct pattern { int tone; u8 *data[10]; u32 *siz[10]; u32 seq[10]; } pattern[] = { {TONE_GERMAN_DIALTONE, - {DATA_GA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GA, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1900, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_OLDDIALTONE, - {DATA_GO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GO, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1998, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_AMERICAN_DIALTONE, - {DATA_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_DIALPBX, - {DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, DATA_GA, DATA_S, DATA_GA, DATA_S, 0, 0, 0, 0}, + {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0}, {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, {TONE_GERMAN_OLDDIALPBX, - {DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0}, + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0}, {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, {TONE_AMERICAN_DIALPBX, - {DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, NULL, NULL, NULL, NULL}, - {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, NULL, NULL, NULL, NULL}, + {DATA_DT, DATA_S, DATA_DT, DATA_S, DATA_DT, DATA_S, 0, 0, 0, 0}, + {SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, SIZE_DT, SIZE_S, 0, 0, 0, 0}, {2000, 2000, 2000, 2000, 2000, 12000, 0, 0, 0, 0} }, {TONE_GERMAN_RINGING, - {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_OLDRINGING, - {DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {8000, 40000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_AMERICAN_RINGING, - {DATA_RI, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_RI, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {8000, 32000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_RINGPBX, - {DATA_GA, DATA_S, DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0}, + {SIZE_GA, SIZE_S, SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0}, {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_OLDRINGPBX, - {DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0}, + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0}, {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} }, {TONE_AMERICAN_RINGPBX, - {DATA_RI, DATA_S, DATA_RI, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_RI, DATA_S, DATA_RI, DATA_S, 0, 0, 0, 0, 0, 0}, + {SIZE_RI, SIZE_S, SIZE_RI, SIZE_S, 0, 0, 0, 0, 0, 0}, {4000, 4000, 4000, 28000, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_BUSY, - {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_OLDBUSY, - {DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_AMERICAN_BUSY, - {DATA_BU, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_BU, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_BU, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_BU, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_HANGUP, - {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {4000, 4000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_OLDHANGUP, - {DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {1000, 5000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_AMERICAN_HANGUP, - {DATA_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_DT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_DT, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {8000, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_SPECIAL_INFO, - {DATA_S1, DATA_S2, DATA_S3, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_S1, DATA_S2, DATA_S3, DATA_S, 0, 0, 0, 0, 0, 0}, + {SIZE_S1, SIZE_S2, SIZE_S3, SIZE_S, 0, 0, 0, 0, 0, 0}, {2666, 2666, 2666, 8002, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_GASSENBESETZT, - {DATA_GA, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GA, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GA, DATA_S, 0, 0, 0, 0, 0, 0, 0, 0}, + {SIZE_GA, SIZE_S, 0, 0, 0, 0, 0, 0, 0, 0}, {2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0} }, {TONE_GERMAN_AUFSCHALTTON, - {DATA_GO, DATA_S, DATA_GO, DATA_S, NULL, NULL, NULL, NULL, NULL, NULL}, - {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, NULL, NULL, NULL, NULL, NULL, NULL}, + {DATA_GO, DATA_S, DATA_GO, DATA_S, 0, 0, 0, 0, 0, 0}, + {SIZE_GO, SIZE_S, SIZE_GO, SIZE_S, 0, 0, 0, 0, 0, 0}, {1000, 5000, 1000, 17000, 0, 0, 0, 0, 0, 0} }, {0, - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, }; @@ -467,7 +467,7 @@ dsp_tone_timeout(void *arg) /* set next tone */ if (pat->data[index] == DATA_S) - dsp_tone_hw_message(dsp, NULL, 0); + dsp_tone_hw_message(dsp, 0, 0); else dsp_tone_hw_message(dsp, pat->data[index], *(pat->siz[index])); /* set timer */ diff --git a/trunk/drivers/isdn/mISDN/l1oip_codec.c b/trunk/drivers/isdn/mISDN/l1oip_codec.c index 2ec4b28d9edc..a2dc4570ef43 100644 --- a/trunk/drivers/isdn/mISDN/l1oip_codec.c +++ b/trunk/drivers/isdn/mISDN/l1oip_codec.c @@ -49,7 +49,6 @@ NOTE: The bytes are handled as they are law-encoded. #include #include #include "core.h" -#include "l1oip.h" /* definitions of codec. don't use calculations, code may run slower. */ diff --git a/trunk/drivers/isdn/mISDN/l1oip_core.c b/trunk/drivers/isdn/mISDN/l1oip_core.c index 0884dd6892f8..e42150a57780 100644 --- a/trunk/drivers/isdn/mISDN/l1oip_core.c +++ b/trunk/drivers/isdn/mISDN/l1oip_core.c @@ -469,7 +469,7 @@ l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase, static void l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) { - u32 packet_id; + u32 id; u8 channel; u8 remotecodec; u16 timebase; @@ -508,7 +508,7 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) } /* get id flag */ - packet_id = (*buf>>4)&1; + id = (*buf>>4)&1; /* check coding */ remotecodec = (*buf) & 0x0f; @@ -520,11 +520,11 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) buf++; len--; - /* check packet_id */ - if (packet_id) { + /* check id */ + if (id) { if (!hc->id) { printk(KERN_WARNING "%s: packet error - packet has id " - "0x%x, but we have not\n", __func__, packet_id); + "0x%x, but we have not\n", __func__, id); return; } if (len < 4) { @@ -532,16 +532,16 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) "short for ID value\n", __func__); return; } - packet_id = (*buf++) << 24; - packet_id += (*buf++) << 16; - packet_id += (*buf++) << 8; - packet_id += (*buf++); + id = (*buf++) << 24; + id += (*buf++) << 16; + id += (*buf++) << 8; + id += (*buf++); len -= 4; - if (packet_id != hc->id) { + if (id != hc->id) { printk(KERN_WARNING "%s: packet error - ID mismatch, " "got 0x%x, we 0x%x\n", - __func__, packet_id, hc->id); + __func__, id, hc->id); return; } } else { diff --git a/trunk/drivers/isdn/mISDN/layer1.c b/trunk/drivers/isdn/mISDN/layer1.c index b73e952d12cf..fced1a2755f8 100644 --- a/trunk/drivers/isdn/mISDN/layer1.c +++ b/trunk/drivers/isdn/mISDN/layer1.c @@ -18,11 +18,10 @@ #include #include -#include "core.h" #include "layer1.h" #include "fsm.h" -static u_int *debug; +static int *debug; struct layer1 { u_long Flags; diff --git a/trunk/drivers/isdn/mISDN/layer2.c b/trunk/drivers/isdn/mISDN/layer2.c index d6e2863f224a..a7915a156c04 100644 --- a/trunk/drivers/isdn/mISDN/layer2.c +++ b/trunk/drivers/isdn/mISDN/layer2.c @@ -15,12 +15,10 @@ * */ -#include -#include "core.h" #include "fsm.h" #include "layer2.h" -static u_int *debug; +static int *debug; static struct Fsm l2fsm = {NULL, 0, 0, NULL, NULL}; @@ -467,7 +465,7 @@ IsRNR(u_char *data, struct layer2 *l2) data[0] == RNR : (data[0] & 0xf) == RNR; } -static int +int iframe_error(struct layer2 *l2, struct sk_buff *skb) { u_int i; @@ -485,7 +483,7 @@ iframe_error(struct layer2 *l2, struct sk_buff *skb) return 0; } -static int +int super_error(struct layer2 *l2, struct sk_buff *skb) { if (skb->len != l2addrsize(l2) + @@ -494,7 +492,7 @@ super_error(struct layer2 *l2, struct sk_buff *skb) return 0; } -static int +int unnum_error(struct layer2 *l2, struct sk_buff *skb, int wantrsp) { int rsp = (*skb->data & 0x2) >> 1; @@ -507,7 +505,7 @@ unnum_error(struct layer2 *l2, struct sk_buff *skb, int wantrsp) return 0; } -static int +int UI_error(struct layer2 *l2, struct sk_buff *skb) { int rsp = *skb->data & 0x2; @@ -520,7 +518,7 @@ UI_error(struct layer2 *l2, struct sk_buff *skb) return 0; } -static int +int FRMR_error(struct layer2 *l2, struct sk_buff *skb) { u_int headers = l2addrsize(l2) + 1; @@ -1067,7 +1065,7 @@ l2_st6_dm_release(struct FsmInst *fi, int event, void *arg) } } -static void +void enquiry_cr(struct layer2 *l2, u_char typ, u_char cr, u_char pf) { struct sk_buff *skb; diff --git a/trunk/drivers/isdn/mISDN/socket.c b/trunk/drivers/isdn/mISDN/socket.c index 37a2de18cfd0..e5a20f9542d1 100644 --- a/trunk/drivers/isdn/mISDN/socket.c +++ b/trunk/drivers/isdn/mISDN/socket.c @@ -18,7 +18,7 @@ #include #include "core.h" -static u_int *debug; +static int *debug; static struct proto mISDN_proto = { .name = "misdn", diff --git a/trunk/drivers/isdn/mISDN/stack.c b/trunk/drivers/isdn/mISDN/stack.c index d55b14ae4e99..54cfddcc4784 100644 --- a/trunk/drivers/isdn/mISDN/stack.c +++ b/trunk/drivers/isdn/mISDN/stack.c @@ -36,7 +36,7 @@ _queue_message(struct mISDNstack *st, struct sk_buff *skb) } } -static int +int mISDN_queue_message(struct mISDNchannel *ch, struct sk_buff *skb) { _queue_message(ch->st, skb); diff --git a/trunk/drivers/isdn/mISDN/tei.c b/trunk/drivers/isdn/mISDN/tei.c index 5c43d19e7c11..6fbae42127bf 100644 --- a/trunk/drivers/isdn/mISDN/tei.c +++ b/trunk/drivers/isdn/mISDN/tei.c @@ -393,7 +393,7 @@ dl_unit_data(struct manager *mgr, struct sk_buff *skb) return 0; } -static unsigned int +unsigned int random_ri(void) { u16 x; @@ -1287,7 +1287,7 @@ create_teimanager(struct mISDNdevice *dev) if (!mgr) return -ENOMEM; INIT_LIST_HEAD(&mgr->layer2); - rwlock_init(&mgr->lock); + mgr->lock = __RW_LOCK_UNLOCKED(mgr->lock); skb_queue_head_init(&mgr->sendq); mgr->nextid = 1; mgr->lastid = MISDN_ID_NONE; diff --git a/trunk/drivers/isdn/mISDN/timerdev.c b/trunk/drivers/isdn/mISDN/timerdev.c index f2b32186d4a1..875fabe16e36 100644 --- a/trunk/drivers/isdn/mISDN/timerdev.c +++ b/trunk/drivers/isdn/mISDN/timerdev.c @@ -23,9 +23,8 @@ #include #include #include -#include "core.h" -static u_int *debug; +static int *debug; struct mISDNtimerdev { @@ -86,7 +85,7 @@ mISDN_close(struct inode *ino, struct file *filep) } static ssize_t -mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) +mISDN_read(struct file *filep, char *buf, size_t count, loff_t *off) { struct mISDNtimerdev *dev = filep->private_data; struct mISDNtimer *timer; @@ -116,7 +115,7 @@ mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) timer = (struct mISDNtimer *)dev->expired.next; list_del(&timer->list); spin_unlock_irqrestore(&dev->lock, flags); - if (put_user(timer->id, (int __user *)buf)) + if (put_user(timer->id, (int *)buf)) ret = -EFAULT; else ret = sizeof(int); @@ -275,7 +274,7 @@ static struct miscdevice mISDNtimer = { }; int -mISDN_inittimer(u_int *deb) +mISDN_inittimer(int *deb) { int err; diff --git a/trunk/drivers/net/sfc/Makefile b/trunk/drivers/net/sfc/Makefile index b89f9be3cb13..e507daa4f0e8 100644 --- a/trunk/drivers/net/sfc/Makefile +++ b/trunk/drivers/net/sfc/Makefile @@ -1,5 +1,5 @@ -sfc-y += efx.o falcon.o tx.o rx.o falcon_gmac.o \ - falcon_xmac.o selftest.o ethtool.o xfp_phy.o \ +sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ + selftest.o ethtool.o xfp_phy.o \ mdio_10g.o tenxpress.o boards.o sfe4001.o sfc-$(CONFIG_SFC_MTD) += mtd.o diff --git a/trunk/drivers/net/sfc/boards.c b/trunk/drivers/net/sfc/boards.c index 64903496aa9a..edf026280bec 100644 --- a/trunk/drivers/net/sfc/boards.c +++ b/trunk/drivers/net/sfc/boards.c @@ -1,6 +1,6 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 Solarflare Communications Inc. + * Copyright 2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -231,40 +231,70 @@ static int sfe4002_init(struct efx_nic *efx) /* This will get expanded as board-specific details get moved out of the * PHY drivers. */ struct efx_board_data { - enum efx_board_type type; const char *ref_model; const char *gen_type; int (*init) (struct efx_nic *nic); }; +static int dummy_init(struct efx_nic *nic) +{ + return 0; +} static struct efx_board_data board_data[] = { - { EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init }, - { EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init }, - { EFX_BOARD_SFN4111T, "SFN4111T", "100/1000/10GBASE-T adapter", - sfn4111t_init }, + [EFX_BOARD_INVALID] = + {NULL, NULL, dummy_init}, + [EFX_BOARD_SFE4001] = + {"SFE4001", "10GBASE-T adapter", sfe4001_init}, + [EFX_BOARD_SFE4002] = + {"SFE4002", "XFP adapter", sfe4002_init}, }; -void efx_set_board_info(struct efx_nic *efx, u16 revision_info) +int efx_set_board_info(struct efx_nic *efx, u16 revision_info) { - struct efx_board_data *data = NULL; - int i; + int rc = 0; + struct efx_board_data *data; - efx->board_info.type = BOARD_TYPE(revision_info); - efx->board_info.major = BOARD_MAJOR(revision_info); - efx->board_info.minor = BOARD_MINOR(revision_info); + if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) { + EFX_ERR(efx, "squashing unknown board type %d\n", + BOARD_TYPE(revision_info)); + revision_info = 0; + } + + if (BOARD_TYPE(revision_info) == 0) { + efx->board_info.major = 0; + efx->board_info.minor = 0; + /* For early boards that don't have revision info. there is + * only 1 board for each PHY type, so we can work it out, with + * the exception of the PHY-less boards. */ + switch (efx->phy_type) { + case PHY_TYPE_10XPRESS: + efx->board_info.type = EFX_BOARD_SFE4001; + break; + case PHY_TYPE_XFP: + efx->board_info.type = EFX_BOARD_SFE4002; + break; + default: + efx->board_info.type = 0; + break; + } + } else { + efx->board_info.type = BOARD_TYPE(revision_info); + efx->board_info.major = BOARD_MAJOR(revision_info); + efx->board_info.minor = BOARD_MINOR(revision_info); + } - for (i = 0; i < ARRAY_SIZE(board_data); i++) - if (board_data[i].type == efx->board_info.type) - data = &board_data[i]; + data = &board_data[efx->board_info.type]; - if (data) { + /* Report the board model number or generic type for recognisable + * boards. */ + if (efx->board_info.type != 0) EFX_INFO(efx, "board is %s rev %c%d\n", (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC) ? data->ref_model : data->gen_type, 'A' + efx->board_info.major, efx->board_info.minor); - efx->board_info.init = data->init; - } else { - EFX_ERR(efx, "unknown board type %d\n", efx->board_info.type); - } + + efx->board_info.init = data->init; + + return rc; } diff --git a/trunk/drivers/net/sfc/boards.h b/trunk/drivers/net/sfc/boards.h index d93c6c6a7548..c6e01b64bfb4 100644 --- a/trunk/drivers/net/sfc/boards.h +++ b/trunk/drivers/net/sfc/boards.h @@ -1,6 +1,6 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 Solarflare Communications Inc. + * Copyright 2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -12,16 +12,14 @@ /* Board IDs (must fit in 8 bits) */ enum efx_board_type { - EFX_BOARD_SFE4001 = 1, + EFX_BOARD_INVALID = 0, + EFX_BOARD_SFE4001 = 1, /* SFE4001 (10GBASE-T) */ EFX_BOARD_SFE4002 = 2, - EFX_BOARD_SFN4111T = 0x51, + /* Insert new types before here */ + EFX_BOARD_MAX }; -extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info); - -/* SFE4001 (10GBASE-T) */ +extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info); extern int sfe4001_init(struct efx_nic *efx); -/* SFN4111T (100/1000/10GBASE-T) */ -extern int sfn4111t_init(struct efx_nic *efx); #endif diff --git a/trunk/drivers/net/sfc/efx.c b/trunk/drivers/net/sfc/efx.c index 086629c0fe57..e5024bb8a46e 100644 --- a/trunk/drivers/net/sfc/efx.c +++ b/trunk/drivers/net/sfc/efx.c @@ -21,12 +21,14 @@ #include #include #include "net_driver.h" +#include "gmii.h" #include "ethtool.h" #include "tx.h" #include "rx.h" #include "efx.h" #include "mdio_10g.h" #include "falcon.h" +#include "mac.h" #define EFX_MAX_MTU (9 * 1024) @@ -37,12 +39,6 @@ */ static struct workqueue_struct *refill_workqueue; -/* Reset workqueue. If any NIC has a hardware failure then a reset will be - * queued onto this work queue. This is not a per-nic work queue, because - * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised. - */ -static struct workqueue_struct *reset_workqueue; - /************************************************************************** * * Configurable values @@ -62,15 +58,13 @@ MODULE_PARM_DESC(lro, "Large receive offload acceleration"); /* * Use separate channels for TX and RX events * - * Set this to 1 to use separate channels for TX and RX. It allows us - * to control interrupt affinity separately for TX and RX. + * Set this to 1 to use separate channels for TX and RX. It allows us to + * apply a higher level of interrupt moderation to TX events. * - * This is only used in MSI-X interrupt mode + * This is forced to 0 for MSI interrupt mode as the interrupt vector + * is not written */ -static unsigned int separate_tx_channels; -module_param(separate_tx_channels, uint, 0644); -MODULE_PARM_DESC(separate_tx_channels, - "Use separate channels for TX and RX"); +static unsigned int separate_tx_and_rx_channels = true; /* This is the weight assigned to each of the (per-channel) virtual * NAPI devices. @@ -129,10 +123,6 @@ static unsigned int rss_cpus; module_param(rss_cpus, uint, 0444); MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling"); -static int phy_flash_cfg; -module_param(phy_flash_cfg, int, 0644); -MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially"); - /************************************************************************** * * Utility functions and prototypes @@ -354,27 +344,6 @@ static int efx_probe_channel(struct efx_channel *channel) } -static void efx_set_channel_names(struct efx_nic *efx) -{ - struct efx_channel *channel; - const char *type = ""; - int number; - - efx_for_each_channel(channel, efx) { - number = channel->channel; - if (efx->n_channels > efx->n_rx_queues) { - if (channel->channel < efx->n_rx_queues) { - type = "-rx"; - } else { - type = "-tx"; - number -= efx->n_rx_queues; - } - } - snprintf(channel->name, sizeof(channel->name), - "%s%s-%d", efx->name, type, number); - } -} - /* Channels are shutdown and reinitialised whilst the NIC is running * to propagate configuration changes (mtu, checksum offload), or * to clear hardware error conditions @@ -549,8 +518,26 @@ static void efx_link_status_changed(struct efx_nic *efx) /* Status message for kernel log */ if (efx->link_up) { - EFX_INFO(efx, "link up at %uMbps %s-duplex (MTU %d)%s\n", - efx->link_speed, efx->link_fd ? "full" : "half", + struct mii_if_info *gmii = &efx->mii; + unsigned adv, lpa; + /* NONE here means direct XAUI from the controller, with no + * MDIO-attached device we can query. */ + if (efx->phy_type != PHY_TYPE_NONE) { + adv = gmii_advertised(gmii); + lpa = gmii_lpa(gmii); + } else { + lpa = GM_LPA_10000 | LPA_DUPLEX; + adv = lpa; + } + EFX_INFO(efx, "link up at %dMbps %s-duplex " + "(adv %04x lpa %04x) (MTU %d)%s\n", + (efx->link_options & GM_LPA_10000 ? 10000 : + (efx->link_options & GM_LPA_1000 ? 1000 : + (efx->link_options & GM_LPA_100 ? 100 : + 10))), + (efx->link_options & GM_LPA_DUPLEX ? + "full" : "half"), + adv, lpa, efx->net_dev->mtu, (efx->promiscuous ? " [PROMISC]" : "")); } else { @@ -574,28 +561,10 @@ void __efx_reconfigure_port(struct efx_nic *efx) netif_addr_unlock_bh(efx->net_dev); } - falcon_deconfigure_mac_wrapper(efx); - - /* Reconfigure the PHY, disabling transmit in mac level loopback. */ - if (LOOPBACK_INTERNAL(efx)) - efx->phy_mode |= PHY_MODE_TX_DISABLED; - else - efx->phy_mode &= ~PHY_MODE_TX_DISABLED; - efx->phy_op->reconfigure(efx); - - if (falcon_switch_mac(efx)) - goto fail; - - efx->mac_op->reconfigure(efx); + falcon_reconfigure_xmac(efx); /* Inform kernel of loss/gain of carrier */ efx_link_status_changed(efx); - return; - -fail: - EFX_ERR(efx, "failed to reconfigure MAC\n"); - efx->phy_op->fini(efx); - efx->port_initialized = false; } /* Reinitialise the MAC to pick up new PHY settings, even if the port is @@ -612,9 +581,10 @@ void efx_reconfigure_port(struct efx_nic *efx) /* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all() * we don't efx_reconfigure_port() if the port is disabled. Care is taken * in efx_stop_all() and efx_start_port() to prevent PHY events being lost */ -static void efx_phy_work(struct work_struct *data) +static void efx_reconfigure_work(struct work_struct *data) { - struct efx_nic *efx = container_of(data, struct efx_nic, phy_work); + struct efx_nic *efx = container_of(data, struct efx_nic, + reconfigure_work); mutex_lock(&efx->mac_lock); if (efx->port_enabled) @@ -622,16 +592,6 @@ static void efx_phy_work(struct work_struct *data) mutex_unlock(&efx->mac_lock); } -static void efx_mac_work(struct work_struct *data) -{ - struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); - - mutex_lock(&efx->mac_lock); - if (efx->port_enabled) - efx->mac_op->irq(efx); - mutex_unlock(&efx->mac_lock); -} - static int efx_probe_port(struct efx_nic *efx) { int rc; @@ -643,9 +603,6 @@ static int efx_probe_port(struct efx_nic *efx) if (rc) goto err; - if (phy_flash_cfg) - efx->phy_mode = PHY_MODE_SPECIAL; - /* Sanity check MAC address */ if (is_valid_ether_addr(efx->mac_address)) { memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN); @@ -674,30 +631,23 @@ static int efx_init_port(struct efx_nic *efx) EFX_LOG(efx, "init port\n"); - rc = efx->phy_op->init(efx); + /* Initialise the MAC and PHY */ + rc = falcon_init_xmac(efx); if (rc) return rc; - efx->phy_op->reconfigure(efx); - - mutex_lock(&efx->mac_lock); - rc = falcon_switch_mac(efx); - mutex_unlock(&efx->mac_lock); - if (rc) - goto fail; - efx->mac_op->reconfigure(efx); efx->port_initialized = true; efx->stats_enabled = true; - return 0; -fail: - efx->phy_op->fini(efx); - return rc; + /* Reconfigure port to program MAC registers */ + falcon_reconfigure_xmac(efx); + + return 0; } /* Allow efx_reconfigure_port() to be scheduled, and close the window * between efx_stop_port and efx_flush_all whereby a previously scheduled - * efx_phy_work()/efx_mac_work() may have been cancelled */ + * efx_reconfigure_port() may have been cancelled */ static void efx_start_port(struct efx_nic *efx) { EFX_LOG(efx, "start port\n"); @@ -706,14 +656,13 @@ static void efx_start_port(struct efx_nic *efx) mutex_lock(&efx->mac_lock); efx->port_enabled = true; __efx_reconfigure_port(efx); - efx->mac_op->irq(efx); mutex_unlock(&efx->mac_lock); } -/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing, - * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work - * and efx_mac_work may still be scheduled via NAPI processing until - * efx_flush_all() is called */ +/* Prevent efx_reconfigure_work and efx_monitor() from executing, and + * efx_set_multicast_list() from scheduling efx_reconfigure_work. + * efx_reconfigure_work can still be scheduled via NAPI processing + * until efx_flush_all() is called */ static void efx_stop_port(struct efx_nic *efx) { EFX_LOG(efx, "stop port\n"); @@ -736,7 +685,7 @@ static void efx_fini_port(struct efx_nic *efx) if (!efx->port_initialized) return; - efx->phy_op->fini(efx); + falcon_fini_xmac(efx); efx->port_initialized = false; efx->link_up = false; @@ -884,33 +833,26 @@ static void efx_probe_interrupts(struct efx_nic *efx) if (efx->interrupt_mode == EFX_INT_MODE_MSIX) { struct msix_entry xentries[EFX_MAX_CHANNELS]; int wanted_ints; - int rx_queues; /* We want one RX queue and interrupt per CPU package * (or as specified by the rss_cpus module parameter). * We will need one channel per interrupt. */ - rx_queues = rss_cpus ? rss_cpus : efx_wanted_rx_queues(); - wanted_ints = rx_queues + (separate_tx_channels ? 1 : 0); - wanted_ints = min(wanted_ints, max_channels); + wanted_ints = rss_cpus ? rss_cpus : efx_wanted_rx_queues(); + efx->n_rx_queues = min(wanted_ints, max_channels); - for (i = 0; i < wanted_ints; i++) + for (i = 0; i < efx->n_rx_queues; i++) xentries[i].entry = i; - rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints); + rc = pci_enable_msix(efx->pci_dev, xentries, efx->n_rx_queues); if (rc > 0) { - EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors" - " available (%d < %d).\n", rc, wanted_ints); - EFX_ERR(efx, "WARNING: Performance may be reduced.\n"); - EFX_BUG_ON_PARANOID(rc >= wanted_ints); - wanted_ints = rc; + EFX_BUG_ON_PARANOID(rc >= efx->n_rx_queues); + efx->n_rx_queues = rc; rc = pci_enable_msix(efx->pci_dev, xentries, - wanted_ints); + efx->n_rx_queues); } if (rc == 0) { - efx->n_rx_queues = min(rx_queues, wanted_ints); - efx->n_channels = wanted_ints; - for (i = 0; i < wanted_ints; i++) + for (i = 0; i < efx->n_rx_queues; i++) efx->channel[i].irq = xentries[i].vector; } else { /* Fall back to single channel MSI */ @@ -922,7 +864,6 @@ static void efx_probe_interrupts(struct efx_nic *efx) /* Try single interrupt MSI */ if (efx->interrupt_mode == EFX_INT_MODE_MSI) { efx->n_rx_queues = 1; - efx->n_channels = 1; rc = pci_enable_msi(efx->pci_dev); if (rc == 0) { efx->channel[0].irq = efx->pci_dev->irq; @@ -935,7 +876,6 @@ static void efx_probe_interrupts(struct efx_nic *efx) /* Assume legacy interrupts */ if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) { efx->n_rx_queues = 1; - efx->n_channels = 1 + (separate_tx_channels ? 1 : 0); efx->legacy_irq = efx->pci_dev->irq; } } @@ -960,8 +900,8 @@ static void efx_set_channels(struct efx_nic *efx) struct efx_rx_queue *rx_queue; efx_for_each_tx_queue(tx_queue, efx) { - if (separate_tx_channels) - tx_queue->channel = &efx->channel[efx->n_channels-1]; + if (!EFX_INT_MODE_USE_MSI(efx) && separate_tx_and_rx_channels) + tx_queue->channel = &efx->channel[1]; else tx_queue->channel = &efx->channel[0]; tx_queue->channel->used_flags |= EFX_USED_BY_TX; @@ -1038,7 +978,6 @@ static int efx_probe_all(struct efx_nic *efx) goto fail3; } } - efx_set_channel_names(efx); return 0; @@ -1104,8 +1043,7 @@ static void efx_flush_all(struct efx_nic *efx) cancel_delayed_work_sync(&rx_queue->work); /* Stop scheduled port reconfigurations */ - cancel_work_sync(&efx->mac_work); - cancel_work_sync(&efx->phy_work); + cancel_work_sync(&efx->reconfigure_work); } @@ -1142,7 +1080,7 @@ static void efx_stop_all(struct efx_nic *efx) * window to loose phy events */ efx_stop_port(efx); - /* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */ + /* Flush reconfigure_work, refill_workqueue, monitor_work */ efx_flush_all(efx); /* Isolate the MAC from the TX and RX engines, so that queue @@ -1214,31 +1152,25 @@ static void efx_monitor(struct work_struct *data) { struct efx_nic *efx = container_of(data, struct efx_nic, monitor_work.work); - int rc; + int rc = 0; EFX_TRACE(efx, "hardware monitor executing on CPU %d\n", raw_smp_processor_id()); + /* If the mac_lock is already held then it is likely a port * reconfiguration is already in place, which will likely do * most of the work of check_hw() anyway. */ - if (!mutex_trylock(&efx->mac_lock)) - goto out_requeue; - if (!efx->port_enabled) - goto out_unlock; - rc = efx->board_info.monitor(efx); - if (rc) { - EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", - (rc == -ERANGE) ? "reported fault" : "failed"); - efx->phy_mode |= PHY_MODE_LOW_POWER; - falcon_sim_phy_event(efx); + if (!mutex_trylock(&efx->mac_lock)) { + queue_delayed_work(efx->workqueue, &efx->monitor_work, + efx_monitor_interval); + return; } - efx->phy_op->poll(efx); - efx->mac_op->poll(efx); -out_unlock: + if (efx->port_enabled) + rc = falcon_check_xmac(efx); mutex_unlock(&efx->mac_lock); -out_requeue: + queue_delayed_work(efx->workqueue, &efx->monitor_work, efx_monitor_interval); } @@ -1372,7 +1304,7 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) if (!spin_trylock(&efx->stats_lock)) return stats; if (efx->stats_enabled) { - efx->mac_op->update_stats(efx); + falcon_update_stats_xmac(efx); falcon_update_nic_stats(efx); } spin_unlock(&efx->stats_lock); @@ -1495,7 +1427,7 @@ static void efx_set_multicast_list(struct net_device *net_dev) return; if (changed) - queue_work(efx->workqueue, &efx->phy_work); + queue_work(efx->workqueue, &efx->reconfigure_work); /* Create and activate new global multicast hash table */ falcon_set_multicast_hash(efx); @@ -1517,21 +1449,17 @@ static const struct net_device_ops efx_netdev_ops = { #endif }; -static void efx_update_name(struct efx_nic *efx) -{ - strcpy(efx->name, efx->net_dev->name); - efx_mtd_rename(efx); - efx_set_channel_names(efx); -} - static int efx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct net_device *net_dev = ptr; - if (net_dev->netdev_ops == &efx_netdev_ops && - event == NETDEV_CHANGENAME) - efx_update_name(netdev_priv(net_dev)); + if (net_dev->netdev_ops == &efx_netdev_ops && event == NETDEV_CHANGENAME) { + struct efx_nic *efx = netdev_priv(net_dev); + + strcpy(efx->name, net_dev->name); + efx_mtd_rename(efx); + } return NOTIFY_DONE; } @@ -1540,14 +1468,6 @@ static struct notifier_block efx_netdev_notifier = { .notifier_call = efx_netdev_event, }; -static ssize_t -show_phy_type(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - return sprintf(buf, "%d\n", efx->phy_type); -} -static DEVICE_ATTR(phy_type, 0644, show_phy_type, NULL); - static int efx_register_netdev(struct efx_nic *efx) { struct net_device *net_dev = efx->net_dev; @@ -1563,7 +1483,7 @@ static int efx_register_netdev(struct efx_nic *efx) netif_carrier_off(efx->net_dev); /* Clear MAC statistics */ - efx->mac_op->update_stats(efx); + falcon_update_stats_xmac(efx); memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); rc = register_netdev(net_dev); @@ -1571,22 +1491,9 @@ static int efx_register_netdev(struct efx_nic *efx) EFX_ERR(efx, "could not register net dev\n"); return rc; } - - rtnl_lock(); - efx_update_name(efx); - rtnl_unlock(); - - rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type); - if (rc) { - EFX_ERR(efx, "failed to init net dev attributes\n"); - goto fail_registered; - } + strcpy(efx->name, net_dev->name); return 0; - -fail_registered: - unregister_netdev(net_dev); - return rc; } static void efx_unregister_netdev(struct efx_nic *efx) @@ -1606,7 +1513,6 @@ static void efx_unregister_netdev(struct efx_nic *efx) if (efx_dev_registered(efx)) { strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name)); - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type); unregister_netdev(efx->net_dev); } } @@ -1621,6 +1527,8 @@ static void efx_unregister_netdev(struct efx_nic *efx) * before reset. */ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) { + int rc; + EFX_ASSERT_RESET_SERIALISED(efx); /* The net_dev->get_stats handler is quite slow, and will fail @@ -1633,7 +1541,9 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd) mutex_lock(&efx->mac_lock); mutex_lock(&efx->spi_lock); - efx->phy_op->get_settings(efx, ecmd); + rc = falcon_xmac_get_settings(efx, ecmd); + if (rc) + EFX_ERR(efx, "could not back up PHY settings\n"); efx_fini_channels(efx); } @@ -1658,7 +1568,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok) if (ok) { efx_init_channels(efx); - if (efx->phy_op->set_settings(efx, ecmd)) + if (falcon_xmac_set_settings(efx, ecmd)) EFX_ERR(efx, "could not restore PHY settings\n"); } @@ -1787,7 +1697,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) efx->reset_pending = method; - queue_work(reset_workqueue, &efx->reset_work); + queue_work(efx->reset_workqueue, &efx->reset_work); } /************************************************************************** @@ -1821,16 +1731,10 @@ int efx_port_dummy_op_int(struct efx_nic *efx) void efx_port_dummy_op_void(struct efx_nic *efx) {} void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {} -static struct efx_mac_operations efx_dummy_mac_operations = { - .reconfigure = efx_port_dummy_op_void, - .poll = efx_port_dummy_op_void, - .irq = efx_port_dummy_op_void, -}; - static struct efx_phy_operations efx_dummy_phy_operations = { .init = efx_port_dummy_op_int, .reconfigure = efx_port_dummy_op_void, - .poll = efx_port_dummy_op_void, + .check_hw = efx_port_dummy_op_int, .fini = efx_port_dummy_op_void, .clear_interrupt = efx_port_dummy_op_void, }; @@ -1839,7 +1743,6 @@ static struct efx_board efx_dummy_board_info = { .init = efx_port_dummy_op_int, .init_leds = efx_port_dummy_op_int, .set_fault_led = efx_port_dummy_op_blink, - .monitor = efx_port_dummy_op_int, .blink = efx_port_dummy_op_blink, .fini = efx_port_dummy_op_void, }; @@ -1859,7 +1762,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, struct efx_channel *channel; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; - int i; + int i, rc; /* Initialise common structures */ memset(efx, 0, sizeof(*efx)); @@ -1879,11 +1782,9 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, spin_lock_init(&efx->netif_stop_lock); spin_lock_init(&efx->stats_lock); mutex_init(&efx->mac_lock); - efx->mac_op = &efx_dummy_mac_operations; efx->phy_op = &efx_dummy_phy_operations; efx->mii.dev = net_dev; - INIT_WORK(&efx->phy_work, efx_phy_work); - INIT_WORK(&efx->mac_work, efx_mac_work); + INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work); atomic_set(&efx->netif_stop_count, 1); for (i = 0; i < EFX_MAX_CHANNELS; i++) { @@ -1930,14 +1831,33 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, interrupt_mode); efx->workqueue = create_singlethread_workqueue("sfc_work"); - if (!efx->workqueue) - return -ENOMEM; + if (!efx->workqueue) { + rc = -ENOMEM; + goto fail1; + } + + efx->reset_workqueue = create_singlethread_workqueue("sfc_reset"); + if (!efx->reset_workqueue) { + rc = -ENOMEM; + goto fail2; + } return 0; + + fail2: + destroy_workqueue(efx->workqueue); + efx->workqueue = NULL; + + fail1: + return rc; } static void efx_fini_struct(struct efx_nic *efx) { + if (efx->reset_workqueue) { + destroy_workqueue(efx->reset_workqueue); + efx->reset_workqueue = NULL; + } if (efx->workqueue) { destroy_workqueue(efx->workqueue); efx->workqueue = NULL; @@ -1983,6 +1903,8 @@ static void efx_pci_remove(struct pci_dev *pci_dev) if (!efx) return; + efx_mtd_remove(efx); + /* Mark the NIC as fini, then stop the interface */ rtnl_lock(); efx->state = STATE_FINI; @@ -1996,13 +1918,11 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_unregister_netdev(efx); - efx_mtd_remove(efx); - /* Wait for any scheduled resets to complete. No more will be * scheduled from this point because efx_stop_all() has been * called, we are no longer registered with driverlink, and * the net_device's have been removed. */ - cancel_work_sync(&efx->reset_work); + flush_workqueue(efx->reset_workqueue); efx_pci_remove_main(efx); @@ -2063,7 +1983,6 @@ static int efx_pci_probe_main(struct efx_nic *efx) efx_fini_port(efx); fail5: fail4: - efx->board_info.fini(efx); fail3: efx_fini_napi(efx); fail2: @@ -2117,23 +2036,14 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, * we're in STATE_INIT. */ for (i = 0; i < 5; i++) { rc = efx_pci_probe_main(efx); + if (rc == 0) + break; /* Serialise against efx_reset(). No more resets will be * scheduled since efx_stop_all() has been called, and we * have not and never have been registered with either * the rtnetlink or driverlink layers. */ - cancel_work_sync(&efx->reset_work); - - if (rc == 0) { - if (efx->reset_pending != RESET_TYPE_NONE) { - /* If there was a scheduled reset during - * probe, the NIC is probably hosed anyway */ - efx_pci_remove_main(efx); - rc = -EIO; - } else { - break; - } - } + flush_workqueue(efx->reset_workqueue); /* Retry if a recoverably reset event has been scheduled */ if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && @@ -2151,15 +2061,17 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, /* Switch to the running state before we expose the device to * the OS. This is to ensure that the initial gathering of * MAC stats succeeds. */ + rtnl_lock(); efx->state = STATE_RUNNING; - - efx_mtd_probe(efx); /* allowed to fail */ + rtnl_unlock(); rc = efx_register_netdev(efx); if (rc) goto fail5; EFX_LOG(efx, "initialisation successful\n"); + + efx_mtd_probe(efx); /* allowed to fail */ return 0; fail5: @@ -2207,11 +2119,6 @@ static int __init efx_init_module(void) rc = -ENOMEM; goto err_refill; } - reset_workqueue = create_singlethread_workqueue("sfc_reset"); - if (!reset_workqueue) { - rc = -ENOMEM; - goto err_reset; - } rc = pci_register_driver(&efx_pci_driver); if (rc < 0) @@ -2220,8 +2127,6 @@ static int __init efx_init_module(void) return 0; err_pci: - destroy_workqueue(reset_workqueue); - err_reset: destroy_workqueue(refill_workqueue); err_refill: unregister_netdevice_notifier(&efx_netdev_notifier); @@ -2234,7 +2139,6 @@ static void __exit efx_exit_module(void) printk(KERN_INFO "Solarflare NET driver unloading\n"); pci_unregister_driver(&efx_pci_driver); - destroy_workqueue(reset_workqueue); destroy_workqueue(refill_workqueue); unregister_netdevice_notifier(&efx_netdev_notifier); diff --git a/trunk/drivers/net/sfc/enum.h b/trunk/drivers/net/sfc/enum.h index 60cbc6e1e66b..41e758e8fdb1 100644 --- a/trunk/drivers/net/sfc/enum.h +++ b/trunk/drivers/net/sfc/enum.h @@ -1,6 +1,6 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 Solarflare Communications Inc. + * Copyright 2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -13,24 +13,22 @@ /** * enum efx_loopback_mode - loopback modes * @LOOPBACK_NONE: no loopback - * @LOOPBACK_GMAC: loopback within GMAC at unspecified level - * @LOOPBACK_XGMII: loopback within XMAC at XGMII level - * @LOOPBACK_XGXS: loopback within XMAC at XGXS level - * @LOOPBACK_XAUI: loopback within XMAC at XAUI level - * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level - * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level - * @LOOPBACK_PCS: loopback within 10G PHY at PCS level - * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level + * @LOOPBACK_XGMII: loopback within MAC at XGMII level + * @LOOPBACK_XGXS: loopback within MAC at XGXS level + * @LOOPBACK_XAUI: loopback within MAC at XAUI level + * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level + * @LOOPBACK_PCS: loopback within PHY at PCS level + * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!) */ /* Please keep in order and up-to-date w.r.t the following two #defines */ enum efx_loopback_mode { LOOPBACK_NONE = 0, - LOOPBACK_GMAC = 1, + LOOPBACK_MAC = 1, LOOPBACK_XGMII = 2, LOOPBACK_XGXS = 3, LOOPBACK_XAUI = 4, - LOOPBACK_GPHY = 5, + LOOPBACK_PHY = 5, LOOPBACK_PHYXS = 6, LOOPBACK_PCS = 7, LOOPBACK_PMAPMD = 8, @@ -47,19 +45,15 @@ extern const char *efx_loopback_mode_names[]; LOOPBACK_MODE_NAME(efx->loopback_mode) /* These loopbacks occur within the controller */ -#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_GMAC) | \ - (1 << LOOPBACK_XGMII)| \ - (1 << LOOPBACK_XGXS) | \ - (1 << LOOPBACK_XAUI)) +#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \ + (1 << LOOPBACK_XGXS) | \ + (1 << LOOPBACK_XAUI)) #define LOOPBACK_MASK(_efx) \ (1 << (_efx)->loopback_mode) #define LOOPBACK_INTERNAL(_efx) \ - (!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx))) - -#define LOOPBACK_CHANGED(_from, _to, _mask) \ - (!!((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & (_mask))) + (!!(LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx))) #define LOOPBACK_OUT_OF(_from, _to, _mask) \ ((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask))) diff --git a/trunk/drivers/net/sfc/ethtool.c b/trunk/drivers/net/sfc/ethtool.c index 3aaece6b12cc..cd92c4d8dbc5 100644 --- a/trunk/drivers/net/sfc/ethtool.c +++ b/trunk/drivers/net/sfc/ethtool.c @@ -12,24 +12,24 @@ #include #include #include "net_driver.h" -#include "workarounds.h" #include "selftest.h" #include "efx.h" #include "ethtool.h" #include "falcon.h" +#include "gmii.h" #include "spi.h" -#include "mdio_10g.h" +#include "mac.h" const char *efx_loopback_mode_names[] = { [LOOPBACK_NONE] = "NONE", - [LOOPBACK_GMAC] = "GMAC", + [LOOPBACK_MAC] = "MAC", [LOOPBACK_XGMII] = "XGMII", [LOOPBACK_XGXS] = "XGXS", [LOOPBACK_XAUI] = "XAUI", - [LOOPBACK_GPHY] = "GPHY", - [LOOPBACK_PHYXS] = "PHYXS", - [LOOPBACK_PCS] = "PCS", - [LOOPBACK_PMAPMD] = "PMA/PMD", + [LOOPBACK_PHY] = "PHY", + [LOOPBACK_PHYXS] = "PHY(XS)", + [LOOPBACK_PCS] = "PHY(PCS)", + [LOOPBACK_PMAPMD] = "PHY(PMAPMD)", [LOOPBACK_NETWORK] = "NETWORK", }; @@ -182,16 +182,12 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { */ /* Identify device by flashing LEDs */ -static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count) +static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds) { struct efx_nic *efx = netdev_priv(net_dev); efx->board_info.blink(efx, 1); - set_current_state(TASK_INTERRUPTIBLE); - if (count) - schedule_timeout(count * HZ); - else - schedule(); + schedule_timeout_interruptible(seconds * HZ); efx->board_info.blink(efx, 0); return 0; } @@ -201,15 +197,13 @@ int efx_ethtool_get_settings(struct net_device *net_dev, struct ethtool_cmd *ecmd) { struct efx_nic *efx = netdev_priv(net_dev); + int rc; mutex_lock(&efx->mac_lock); - efx->phy_op->get_settings(efx, ecmd); + rc = falcon_xmac_get_settings(efx, ecmd); mutex_unlock(&efx->mac_lock); - /* Falcon GMAC does not support 1000Mbps HD */ - ecmd->supported &= ~SUPPORTED_1000baseT_Half; - - return 0; + return rc; } /* This must be called with rtnl_lock held. */ @@ -219,18 +213,8 @@ int efx_ethtool_set_settings(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); int rc; - if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg) - return -EINVAL; - - /* Falcon GMAC does not support 1000Mbps HD */ - if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { - EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" - " setting\n"); - return -EINVAL; - } - mutex_lock(&efx->mac_lock); - rc = efx->phy_op->set_settings(efx, ecmd); + rc = falcon_xmac_set_settings(efx, ecmd); mutex_unlock(&efx->mac_lock); if (!rc) efx_reconfigure_port(efx); @@ -254,10 +238,10 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev, * @strings: Ethtool strings, or %NULL * @data: Ethtool test results, or %NULL * @test: Pointer to test result (used only if data != %NULL) - * @unit_format: Unit name format (e.g. "chan\%d") - * @unit_id: Unit id (e.g. 0 for "chan0") + * @unit_format: Unit name format (e.g. "channel\%d") + * @unit_id: Unit id (e.g. 0 for "channel0") * @test_format: Test name format (e.g. "loopback.\%s.tx.sent") - * @test_id: Test id (e.g. "PHYXS" for "loopback.PHYXS.tx_sent") + * @test_id: Test id (e.g. "PHY" for "loopback.PHY.tx_sent") * * Fill in an individual self-test entry. */ @@ -274,20 +258,18 @@ static void efx_fill_test(unsigned int test_index, /* Fill string, if applicable */ if (strings) { - if (strchr(unit_format, '%')) - snprintf(unit_str.name, sizeof(unit_str.name), - unit_format, unit_id); - else - strcpy(unit_str.name, unit_format); + snprintf(unit_str.name, sizeof(unit_str.name), + unit_format, unit_id); snprintf(test_str.name, sizeof(test_str.name), test_format, test_id); snprintf(strings[test_index].name, sizeof(strings[test_index].name), - "%-6s %-24s", unit_str.name, test_str.name); + "%-9s%-17s", unit_str.name, test_str.name); } } -#define EFX_CHANNEL_NAME(_channel) "chan%d", _channel->channel +#define EFX_PORT_NAME "port%d", 0 +#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel #define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue #define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue #define EFX_LOOPBACK_NAME(_mode, _counter) \ @@ -322,11 +304,11 @@ static int efx_fill_loopback_test(struct efx_nic *efx, } efx_fill_test(test_index++, strings, data, &lb_tests->rx_good, - "rx", 0, + EFX_PORT_NAME, EFX_LOOPBACK_NAME(mode, "rx_good")); efx_fill_test(test_index++, strings, data, &lb_tests->rx_bad, - "rx", 0, + EFX_PORT_NAME, EFX_LOOPBACK_NAME(mode, "rx_bad")); return test_index; @@ -374,9 +356,13 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, efx_fill_test(n++, strings, data, &tests->registers, "core", 0, "registers", NULL); efx_fill_test(n++, strings, data, &tests->phy, - "phy", 0, "bist", NULL); + EFX_PORT_NAME, "phy", NULL); /* Loopback tests */ + efx_fill_test(n++, strings, data, &tests->loopback_speed, + EFX_PORT_NAME, "loopback.speed", NULL); + efx_fill_test(n++, strings, data, &tests->loopback_full_duplex, + EFX_PORT_NAME, "loopback.full_duplex", NULL); for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) { if (!(efx->loopback_modes & (1 << mode))) continue; @@ -568,13 +554,10 @@ static int efx_ethtool_get_eeprom(struct net_device *net_dev, size_t len; int rc; - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; + mutex_lock(&efx->spi_lock); rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, eeprom->len, &len, buf); mutex_unlock(&efx->spi_lock); - eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC; eeprom->len = len; return rc; @@ -591,13 +574,10 @@ static int efx_ethtool_set_eeprom(struct net_device *net_dev, if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC) return -EINVAL; - rc = mutex_lock_interruptible(&efx->spi_lock); - if (rc) - return rc; + mutex_lock(&efx->spi_lock); rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START, eeprom->len, &len, buf); mutex_unlock(&efx->spi_lock); - eeprom->len = len; return rc; } @@ -687,52 +667,23 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, struct ethtool_pauseparam *pause) { struct efx_nic *efx = netdev_priv(net_dev); - enum efx_fc_type wanted_fc; - bool reset; - - wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) | - (pause->tx_pause ? EFX_FC_TX : 0) | - (pause->autoneg ? EFX_FC_AUTO : 0)); - - if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) { - EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n"); - return -EINVAL; - } - - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) && - (wanted_fc & EFX_FC_AUTO)) { - EFX_LOG(efx, "PHY does not support flow control " - "autonegotiation\n"); - return -EINVAL; - } + enum efx_fc_type flow_control = efx->flow_control; + int rc; - /* TX flow control may automatically turn itself off if the - * link partner (intermittently) stops responding to pause - * frames. There isn't any indication that this has happened, - * so the best we do is leave it up to the user to spot this - * and fix it be cycling transmit flow control on this end. */ - reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX); - if (EFX_WORKAROUND_11482(efx) && reset) { - if (falcon_rev(efx) >= FALCON_REV_B0) { - /* Recover by resetting the EM block */ - if (efx->link_up) - falcon_drain_tx_fifo(efx); - } else { - /* Schedule a reset to recover */ - efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); - } - } + flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO); + flow_control |= pause->rx_pause ? EFX_FC_RX : 0; + flow_control |= pause->tx_pause ? EFX_FC_TX : 0; + flow_control |= pause->autoneg ? EFX_FC_AUTO : 0; /* Try to push the pause parameters */ mutex_lock(&efx->mac_lock); - - efx->wanted_fc = wanted_fc; - mdio_clause45_set_pause(efx); - __efx_reconfigure_port(efx); - + rc = falcon_xmac_set_pause(efx, flow_control); mutex_unlock(&efx->mac_lock); - return 0; + if (!rc) + efx_reconfigure_port(efx); + + return rc; } static void efx_ethtool_get_pauseparam(struct net_device *net_dev, @@ -740,9 +691,9 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev, { struct efx_nic *efx = netdev_priv(net_dev); - pause->rx_pause = !!(efx->wanted_fc & EFX_FC_RX); - pause->tx_pause = !!(efx->wanted_fc & EFX_FC_TX); - pause->autoneg = !!(efx->wanted_fc & EFX_FC_AUTO); + pause->rx_pause = !!(efx->flow_control & EFX_FC_RX); + pause->tx_pause = !!(efx->flow_control & EFX_FC_TX); + pause->autoneg = !!(efx->flow_control & EFX_FC_AUTO); } diff --git a/trunk/drivers/net/sfc/falcon.c b/trunk/drivers/net/sfc/falcon.c index 6884dc8c1f82..71e0bed60616 100644 --- a/trunk/drivers/net/sfc/falcon.c +++ b/trunk/drivers/net/sfc/falcon.c @@ -15,11 +15,11 @@ #include #include #include -#include #include "net_driver.h" #include "bitfield.h" #include "efx.h" #include "mac.h" +#include "gmii.h" #include "spi.h" #include "falcon.h" #include "falcon_hwdefs.h" @@ -70,20 +70,6 @@ static int disable_dma_stats; #define RX_DC_ENTRIES_ORDER 2 #define RX_DC_BASE 0x100000 -static const unsigned int -/* "Large" EEPROM device: Atmel AT25640 or similar - * 8 KB, 16-bit address, 32 B write block */ -large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN) - | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN) - | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)), -/* Default flash device: Atmel AT25F1024 - * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */ -default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN) - | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN) - | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN) - | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN) - | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)); - /* RX FIFO XOFF watermark * * When the amount of the RX FIFO increases used increases past this @@ -784,18 +770,15 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue, rx_ev_buf_owner_id_err | rx_ev_eth_crc_err | rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err); - /* Count errors that are not in MAC stats. Ignore expected - * checksum errors during self-test. */ + /* Count errors that are not in MAC stats. */ if (rx_ev_frm_trunc) ++rx_queue->channel->n_rx_frm_trunc; else if (rx_ev_tobe_disc) ++rx_queue->channel->n_rx_tobe_disc; - else if (!efx->loopback_selftest) { - if (rx_ev_ip_hdr_chksum_err) - ++rx_queue->channel->n_rx_ip_hdr_chksum_err; - else if (rx_ev_tcp_udp_chksum_err) - ++rx_queue->channel->n_rx_tcp_udp_chksum_err; - } + else if (rx_ev_ip_hdr_chksum_err) + ++rx_queue->channel->n_rx_ip_hdr_chksum_err; + else if (rx_ev_tcp_udp_chksum_err) + ++rx_queue->channel->n_rx_tcp_udp_chksum_err; if (rx_ev_ip_frag_err) ++rx_queue->channel->n_rx_ip_frag_err; @@ -826,7 +809,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue, #endif if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) && - efx->phy_type == PHY_TYPE_SFX7101)) + efx->phy_type == PHY_TYPE_10XPRESS)) tenxpress_crc_err(efx); } @@ -910,20 +893,22 @@ static void falcon_handle_global_event(struct efx_channel *channel, efx_qword_t *event) { struct efx_nic *efx = channel->efx; - bool handled = false; + bool is_phy_event = false, handled = false; + /* Check for interrupt on either port. Some boards have a + * single PHY wired to the interrupt line for port 1. */ if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) || EFX_QWORD_FIELD(*event, G_PHY1_INTR) || - EFX_QWORD_FIELD(*event, XG_PHY_INTR) || - EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) { - efx->phy_op->clear_interrupt(efx); - queue_work(efx->workqueue, &efx->phy_work); - handled = true; - } + EFX_QWORD_FIELD(*event, XG_PHY_INTR)) + is_phy_event = true; if ((falcon_rev(efx) >= FALCON_REV_B0) && - EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) { - queue_work(efx->workqueue, &efx->mac_work); + EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) + is_phy_event = true; + + if (is_phy_event) { + efx->phy_op->clear_interrupt(efx); + queue_work(efx->workqueue, &efx->reconfigure_work); handled = true; } @@ -1166,19 +1151,6 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic) falcon_generate_event(channel, &test_event); } -void falcon_sim_phy_event(struct efx_nic *efx) -{ - efx_qword_t phy_event; - - EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE); - if (EFX_IS10G(efx)) - EFX_SET_OWORD_FIELD(phy_event, XG_PHY_INTR, 1); - else - EFX_SET_OWORD_FIELD(phy_event, G_PHY0_INTR, 1); - - falcon_generate_event(&efx->channel[0], &phy_event); -} - /************************************************************************** * * Flush handling @@ -1588,7 +1560,7 @@ int falcon_init_interrupt(struct efx_nic *efx) efx_for_each_channel(channel, efx) { rc = request_irq(channel->irq, falcon_msi_interrupt, IRQF_PROBE_SHARED, /* Not shared */ - channel->name, channel); + efx->name, channel); if (rc) { EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq); goto fail2; @@ -1633,45 +1605,32 @@ void falcon_fini_interrupt(struct efx_nic *efx) ************************************************************************** */ -#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t) - -static int falcon_spi_poll(struct efx_nic *efx) -{ - efx_oword_t reg; - falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); - return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0; -} +#define FALCON_SPI_MAX_LEN ((unsigned) sizeof(efx_oword_t)) /* Wait for SPI command completion */ static int falcon_spi_wait(struct efx_nic *efx) { - /* Most commands will finish quickly, so we start polling at - * very short intervals. Sometimes the command may have to - * wait for VPD or expansion ROM access outside of our - * control, so we allow up to 100 ms. */ - unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10); - int i; - - for (i = 0; i < 10; i++) { - if (!falcon_spi_poll(efx)) - return 0; - udelay(10); - } + unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10); + efx_oword_t reg; + bool cmd_en, timer_active; for (;;) { - if (!falcon_spi_poll(efx)) + falcon_read(efx, ®, EE_SPI_HCMD_REG_KER); + cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN); + timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE); + if (!cmd_en && !timer_active) return 0; if (time_after_eq(jiffies, timeout)) { EFX_ERR(efx, "timed out waiting for SPI\n"); return -ETIMEDOUT; } - schedule_timeout_uninterruptible(1); + cpu_relax(); } } int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command, int address, - const void *in, void *out, size_t len) + const void *in, void *out, unsigned int len) { struct efx_nic *efx = spi->efx; bool addressed = (address >= 0); @@ -1684,8 +1643,8 @@ int falcon_spi_cmd(const struct efx_spi_device *spi, return -EINVAL; BUG_ON(!mutex_is_locked(&efx->spi_lock)); - /* Check that previous command is not still running */ - rc = falcon_spi_poll(efx); + /* Check SPI not currently being accessed */ + rc = falcon_spi_wait(efx); if (rc) return rc; @@ -1727,8 +1686,8 @@ int falcon_spi_cmd(const struct efx_spi_device *spi, return 0; } -static size_t -falcon_spi_write_limit(const struct efx_spi_device *spi, size_t start) +static unsigned int +falcon_spi_write_limit(const struct efx_spi_device *spi, unsigned int start) { return min(FALCON_SPI_MAX_LEN, (spi->block_size - (start & (spi->block_size - 1)))); @@ -1741,40 +1700,37 @@ efx_spi_munge_command(const struct efx_spi_device *spi, return command | (((address >> 8) & spi->munge_address) << 3); } -/* Wait up to 10 ms for buffered write completion */ -int falcon_spi_wait_write(const struct efx_spi_device *spi) +int falcon_spi_fast_wait(const struct efx_spi_device *spi) { - struct efx_nic *efx = spi->efx; - unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100); u8 status; - int rc; + int i, rc; + + /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */ + for (i = 0; i < 50; i++) { + udelay(20); - for (;;) { rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status)); if (rc) return rc; if (!(status & SPI_STATUS_NRDY)) return 0; - if (time_after_eq(jiffies, timeout)) { - EFX_ERR(efx, "SPI write timeout on device %d" - " last status=0x%02x\n", - spi->device_id, status); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); } + EFX_ERR(spi->efx, + "timed out waiting for device %d last status=0x%02x\n", + spi->device_id, status); + return -ETIMEDOUT; } int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, size_t len, size_t *retlen, u8 *buffer) { - size_t block_len, pos = 0; - unsigned int command; + unsigned int command, block_len, pos = 0; int rc = 0; while (pos < len) { - block_len = min(len - pos, FALCON_SPI_MAX_LEN); + block_len = min((unsigned int)len - pos, + FALCON_SPI_MAX_LEN); command = efx_spi_munge_command(spi, SPI_READ, start + pos); rc = falcon_spi_cmd(spi, command, start + pos, NULL, @@ -1800,8 +1756,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, size_t len, size_t *retlen, const u8 *buffer) { u8 verify_buffer[FALCON_SPI_MAX_LEN]; - size_t block_len, pos = 0; - unsigned int command; + unsigned int command, block_len, pos = 0; int rc = 0; while (pos < len) { @@ -1809,7 +1764,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, if (rc) break; - block_len = min(len - pos, + block_len = min((unsigned int)len - pos, falcon_spi_write_limit(spi, start + pos)); command = efx_spi_munge_command(spi, SPI_WRITE, start + pos); rc = falcon_spi_cmd(spi, command, start + pos, @@ -1817,7 +1772,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, if (rc) break; - rc = falcon_spi_wait_write(spi); + rc = falcon_spi_fast_wait(spi); if (rc) break; @@ -1850,61 +1805,40 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, * ************************************************************************** */ - -static int falcon_reset_macs(struct efx_nic *efx) +void falcon_drain_tx_fifo(struct efx_nic *efx) { - efx_oword_t reg; + efx_oword_t temp; int count; - if (falcon_rev(efx) < FALCON_REV_B0) { - /* It's not safe to use GLB_CTL_REG to reset the - * macs, so instead use the internal MAC resets - */ - if (!EFX_IS10G(efx)) { - EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1); - falcon_write(efx, ®, GM_CFG1_REG); - udelay(1000); - - EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0); - falcon_write(efx, ®, GM_CFG1_REG); - udelay(1000); - return 0; - } else { - EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1); - falcon_write(efx, ®, XM_GLB_CFG_REG); - - for (count = 0; count < 10000; count++) { - falcon_read(efx, ®, XM_GLB_CFG_REG); - if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0) - return 0; - udelay(10); - } + if ((falcon_rev(efx) < FALCON_REV_B0) || + (efx->loopback_mode != LOOPBACK_NONE)) + return; - EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); - return -ETIMEDOUT; - } - } + falcon_read(efx, &temp, MAC0_CTRL_REG_KER); + /* There is no point in draining more than once */ + if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0)) + return; /* MAC stats will fail whilst the TX fifo is draining. Serialise * the drain sequence with the statistics fetch */ spin_lock(&efx->stats_lock); - falcon_read(efx, ®, MAC0_CTRL_REG_KER); - EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1); - falcon_write(efx, ®, MAC0_CTRL_REG_KER); + EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1); + falcon_write(efx, &temp, MAC0_CTRL_REG_KER); - falcon_read(efx, ®, GLB_CTL_REG_KER); - EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1); - EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1); - EFX_SET_OWORD_FIELD(reg, RST_EM, 1); - falcon_write(efx, ®, GLB_CTL_REG_KER); + /* Reset the MAC and EM block. */ + falcon_read(efx, &temp, GLB_CTL_REG_KER); + EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1); + EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1); + EFX_SET_OWORD_FIELD(temp, RST_EM, 1); + falcon_write(efx, &temp, GLB_CTL_REG_KER); count = 0; while (1) { - falcon_read(efx, ®, GLB_CTL_REG_KER); - if (!EFX_OWORD_FIELD(reg, RST_XGTX) && - !EFX_OWORD_FIELD(reg, RST_XGRX) && - !EFX_OWORD_FIELD(reg, RST_EM)) { + falcon_read(efx, &temp, GLB_CTL_REG_KER); + if (!EFX_OWORD_FIELD(temp, RST_XGTX) && + !EFX_OWORD_FIELD(temp, RST_XGRX) && + !EFX_OWORD_FIELD(temp, RST_EM)) { EFX_LOG(efx, "Completed MAC reset after %d loops\n", count); break; @@ -1921,39 +1855,21 @@ static int falcon_reset_macs(struct efx_nic *efx) /* If we've reset the EM block and the link is up, then * we'll have to kick the XAUI link so the PHY can recover */ - if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx)) + if (efx->link_up && EFX_WORKAROUND_5147(efx)) falcon_reset_xaui(efx); - - return 0; -} - -void falcon_drain_tx_fifo(struct efx_nic *efx) -{ - efx_oword_t reg; - - if ((falcon_rev(efx) < FALCON_REV_B0) || - (efx->loopback_mode != LOOPBACK_NONE)) - return; - - falcon_read(efx, ®, MAC0_CTRL_REG_KER); - /* There is no point in draining more than once */ - if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0)) - return; - - falcon_reset_macs(efx); } void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) { - efx_oword_t reg; + efx_oword_t temp; if (falcon_rev(efx) < FALCON_REV_B0) return; /* Isolate the MAC -> RX */ - falcon_read(efx, ®, RX_CFG_REG_KER); - EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0); - falcon_write(efx, ®, RX_CFG_REG_KER); + falcon_read(efx, &temp, RX_CFG_REG_KER); + EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0); + falcon_write(efx, &temp, RX_CFG_REG_KER); if (!efx->link_up) falcon_drain_tx_fifo(efx); @@ -1965,12 +1881,14 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) int link_speed; bool tx_fc; - switch (efx->link_speed) { - case 10000: link_speed = 3; break; - case 1000: link_speed = 2; break; - case 100: link_speed = 1; break; - default: link_speed = 0; break; - } + if (efx->link_options & GM_LPA_10000) + link_speed = 0x3; + else if (efx->link_options & GM_LPA_1000) + link_speed = 0x2; + else if (efx->link_options & GM_LPA_100) + link_speed = 0x1; + else + link_speed = 0x0; /* MAC_LINK_STATUS controls MAC backpressure but doesn't work * as advertised. Disable to ensure packets are not * indefinitely held and TX queue can be flushed at any point @@ -1996,7 +1914,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) /* Transmission of pause frames when RX crosses the threshold is * covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL. * Action on receipt of pause frames is controller by XM_DIS_FCNTL */ - tx_fc = !!(efx->link_fc & EFX_FC_TX); + tx_fc = !!(efx->flow_control & EFX_FC_TX); falcon_read(efx, ®, RX_CFG_REG_KER); EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc); @@ -2080,8 +1998,7 @@ static int falcon_gmii_wait(struct efx_nic *efx) efx_dword_t md_stat; int count; - /* wait upto 50ms - taken max from datasheet */ - for (count = 0; count < 5000; count++) { + for (count = 0; count < 1000; count++) { /* wait upto 10ms */ falcon_readl(efx, &md_stat, MD_STAT_REG_KER); if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) { if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 || @@ -2245,14 +2162,10 @@ static void falcon_init_mdio(struct mii_if_info *gmii) static int falcon_probe_phy(struct efx_nic *efx) { switch (efx->phy_type) { - case PHY_TYPE_SFX7101: - efx->phy_op = &falcon_sfx7101_phy_ops; - break; - case PHY_TYPE_SFT9001A: - case PHY_TYPE_SFT9001B: - efx->phy_op = &falcon_sft9001_phy_ops; + case PHY_TYPE_10XPRESS: + efx->phy_op = &falcon_tenxpress_phy_ops; break; - case PHY_TYPE_QT2022C2: + case PHY_TYPE_XFP: efx->phy_op = &falcon_xfp_phy_ops; break; default: @@ -2261,59 +2174,10 @@ static int falcon_probe_phy(struct efx_nic *efx) return -1; } - if (efx->phy_op->macs & EFX_XMAC) - efx->loopback_modes |= ((1 << LOOPBACK_XGMII) | - (1 << LOOPBACK_XGXS) | - (1 << LOOPBACK_XAUI)); - if (efx->phy_op->macs & EFX_GMAC) - efx->loopback_modes |= (1 << LOOPBACK_GMAC); - efx->loopback_modes |= efx->phy_op->loopbacks; - + efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks; return 0; } -int falcon_switch_mac(struct efx_nic *efx) -{ - struct efx_mac_operations *old_mac_op = efx->mac_op; - efx_oword_t nic_stat; - unsigned strap_val; - - /* Internal loopbacks override the phy speed setting */ - if (efx->loopback_mode == LOOPBACK_GMAC) { - efx->link_speed = 1000; - efx->link_fd = true; - } else if (LOOPBACK_INTERNAL(efx)) { - efx->link_speed = 10000; - efx->link_fd = true; - } - - efx->mac_op = (EFX_IS10G(efx) ? - &falcon_xmac_operations : &falcon_gmac_operations); - if (old_mac_op == efx->mac_op) - return 0; - - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - - /* Not all macs support a mac-level link state */ - efx->mac_up = true; - - falcon_read(efx, &nic_stat, NIC_STAT_REG); - strap_val = EFX_IS10G(efx) ? 5 : 3; - if (falcon_rev(efx) >= FALCON_REV_B0) { - EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1); - EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val); - falcon_write(efx, &nic_stat, NIC_STAT_REG); - } else { - /* Falcon A1 does not support 1G/10G speed switching - * and must not be used with a PHY that does. */ - BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val); - } - - - EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G'); - return falcon_reset_macs(efx); -} - /* This call is responsible for hooking in the MAC and PHY operations */ int falcon_probe_port(struct efx_nic *efx) { @@ -2330,9 +2194,9 @@ int falcon_probe_port(struct efx_nic *efx) /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ if (falcon_rev(efx) >= FALCON_REV_B0) - efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; + efx->flow_control = EFX_FC_RX | EFX_FC_TX; else - efx->wanted_fc = EFX_FC_RX; + efx->flow_control = EFX_FC_RX; /* Allocate buffer for stats */ rc = falcon_alloc_buffer(efx, &efx->stats_buffer, @@ -2389,15 +2253,12 @@ int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out) __le16 *word, *limit; u32 csum; - spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom; - if (!spi) - return -EINVAL; - region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL); if (!region) return -ENOMEM; nvconfig = region + NVCONFIG_OFFSET; + spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom; mutex_lock(&efx->spi_lock); rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region); mutex_unlock(&efx->spi_lock); @@ -2466,10 +2327,6 @@ static struct { EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) }, { DP_CTRL_REG, EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) }, - { GM_CFG2_REG, - EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) }, - { GMF_CFG0_REG, - EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) }, { XM_GLB_CFG_REG, EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) }, { XM_TX_CFG_REG, @@ -2690,7 +2547,7 @@ static int falcon_spi_device_init(struct efx_nic *efx, struct efx_spi_device *spi_device; if (device_type != 0) { - spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL); + spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL); if (!spi_device) return -ENOMEM; spi_device->device_id = device_id; @@ -2795,7 +2652,6 @@ static int falcon_probe_nvconfig(struct efx_nic *efx) static int falcon_probe_nic_variant(struct efx_nic *efx) { efx_oword_t altera_build; - efx_oword_t nic_stat; falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER); if (EFX_OWORD_FIELD(altera_build, VER_ALL)) { @@ -2803,20 +2659,27 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) return -ENODEV; } - falcon_read(efx, &nic_stat, NIC_STAT_REG); - switch (falcon_rev(efx)) { case FALCON_REV_A0: case 0xff: EFX_ERR(efx, "Falcon rev A0 not supported\n"); return -ENODEV; - case FALCON_REV_A1: + case FALCON_REV_A1:{ + efx_oword_t nic_stat; + + falcon_read(efx, &nic_stat, NIC_STAT_REG); + if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) { EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n"); return -ENODEV; } + if (!EFX_OWORD_FIELD(nic_stat, STRAP_10G)) { + EFX_ERR(efx, "1G mode not supported\n"); + return -ENODEV; + } break; + } case FALCON_REV_B0: break; @@ -2826,9 +2689,6 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) return -ENODEV; } - /* Initial assumed speed */ - efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000; - return 0; } @@ -2836,37 +2696,80 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) static void falcon_probe_spi_devices(struct efx_nic *efx) { efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg; - int boot_dev; + bool has_flash, has_eeprom, boot_is_external; falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER); falcon_read(efx, &nic_stat, NIC_STAT_REG); falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); - if (EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE)) { - boot_dev = (EFX_OWORD_FIELD(nic_stat, SF_PRST) ? - EE_SPI_FLASH : EE_SPI_EEPROM); - EFX_LOG(efx, "Booted from %s\n", - boot_dev == EE_SPI_FLASH ? "flash" : "EEPROM"); - } else { - /* Disable VPD and set clock dividers to safe - * values for initial programming. */ - boot_dev = -1; - EFX_LOG(efx, "Booted from internal ASIC settings;" - " setting SPI config\n"); - EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0, - /* 125 MHz / 7 ~= 20 MHz */ - EE_SF_CLOCK_DIV, 7, - /* 125 MHz / 63 ~= 2 MHz */ - EE_EE_CLOCK_DIV, 63); - falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); - } - - if (boot_dev == EE_SPI_FLASH) - falcon_spi_device_init(efx, &efx->spi_flash, EE_SPI_FLASH, - default_flash_type); - if (boot_dev == EE_SPI_EEPROM) - falcon_spi_device_init(efx, &efx->spi_eeprom, EE_SPI_EEPROM, - large_eeprom_type); + has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST); + has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST); + boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE); + + if (has_flash) { + /* Default flash SPI device: Atmel AT25F1024 + * 128 KB, 24-bit address, 32 KB erase block, + * 256 B write block + */ + u32 flash_device_type = + (17 << SPI_DEV_TYPE_SIZE_LBN) + | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN) + | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN) + | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN) + | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN); + + falcon_spi_device_init(efx, &efx->spi_flash, + EE_SPI_FLASH, flash_device_type); + + if (!boot_is_external) { + /* Disable VPD and set clock dividers to safe + * values for initial programming. + */ + EFX_LOG(efx, "Booted from internal ASIC settings;" + " setting SPI config\n"); + EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0, + /* 125 MHz / 7 ~= 20 MHz */ + EE_SF_CLOCK_DIV, 7, + /* 125 MHz / 63 ~= 2 MHz */ + EE_EE_CLOCK_DIV, 63); + falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER); + } + } + + if (has_eeprom) { + u32 eeprom_device_type; + + /* If it has no flash, it must have a large EEPROM + * for chip config; otherwise check whether 9-bit + * addressing is used for VPD configuration + */ + if (has_flash && + (!boot_is_external || + EFX_OWORD_FIELD(ee_vpd_cfg, EE_VPD_EN_AD9_MODE))) { + /* Default SPI device: Atmel AT25040 or similar + * 512 B, 9-bit address, 8 B write block + */ + eeprom_device_type = + (9 << SPI_DEV_TYPE_SIZE_LBN) + | (1 << SPI_DEV_TYPE_ADDR_LEN_LBN) + | (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN); + } else { + /* "Large" SPI device: Atmel AT25640 or similar + * 8 KB, 16-bit address, 32 B write block + */ + eeprom_device_type = + (13 << SPI_DEV_TYPE_SIZE_LBN) + | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN) + | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN); + } + + falcon_spi_device_init(efx, &efx->spi_eeprom, + EE_SPI_EEPROM, eeprom_device_type); + } + + EFX_LOG(efx, "flash is %s, EEPROM is %s\n", + (has_flash ? "present" : "absent"), + (has_eeprom ? "present" : "absent")); } int falcon_probe_nic(struct efx_nic *efx) @@ -2929,10 +2832,10 @@ int falcon_probe_nic(struct efx_nic *efx) goto fail5; /* Initialise I2C adapter */ - efx->i2c_adap.owner = THIS_MODULE; + efx->i2c_adap.owner = THIS_MODULE; nic_data->i2c_data = falcon_i2c_bit_operations; nic_data->i2c_data.data = efx; - efx->i2c_adap.algo_data = &nic_data->i2c_data; + efx->i2c_adap.algo_data = &nic_data->i2c_data; efx->i2c_adap.dev.parent = &efx->pci_dev->dev; strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name)); rc = i2c_bit_add_bus(&efx->i2c_adap); @@ -2966,18 +2869,20 @@ int falcon_init_nic(struct efx_nic *efx) unsigned thresh; int rc; + /* Set up the address region register. This is only needed + * for the B0 FPGA, but since we are just pushing in the + * reset defaults this may as well be unconditional. */ + EFX_POPULATE_OWORD_4(temp, ADR_REGION0, 0, + ADR_REGION1, (1 << 16), + ADR_REGION2, (2 << 16), + ADR_REGION3, (3 << 16)); + falcon_write(efx, &temp, ADR_REGION_REG_KER); + /* Use on-chip SRAM */ falcon_read(efx, &temp, NIC_STAT_REG); EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1); falcon_write(efx, &temp, NIC_STAT_REG); - /* Set the source of the GMAC clock */ - if (falcon_rev(efx) == FALCON_REV_B0) { - falcon_read(efx, &temp, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true); - falcon_write(efx, &temp, GPIO_CTL_REG_KER); - } - /* Set buffer table mode */ EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL); falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER); diff --git a/trunk/drivers/net/sfc/falcon.h b/trunk/drivers/net/sfc/falcon.h index 7869c3d74383..be025ba7a6c6 100644 --- a/trunk/drivers/net/sfc/falcon.h +++ b/trunk/drivers/net/sfc/falcon.h @@ -12,7 +12,6 @@ #define EFX_FALCON_H #include "net_driver.h" -#include "efx.h" /* * Falcon hardware control @@ -66,7 +65,6 @@ extern int falcon_probe_port(struct efx_nic *efx); extern void falcon_remove_port(struct efx_nic *efx); /* MAC/PHY */ -extern int falcon_switch_mac(struct efx_nic *efx); extern bool falcon_xaui_link_ok(struct efx_nic *efx); extern int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset); @@ -79,7 +77,6 @@ extern int falcon_init_interrupt(struct efx_nic *efx); extern void falcon_enable_interrupts(struct efx_nic *efx); extern void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic); -extern void falcon_sim_phy_event(struct efx_nic *efx); extern void falcon_generate_interrupt(struct efx_nic *efx); extern void falcon_set_int_moderation(struct efx_channel *channel); extern void falcon_disable_interrupts(struct efx_nic *efx); diff --git a/trunk/drivers/net/sfc/falcon_gmac.c b/trunk/drivers/net/sfc/falcon_gmac.c deleted file mode 100644 index 8865eae20ac5..000000000000 --- a/trunk/drivers/net/sfc/falcon_gmac.c +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#include -#include "net_driver.h" -#include "efx.h" -#include "falcon.h" -#include "mac.h" -#include "falcon_hwdefs.h" -#include "falcon_io.h" -#include "gmii.h" - -/************************************************************************** - * - * MAC operations - * - *************************************************************************/ - -static void falcon_reconfigure_gmac(struct efx_nic *efx) -{ - bool loopback, tx_fc, rx_fc, bytemode; - int if_mode; - unsigned int max_frame_len; - efx_oword_t reg; - - /* Configuration register 1 */ - tx_fc = (efx->link_fc & EFX_FC_TX) || !efx->link_fd; - rx_fc = !!(efx->link_fc & EFX_FC_RX); - loopback = (efx->loopback_mode == LOOPBACK_GMAC); - bytemode = (efx->link_speed == 1000); - - EFX_POPULATE_OWORD_5(reg, - GM_LOOP, loopback, - GM_TX_EN, 1, - GM_TX_FC_EN, tx_fc, - GM_RX_EN, 1, - GM_RX_FC_EN, rx_fc); - falcon_write(efx, ®, GM_CFG1_REG); - udelay(10); - - /* Configuration register 2 */ - if_mode = (bytemode) ? 2 : 1; - EFX_POPULATE_OWORD_5(reg, - GM_IF_MODE, if_mode, - GM_PAD_CRC_EN, 1, - GM_LEN_CHK, 1, - GM_FD, efx->link_fd, - GM_PAMBL_LEN, 0x7/*datasheet recommended */); - - falcon_write(efx, ®, GM_CFG2_REG); - udelay(10); - - /* Max frame len register */ - max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); - EFX_POPULATE_OWORD_1(reg, GM_MAX_FLEN, max_frame_len); - falcon_write(efx, ®, GM_MAX_FLEN_REG); - udelay(10); - - /* FIFO configuration register 0 */ - EFX_POPULATE_OWORD_5(reg, - GMF_FTFENREQ, 1, - GMF_STFENREQ, 1, - GMF_FRFENREQ, 1, - GMF_SRFENREQ, 1, - GMF_WTMENREQ, 1); - falcon_write(efx, ®, GMF_CFG0_REG); - udelay(10); - - /* FIFO configuration register 1 */ - EFX_POPULATE_OWORD_2(reg, - GMF_CFGFRTH, 0x12, - GMF_CFGXOFFRTX, 0xffff); - falcon_write(efx, ®, GMF_CFG1_REG); - udelay(10); - - /* FIFO configuration register 2 */ - EFX_POPULATE_OWORD_2(reg, - GMF_CFGHWM, 0x3f, - GMF_CFGLWM, 0xa); - falcon_write(efx, ®, GMF_CFG2_REG); - udelay(10); - - /* FIFO configuration register 3 */ - EFX_POPULATE_OWORD_2(reg, - GMF_CFGHWMFT, 0x1c, - GMF_CFGFTTH, 0x08); - falcon_write(efx, ®, GMF_CFG3_REG); - udelay(10); - - /* FIFO configuration register 4 */ - EFX_POPULATE_OWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1); - falcon_write(efx, ®, GMF_CFG4_REG); - udelay(10); - - /* FIFO configuration register 5 */ - falcon_read(efx, ®, GMF_CFG5_REG); - EFX_SET_OWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode); - EFX_SET_OWORD_FIELD(reg, GMF_CFGHDPLX, !efx->link_fd); - EFX_SET_OWORD_FIELD(reg, GMF_HSTDRPLT64, !efx->link_fd); - EFX_SET_OWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0); - falcon_write(efx, ®, GMF_CFG5_REG); - udelay(10); - - /* MAC address */ - EFX_POPULATE_OWORD_4(reg, - GM_HWADDR_5, efx->net_dev->dev_addr[5], - GM_HWADDR_4, efx->net_dev->dev_addr[4], - GM_HWADDR_3, efx->net_dev->dev_addr[3], - GM_HWADDR_2, efx->net_dev->dev_addr[2]); - falcon_write(efx, ®, GM_ADR1_REG); - udelay(10); - EFX_POPULATE_OWORD_2(reg, - GM_HWADDR_1, efx->net_dev->dev_addr[1], - GM_HWADDR_0, efx->net_dev->dev_addr[0]); - falcon_write(efx, ®, GM_ADR2_REG); - udelay(10); - - falcon_reconfigure_mac_wrapper(efx); -} - -static void falcon_update_stats_gmac(struct efx_nic *efx) -{ - struct efx_mac_stats *mac_stats = &efx->mac_stats; - unsigned long old_rx_pause, old_tx_pause; - unsigned long new_rx_pause, new_tx_pause; - int rc; - - rc = falcon_dma_stats(efx, GDmaDone_offset); - if (rc) - return; - - /* Pause frames are erroneously counted as errors (SFC bug 3269) */ - old_rx_pause = mac_stats->rx_pause; - old_tx_pause = mac_stats->tx_pause; - - /* Update MAC stats from DMAed values */ - FALCON_STAT(efx, GRxGoodOct, rx_good_bytes); - FALCON_STAT(efx, GRxBadOct, rx_bad_bytes); - FALCON_STAT(efx, GRxMissPkt, rx_missed); - FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier); - FALCON_STAT(efx, GRxPausePkt, rx_pause); - FALCON_STAT(efx, GRxBadPkt, rx_bad); - FALCON_STAT(efx, GRxUcastPkt, rx_unicast); - FALCON_STAT(efx, GRxMcastPkt, rx_multicast); - FALCON_STAT(efx, GRxBcastPkt, rx_broadcast); - FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64); - FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64); - FALCON_STAT(efx, GRx64Pkt, rx_64); - FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127); - FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255); - FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511); - FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023); - FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx); - FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo); - FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo); - FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx); - FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo); - FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo); - FALCON_STAT(efx, GTxGoodBadOct, tx_bytes); - FALCON_STAT(efx, GTxGoodOct, tx_good_bytes); - FALCON_STAT(efx, GTxSglColPkt, tx_single_collision); - FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision); - FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision); - FALCON_STAT(efx, GTxDefPkt, tx_deferred); - FALCON_STAT(efx, GTxLateCol, tx_late_collision); - FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred); - FALCON_STAT(efx, GTxPausePkt, tx_pause); - FALCON_STAT(efx, GTxBadPkt, tx_bad); - FALCON_STAT(efx, GTxUcastPkt, tx_unicast); - FALCON_STAT(efx, GTxMcastPkt, tx_multicast); - FALCON_STAT(efx, GTxBcastPkt, tx_broadcast); - FALCON_STAT(efx, GTxLt64Pkt, tx_lt64); - FALCON_STAT(efx, GTx64Pkt, tx_64); - FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127); - FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255); - FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511); - FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023); - FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx); - FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo); - FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo); - FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp); - FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error); - FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error); - - /* Pause frames are erroneously counted as errors (SFC bug 3269) */ - new_rx_pause = mac_stats->rx_pause; - new_tx_pause = mac_stats->tx_pause; - mac_stats->rx_bad -= (new_rx_pause - old_rx_pause); - mac_stats->tx_bad -= (new_tx_pause - old_tx_pause); - - /* Derive stats that the MAC doesn't provide directly */ - mac_stats->tx_bad_bytes = - mac_stats->tx_bytes - mac_stats->tx_good_bytes; - mac_stats->tx_packets = - mac_stats->tx_lt64 + mac_stats->tx_64 + - mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 + - mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 + - mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo + - mac_stats->tx_gtjumbo; - mac_stats->tx_collision = - mac_stats->tx_single_collision + - mac_stats->tx_multiple_collision + - mac_stats->tx_excessive_collision + - mac_stats->tx_late_collision; - mac_stats->rx_bytes = - mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes; - mac_stats->rx_packets = - mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 + - mac_stats->rx_64 + mac_stats->rx_65_to_127 + - mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 + - mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx + - mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo; - mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad; - mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; -} - -struct efx_mac_operations falcon_gmac_operations = { - .reconfigure = falcon_reconfigure_gmac, - .update_stats = falcon_update_stats_gmac, - .irq = efx_port_dummy_op_void, - .poll = efx_port_dummy_op_void, -}; diff --git a/trunk/drivers/net/sfc/falcon_hwdefs.h b/trunk/drivers/net/sfc/falcon_hwdefs.h index bda8d5bb72e4..040e70ed4ec7 100644 --- a/trunk/drivers/net/sfc/falcon_hwdefs.h +++ b/trunk/drivers/net/sfc/falcon_hwdefs.h @@ -111,18 +111,12 @@ /* NIC status register */ #define NIC_STAT_REG 0x0200 -#define EE_STRAP_EN_LBN 31 -#define EE_STRAP_EN_WIDTH 1 -#define EE_STRAP_OVR_LBN 24 -#define EE_STRAP_OVR_WIDTH 4 #define ONCHIP_SRAM_LBN 16 #define ONCHIP_SRAM_WIDTH 1 #define SF_PRST_LBN 9 #define SF_PRST_WIDTH 1 #define EE_PRST_LBN 8 #define EE_PRST_WIDTH 1 -#define STRAP_PINS_LBN 0 -#define STRAP_PINS_WIDTH 3 /* These bit definitions are extrapolated from the list of numerical * values for STRAP_PINS. */ @@ -136,8 +130,6 @@ /* GPIO control register */ #define GPIO_CTL_REG_KER 0x0210 -#define GPIO_USE_NIC_CLK_LBN (30) -#define GPIO_USE_NIC_CLK_WIDTH (1) #define GPIO_OUTPUTS_LBN (16) #define GPIO_OUTPUTS_WIDTH (4) #define GPIO_INPUTS_LBN (8) @@ -500,107 +492,6 @@ #define MAC_MCAST_HASH_REG0_KER 0xca0 #define MAC_MCAST_HASH_REG1_KER 0xcb0 -/* GMAC configuration register 1 */ -#define GM_CFG1_REG 0xe00 -#define GM_SW_RST_LBN 31 -#define GM_SW_RST_WIDTH 1 -#define GM_LOOP_LBN 8 -#define GM_LOOP_WIDTH 1 -#define GM_RX_FC_EN_LBN 5 -#define GM_RX_FC_EN_WIDTH 1 -#define GM_TX_FC_EN_LBN 4 -#define GM_TX_FC_EN_WIDTH 1 -#define GM_RX_EN_LBN 2 -#define GM_RX_EN_WIDTH 1 -#define GM_TX_EN_LBN 0 -#define GM_TX_EN_WIDTH 1 - -/* GMAC configuration register 2 */ -#define GM_CFG2_REG 0xe10 -#define GM_PAMBL_LEN_LBN 12 -#define GM_PAMBL_LEN_WIDTH 4 -#define GM_IF_MODE_LBN 8 -#define GM_IF_MODE_WIDTH 2 -#define GM_LEN_CHK_LBN 4 -#define GM_LEN_CHK_WIDTH 1 -#define GM_PAD_CRC_EN_LBN 2 -#define GM_PAD_CRC_EN_WIDTH 1 -#define GM_FD_LBN 0 -#define GM_FD_WIDTH 1 - -/* GMAC maximum frame length register */ -#define GM_MAX_FLEN_REG 0xe40 -#define GM_MAX_FLEN_LBN 0 -#define GM_MAX_FLEN_WIDTH 16 - -/* GMAC station address register 1 */ -#define GM_ADR1_REG 0xf00 -#define GM_HWADDR_5_LBN 24 -#define GM_HWADDR_5_WIDTH 8 -#define GM_HWADDR_4_LBN 16 -#define GM_HWADDR_4_WIDTH 8 -#define GM_HWADDR_3_LBN 8 -#define GM_HWADDR_3_WIDTH 8 -#define GM_HWADDR_2_LBN 0 -#define GM_HWADDR_2_WIDTH 8 - -/* GMAC station address register 2 */ -#define GM_ADR2_REG 0xf10 -#define GM_HWADDR_1_LBN 24 -#define GM_HWADDR_1_WIDTH 8 -#define GM_HWADDR_0_LBN 16 -#define GM_HWADDR_0_WIDTH 8 - -/* GMAC FIFO configuration register 0 */ -#define GMF_CFG0_REG 0xf20 -#define GMF_FTFENREQ_LBN 12 -#define GMF_FTFENREQ_WIDTH 1 -#define GMF_STFENREQ_LBN 11 -#define GMF_STFENREQ_WIDTH 1 -#define GMF_FRFENREQ_LBN 10 -#define GMF_FRFENREQ_WIDTH 1 -#define GMF_SRFENREQ_LBN 9 -#define GMF_SRFENREQ_WIDTH 1 -#define GMF_WTMENREQ_LBN 8 -#define GMF_WTMENREQ_WIDTH 1 - -/* GMAC FIFO configuration register 1 */ -#define GMF_CFG1_REG 0xf30 -#define GMF_CFGFRTH_LBN 16 -#define GMF_CFGFRTH_WIDTH 5 -#define GMF_CFGXOFFRTX_LBN 0 -#define GMF_CFGXOFFRTX_WIDTH 16 - -/* GMAC FIFO configuration register 2 */ -#define GMF_CFG2_REG 0xf40 -#define GMF_CFGHWM_LBN 16 -#define GMF_CFGHWM_WIDTH 6 -#define GMF_CFGLWM_LBN 0 -#define GMF_CFGLWM_WIDTH 6 - -/* GMAC FIFO configuration register 3 */ -#define GMF_CFG3_REG 0xf50 -#define GMF_CFGHWMFT_LBN 16 -#define GMF_CFGHWMFT_WIDTH 6 -#define GMF_CFGFTTH_LBN 0 -#define GMF_CFGFTTH_WIDTH 6 - -/* GMAC FIFO configuration register 4 */ -#define GMF_CFG4_REG 0xf60 -#define GMF_HSTFLTRFRM_PAUSE_LBN 12 -#define GMF_HSTFLTRFRM_PAUSE_WIDTH 12 - -/* GMAC FIFO configuration register 5 */ -#define GMF_CFG5_REG 0xf70 -#define GMF_CFGHDPLX_LBN 22 -#define GMF_CFGHDPLX_WIDTH 1 -#define GMF_CFGBYTMODE_LBN 19 -#define GMF_CFGBYTMODE_WIDTH 1 -#define GMF_HSTDRPLT64_LBN 18 -#define GMF_HSTDRPLT64_WIDTH 1 -#define GMF_HSTFLTRFRMDC_PAUSE_LBN 12 -#define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1 - /* XGMAC address register low */ #define XM_ADR_LO_REG 0x1200 #define XM_ADR_3_LBN 24 @@ -1053,8 +944,6 @@ #define XG_MNT_INTR_B0_WIDTH 1 #define RX_RECOVERY_A1_LBN 11 #define RX_RECOVERY_A1_WIDTH 1 -#define XFP_PHY_INTR_LBN 10 -#define XFP_PHY_INTR_WIDTH 1 #define XG_PHY_INTR_LBN 9 #define XG_PHY_INTR_WIDTH 1 #define G_PHY1_INTR_LBN 8 @@ -1073,103 +962,54 @@ ************************************************************************** * */ - #define GRxGoodOct_offset 0x0 -#define GRxGoodOct_WIDTH 48 #define GRxBadOct_offset 0x8 -#define GRxBadOct_WIDTH 48 #define GRxMissPkt_offset 0x10 -#define GRxMissPkt_WIDTH 32 #define GRxFalseCRS_offset 0x14 -#define GRxFalseCRS_WIDTH 32 #define GRxPausePkt_offset 0x18 -#define GRxPausePkt_WIDTH 32 #define GRxBadPkt_offset 0x1C -#define GRxBadPkt_WIDTH 32 #define GRxUcastPkt_offset 0x20 -#define GRxUcastPkt_WIDTH 32 #define GRxMcastPkt_offset 0x24 -#define GRxMcastPkt_WIDTH 32 #define GRxBcastPkt_offset 0x28 -#define GRxBcastPkt_WIDTH 32 #define GRxGoodLt64Pkt_offset 0x2C -#define GRxGoodLt64Pkt_WIDTH 32 #define GRxBadLt64Pkt_offset 0x30 -#define GRxBadLt64Pkt_WIDTH 32 #define GRx64Pkt_offset 0x34 -#define GRx64Pkt_WIDTH 32 #define GRx65to127Pkt_offset 0x38 -#define GRx65to127Pkt_WIDTH 32 #define GRx128to255Pkt_offset 0x3C -#define GRx128to255Pkt_WIDTH 32 #define GRx256to511Pkt_offset 0x40 -#define GRx256to511Pkt_WIDTH 32 #define GRx512to1023Pkt_offset 0x44 -#define GRx512to1023Pkt_WIDTH 32 #define GRx1024to15xxPkt_offset 0x48 -#define GRx1024to15xxPkt_WIDTH 32 #define GRx15xxtoJumboPkt_offset 0x4C -#define GRx15xxtoJumboPkt_WIDTH 32 #define GRxGtJumboPkt_offset 0x50 -#define GRxGtJumboPkt_WIDTH 32 #define GRxFcsErr64to15xxPkt_offset 0x54 -#define GRxFcsErr64to15xxPkt_WIDTH 32 #define GRxFcsErr15xxtoJumboPkt_offset 0x58 -#define GRxFcsErr15xxtoJumboPkt_WIDTH 32 #define GRxFcsErrGtJumboPkt_offset 0x5C -#define GRxFcsErrGtJumboPkt_WIDTH 32 #define GTxGoodBadOct_offset 0x80 -#define GTxGoodBadOct_WIDTH 48 #define GTxGoodOct_offset 0x88 -#define GTxGoodOct_WIDTH 48 #define GTxSglColPkt_offset 0x90 -#define GTxSglColPkt_WIDTH 32 #define GTxMultColPkt_offset 0x94 -#define GTxMultColPkt_WIDTH 32 #define GTxExColPkt_offset 0x98 -#define GTxExColPkt_WIDTH 32 #define GTxDefPkt_offset 0x9C -#define GTxDefPkt_WIDTH 32 #define GTxLateCol_offset 0xA0 -#define GTxLateCol_WIDTH 32 #define GTxExDefPkt_offset 0xA4 -#define GTxExDefPkt_WIDTH 32 #define GTxPausePkt_offset 0xA8 -#define GTxPausePkt_WIDTH 32 #define GTxBadPkt_offset 0xAC -#define GTxBadPkt_WIDTH 32 #define GTxUcastPkt_offset 0xB0 -#define GTxUcastPkt_WIDTH 32 #define GTxMcastPkt_offset 0xB4 -#define GTxMcastPkt_WIDTH 32 #define GTxBcastPkt_offset 0xB8 -#define GTxBcastPkt_WIDTH 32 #define GTxLt64Pkt_offset 0xBC -#define GTxLt64Pkt_WIDTH 32 #define GTx64Pkt_offset 0xC0 -#define GTx64Pkt_WIDTH 32 #define GTx65to127Pkt_offset 0xC4 -#define GTx65to127Pkt_WIDTH 32 #define GTx128to255Pkt_offset 0xC8 -#define GTx128to255Pkt_WIDTH 32 #define GTx256to511Pkt_offset 0xCC -#define GTx256to511Pkt_WIDTH 32 #define GTx512to1023Pkt_offset 0xD0 -#define GTx512to1023Pkt_WIDTH 32 #define GTx1024to15xxPkt_offset 0xD4 -#define GTx1024to15xxPkt_WIDTH 32 #define GTx15xxtoJumboPkt_offset 0xD8 -#define GTx15xxtoJumboPkt_WIDTH 32 #define GTxGtJumboPkt_offset 0xDC -#define GTxGtJumboPkt_WIDTH 32 #define GTxNonTcpUdpPkt_offset 0xE0 -#define GTxNonTcpUdpPkt_WIDTH 16 #define GTxMacSrcErrPkt_offset 0xE4 -#define GTxMacSrcErrPkt_WIDTH 16 #define GTxIpSrcErrPkt_offset 0xE8 -#define GTxIpSrcErrPkt_WIDTH 16 #define GDmaDone_offset 0xEC -#define GDmaDone_WIDTH 32 #define XgRxOctets_offset 0x0 #define XgRxOctets_WIDTH 48 diff --git a/trunk/drivers/net/sfc/falcon_xmac.c b/trunk/drivers/net/sfc/falcon_xmac.c index 5a03713685ac..d4012314dd01 100644 --- a/trunk/drivers/net/sfc/falcon_xmac.c +++ b/trunk/drivers/net/sfc/falcon_xmac.c @@ -15,6 +15,7 @@ #include "falcon_hwdefs.h" #include "falcon_io.h" #include "mac.h" +#include "gmii.h" #include "mdio_10g.h" #include "phy.h" #include "boards.h" @@ -25,6 +26,24 @@ * MAC operations * *************************************************************************/ +static int falcon_reset_xmac(struct efx_nic *efx) +{ + efx_oword_t reg; + int count; + + EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1); + falcon_write(efx, ®, XM_GLB_CFG_REG); + + for (count = 0; count < 10000; count++) { /* wait upto 100ms */ + falcon_read(efx, ®, XM_GLB_CFG_REG); + if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0) + return 0; + udelay(10); + } + + EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); + return -ETIMEDOUT; +} /* Configure the XAUI driver that is an output from Falcon */ static void falcon_setup_xaui(struct efx_nic *efx) @@ -80,20 +99,31 @@ int falcon_reset_xaui(struct efx_nic *efx) return -ETIMEDOUT; } -static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) +static bool falcon_xgmii_status(struct efx_nic *efx) { efx_oword_t reg; - if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) - return; + if (falcon_rev(efx) < FALCON_REV_B0) + return true; - /* We expect xgmii faults if the wireside link is up */ - if (!EFX_WORKAROUND_5147(efx) || !efx->link_up) - return; + /* The ISR latches, so clear it and re-read */ + falcon_read(efx, ®, XM_MGT_INT_REG_B0); + falcon_read(efx, ®, XM_MGT_INT_REG_B0); - /* We can only use this interrupt to signal the negative edge of - * xaui_align [we have to poll the positive edge]. */ - if (!efx->mac_up) + if (EFX_OWORD_FIELD(reg, XM_LCLFLT) || + EFX_OWORD_FIELD(reg, XM_RMTFLT)) { + EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg)); + return false; + } + + return true; +} + +static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) +{ + efx_oword_t reg; + + if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) return; /* Flush the ISR */ @@ -106,7 +136,35 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) falcon_write(efx, ®, XM_MGT_INT_MSK_REG_B0); } -/* Get status of XAUI link */ +int falcon_init_xmac(struct efx_nic *efx) +{ + int rc; + + /* Initialize the PHY first so the clock is around */ + rc = efx->phy_op->init(efx); + if (rc) + goto fail1; + + rc = falcon_reset_xaui(efx); + if (rc) + goto fail2; + + /* Wait again. Give the PHY and MAC time to come back */ + schedule_timeout_uninterruptible(HZ / 10); + + rc = falcon_reset_xmac(efx); + if (rc) + goto fail2; + + falcon_mask_status_intr(efx, true); + return 0; + + fail2: + efx->phy_op->fini(efx); + fail1: + return rc; +} + bool falcon_xaui_link_ok(struct efx_nic *efx) { efx_oword_t reg; @@ -130,10 +188,18 @@ bool falcon_xaui_link_ok(struct efx_nic *efx) EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET); falcon_write(efx, ®, XX_CORE_STAT_REG); - /* If the link is up, then check the phy side of the xaui link */ - if (efx->link_up && link_ok) + /* If the link is up, then check the phy side of the xaui link + * (error conditions from the wire side propoagate back through + * the phy to the xaui side). */ + if (efx->link_up && link_ok) { if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS)) link_ok = mdio_clause45_phyxgxs_lane_sync(efx); + } + + /* If the PHY and XAUI links are up, then check the mac's xgmii + * fault state */ + if (efx->link_up && link_ok) + link_ok = falcon_xgmii_status(efx); return link_ok; } @@ -142,7 +208,7 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx) { unsigned int max_frame_len; efx_oword_t reg; - bool rx_fc = !!(efx->link_fc & EFX_FC_RX); + bool rx_fc = !!(efx->flow_control & EFX_FC_RX); /* Configure MAC - cut-thru mode is hard wired on */ EFX_POPULATE_DWORD_3(reg, @@ -245,39 +311,70 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails * to come back up. Bash it until it comes back up */ -static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries) +static bool falcon_check_xaui_link_up(struct efx_nic *efx) { - efx->mac_up = falcon_xaui_link_ok(efx); + int max_tries, tries; + tries = EFX_WORKAROUND_5147(efx) ? 5 : 1; + max_tries = tries; if ((efx->loopback_mode == LOOPBACK_NETWORK) || + (efx->phy_type == PHY_TYPE_NONE) || efx_phy_mode_disabled(efx->phy_mode)) - /* XAUI link is expected to be down */ - return; + return false; - while (!efx->mac_up && tries) { - EFX_LOG(efx, "bashing xaui\n"); + while (tries) { + if (falcon_xaui_link_ok(efx)) + return true; + + EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n", + __func__, tries); falcon_reset_xaui(efx); udelay(200); - - efx->mac_up = falcon_xaui_link_ok(efx); - --tries; + tries--; } + + EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n", + max_tries); + return false; } -static void falcon_reconfigure_xmac(struct efx_nic *efx) +void falcon_reconfigure_xmac(struct efx_nic *efx) { + bool xaui_link_ok; + falcon_mask_status_intr(efx, false); + falcon_deconfigure_mac_wrapper(efx); + + /* Reconfigure the PHY, disabling transmit in mac level loopback. */ + if (LOOPBACK_INTERNAL(efx)) + efx->phy_mode |= PHY_MODE_TX_DISABLED; + else + efx->phy_mode &= ~PHY_MODE_TX_DISABLED; + efx->phy_op->reconfigure(efx); + falcon_reconfigure_xgxs_core(efx); falcon_reconfigure_xmac_core(efx); falcon_reconfigure_mac_wrapper(efx); - falcon_check_xaui_link_up(efx, 5); - falcon_mask_status_intr(efx, true); + /* Ensure XAUI link is up */ + xaui_link_ok = falcon_check_xaui_link_up(efx); + + if (xaui_link_ok && efx->link_up) + falcon_mask_status_intr(efx, true); +} + +void falcon_fini_xmac(struct efx_nic *efx) +{ + /* Isolate the MAC - PHY */ + falcon_deconfigure_mac_wrapper(efx); + + /* Potentially power down the PHY */ + efx->phy_op->fini(efx); } -static void falcon_update_stats_xmac(struct efx_nic *efx) +void falcon_update_stats_xmac(struct efx_nic *efx) { struct efx_mac_stats *mac_stats = &efx->mac_stats; int rc; @@ -342,35 +439,97 @@ static void falcon_update_stats_xmac(struct efx_nic *efx) mac_stats->rx_control * 64); } -static void falcon_xmac_irq(struct efx_nic *efx) +int falcon_check_xmac(struct efx_nic *efx) { - /* The XGMII link has a transient fault, which indicates either: - * - there's a transient xgmii fault - * - falcon's end of the xaui link may need a kick - * - the wire-side link may have gone down, but the lasi/poll() - * hasn't noticed yet. - * - * We only want to even bother polling XAUI if we're confident it's - * not (1) or (3). In both cases, the only reliable way to spot this - * is to wait a bit. We do this here by forcing the mac link state - * to down, and waiting for the mac poll to come round and check - */ - efx->mac_up = false; + bool xaui_link_ok; + int rc; + + if ((efx->loopback_mode == LOOPBACK_NETWORK) || + efx_phy_mode_disabled(efx->phy_mode)) + return 0; + + falcon_mask_status_intr(efx, false); + xaui_link_ok = falcon_xaui_link_ok(efx); + + if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok) + falcon_reset_xaui(efx); + + /* Call the PHY check_hw routine */ + rc = efx->phy_op->check_hw(efx); + + /* Unmask interrupt if everything was (and still is) ok */ + if (xaui_link_ok && efx->link_up) + falcon_mask_status_intr(efx, true); + + return rc; } -static void falcon_poll_xmac(struct efx_nic *efx) +/* Simulate a PHY event */ +void falcon_xmac_sim_phy_event(struct efx_nic *efx) { - if (!EFX_WORKAROUND_5147(efx) || !efx->link_up || efx->mac_up) - return; + efx_qword_t phy_event; - falcon_mask_status_intr(efx, false); - falcon_check_xaui_link_up(efx, 1); - falcon_mask_status_intr(efx, true); + EFX_POPULATE_QWORD_2(phy_event, + EV_CODE, GLOBAL_EV_DECODE, + XG_PHY_INTR, 1); + falcon_generate_event(&efx->channel[0], &phy_event); +} + +int falcon_xmac_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +{ + mdio_clause45_get_settings(efx, ecmd); + ecmd->transceiver = XCVR_INTERNAL; + ecmd->phy_address = efx->mii.phy_id; + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->duplex = DUPLEX_FULL; + return 0; +} + +int falcon_xmac_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +{ + if (ecmd->transceiver != XCVR_INTERNAL) + return -EINVAL; + if (ecmd->autoneg != AUTONEG_DISABLE) + return -EINVAL; + if (ecmd->duplex != DUPLEX_FULL) + return -EINVAL; + + return mdio_clause45_set_settings(efx, ecmd); } -struct efx_mac_operations falcon_xmac_operations = { - .reconfigure = falcon_reconfigure_xmac, - .update_stats = falcon_update_stats_xmac, - .irq = falcon_xmac_irq, - .poll = falcon_poll_xmac, -}; + +int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control) +{ + bool reset; + + if (flow_control & EFX_FC_AUTO) { + EFX_LOG(efx, "10G does not support flow control " + "autonegotiation\n"); + return -EINVAL; + } + + if ((flow_control & EFX_FC_TX) && !(flow_control & EFX_FC_RX)) + return -EINVAL; + + /* TX flow control may automatically turn itself off if the + * link partner (intermittently) stops responding to pause + * frames. There isn't any indication that this has happened, + * so the best we do is leave it up to the user to spot this + * and fix it be cycling transmit flow control on this end. */ + reset = ((flow_control & EFX_FC_TX) && + !(efx->flow_control & EFX_FC_TX)); + if (EFX_WORKAROUND_11482(efx) && reset) { + if (falcon_rev(efx) >= FALCON_REV_B0) { + /* Recover by resetting the EM block */ + if (efx->link_up) + falcon_drain_tx_fifo(efx); + } else { + /* Schedule a reset to recover */ + efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); + } + } + + efx->flow_control = flow_control; + + return 0; +} diff --git a/trunk/drivers/net/sfc/gmii.h b/trunk/drivers/net/sfc/gmii.h index dfccaa7b573e..d25bbd1297f4 100644 --- a/trunk/drivers/net/sfc/gmii.h +++ b/trunk/drivers/net/sfc/gmii.h @@ -1,7 +1,7 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 Solarflare Communications Inc. + * Copyright 2006 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -57,4 +57,139 @@ #define ISR_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */ #define ISR_JABBER 0x0001 /* Bit 0 - jabber */ +/* Logically extended advertisement register */ +#define GM_ADVERTISE_SLCT ADVERTISE_SLCT +#define GM_ADVERTISE_CSMA ADVERTISE_CSMA +#define GM_ADVERTISE_10HALF ADVERTISE_10HALF +#define GM_ADVERTISE_1000XFULL ADVERTISE_1000XFULL +#define GM_ADVERTISE_10FULL ADVERTISE_10FULL +#define GM_ADVERTISE_1000XHALF ADVERTISE_1000XHALF +#define GM_ADVERTISE_100HALF ADVERTISE_100HALF +#define GM_ADVERTISE_1000XPAUSE ADVERTISE_1000XPAUSE +#define GM_ADVERTISE_100FULL ADVERTISE_100FULL +#define GM_ADVERTISE_1000XPSE_ASYM ADVERTISE_1000XPSE_ASYM +#define GM_ADVERTISE_100BASE4 ADVERTISE_100BASE4 +#define GM_ADVERTISE_PAUSE_CAP ADVERTISE_PAUSE_CAP +#define GM_ADVERTISE_PAUSE_ASYM ADVERTISE_PAUSE_ASYM +#define GM_ADVERTISE_RESV ADVERTISE_RESV +#define GM_ADVERTISE_RFAULT ADVERTISE_RFAULT +#define GM_ADVERTISE_LPACK ADVERTISE_LPACK +#define GM_ADVERTISE_NPAGE ADVERTISE_NPAGE +#define GM_ADVERTISE_1000FULL (ADVERTISE_1000FULL << 8) +#define GM_ADVERTISE_1000HALF (ADVERTISE_1000HALF << 8) +#define GM_ADVERTISE_1000 (GM_ADVERTISE_1000FULL | \ + GM_ADVERTISE_1000HALF) +#define GM_ADVERTISE_FULL (GM_ADVERTISE_1000FULL | \ + ADVERTISE_FULL) +#define GM_ADVERTISE_ALL (GM_ADVERTISE_1000FULL | \ + GM_ADVERTISE_1000HALF | \ + ADVERTISE_ALL) + +/* Logically extended link partner ability register */ +#define GM_LPA_SLCT LPA_SLCT +#define GM_LPA_10HALF LPA_10HALF +#define GM_LPA_1000XFULL LPA_1000XFULL +#define GM_LPA_10FULL LPA_10FULL +#define GM_LPA_1000XHALF LPA_1000XHALF +#define GM_LPA_100HALF LPA_100HALF +#define GM_LPA_1000XPAUSE LPA_1000XPAUSE +#define GM_LPA_100FULL LPA_100FULL +#define GM_LPA_1000XPAUSE_ASYM LPA_1000XPAUSE_ASYM +#define GM_LPA_100BASE4 LPA_100BASE4 +#define GM_LPA_PAUSE_CAP LPA_PAUSE_CAP +#define GM_LPA_PAUSE_ASYM LPA_PAUSE_ASYM +#define GM_LPA_RESV LPA_RESV +#define GM_LPA_RFAULT LPA_RFAULT +#define GM_LPA_LPACK LPA_LPACK +#define GM_LPA_NPAGE LPA_NPAGE +#define GM_LPA_1000FULL (LPA_1000FULL << 6) +#define GM_LPA_1000HALF (LPA_1000HALF << 6) +#define GM_LPA_10000FULL 0x00040000 +#define GM_LPA_10000HALF 0x00080000 +#define GM_LPA_DUPLEX (GM_LPA_1000FULL | GM_LPA_10000FULL \ + | LPA_DUPLEX) +#define GM_LPA_10 (LPA_10FULL | LPA_10HALF) +#define GM_LPA_100 LPA_100 +#define GM_LPA_1000 (GM_LPA_1000FULL | GM_LPA_1000HALF) +#define GM_LPA_10000 (GM_LPA_10000FULL | GM_LPA_10000HALF) + +/* Retrieve GMII autonegotiation advertised abilities + * + * The MII advertisment register (MII_ADVERTISE) is logically extended + * to include advertisement bits ADVERTISE_1000FULL and + * ADVERTISE_1000HALF from MII_CTRL1000. The result can be tested + * against the GM_ADVERTISE_xxx constants. + */ +static inline unsigned int gmii_advertised(struct mii_if_info *gmii) +{ + unsigned int advertise; + unsigned int ctrl1000; + + advertise = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_ADVERTISE); + ctrl1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000); + return (((ctrl1000 << 8) & GM_ADVERTISE_1000) | advertise); +} + +/* Retrieve GMII autonegotiation link partner abilities + * + * The MII link partner ability register (MII_LPA) is logically + * extended by adding bits LPA_1000HALF and LPA_1000FULL from + * MII_STAT1000. The result can be tested against the GM_LPA_xxx + * constants. + */ +static inline unsigned int gmii_lpa(struct mii_if_info *gmii) +{ + unsigned int lpa; + unsigned int stat1000; + + lpa = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_LPA); + stat1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_STAT1000); + return (((stat1000 << 6) & GM_LPA_1000) | lpa); +} + +/* Calculate GMII autonegotiated link technology + * + * "negotiated" should be the result of gmii_advertised() logically + * ANDed with the result of gmii_lpa(). + * + * "tech" will be negotiated with the unused bits masked out. For + * example, if both ends of the link are capable of both + * GM_LPA_1000FULL and GM_LPA_100FULL, GM_LPA_100FULL will be masked + * out. + */ +static inline unsigned int gmii_nway_result(unsigned int negotiated) +{ + unsigned int other_bits; + + /* Mask out the speed and duplexity bits */ + other_bits = negotiated & ~(GM_LPA_10 | GM_LPA_100 | GM_LPA_1000); + + if (negotiated & GM_LPA_1000FULL) + return (other_bits | GM_LPA_1000FULL); + else if (negotiated & GM_LPA_1000HALF) + return (other_bits | GM_LPA_1000HALF); + else + return (other_bits | mii_nway_result(negotiated)); +} + +/* Calculate GMII non-autonegotiated link technology + * + * This provides an equivalent to gmii_nway_result for the case when + * autonegotiation is disabled. + */ +static inline unsigned int gmii_forced_result(unsigned int bmcr) +{ + unsigned int result; + int full_duplex; + + full_duplex = bmcr & BMCR_FULLDPLX; + if (bmcr & BMCR_SPEED1000) + result = full_duplex ? GM_LPA_1000FULL : GM_LPA_1000HALF; + else if (bmcr & BMCR_SPEED100) + result = full_duplex ? GM_LPA_100FULL : GM_LPA_100HALF; + else + result = full_duplex ? GM_LPA_10FULL : GM_LPA_10HALF; + return result; +} + #endif /* EFX_GMII_H */ diff --git a/trunk/drivers/net/sfc/mac.h b/trunk/drivers/net/sfc/mac.h index 4e7074278fe1..a31571c69137 100644 --- a/trunk/drivers/net/sfc/mac.h +++ b/trunk/drivers/net/sfc/mac.h @@ -1,7 +1,7 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2008 Solarflare Communications Inc. + * Copyright 2006-2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -13,7 +13,17 @@ #include "net_driver.h" -extern struct efx_mac_operations falcon_gmac_operations; -extern struct efx_mac_operations falcon_xmac_operations; +extern int falcon_init_xmac(struct efx_nic *efx); +extern void falcon_reconfigure_xmac(struct efx_nic *efx); +extern void falcon_update_stats_xmac(struct efx_nic *efx); +extern void falcon_fini_xmac(struct efx_nic *efx); +extern int falcon_check_xmac(struct efx_nic *efx); +extern void falcon_xmac_sim_phy_event(struct efx_nic *efx); +extern int falcon_xmac_get_settings(struct efx_nic *efx, + struct ethtool_cmd *ecmd); +extern int falcon_xmac_set_settings(struct efx_nic *efx, + struct ethtool_cmd *ecmd); +extern int falcon_xmac_set_pause(struct efx_nic *efx, + enum efx_fc_type pause_params); #endif diff --git a/trunk/drivers/net/sfc/mdio_10g.c b/trunk/drivers/net/sfc/mdio_10g.c index 037601e0b9d7..19e25210b687 100644 --- a/trunk/drivers/net/sfc/mdio_10g.c +++ b/trunk/drivers/net/sfc/mdio_10g.c @@ -47,16 +47,13 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, if (LOOPBACK_INTERNAL(efx)) return 0; - if (mmd != MDIO_MMD_AN) { - /* Read MMD STATUS2 to check it is responding. */ - status = mdio_clause45_read(efx, phy_id, mmd, - MDIO_MMDREG_STAT2); - if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & - ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != - MDIO_MMDREG_STAT2_PRESENT_VAL) { - EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); - return -EIO; - } + /* Read MMD STATUS2 to check it is responding. */ + status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2); + if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & + ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != + MDIO_MMDREG_STAT2_PRESENT_VAL) { + EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); + return -EIO; } /* Read MMD STATUS 1 to check for fault. */ @@ -124,18 +121,16 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, int mdio_clause45_check_mmds(struct efx_nic *efx, unsigned int mmd_mask, unsigned int fatal_mask) { - u32 devices; - int mmd = 0, probe_mmd; + int devices, mmd = 0; + int probe_mmd; /* Historically we have probed the PHYXS to find out what devices are * present,but that doesn't work so well if the PHYXS isn't expected * to exist, if so just find the first item in the list supplied. */ - probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS : + probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS0_PHYXS) ? MDIO_MMD_PHYXS : __ffs(mmd_mask); - devices = (mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS0) | - mdio_clause45_read(efx, efx->mii.phy_id, - probe_mmd, MDIO_MMDREG_DEVS1) << 16); + devices = mdio_clause45_read(efx, efx->mii.phy_id, + probe_mmd, MDIO_MMDREG_DEVS0); /* Check all the expected MMDs are present */ if (devices < 0) { @@ -180,17 +175,14 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) else if (efx_phy_mode_disabled(efx->phy_mode)) return false; else if (efx->loopback_mode == LOOPBACK_PHYXS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS | + MDIO_MMDREG_DEVS0_PCS | + MDIO_MMDREG_DEVS0_PMAPMD); else if (efx->loopback_mode == LOOPBACK_PCS) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~(MDIO_MMDREG_DEVS0_PCS | + MDIO_MMDREG_DEVS0_PMAPMD); else if (efx->loopback_mode == LOOPBACK_PMAPMD) - mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_AN); + mmd_mask &= ~MDIO_MMDREG_DEVS0_PMAPMD; while (mmd_mask) { if (mmd_mask & 1) { @@ -211,24 +203,61 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) void mdio_clause45_transmit_disable(struct efx_nic *efx) { - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN, - efx->phy_mode & PHY_MODE_TX_DISABLED); + int phy_id = efx->mii.phy_id; + int ctrl1, ctrl2; + + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_TXDIS); + if (efx->phy_mode & PHY_MODE_TX_DISABLED) + ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN); + else + ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN); + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_TXDIS, ctrl2); } void mdio_clause45_phy_reconfigure(struct efx_nic *efx) { int phy_id = efx->mii.phy_id; + int ctrl1, ctrl2; + + /* Handle (with debouncing) PMA/PMD loopback */ + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_CTRL1); + + if (efx->loopback_mode == LOOPBACK_PMAPMD) + ctrl2 |= (1 << MDIO_PMAPMD_CTRL1_LBACK_LBN); + else + ctrl2 &= ~(1 << MDIO_PMAPMD_CTRL1_LBACK_LBN); + + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_CTRL1, ctrl2); + + /* Handle (with debouncing) PCS loopback */ + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, + MDIO_MMDREG_CTRL1); + if (efx->loopback_mode == LOOPBACK_PCS) + ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + else + ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PCS, + MDIO_MMDREG_CTRL1, ctrl2); + + /* Handle (with debouncing) PHYXS network loopback */ + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, + MDIO_MMDREG_CTRL1); + if (efx->loopback_mode == LOOPBACK_NETWORK) + ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + else + ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PMAPMD); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_PCS); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN, - efx->loopback_mode == LOOPBACK_NETWORK); + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS, + MDIO_MMDREG_CTRL1, ctrl2); } static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx, @@ -236,13 +265,21 @@ static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx, { int phy = efx->mii.phy_id; int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1); + int ctrl1, ctrl2; EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n", mmd, lpower); if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) { - mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1, - MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower); + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy, + mmd, MDIO_MMDREG_CTRL1); + if (lpower) + ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LPOWER_LBN); + else + ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LPOWER_LBN); + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy, mmd, + MDIO_MMDREG_CTRL1, ctrl2); } } @@ -250,7 +287,6 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, int low_power, unsigned int mmd_mask) { int mmd = 0; - mmd_mask &= ~MDIO_MMDREG_DEVS_AN; while (mmd_mask) { if (mmd_mask & 1) mdio_clause45_set_mmd_lpower(efx, low_power, mmd); @@ -259,314 +295,101 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, } } -static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp) -{ - int phy_id = efx->mii.phy_id; - u32 result = 0; - int reg; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr); - if (reg & ADVERTISE_10HALF) - result |= ADVERTISED_10baseT_Half; - if (reg & ADVERTISE_10FULL) - result |= ADVERTISED_10baseT_Full; - if (reg & ADVERTISE_100HALF) - result |= ADVERTISED_100baseT_Half; - if (reg & ADVERTISE_100FULL) - result |= ADVERTISED_100baseT_Full; - if (reg & LPA_RESV) - result |= xnp; - - return result; -} - /** * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. * @efx: Efx NIC * @ecmd: Buffer for settings * * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. + * ecmd have been filled out based on the PMA type. */ void mdio_clause45_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - mdio_clause45_get_settings_ext(efx, ecmd, 0, 0); -} + int pma_type; -/** - * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO. - * @efx: Efx NIC - * @ecmd: Buffer for settings - * @xnp: Advertised Extended Next Page state - * @xnp_lpa: Link Partner's advertised XNP state - * - * On return the 'port', 'speed', 'supported' and 'advertising' fields of - * ecmd have been filled out. - */ -void mdio_clause45_get_settings_ext(struct efx_nic *efx, - struct ethtool_cmd *ecmd, - u32 xnp, u32 xnp_lpa) -{ - int phy_id = efx->mii.phy_id; - int reg; + /* If no PMA is present we are presumably talking something XAUI-ish + * like CX4. Which we report as FIBRE (see below) */ + if ((efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)) == 0) { + ecmd->speed = SPEED_10000; + ecmd->port = PORT_FIBRE; + ecmd->supported = SUPPORTED_FIBRE; + ecmd->advertising = ADVERTISED_FIBRE; + return; + } - ecmd->transceiver = XCVR_INTERNAL; - ecmd->phy_address = phy_id; + pma_type = mdio_clause45_read(efx, efx->mii.phy_id, + MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL2); + pma_type &= MDIO_PMAPMD_CTRL2_TYPE_MASK; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL2); - switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) { + switch (pma_type) { + /* We represent CX4 as fibre in the absence of anything + better. */ + case MDIO_PMAPMD_CTRL2_10G_CX4: + ecmd->speed = SPEED_10000; + ecmd->port = PORT_FIBRE; + ecmd->supported = SUPPORTED_FIBRE; + ecmd->advertising = ADVERTISED_FIBRE; + break; + /* 10G Base-T */ case MDIO_PMAPMD_CTRL2_10G_BT: + ecmd->speed = SPEED_10000; + ecmd->port = PORT_TP; + ecmd->supported = SUPPORTED_TP | SUPPORTED_10000baseT_Full; + ecmd->advertising = (ADVERTISED_FIBRE + | ADVERTISED_10000baseT_Full); + break; case MDIO_PMAPMD_CTRL2_1G_BT: + ecmd->speed = SPEED_1000; + ecmd->port = PORT_TP; + ecmd->supported = SUPPORTED_TP | SUPPORTED_1000baseT_Full; + ecmd->advertising = (ADVERTISED_FIBRE + | ADVERTISED_1000baseT_Full); + break; case MDIO_PMAPMD_CTRL2_100_BT: + ecmd->speed = SPEED_100; + ecmd->port = PORT_TP; + ecmd->supported = SUPPORTED_TP | SUPPORTED_100baseT_Full; + ecmd->advertising = (ADVERTISED_FIBRE + | ADVERTISED_100baseT_Full); + break; case MDIO_PMAPMD_CTRL2_10_BT: + ecmd->speed = SPEED_10; ecmd->port = PORT_TP; - ecmd->supported = SUPPORTED_TP; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_SPEED); - if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN)) - ecmd->supported |= SUPPORTED_10000baseT_Full; - if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN)) - ecmd->supported |= (SUPPORTED_1000baseT_Full | - SUPPORTED_1000baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN)) - ecmd->supported |= (SUPPORTED_100baseT_Full | - SUPPORTED_100baseT_Half); - if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN)) - ecmd->supported |= (SUPPORTED_10baseT_Full | - SUPPORTED_10baseT_Half); - ecmd->advertising = ADVERTISED_TP; + ecmd->supported = SUPPORTED_TP | SUPPORTED_10baseT_Full; + ecmd->advertising = ADVERTISED_FIBRE | ADVERTISED_10baseT_Full; break; - - /* We represent CX4 as fibre in the absence of anything better */ - case MDIO_PMAPMD_CTRL2_10G_CX4: - /* All the other defined modes are flavours of optical */ + /* All the other defined modes are flavours of + * 10G optical */ default: + ecmd->speed = SPEED_10000; ecmd->port = PORT_FIBRE; ecmd->supported = SUPPORTED_FIBRE; ecmd->advertising = ADVERTISED_FIBRE; break; } - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - ecmd->supported |= SUPPORTED_Autoneg; - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - ecmd->autoneg = AUTONEG_ENABLE; - ecmd->advertising |= - ADVERTISED_Autoneg | - mdio_clause45_get_an(efx, - MDIO_AN_ADVERTISE, xnp); - } else - ecmd->autoneg = AUTONEG_DISABLE; - } else - ecmd->autoneg = AUTONEG_DISABLE; - - /* If AN is enabled and complete, report best common mode */ - if (ecmd->autoneg && - (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_MMDREG_STAT1) & - (1 << MDIO_AN_STATUS_AN_DONE_LBN))) { - u32 common, lpa; - lpa = mdio_clause45_get_an(efx, MDIO_AN_LPA, xnp_lpa); - common = ecmd->advertising & lpa; - if (common & ADVERTISED_10000baseT_Full) { - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - } else if (common & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { - ecmd->speed = SPEED_1000; - ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full); - } else if (common & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { - ecmd->speed = SPEED_100; - ecmd->duplex = !!(common & ADVERTISED_100baseT_Full); - } else { - ecmd->speed = SPEED_10; - ecmd->duplex = !!(common & ADVERTISED_10baseT_Full); - } - } else { - /* Report forced settings */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) * - ((reg & BMCR_SPEED100) ? 100 : 10)); - ecmd->duplex = (reg & BMCR_FULLDPLX || - ecmd->speed == SPEED_10000); - } } /** * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO. * @efx: Efx NIC * @ecmd: New settings + * + * Currently this just enforces that we are _not_ changing the + * 'port', 'speed', 'supported' or 'advertising' settings as these + * cannot be changed on any currently supported PHY. */ int mdio_clause45_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { - int phy_id = efx->mii.phy_id; - struct ethtool_cmd prev; - u32 required; - int ctrl1_bits, reg; - - efx->phy_op->get_settings(efx, &prev); - - if (ecmd->advertising == prev.advertising && - ecmd->speed == prev.speed && - ecmd->duplex == prev.duplex && - ecmd->port == prev.port && - ecmd->autoneg == prev.autoneg) + struct ethtool_cmd tmpcmd; + mdio_clause45_get_settings(efx, &tmpcmd); + /* None of the current PHYs support more than one mode + * of operation (and only 10GBT ever will), so keep things + * simple for now */ + if ((ecmd->speed == tmpcmd.speed) && (ecmd->port == tmpcmd.port) && + (ecmd->supported == tmpcmd.supported) && + (ecmd->advertising == tmpcmd.advertising)) return 0; - - /* We can only change these settings for -T PHYs */ - if (prev.port != PORT_TP || ecmd->port != PORT_TP) - return -EINVAL; - - /* Check that PHY supports these settings and work out the - * basic control bits */ - if (ecmd->duplex) { - switch (ecmd->speed) { - case SPEED_10: - ctrl1_bits = BMCR_FULLDPLX; - required = SUPPORTED_10baseT_Full; - break; - case SPEED_100: - ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX; - required = SUPPORTED_100baseT_Full; - break; - case SPEED_1000: - ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX; - required = SUPPORTED_1000baseT_Full; - break; - case SPEED_10000: - ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 | - BMCR_FULLDPLX); - required = SUPPORTED_10000baseT_Full; - break; - default: - return -EINVAL; - } - } else { - switch (ecmd->speed) { - case SPEED_10: - ctrl1_bits = 0; - required = SUPPORTED_10baseT_Half; - break; - case SPEED_100: - ctrl1_bits = BMCR_SPEED100; - required = SUPPORTED_100baseT_Half; - break; - case SPEED_1000: - ctrl1_bits = BMCR_SPEED1000; - required = SUPPORTED_1000baseT_Half; - break; - default: - return -EINVAL; - } - } - if (ecmd->autoneg) - required |= SUPPORTED_Autoneg; - required |= ecmd->advertising; - if (required & ~prev.supported) - return -EINVAL; - - /* Set the basic control bits */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - MDIO_MMDREG_CTRL1); - reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c); - reg |= ctrl1_bits; - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1, - reg); - - /* Set the AN registers */ - if (ecmd->autoneg != prev.autoneg || - ecmd->advertising != prev.advertising) { - bool xnp = false; - - if (efx->phy_op->set_xnp_advertise) - xnp = efx->phy_op->set_xnp_advertise(efx, - ecmd->advertising); - - if (ecmd->autoneg) { - reg = 0; - if (ecmd->advertising & ADVERTISED_10baseT_Half) - reg |= ADVERTISE_10HALF; - if (ecmd->advertising & ADVERTISED_10baseT_Full) - reg |= ADVERTISE_10FULL; - if (ecmd->advertising & ADVERTISED_100baseT_Half) - reg |= ADVERTISE_100HALF; - if (ecmd->advertising & ADVERTISED_100baseT_Full) - reg |= ADVERTISE_100FULL; - if (xnp) - reg |= ADVERTISE_RESV; - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); - } - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (ecmd->autoneg) - reg |= BMCR_ANENABLE | BMCR_ANRESTART; - else - reg &= ~BMCR_ANENABLE; - if (xnp) - reg |= 1 << MDIO_AN_CTRL_XNP_LBN; - else - reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); - } - - return 0; -} - -void mdio_clause45_set_pause(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - int reg; - - if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) { - /* Set pause capability advertising */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE); - reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - reg |= efx_fc_advertise(efx->wanted_fc); - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_ADVERTISE, reg); - - /* Restart auto-negotiation */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1); - if (reg & BMCR_ANENABLE) { - reg |= BMCR_ANRESTART; - mdio_clause45_write(efx, phy_id, MDIO_MMD_AN, - MDIO_MMDREG_CTRL1, reg); - } - } -} - -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx) -{ - int phy_id = efx->mii.phy_id; - int lpa; - - if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN))) - return efx->wanted_fc; - lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA); - return efx_fc_resolve(efx->wanted_fc, lpa); -} - -void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense) -{ - int old_val = mdio_clause45_read(efx, prt, dev, addr); - int new_val; - - if (sense) - new_val = old_val | (1 << bit); - else - new_val = old_val & ~(1 << bit); - if (old_val != new_val) - mdio_clause45_write(efx, prt, dev, addr, new_val); + return -EOPNOTSUPP; } diff --git a/trunk/drivers/net/sfc/mdio_10g.h b/trunk/drivers/net/sfc/mdio_10g.h index 409118228b1d..db9f358349c6 100644 --- a/trunk/drivers/net/sfc/mdio_10g.h +++ b/trunk/drivers/net/sfc/mdio_10g.h @@ -33,8 +33,6 @@ #define MDIO_MMD_TC (6) /* Auto negotiation */ #define MDIO_MMD_AN (7) -/* Clause 22 extension */ -#define MDIO_MMD_C22EXT 29 /* Generic register locations */ #define MDIO_MMDREG_CTRL1 (0) @@ -75,26 +73,14 @@ #define MDIO_ID_MODEL(_id32) ((_id32 >> 4) & 0x3f) #define MDIO_ID_OUI(_id32) (_id32 >> 10) -/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out +/* Bits in MMDREG_DEVS0. Someone thoughtfully layed things out * so the 'bit present' bit number of an MMD is the number of * that MMD */ #define DEV_PRESENT_BIT(_b) (1 << _b) -#define MDIO_MMDREG_DEVS_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS) -#define MDIO_MMDREG_DEVS_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS) -#define MDIO_MMDREG_DEVS_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD) -#define MDIO_MMDREG_DEVS_AN DEV_PRESENT_BIT(MDIO_MMD_AN) -#define MDIO_MMDREG_DEVS_C22EXT DEV_PRESENT_BIT(MDIO_MMD_C22EXT) - -/* Bits in MMDREG_SPEED */ -#define MDIO_MMDREG_SPEED_10G_LBN 0 -#define MDIO_MMDREG_SPEED_10G_WIDTH 1 -#define MDIO_MMDREG_SPEED_1000M_LBN 4 -#define MDIO_MMDREG_SPEED_1000M_WIDTH 1 -#define MDIO_MMDREG_SPEED_100M_LBN 5 -#define MDIO_MMDREG_SPEED_100M_WIDTH 1 -#define MDIO_MMDREG_SPEED_10M_LBN 6 -#define MDIO_MMDREG_SPEED_10M_WIDTH 1 +#define MDIO_MMDREG_DEVS0_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS) +#define MDIO_MMDREG_DEVS0_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS) +#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD) /* Bits in MMDREG_STAT2 */ #define MDIO_MMDREG_STAT2_PRESENT_VAL (2) @@ -128,30 +114,17 @@ #define MDIO_PMAPMD_CTRL2_10_BT (0xf) #define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf) -/* PMA 10GBT registers */ -#define MDIO_PMAPMD_10GBT_TXPWR (131) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0) -#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1) - /* PHY XGXS lane state */ #define MDIO_PHYXS_LANE_STATE (0x18) #define MDIO_PHYXS_LANE_ALIGNED_LBN (12) /* AN registers */ -#define MDIO_AN_CTRL_XNP_LBN 13 #define MDIO_AN_STATUS (1) #define MDIO_AN_STATUS_XNP_LBN (7) #define MDIO_AN_STATUS_PAGE_LBN (6) #define MDIO_AN_STATUS_AN_DONE_LBN (5) #define MDIO_AN_STATUS_LP_AN_CAP_LBN (0) -#define MDIO_AN_ADVERTISE 16 -#define MDIO_AN_ADVERTISE_XNP_LBN 12 -#define MDIO_AN_LPA 19 -#define MDIO_AN_XNP 22 -#define MDIO_AN_LPA_XNP 25 - -#define MDIO_AN_10GBT_ADVERTISE 32 #define MDIO_AN_10GBT_STATUS (33) #define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */ #define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */ @@ -278,29 +251,12 @@ extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx, extern void mdio_clause45_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); -/* Read (some of) the PHY settings over MDIO */ -extern void -mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd, - u32 xnp, u32 xnp_lpa); - /* Set (some of) the PHY settings over MDIO */ extern int mdio_clause45_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); -/* Set pause parameters to be advertised through AN (if available) */ -extern void mdio_clause45_set_pause(struct efx_nic *efx); - -/* Get pause parameters from AN if available (otherwise return - * requested pause parameters) - */ -enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx); - /* Wait for specified MMDs to exit reset within a timeout */ extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask); -/* Set or clear flag, debouncing */ -extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, - u16 addr, int bit, bool sense); - #endif /* EFX_MDIO_10G_H */ diff --git a/trunk/drivers/net/sfc/mtd.c b/trunk/drivers/net/sfc/mtd.c index 665cafb88d6a..a1e6c2875fc0 100644 --- a/trunk/drivers/net/sfc/mtd.c +++ b/trunk/drivers/net/sfc/mtd.c @@ -76,7 +76,7 @@ static int efx_spi_unlock(const struct efx_spi_device *spi) rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status)); if (rc) return rc; - rc = falcon_spi_wait_write(spi); + rc = falcon_spi_fast_wait(spi); if (rc) return rc; diff --git a/trunk/drivers/net/sfc/net_driver.h b/trunk/drivers/net/sfc/net_driver.h index 03feaee04acd..e596c9a6a4c4 100644 --- a/trunk/drivers/net/sfc/net_driver.h +++ b/trunk/drivers/net/sfc/net_driver.h @@ -42,7 +42,7 @@ #ifndef EFX_DRIVER_NAME #define EFX_DRIVER_NAME "sfc" #endif -#define EFX_DRIVER_VERSION "2.3" +#define EFX_DRIVER_VERSION "2.2" #ifdef EFX_ENABLE_DEBUG #define EFX_BUG_ON_PARANOID(x) BUG_ON(x) @@ -327,7 +327,6 @@ enum efx_rx_alloc_method { * * @efx: Associated Efx NIC * @channel: Channel instance number - * @name: Name for channel and IRQ * @used_flags: Channel is used by net driver * @enabled: Channel enabled indicator * @irq: IRQ number (MSI and MSI-X only) @@ -358,7 +357,6 @@ enum efx_rx_alloc_method { struct efx_channel { struct efx_nic *efx; int channel; - char name[IFNAMSIZ + 6]; int used_flags; bool enabled; int irq; @@ -453,20 +451,16 @@ enum efx_int_mode { enum phy_type { PHY_TYPE_NONE = 0, - PHY_TYPE_TXC43128 = 1, - PHY_TYPE_88E1111 = 2, - PHY_TYPE_SFX7101 = 3, - PHY_TYPE_QT2022C2 = 4, + PHY_TYPE_CX4_RTMR = 1, + PHY_TYPE_1G_ALASKA = 2, + PHY_TYPE_10XPRESS = 3, + PHY_TYPE_XFP = 4, PHY_TYPE_PM8358 = 6, - PHY_TYPE_SFT9001A = 8, - PHY_TYPE_SFT9001B = 10, PHY_TYPE_MAX /* Insert any new items before this */ }; #define PHY_ADDR_INVALID 0xff -#define EFX_IS10G(efx) ((efx)->link_speed == 10000) - enum nic_state { STATE_INIT = 0, STATE_RUNNING = 1, @@ -507,55 +501,6 @@ enum efx_fc_type { EFX_FC_AUTO = 4, }; -/* Supported MAC bit-mask */ -enum efx_mac_type { - EFX_GMAC = 1, - EFX_XMAC = 2, -}; - -static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc) -{ - unsigned int adv = 0; - if (wanted_fc & EFX_FC_RX) - adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - if (wanted_fc & EFX_FC_TX) - adv ^= ADVERTISE_PAUSE_ASYM; - return adv; -} - -static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc, - unsigned int lpa) -{ - unsigned int adv = efx_fc_advertise(wanted_fc); - - if (!(wanted_fc & EFX_FC_AUTO)) - return wanted_fc; - - if (adv & lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX | EFX_FC_TX; - if (adv & lpa & ADVERTISE_PAUSE_ASYM) { - if (adv & ADVERTISE_PAUSE_CAP) - return EFX_FC_RX; - if (lpa & ADVERTISE_PAUSE_CAP) - return EFX_FC_TX; - } - return 0; -} - -/** - * struct efx_mac_operations - Efx MAC operations table - * @reconfigure: Reconfigure MAC. Serialised by the mac_lock - * @update_stats: Update statistics - * @irq: Hardware MAC event callback. Serialised by the mac_lock - * @poll: Poll for hardware state. Serialised by the mac_lock - */ -struct efx_mac_operations { - void (*reconfigure) (struct efx_nic *efx); - void (*update_stats) (struct efx_nic *efx); - void (*irq) (struct efx_nic *efx); - void (*poll) (struct efx_nic *efx); -}; - /** * struct efx_phy_operations - Efx PHY operations table * @init: Initialise PHY @@ -563,27 +508,17 @@ struct efx_mac_operations { * @reconfigure: Reconfigure PHY (e.g. for new link parameters) * @clear_interrupt: Clear down interrupt * @blink: Blink LEDs - * @poll: Poll for hardware state. Serialised by the mac_lock. - * @get_settings: Get ethtool settings. Serialised by the mac_lock. - * @set_settings: Set ethtool settings. Serialised by the mac_lock. - * @set_xnp_advertise: Set abilities advertised in Extended Next Page - * (only needed where AN bit is set in mmds) + * @check_hw: Check hardware * @mmds: MMD presence mask * @loopbacks: Supported loopback modes mask */ struct efx_phy_operations { - enum efx_mac_type macs; int (*init) (struct efx_nic *efx); void (*fini) (struct efx_nic *efx); void (*reconfigure) (struct efx_nic *efx); void (*clear_interrupt) (struct efx_nic *efx); - void (*poll) (struct efx_nic *efx); + int (*check_hw) (struct efx_nic *efx); int (*test) (struct efx_nic *efx); - void (*get_settings) (struct efx_nic *efx, - struct ethtool_cmd *ecmd); - int (*set_settings) (struct efx_nic *efx, - struct ethtool_cmd *ecmd); - bool (*set_xnp_advertise) (struct efx_nic *efx, u32); int mmds; unsigned loopbacks; }; @@ -700,6 +635,7 @@ union efx_multicast_hash { * @legacy_irq: IRQ number * @workqueue: Workqueue for port reconfigures and the HW monitor. * Work items do not hold and must not acquire RTNL. + * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL. * @reset_work: Scheduled reset workitem * @monitor_work: Hardware monitor workitem * @membase_phys: Memory BAR value as physical address @@ -714,7 +650,6 @@ union efx_multicast_hash { * @rx_queue: RX DMA queues * @channel: Channels * @n_rx_queues: Number of RX queues - * @n_channels: Number of channels in use * @rx_buffer_len: RX buffer length * @rx_buffer_order: Order (log2) of number of pages for each RX buffer * @irq_status: Interrupt status buffer @@ -732,10 +667,10 @@ union efx_multicast_hash { * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, * @port_inhibited, efx_monitor() and efx_reconfigure_port() * @port_enabled: Port enabled indicator. - * Serialises efx_stop_all(), efx_start_all(), efx_monitor(), - * efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read - * under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all - * three must be held to modify it. + * Serialises efx_stop_all(), efx_start_all() and efx_monitor() and + * efx_reconfigure_work with kernel interfaces. Safe to read under any + * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must + * be held to modify it. * @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock * @port_initialized: Port initialized? * @net_dev: Operating system network device. Consider holding the rtnl lock @@ -749,7 +684,6 @@ union efx_multicast_hash { * @stats_lock: Statistics update lock. Serialises statistics fetches * @stats_enabled: Temporarily disable statistics fetches. * Serialised by @stats_lock - * @mac_op: MAC interface * @mac_address: Permanent MAC address * @phy_type: PHY type * @phy_lock: PHY access lock @@ -757,17 +691,13 @@ union efx_multicast_hash { * @phy_data: PHY private data (including PHY-specific stats) * @mii: PHY interface * @phy_mode: PHY operating mode. Serialised by @mac_lock. - * @mac_up: MAC link state * @link_up: Link status - * @link_fd: Link is full duplex - * @link_fc: Actualy flow control flags - * @link_speed: Link speed (Mbps) + * @link_options: Link options (MII/GMII format) * @n_link_state_changes: Number of times the link has changed state * @promiscuous: Promiscuous flag. Protected by netif_tx_lock. * @multicast_hash: Multicast hash table - * @wanted_fc: Wanted flow control flags - * @phy_work: work item for dealing with PHY events - * @mac_work: work item for dealing with MAC events + * @flow_control: Flow control flags - separate RX/TX so can't use link_options + * @reconfigure_work: work item for dealing with PHY events * @loopback_mode: Loopback status * @loopback_modes: Supported loopback mode bitmask * @loopback_selftest: Offline self-test private state @@ -781,6 +711,7 @@ struct efx_nic { const struct efx_nic_type *type; int legacy_irq; struct workqueue_struct *workqueue; + struct workqueue_struct *reset_workqueue; struct work_struct reset_work; struct delayed_work monitor_work; resource_size_t membase_phys; @@ -799,7 +730,6 @@ struct efx_nic { struct efx_channel channel[EFX_MAX_CHANNELS]; int n_rx_queues; - int n_channels; unsigned int rx_buffer_len; unsigned int rx_buffer_order; @@ -815,7 +745,6 @@ struct efx_nic { struct falcon_nic_data *nic_data; struct mutex mac_lock; - struct work_struct mac_work; bool port_enabled; bool port_inhibited; @@ -831,27 +760,23 @@ struct efx_nic { spinlock_t stats_lock; bool stats_enabled; - struct efx_mac_operations *mac_op; unsigned char mac_address[ETH_ALEN]; enum phy_type phy_type; spinlock_t phy_lock; - struct work_struct phy_work; struct efx_phy_operations *phy_op; void *phy_data; struct mii_if_info mii; enum efx_phy_mode phy_mode; - bool mac_up; bool link_up; - bool link_fd; - enum efx_fc_type link_fc; - unsigned int link_speed; + unsigned int link_options; unsigned int n_link_state_changes; bool promiscuous; union efx_multicast_hash multicast_hash; - enum efx_fc_type wanted_fc; + enum efx_fc_type flow_control; + struct work_struct reconfigure_work; atomic_t rx_reset; enum efx_loopback_mode loopback_mode; diff --git a/trunk/drivers/net/sfc/phy.h b/trunk/drivers/net/sfc/phy.h index 58c493ef81bb..f746536f4ffa 100644 --- a/trunk/drivers/net/sfc/phy.h +++ b/trunk/drivers/net/sfc/phy.h @@ -1,6 +1,6 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 Solarflare Communications Inc. + * Copyright 2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -11,10 +11,9 @@ #define EFX_PHY_H /**************************************************************************** - * 10Xpress (SFX7101 and SFT9001) PHYs + * 10Xpress (SFX7101) PHY */ -extern struct efx_phy_operations falcon_sfx7101_phy_ops; -extern struct efx_phy_operations falcon_sft9001_phy_ops; +extern struct efx_phy_operations falcon_tenxpress_phy_ops; extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink); extern void tenxpress_crc_err(struct efx_nic *efx); diff --git a/trunk/drivers/net/sfc/selftest.c b/trunk/drivers/net/sfc/selftest.c index 6bb09f263b33..362956e3fe17 100644 --- a/trunk/drivers/net/sfc/selftest.c +++ b/trunk/drivers/net/sfc/selftest.c @@ -26,6 +26,7 @@ #include "selftest.h" #include "boards.h" #include "workarounds.h" +#include "mac.h" #include "spi.h" #include "falcon_io.h" #include "mdio_10g.h" @@ -104,11 +105,9 @@ static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests) goto out; } - if (EFX_IS10G(efx)) { - rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); - if (rc) - goto out; - } + rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0); + if (rc) + goto out; out: mutex_unlock(&efx->mac_lock); @@ -594,14 +593,12 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd, efx->loopback_mode = mode; efx_reconfigure_port(efx); - /* Wait for the PHY to signal the link is up. Interrupts - * are enabled for PHY's using LASI, otherwise we poll() - * quickly */ + /* Wait for the PHY to signal the link is up */ count = 0; do { struct efx_channel *channel = &efx->channel[0]; - efx->phy_op->poll(efx); + falcon_check_xmac(efx); schedule_timeout_uninterruptible(HZ / 10); if (channel->work_pending) efx_process_channel_now(channel); @@ -609,12 +606,13 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd, flush_workqueue(efx->workqueue); rmb(); - /* We need both the phy and xaui links to be ok. - * rather than relying on the falcon_xmac irq/poll - * regime, just poll xaui directly */ + /* efx->link_up can be 1 even if the XAUI link is down, + * (bug5762). Usually, it's not worth bothering with the + * difference, but for selftests, we need that extra + * guarantee that the link is really, really, up. + */ link_up = efx->link_up; - if (link_up && EFX_IS10G(efx) && - !falcon_xaui_link_ok(efx)) + if (!falcon_xaui_link_ok(efx)) link_up = false; } while ((++count < 20) && !link_up); @@ -702,15 +700,8 @@ int efx_offline_test(struct efx_nic *efx, */ mutex_lock(&efx->mac_lock); efx->port_inhibited = true; - if (efx->loopback_modes) { - /* We need the 312 clock from the PHY to test the XMAC - * registers, so move into XGMII loopback if available */ - if (efx->loopback_modes & (1 << LOOPBACK_XGMII)) - efx->loopback_mode = LOOPBACK_XGMII; - else - efx->loopback_mode = __ffs(efx->loopback_modes); - } - + if (efx->loopback_modes) + efx->loopback_mode = __ffs(efx->loopback_modes); __efx_reconfigure_port(efx); mutex_unlock(&efx->mac_lock); @@ -730,6 +721,7 @@ int efx_offline_test(struct efx_nic *efx, if (ecmd_test.autoneg == AUTONEG_ENABLE) { ecmd_test.autoneg = AUTONEG_DISABLE; ecmd_test.duplex = DUPLEX_FULL; + ecmd_test.speed = SPEED_10000; } efx->loopback_mode = LOOPBACK_NONE; @@ -740,6 +732,9 @@ int efx_offline_test(struct efx_nic *efx, return rc; } + tests->loopback_speed = ecmd_test.speed; + tests->loopback_full_duplex = ecmd_test.duplex; + rc = efx_test_phy(efx, tests); if (rc && !rc2) rc2 = rc; diff --git a/trunk/drivers/net/sfc/selftest.h b/trunk/drivers/net/sfc/selftest.h index 252f7d717242..fc15df15d766 100644 --- a/trunk/drivers/net/sfc/selftest.h +++ b/trunk/drivers/net/sfc/selftest.h @@ -39,6 +39,8 @@ struct efx_self_tests { /* offline tests */ int registers; int phy; + int loopback_speed; + int loopback_full_duplex; struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; }; diff --git a/trunk/drivers/net/sfc/sfe4001.c b/trunk/drivers/net/sfc/sfe4001.c index 16b80acb9992..aa576c559ec8 100644 --- a/trunk/drivers/net/sfc/sfe4001.c +++ b/trunk/drivers/net/sfc/sfe4001.c @@ -1,6 +1,6 @@ /**************************************************************************** * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 Solarflare Communications Inc. + * Copyright 2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -8,21 +8,10 @@ */ /***************************************************************************** - * Support for the SFE4001 and SFN4111T NICs. - * - * The SFE4001 does not power-up fully at reset due to its high power - * consumption. We control its power via a PCA9539 I/O expander. - * Both boards have a MAX6647 temperature monitor which we expose to - * the lm90 driver. - * - * This also provides minimal support for reflashing the PHY, which is - * initiated by resetting it with the FLASH_CFG_1 pin pulled down. - * On SFE4001 rev A2 and later this is connected to the 3V3X output of - * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3. - * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually - * exclusive with the network device being open. + * Support for the SFE4001 NIC: driver code for the PCA9539 I/O expander that + * controls the PHY power rails, and for the MAX6647 temp. sensor used to check + * the PHY */ - #include #include "net_driver.h" #include "efx.h" @@ -182,30 +171,39 @@ static int sfe4001_poweron(struct efx_nic *efx) return rc; } -static int sfn4111t_reset(struct efx_nic *efx) +static int sfe4001_check_hw(struct efx_nic *efx) { - efx_oword_t reg; + s32 status; - /* GPIO pins are also used for I2C, so block that temporarily */ - mutex_lock(&efx->i2c_adap.bus_lock); + /* If XAUI link is up then do not monitor */ + if (EFX_WORKAROUND_7884(efx) && falcon_xaui_link_ok(efx)) + return 0; - falcon_read(efx, ®, GPIO_CTL_REG_KER); - EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true); - EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false); - falcon_write(efx, ®, GPIO_CTL_REG_KER); - msleep(1000); - EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true); - EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true); - EFX_SET_OWORD_FIELD(reg, GPIO3_OUT, - !(efx->phy_mode & PHY_MODE_SPECIAL)); - falcon_write(efx, ®, GPIO_CTL_REG_KER); + /* Check the powered status of the PHY. Lack of power implies that + * the MAX6647 has shut down power to it, probably due to a temp. + * alarm. Reading the power status rather than the MAX6647 status + * directly because the later is read-to-clear and would thus + * start to power up the PHY again when polled, causing us to blip + * the power undesirably. + * We know we can read from the IO expander because we did + * it during power-on. Assume failure now is bad news. */ + status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN); + if (status >= 0 && + (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0) + return 0; - mutex_unlock(&efx->i2c_adap.bus_lock); + /* Use board power control, not PHY power control */ + sfe4001_poweroff(efx); + efx->phy_mode = PHY_MODE_OFF; - ssleep(1); - return 0; + return (status < 0) ? -EIO : -ERANGE; } +/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin + * using the 3V3X output of the IO-expander. Allow the user to set + * this when the device is stopped, and keep it stopped then. + */ + static ssize_t show_phy_flash_cfg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -233,10 +231,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev, err = -EBUSY; } else { efx->phy_mode = new_mode; - if (efx->board_info.type == EFX_BOARD_SFE4001) - err = sfe4001_poweron(efx); - else - err = sfn4111t_reset(efx); + err = sfe4001_poweron(efx); efx_reconfigure_port(efx); } rtnl_unlock(); @@ -256,34 +251,6 @@ static void sfe4001_fini(struct efx_nic *efx) i2c_unregister_device(efx->board_info.hwmon_client); } -static int sfe4001_check_hw(struct efx_nic *efx) -{ - s32 status; - - /* If XAUI link is up then do not monitor */ - if (EFX_WORKAROUND_7884(efx) && efx->mac_up) - return 0; - - /* Check the powered status of the PHY. Lack of power implies that - * the MAX6647 has shut down power to it, probably due to a temp. - * alarm. Reading the power status rather than the MAX6647 status - * directly because the later is read-to-clear and would thus - * start to power up the PHY again when polled, causing us to blip - * the power undesirably. - * We know we can read from the IO expander because we did - * it during power-on. Assume failure now is bad news. */ - status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN); - if (status >= 0 && - (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0) - return 0; - - /* Use board power control, not PHY power control */ - sfe4001_poweroff(efx); - efx->phy_mode = PHY_MODE_OFF; - - return (status < 0) ? -EIO : -ERANGE; -} - static struct i2c_board_info sfe4001_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), .irq = -1, @@ -345,61 +312,3 @@ int sfe4001_init(struct efx_nic *efx) i2c_unregister_device(efx->board_info.hwmon_client); return rc; } - -static int sfn4111t_check_hw(struct efx_nic *efx) -{ - s32 status; - - /* If XAUI link is up then do not monitor */ - if (EFX_WORKAROUND_7884(efx) && efx->mac_up) - return 0; - - /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */ - status = i2c_smbus_read_byte_data(efx->board_info.hwmon_client, - MAX664X_REG_RSL); - if (status < 0) - return -EIO; - if (status & 0x57) - return -ERANGE; - return 0; -} - -static void sfn4111t_fini(struct efx_nic *efx) -{ - EFX_INFO(efx, "%s\n", __func__); - - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - i2c_unregister_device(efx->board_info.hwmon_client); -} - -static struct i2c_board_info sfn4111t_hwmon_info = { - I2C_BOARD_INFO("max6647", 0x4e), - .irq = -1, -}; - -int sfn4111t_init(struct efx_nic *efx) -{ - int rc; - - efx->board_info.hwmon_client = - i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info); - if (!efx->board_info.hwmon_client) - return -EIO; - - efx->board_info.blink = tenxpress_phy_blink; - efx->board_info.monitor = sfn4111t_check_hw; - efx->board_info.fini = sfn4111t_fini; - - rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - if (rc) - goto fail_hwmon; - - if (efx->phy_mode & PHY_MODE_SPECIAL) - sfn4111t_reset(efx); - - return 0; - -fail_hwmon: - i2c_unregister_device(efx->board_info.hwmon_client); - return rc; -} diff --git a/trunk/drivers/net/sfc/spi.h b/trunk/drivers/net/sfc/spi.h index 1b1ceb411671..c4aca132348a 100644 --- a/trunk/drivers/net/sfc/spi.h +++ b/trunk/drivers/net/sfc/spi.h @@ -68,8 +68,8 @@ struct efx_spi_device { }; int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command, - int address, const void* in, void *out, size_t len); -int falcon_spi_wait_write(const struct efx_spi_device *spi); + int address, const void* in, void *out, unsigned int len); +int falcon_spi_fast_wait(const struct efx_spi_device *spi); int falcon_spi_read(const struct efx_spi_device *spi, loff_t start, size_t len, size_t *retlen, u8 *buffer); int falcon_spi_write(const struct efx_spi_device *spi, loff_t start, diff --git a/trunk/drivers/net/sfc/tenxpress.c b/trunk/drivers/net/sfc/tenxpress.c index b3ca2dc8040d..8d41c29b9d7b 100644 --- a/trunk/drivers/net/sfc/tenxpress.c +++ b/trunk/drivers/net/sfc/tenxpress.c @@ -1,6 +1,6 @@ /**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2007-2008 Solarflare Communications Inc. + * Driver for Solarflare 802.3an compliant PHY + * Copyright 2007 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -10,76 +10,45 @@ #include #include #include "efx.h" +#include "gmii.h" #include "mdio_10g.h" #include "falcon.h" #include "phy.h" #include "falcon_hwdefs.h" #include "boards.h" -#include "workarounds.h" -#include "selftest.h" +#include "mac.h" -/* We expect these MMDs to be in the package. SFT9001 also has a - * clause 22 extension MMD, but since it doesn't have all the generic - * MMD registers it is pointless to include it here. - */ -#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PHYXS | \ - MDIO_MMDREG_DEVS_AN) - -#define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ - (1 << LOOPBACK_PCS) | \ - (1 << LOOPBACK_PMAPMD) | \ - (1 << LOOPBACK_NETWORK)) - -#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \ - (1 << LOOPBACK_PHYXS) | \ - (1 << LOOPBACK_PCS) | \ - (1 << LOOPBACK_PMAPMD) | \ - (1 << LOOPBACK_NETWORK)) +/* We expect these MMDs to be in the package */ +/* AN not here as mdio_check_mmds() requires STAT2 support */ +#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PMAPMD | \ + MDIO_MMDREG_DEVS0_PCS | \ + MDIO_MMDREG_DEVS0_PHYXS) + +#define TENXPRESS_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ + (1 << LOOPBACK_PCS) | \ + (1 << LOOPBACK_PMAPMD) | \ + (1 << LOOPBACK_NETWORK)) /* We complain if we fail to see the link partner as 10G capable this many * times in a row (must be > 1 as sampling the autoneg. registers is racy) */ #define MAX_BAD_LP_TRIES (5) -/* LASI Control */ -#define PMA_PMD_LASI_CTRL 36866 -#define PMA_PMD_LASI_STATUS 36869 -#define PMA_PMD_LS_ALARM_LBN 0 -#define PMA_PMD_LS_ALARM_WIDTH 1 -#define PMA_PMD_TX_ALARM_LBN 1 -#define PMA_PMD_TX_ALARM_WIDTH 1 -#define PMA_PMD_RX_ALARM_LBN 2 -#define PMA_PMD_RX_ALARM_WIDTH 1 -#define PMA_PMD_AN_ALARM_LBN 3 -#define PMA_PMD_AN_ALARM_WIDTH 1 - /* Extended control register */ -#define PMA_PMD_XCONTROL_REG 49152 -#define PMA_PMD_EXT_GMII_EN_LBN 1 -#define PMA_PMD_EXT_GMII_EN_WIDTH 1 -#define PMA_PMD_EXT_CLK_OUT_LBN 2 -#define PMA_PMD_EXT_CLK_OUT_WIDTH 1 -#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */ -#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1 -#define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */ -#define PMA_PMD_EXT_CLK312_WIDTH 1 -#define PMA_PMD_EXT_LPOWER_LBN 12 -#define PMA_PMD_EXT_LPOWER_WIDTH 1 -#define PMA_PMD_EXT_SSR_LBN 15 -#define PMA_PMD_EXT_SSR_WIDTH 1 +#define PMA_PMD_XCONTROL_REG 0xc000 +#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 +#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1 /* extended status register */ -#define PMA_PMD_XSTATUS_REG 49153 +#define PMA_PMD_XSTATUS_REG 0xc001 #define PMA_PMD_XSTAT_FLP_LBN (12) /* LED control register */ -#define PMA_PMD_LED_CTRL_REG 49159 +#define PMA_PMD_LED_CTRL_REG (0xc007) #define PMA_PMA_LED_ACTIVITY_LBN (3) /* LED function override register */ -#define PMA_PMD_LED_OVERR_REG 49161 +#define PMA_PMD_LED_OVERR_REG (0xc009) /* Bit positions for different LEDs (there are more but not wired on SFE4001)*/ #define PMA_PMD_LED_LINK_LBN (0) #define PMA_PMD_LED_SPEED_LBN (2) @@ -90,80 +59,41 @@ #define PMA_PMD_LED_ON (1) #define PMA_PMD_LED_OFF (2) #define PMA_PMD_LED_FLASH (3) -#define PMA_PMD_LED_MASK 3 /* All LEDs under hardware control */ #define PMA_PMD_LED_FULL_AUTO (0) /* Green and Amber under hardware control, Red off */ #define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) -#define PMA_PMD_SPEED_ENABLE_REG 49192 -#define PMA_PMD_100TX_ADV_LBN 1 -#define PMA_PMD_100TX_ADV_WIDTH 1 -#define PMA_PMD_1000T_ADV_LBN 2 -#define PMA_PMD_1000T_ADV_WIDTH 1 -#define PMA_PMD_10000T_ADV_LBN 3 -#define PMA_PMD_10000T_ADV_WIDTH 1 -#define PMA_PMD_SPEED_LBN 4 -#define PMA_PMD_SPEED_WIDTH 4 - -/* Serdes control registers - SFT9001 only */ -#define PMA_PMD_CSERDES_CTRL_REG 64258 -/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */ -#define PMA_PMD_CSERDES_DEFAULT 0x000f - -/* Misc register defines - SFX7101 only */ -#define PCS_CLOCK_CTRL_REG 55297 + +/* Special Software reset register */ +#define PMA_PMD_EXT_CTRL_REG 49152 +#define PMA_PMD_EXT_SSR_LBN 15 + +/* Misc register defines */ +#define PCS_CLOCK_CTRL_REG 0xd801 #define PLL312_RST_N_LBN 2 -#define PCS_SOFT_RST2_REG 55302 +#define PCS_SOFT_RST2_REG 0xd806 #define SERDES_RST_N_LBN 13 #define XGXS_RST_N_LBN 12 -#define PCS_TEST_SELECT_REG 55303 /* PRM 10.5.8 */ +#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */ #define CLK312_EN_LBN 3 /* PHYXS registers */ -#define PHYXS_XCONTROL_REG 49152 -#define PHYXS_RESET_LBN 15 -#define PHYXS_RESET_WIDTH 1 - #define PHYXS_TEST1 (49162) #define LOOPBACK_NEAR_LBN (8) #define LOOPBACK_NEAR_WIDTH (1) -#define PCS_10GBASET_STAT1 32 -#define PCS_10GBASET_BLKLK_LBN 0 -#define PCS_10GBASET_BLKLK_WIDTH 1 - /* Boot status register */ -#define PCS_BOOT_STATUS_REG 53248 +#define PCS_BOOT_STATUS_REG (0xd000) #define PCS_BOOT_FATAL_ERR_LBN (0) #define PCS_BOOT_PROGRESS_LBN (1) #define PCS_BOOT_PROGRESS_WIDTH (2) #define PCS_BOOT_COMPLETE_LBN (3) - #define PCS_BOOT_MAX_DELAY (100) #define PCS_BOOT_POLL_DELAY (10) -/* 100M/1G PHY registers */ -#define GPHY_XCONTROL_REG 49152 -#define GPHY_ISOLATE_LBN 10 -#define GPHY_ISOLATE_WIDTH 1 -#define GPHY_DUPLEX_LBN 8 -#define GPHY_DUPLEX_WIDTH 1 -#define GPHY_LOOPBACK_NEAR_LBN 14 -#define GPHY_LOOPBACK_NEAR_WIDTH 1 - -#define C22EXT_STATUS_REG 49153 -#define C22EXT_STATUS_LINK_LBN 2 -#define C22EXT_STATUS_LINK_WIDTH 1 - -#define C22EXT_MSTSLV_REG 49162 -#define C22EXT_MSTSLV_1000_HD_LBN 10 -#define C22EXT_MSTSLV_1000_HD_WIDTH 1 -#define C22EXT_MSTSLV_1000_FD_LBN 11 -#define C22EXT_MSTSLV_1000_FD_WIDTH 1 - /* Time to wait between powering down the LNPGA and turning off the power * rails */ #define LNPGA_PDOWN_WAIT (HZ / 5) @@ -187,38 +117,6 @@ void tenxpress_crc_err(struct efx_nic *efx) atomic_inc(&phy_data->bad_crc_count); } -static ssize_t show_phy_short_reach(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - int reg; - - reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR); - return sprintf(buf, "%d\n", - !!(reg & (1 << MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN))); -} - -static ssize_t set_phy_short_reach(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - - rtnl_lock(); - mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - MDIO_PMAPMD_10GBT_TXPWR, - MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN, - count != 0 && *buf != '0'); - efx_reconfigure_port(efx); - rtnl_unlock(); - - return count; -} - -static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, - set_phy_short_reach); - /* Check that the C166 has booted successfully */ static int tenxpress_phy_check(struct efx_nic *efx) { @@ -250,42 +148,27 @@ static int tenxpress_phy_check(struct efx_nic *efx) static int tenxpress_init(struct efx_nic *efx) { - int phy_id = efx->mii.phy_id; - int reg; - int rc; + int rc, reg; - if (efx->phy_type == PHY_TYPE_SFX7101) { - /* Enable 312.5 MHz clock */ - mdio_clause45_write(efx, phy_id, - MDIO_MMD_PCS, PCS_TEST_SELECT_REG, - 1 << CLK312_EN_LBN); - } else { - /* Enable 312.5 MHz clock and GMII */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); - reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | - (1 << PMA_PMD_EXT_CLK_OUT_LBN) | - (1 << PMA_PMD_EXT_CLK312_LBN)); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, GPHY_ISOLATE_LBN, - false); - } + /* Turn on the clock */ + reg = (1 << CLK312_EN_LBN); + mdio_clause45_write(efx, efx->mii.phy_id, + MDIO_MMD_PCS, PCS_TEST_SELECT_REG, reg); rc = tenxpress_phy_check(efx); if (rc < 0) return rc; /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ - if (efx->phy_type == PHY_TYPE_SFX7101) { - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_CTRL_REG, - PMA_PMA_LED_ACTIVITY_LBN, - true); - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, PMA_PMD_LED_DEFAULT); - } + reg = mdio_clause45_read(efx, efx->mii.phy_id, + MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG); + reg |= (1 << PMA_PMA_LED_ACTIVITY_LBN); + mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_LED_CTRL_REG, reg); + + reg = PMA_PMD_LED_DEFAULT; + mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_LED_OVERR_REG, reg); return rc; } @@ -301,43 +184,22 @@ static int tenxpress_phy_init(struct efx_nic *efx) efx->phy_data = phy_data; phy_data->phy_mode = efx->phy_mode; - if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { - if (efx->phy_type == PHY_TYPE_SFT9001A) { - int reg; - reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); - reg |= (1 << PMA_PMD_EXT_SSR_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdelay(200); - } - - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); - if (rc < 0) - goto fail; + rc = mdio_clause45_wait_reset_mmds(efx, + TENXPRESS_REQUIRED_DEVS); + if (rc < 0) + goto fail; - rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); - if (rc < 0) - goto fail; - } + rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); + if (rc < 0) + goto fail; rc = tenxpress_init(efx); if (rc < 0) goto fail; - if (efx->phy_type == PHY_TYPE_SFT9001B) { - rc = device_create_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - if (rc) - goto fail; - } - schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ - /* Let XGXS and SerDes out of reset */ + /* Let XGXS and SerDes out of reset and resets 10XPress */ falcon_reset_xaui(efx); return 0; @@ -348,24 +210,21 @@ static int tenxpress_phy_init(struct efx_nic *efx) return rc; } -/* Perform a "special software reset" on the PHY. The caller is - * responsible for saving and restoring the PHY hardware registers - * properly, and masking/unmasking LASI */ static int tenxpress_special_reset(struct efx_nic *efx) { int rc, reg; /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so * a special software reset can glitch the XGMAC sufficiently for stats - * requests to fail. Since we don't often special_reset, just lock. */ + * requests to fail. Since we don't ofen special_reset, just lock. */ spin_lock(&efx->stats_lock); /* Initiate reset */ reg = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); + MDIO_MMD_PMAPMD, PMA_PMD_EXT_CTRL_REG); reg |= (1 << PMA_PMD_EXT_SSR_LBN); mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); + PMA_PMD_EXT_CTRL_REG, reg); mdelay(200); @@ -380,254 +239,190 @@ static int tenxpress_special_reset(struct efx_nic *efx) if (rc < 0) goto unlock; - /* Wait for the XGXS state machine to churn */ - mdelay(10); unlock: spin_unlock(&efx->stats_lock); return rc; } -static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok) +static void tenxpress_set_bad_lp(struct efx_nic *efx, bool bad_lp) { struct tenxpress_phy_data *pd = efx->phy_data; - int phy_id = efx->mii.phy_id; - bool bad_lp; int reg; - if (link_ok) { - bad_lp = false; - } else { - /* Check that AN has started but not completed. */ - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, - MDIO_AN_STATUS); - if (!(reg & (1 << MDIO_AN_STATUS_LP_AN_CAP_LBN))) - return; /* LP status is unknown */ - bad_lp = !(reg & (1 << MDIO_AN_STATUS_AN_DONE_LBN)); - if (bad_lp) - pd->bad_lp_tries++; - } - /* Nothing to do if all is well and was previously so. */ - if (!pd->bad_lp_tries) + if (!(bad_lp || pd->bad_lp_tries)) return; - /* Use the RX (red) LED as an error indicator once we've seen AN - * failure several times in a row, and also log a message. */ - if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG); - reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN); - if (!bad_lp) { - reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN; - } else { - reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN; - EFX_ERR(efx, "appears to be plugged into a port" - " that is not 10GBASE-T capable. The PHY" - " supports 10GBASE-T ONLY, so no link can" - " be established\n"); - } - mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_LED_OVERR_REG, reg); - pd->bad_lp_tries = bad_lp; - } -} - -static bool sfx7101_link_ok(struct efx_nic *efx) -{ - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PHYXS); -} + reg = mdio_clause45_read(efx, efx->mii.phy_id, + MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG); -static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - int phy_id = efx->mii.phy_id; - u32 reg; - - if (efx->loopback_mode == LOOPBACK_GPHY) - return true; - else if (efx_phy_mode_disabled(efx->phy_mode)) - return false; - else if (efx->loopback_mode) - return mdio_clause45_links_ok(efx, - MDIO_MMDREG_DEVS_PMAPMD | - MDIO_MMDREG_DEVS_PCS | - MDIO_MMDREG_DEVS_PHYXS); - - /* We must use the same definition of link state as LASI, - * otherwise we can miss a link state transition - */ - if (ecmd->speed == 10000) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, - PCS_10GBASET_STAT1); - return reg & (1 << PCS_10GBASET_BLKLK_LBN); + if (bad_lp) + pd->bad_lp_tries++; + else + pd->bad_lp_tries = 0; + + if (pd->bad_lp_tries == MAX_BAD_LP_TRIES) { + pd->bad_lp_tries = 0; /* Restart count */ + reg &= ~(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN); + reg |= (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN); + EFX_ERR(efx, "This NIC appears to be plugged into" + " a port that is not 10GBASE-T capable.\n" + " This PHY is 10GBASE-T ONLY, so no link can" + " be established.\n"); } else { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - C22EXT_STATUS_REG); - return reg & (1 << C22EXT_STATUS_LINK_LBN); + reg |= (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN); } + mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_LED_OVERR_REG, reg); } -static void tenxpress_ext_loopback(struct efx_nic *efx) +/* Check link status and return a boolean OK value. If the link is NOT + * OK we have a quick rummage round to see if we appear to be plugged + * into a non-10GBT port and if so warn the user that they won't get + * link any time soon as we are 10GBT only, unless caller specified + * not to do this check (it isn't useful in loopback) */ +static bool tenxpress_link_ok(struct efx_nic *efx, bool check_lp) { - int phy_id = efx->mii.phy_id; + bool ok = mdio_clause45_links_ok(efx, TENXPRESS_REQUIRED_DEVS); + + if (ok) { + tenxpress_set_bad_lp(efx, false); + } else if (check_lp) { + /* Are we plugged into the wrong sort of link? */ + bool bad_lp = false; + int phy_id = efx->mii.phy_id; + int an_stat = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, + MDIO_AN_STATUS); + int xphy_stat = mdio_clause45_read(efx, phy_id, + MDIO_MMD_PMAPMD, + PMA_PMD_XSTATUS_REG); + /* Are we plugged into anything that sends FLPs? If + * not we can't distinguish between not being plugged + * in and being plugged into a non-AN antique. The FLP + * bit has the advantage of not clearing when autoneg + * restarts. */ + if (!(xphy_stat & (1 << PMA_PMD_XSTAT_FLP_LBN))) { + tenxpress_set_bad_lp(efx, false); + return ok; + } - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS, - PHYXS_TEST1, LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_PHYXS); - if (efx->phy_type != PHY_TYPE_SFX7101) - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, - GPHY_LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_GPHY); + /* If it can do 10GBT it must be XNP capable */ + bad_lp = !(an_stat & (1 << MDIO_AN_STATUS_XNP_LBN)); + if (!bad_lp && (an_stat & (1 << MDIO_AN_STATUS_PAGE_LBN))) { + bad_lp = !(mdio_clause45_read(efx, phy_id, + MDIO_MMD_AN, MDIO_AN_10GBT_STATUS) & + (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)); + } + tenxpress_set_bad_lp(efx, bad_lp); + } + return ok; } -static void tenxpress_low_power(struct efx_nic *efx) +static void tenxpress_phyxs_loopback(struct efx_nic *efx) { int phy_id = efx->mii.phy_id; + int ctrl1, ctrl2; - if (efx->phy_type == PHY_TYPE_SFX7101) - mdio_clause45_set_mmds_lpower( - efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), - TENXPRESS_REQUIRED_DEVS); + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, + PHYXS_TEST1); + if (efx->loopback_mode == LOOPBACK_PHYXS) + ctrl2 |= (1 << LOOPBACK_NEAR_LBN); else - mdio_clause45_set_flag( - efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, PMA_PMD_EXT_LPOWER_LBN, - !!(efx->phy_mode & PHY_MODE_LOW_POWER)); + ctrl2 &= ~(1 << LOOPBACK_NEAR_LBN); + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS, + PHYXS_TEST1, ctrl2); } static void tenxpress_phy_reconfigure(struct efx_nic *efx) { struct tenxpress_phy_data *phy_data = efx->phy_data; - struct ethtool_cmd ecmd; - bool phy_mode_change, loop_reset, loop_toggle, loopback; + bool loop_change = LOOPBACK_OUT_OF(phy_data, efx, + TENXPRESS_LOOPBACKS); - if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) { + if (efx->phy_mode & PHY_MODE_SPECIAL) { phy_data->phy_mode = efx->phy_mode; return; } - tenxpress_low_power(efx); - - phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL && - phy_data->phy_mode != PHY_MODE_NORMAL); - loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks; - loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks); - loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) || - LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY)); - - if (loop_reset || loop_toggle || loopback || phy_mode_change) { - int rc; - - efx->phy_op->get_settings(efx, &ecmd); - - if (loop_reset || phy_mode_change) { - tenxpress_special_reset(efx); - - /* Reset XAUI if we were in 10G, and are staying - * in 10G. If we're moving into and out of 10G - * then xaui will be reset anyway */ - if (EFX_IS10G(efx)) - falcon_reset_xaui(efx); - } - - if (efx->phy_type != PHY_TYPE_SFX7101) { - /* Only change autoneg once, on coming out or - * going into loopback */ - if (loop_toggle) - ecmd.autoneg = !loopback; - if (loopback) { - ecmd.duplex = DUPLEX_FULL; - if (efx->loopback_mode == LOOPBACK_GPHY) - ecmd.speed = SPEED_1000; - else - ecmd.speed = SPEED_10000; - } - } - - rc = efx->phy_op->set_settings(efx, &ecmd); - WARN_ON(rc); + /* When coming out of transmit disable, coming out of low power + * mode, or moving out of any PHY internal loopback mode, + * perform a special software reset */ + if ((efx->phy_mode == PHY_MODE_NORMAL && + phy_data->phy_mode != PHY_MODE_NORMAL) || + loop_change) { + tenxpress_special_reset(efx); + falcon_reset_xaui(efx); } mdio_clause45_transmit_disable(efx); mdio_clause45_phy_reconfigure(efx); - tenxpress_ext_loopback(efx); + tenxpress_phyxs_loopback(efx); phy_data->loopback_mode = efx->loopback_mode; phy_data->phy_mode = efx->phy_mode; + efx->link_up = tenxpress_link_ok(efx, false); + efx->link_options = GM_LPA_10000FULL; +} - if (efx->phy_type == PHY_TYPE_SFX7101) { - efx->link_speed = 10000; - efx->link_fd = true; - efx->link_up = sfx7101_link_ok(efx); - } else { - efx->phy_op->get_settings(efx, &ecmd); - efx->link_speed = ecmd.speed; - efx->link_fd = ecmd.duplex == DUPLEX_FULL; - efx->link_up = sft9001_link_ok(efx, &ecmd); - } - efx->link_fc = mdio_clause45_get_pause(efx); +static void tenxpress_phy_clear_interrupt(struct efx_nic *efx) +{ + /* Nothing done here - LASI interrupts aren't reliable so poll */ } + /* Poll PHY for interrupt */ -static void tenxpress_phy_poll(struct efx_nic *efx) +static int tenxpress_phy_check_hw(struct efx_nic *efx) { struct tenxpress_phy_data *phy_data = efx->phy_data; - bool change = false, link_ok; - unsigned link_fc; + bool link_ok; + int rc = 0; - if (efx->phy_type == PHY_TYPE_SFX7101) { - link_ok = sfx7101_link_ok(efx); - if (link_ok != efx->link_up) { - change = true; - } else { - link_fc = mdio_clause45_get_pause(efx); - if (link_fc != efx->link_fc) - change = true; - } - sfx7101_check_bad_lp(efx, link_ok); - } else { - u32 status = mdio_clause45_read(efx, efx->mii.phy_id, - MDIO_MMD_PMAPMD, - PMA_PMD_LASI_STATUS); - if (status & (1 << PMA_PMD_LS_ALARM_LBN)) - change = true; - } + link_ok = tenxpress_link_ok(efx, true); - if (change) - falcon_sim_phy_event(efx); + if (link_ok != efx->link_up) + falcon_xmac_sim_phy_event(efx); if (phy_data->phy_mode != PHY_MODE_NORMAL) - return; + return 0; - if (EFX_WORKAROUND_10750(efx) && - atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) { + if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) { EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n"); falcon_reset_xaui(efx); atomic_set(&phy_data->bad_crc_count, 0); } + + rc = efx->board_info.monitor(efx); + if (rc) { + EFX_ERR(efx, "Board sensor %s; shutting down PHY\n", + (rc == -ERANGE) ? "reported fault" : "failed"); + if (efx->phy_mode & PHY_MODE_OFF) { + /* Assume that board has shut PHY off */ + phy_data->phy_mode = PHY_MODE_OFF; + } else { + efx->phy_mode |= PHY_MODE_LOW_POWER; + mdio_clause45_set_mmds_lpower(efx, true, + efx->phy_op->mmds); + phy_data->phy_mode |= PHY_MODE_LOW_POWER; + } + } + + return rc; } static void tenxpress_phy_fini(struct efx_nic *efx) { int reg; - if (efx->phy_type == PHY_TYPE_SFT9001B) { - device_remove_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - } else { - /* Power down the LNPGA */ - reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); - mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - - /* Waiting here ensures that the board fini, which can turn - * off the power to the PHY, won't get run until the LNPGA - * powerdown has been given long enough to complete. */ - schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ - } + /* Power down the LNPGA */ + reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); + mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_XCONTROL_REG, reg); + + /* Waiting here ensures that the board fini, which can turn off the + * power to the PHY, won't get run until the LNPGA powerdown has been + * given long enough to complete. */ + schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ kfree(efx->phy_data); efx->phy_data = NULL; @@ -657,134 +452,13 @@ static int tenxpress_phy_test(struct efx_nic *efx) return tenxpress_special_reset(efx); } -static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) -{ - int phy = efx->mii.phy_id; - u32 lpa = 0; - int reg; - - if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT, - C22EXT_MSTSLV_REG); - if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN)) - lpa |= ADVERTISED_1000baseT_Half; - if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN)) - lpa |= ADVERTISED_1000baseT_Full; - } - reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS); - if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN)) - lpa |= ADVERTISED_10000baseT_Full; - return lpa; -} - -static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full, - tenxpress_get_xnp_lpa(efx)); - ecmd->supported |= SUPPORTED_10000baseT_Full; - ecmd->advertising |= ADVERTISED_10000baseT_Full; -} - -static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - int phy_id = efx->mii.phy_id; - u32 xnp_adv = 0; - int reg; - - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, - PMA_PMD_SPEED_ENABLE_REG); - if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN))) - xnp_adv |= ADVERTISED_100baseT_Full; - if (reg & (1 << PMA_PMD_1000T_ADV_LBN)) - xnp_adv |= ADVERTISED_1000baseT_Full; - if (reg & (1 << PMA_PMD_10000T_ADV_LBN)) - xnp_adv |= ADVERTISED_10000baseT_Full; - - mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv, - tenxpress_get_xnp_lpa(efx)); - - ecmd->supported |= (SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full); - - /* Use the vendor defined C22ext register for duplex settings */ - if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) { - reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG); - ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ? - DUPLEX_FULL : DUPLEX_HALF); - } -} - -static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - int phy_id = efx->mii.phy_id; - int rc; - - rc = mdio_clause45_set_settings(efx, ecmd); - if (rc) - return rc; - - if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) - mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN, - ecmd->duplex == DUPLEX_FULL); - - return rc; -} - -static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising) -{ - int phy = efx->mii.phy_id; - int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD, - PMA_PMD_SPEED_ENABLE_REG); - bool enabled; - - reg &= ~((1 << 2) | (1 << 3)); - if (EFX_WORKAROUND_13204(efx) && - (advertising & ADVERTISED_100baseT_Full)) - reg |= 1 << PMA_PMD_100TX_ADV_LBN; - if (advertising & ADVERTISED_1000baseT_Full) - reg |= 1 << PMA_PMD_1000T_ADV_LBN; - if (advertising & ADVERTISED_10000baseT_Full) - reg |= 1 << PMA_PMD_10000T_ADV_LBN; - mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD, - PMA_PMD_SPEED_ENABLE_REG, reg); - - enabled = (advertising & - (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_10000baseT_Full)); - if (EFX_WORKAROUND_13204(efx)) - enabled |= (advertising & ADVERTISED_100baseT_Full); - return enabled; -} - -struct efx_phy_operations falcon_sfx7101_phy_ops = { - .macs = EFX_XMAC, - .init = tenxpress_phy_init, - .reconfigure = tenxpress_phy_reconfigure, - .poll = tenxpress_phy_poll, - .fini = tenxpress_phy_fini, - .clear_interrupt = efx_port_dummy_op_void, - .test = tenxpress_phy_test, - .get_settings = sfx7101_get_settings, - .set_settings = mdio_clause45_set_settings, - .mmds = TENXPRESS_REQUIRED_DEVS, - .loopbacks = SFX7101_LOOPBACKS, -}; - -struct efx_phy_operations falcon_sft9001_phy_ops = { - .macs = EFX_GMAC | EFX_XMAC, +struct efx_phy_operations falcon_tenxpress_phy_ops = { .init = tenxpress_phy_init, .reconfigure = tenxpress_phy_reconfigure, - .poll = tenxpress_phy_poll, + .check_hw = tenxpress_phy_check_hw, .fini = tenxpress_phy_fini, - .clear_interrupt = efx_port_dummy_op_void, + .clear_interrupt = tenxpress_phy_clear_interrupt, .test = tenxpress_phy_test, - .get_settings = sft9001_get_settings, - .set_settings = sft9001_set_settings, - .set_xnp_advertise = sft9001_set_xnp_advertise, .mmds = TENXPRESS_REQUIRED_DEVS, - .loopbacks = SFT9001_LOOPBACKS, + .loopbacks = TENXPRESS_LOOPBACKS, }; diff --git a/trunk/drivers/net/sfc/workarounds.h b/trunk/drivers/net/sfc/workarounds.h index 82e03e1d7371..ec50b90f4285 100644 --- a/trunk/drivers/net/sfc/workarounds.h +++ b/trunk/drivers/net/sfc/workarounds.h @@ -17,20 +17,17 @@ #define EFX_WORKAROUND_ALWAYS(efx) 1 #define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) -#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) -#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101) -#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A) /* XAUI resets if link not detected */ #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS /* RX PCIe double split performance issue */ #define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS /* Bit-bashed I2C reads cause performance drop */ -#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G +#define EFX_WORKAROUND_7884 EFX_WORKAROUND_ALWAYS /* TX pkt parser problem with <= 16 byte TXes */ #define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS /* Low rate CRC errors require XAUI reset */ -#define EFX_WORKAROUND_10750 EFX_WORKAROUND_SFX7101 +#define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS /* TX_EV_PKT_ERR can be caused by a dangling TX descriptor * or a PCIe error (bug 11028) */ #define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS @@ -54,9 +51,4 @@ /* Leak overlength packets rather than free */ #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A -/* Need to send XNP pages for 100BaseT */ -#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A -/* Need to keep AN enabled */ -#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A - #endif /* EFX_WORKAROUNDS_H */ diff --git a/trunk/drivers/net/sfc/xfp_phy.c b/trunk/drivers/net/sfc/xfp_phy.c index 2d50b6ecf5f9..91f024662101 100644 --- a/trunk/drivers/net/sfc/xfp_phy.c +++ b/trunk/drivers/net/sfc/xfp_phy.c @@ -7,21 +7,22 @@ * by the Free Software Foundation, incorporated herein by reference. */ /* - * Driver for XFP optical PHYs (plus some support specific to the Quake 2022/32) + * Driver for XFP optical PHYs (plus some support specific to the Quake 2032) * See www.amcc.com for details (search for qt2032) */ #include #include #include "efx.h" +#include "gmii.h" #include "mdio_10g.h" #include "xenpack.h" #include "phy.h" -#include "falcon.h" +#include "mac.h" -#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \ - MDIO_MMDREG_DEVS_PMAPMD | \ - MDIO_MMDREG_DEVS_PHYXS) +#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS | \ + MDIO_MMDREG_DEVS0_PMAPMD | \ + MDIO_MMDREG_DEVS0_PHYXS) #define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \ (1 << LOOPBACK_PMAPMD) | \ @@ -64,7 +65,7 @@ static int xfp_reset_phy(struct efx_nic *efx) /* Check that all the MMDs we expect are present and responding. We * expect faults on some if the link is down, but not on the PHY XS */ rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS, - MDIO_MMDREG_DEVS_PHYXS); + MDIO_MMDREG_DEVS0_PHYXS); if (rc < 0) goto fail; @@ -119,12 +120,24 @@ static int xfp_link_ok(struct efx_nic *efx) return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS); } -static void xfp_phy_poll(struct efx_nic *efx) +static int xfp_phy_check_hw(struct efx_nic *efx) { + int rc = 0; int link_up = xfp_link_ok(efx); /* Simulate a PHY event if link state has changed */ if (link_up != efx->link_up) - falcon_sim_phy_event(efx); + falcon_xmac_sim_phy_event(efx); + + rc = efx->board_info.monitor(efx); + if (rc) { + struct xfp_phy_data *phy_data = efx->phy_data; + EFX_ERR(efx, "XFP sensor alert; putting PHY into low power\n"); + efx->phy_mode |= PHY_MODE_LOW_POWER; + mdio_clause45_set_mmds_lpower(efx, 1, XFP_REQUIRED_DEVS); + phy_data->phy_mode |= PHY_MODE_LOW_POWER; + } + + return rc; } static void xfp_phy_reconfigure(struct efx_nic *efx) @@ -141,9 +154,7 @@ static void xfp_phy_reconfigure(struct efx_nic *efx) phy_data->phy_mode = efx->phy_mode; efx->link_up = xfp_link_ok(efx); - efx->link_speed = 10000; - efx->link_fd = true; - efx->link_fc = efx->wanted_fc; + efx->link_options = GM_LPA_10000FULL; } @@ -158,14 +169,11 @@ static void xfp_phy_fini(struct efx_nic *efx) } struct efx_phy_operations falcon_xfp_phy_ops = { - .macs = EFX_XMAC, .init = xfp_phy_init, .reconfigure = xfp_phy_reconfigure, - .poll = xfp_phy_poll, + .check_hw = xfp_phy_check_hw, .fini = xfp_phy_fini, .clear_interrupt = xfp_phy_clear_interrupt, - .get_settings = mdio_clause45_get_settings, - .set_settings = mdio_clause45_set_settings, .mmds = XFP_REQUIRED_DEVS, .loopbacks = XFP_LOOPBACKS, }; diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c b/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c index dbf52e8bbd7a..417a2d7b5764 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -313,29 +313,14 @@ static void rtl8187_rx_cb(struct urb *urb) struct rtl8187_rx_hdr *hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); flags = le32_to_cpu(hdr->flags); - signal = hdr->signal & 0x7f; + /* As with the RTL8187B below, the AGC is used to calculate + * signal strength and quality. In this case, the scaling + * constants are derived from the output of p54usb. + */ + quality = 130 - ((41 * hdr->agc) >> 6); + signal = -4 - ((27 * hdr->agc) >> 6); rx_status.antenna = (hdr->signal >> 7) & 1; - rx_status.noise = hdr->noise; rx_status.mactime = le64_to_cpu(hdr->mac_time); - priv->quality = signal; - rx_status.qual = priv->quality; - priv->noise = hdr->noise; - rate = (flags >> 20) & 0xF; - if (rate > 3) { /* OFDM rate */ - if (signal > 90) - signal = 90; - else if (signal < 25) - signal = 25; - signal = 90 - signal; - } else { /* CCK rate */ - if (signal > 95) - signal = 95; - else if (signal < 30) - signal = 30; - signal = 95 - signal; - } - rx_status.signal = signal; - priv->signal = signal; } else { struct rtl8187b_rx_hdr *hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); @@ -353,18 +338,18 @@ static void rtl8187_rx_cb(struct urb *urb) */ flags = le32_to_cpu(hdr->flags); quality = 170 - hdr->agc; - if (quality > 100) - quality = 100; signal = 14 - hdr->agc / 2; - rx_status.qual = quality; - priv->quality = quality; - rx_status.signal = signal; - priv->signal = signal; rx_status.antenna = (hdr->rssi >> 7) & 1; rx_status.mactime = le64_to_cpu(hdr->mac_time); - rate = (flags >> 20) & 0xF; } + if (quality > 100) + quality = 100; + rx_status.qual = quality; + priv->quality = quality; + rx_status.signal = signal; + priv->signal = signal; + rate = (flags >> 20) & 0xF; skb_trim(skb, flags & 0x0FFF); rx_status.rate_idx = rate; rx_status.freq = dev->conf.channel->center_freq; @@ -1293,6 +1278,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, priv->mode = NL80211_IFTYPE_MONITOR; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS; eeprom.data = dev; @@ -1408,13 +1394,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr >> 8; } - if (priv->is_rtl8187b) { + if (priv->is_rtl8187b) printk(KERN_WARNING "rtl8187: 8187B chip detected.\n"); - dev->flags |= IEEE80211_HW_SIGNAL_DBM; - } else { - dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC; - dev->max_signal = 65; - } /* * XXX: Once this driver supports anything that requires