diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 706884ae8fcd..eaab3d87dcf3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -156,7 +156,7 @@ static const char *yukon2_name[] = { | |||
156 | 156 | ||
157 | static void sky2_set_multicast(struct net_device *dev); | 157 | static void sky2_set_multicast(struct net_device *dev); |
158 | 158 | ||
159 | /* Access to external PHY */ | 159 | /* Access to PHY via serial interconnect */ |
160 | static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) | 160 | static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) |
161 | { | 161 | { |
162 | int i; | 162 | int i; |
@@ -166,13 +166,22 @@ static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val) | |||
166 | GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); | 166 | GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg)); |
167 | 167 | ||
168 | for (i = 0; i < PHY_RETRIES; i++) { | 168 | for (i = 0; i < PHY_RETRIES; i++) { |
169 | if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) | 169 | u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); |
170 | if (ctrl == 0xffff) | ||
171 | goto io_error; | ||
172 | |||
173 | if (!(ctrl & GM_SMI_CT_BUSY)) | ||
170 | return 0; | 174 | return 0; |
171 | udelay(1); | 175 | |
176 | udelay(10); | ||
172 | } | 177 | } |
173 | 178 | ||
174 | printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name); | 179 | dev_warn(&hw->pdev->dev,"%s: phy write timeout\n", hw->dev[port]->name); |
175 | return -ETIMEDOUT; | 180 | return -ETIMEDOUT; |
181 | |||
182 | io_error: | ||
183 | dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); | ||
184 | return -EIO; | ||
176 | } | 185 | } |
177 | 186 | ||
178 | static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) | 187 | static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) |
@@ -183,23 +192,29 @@ static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val) | |||
183 | | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); | 192 | | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); |
184 | 193 | ||
185 | for (i = 0; i < PHY_RETRIES; i++) { | 194 | for (i = 0; i < PHY_RETRIES; i++) { |
186 | if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) { | 195 | u16 ctrl = gma_read16(hw, port, GM_SMI_CTRL); |
196 | if (ctrl == 0xffff) | ||
197 | goto io_error; | ||
198 | |||
199 | if (ctrl & GM_SMI_CT_RD_VAL) { | ||
187 | *val = gma_read16(hw, port, GM_SMI_DATA); | 200 | *val = gma_read16(hw, port, GM_SMI_DATA); |
188 | return 0; | 201 | return 0; |
189 | } | 202 | } |
190 | 203 | ||
191 | udelay(1); | 204 | udelay(10); |
192 | } | 205 | } |
193 | 206 | ||
207 | dev_warn(&hw->pdev->dev, "%s: phy read timeout\n", hw->dev[port]->name); | ||
194 | return -ETIMEDOUT; | 208 | return -ETIMEDOUT; |
209 | io_error: | ||
210 | dev_err(&hw->pdev->dev, "%s: phy I/O error\n", hw->dev[port]->name); | ||
211 | return -EIO; | ||
195 | } | 212 | } |
196 | 213 | ||
197 | static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) | 214 | static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg) |
198 | { | 215 | { |
199 | u16 v; | 216 | u16 v; |
200 | 217 | __gm_phy_read(hw, port, reg, &v); | |
201 | if (__gm_phy_read(hw, port, reg, &v) != 0) | ||
202 | printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name); | ||
203 | return v; | 218 | return v; |
204 | } | 219 | } |
205 | 220 | ||