aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMasakazu Mokuno <mokuno@sm.sony.co.jp>2008-02-07 05:58:32 -0500
committerJeff Garzik <jeff@garzik.org>2008-02-11 10:29:52 -0500
commit01fed4c284def58b8a9ee0b915c3956b93c670b7 (patch)
tree830ddb0858e83ee2c716bb9b7a0de40858d7f95f /drivers
parent7bc56b92b025c13f8d3c9b049ed816db464fb0b5 (diff)
PS3: gelic: add support for port link status
Add support for interrupt driven port link status detection. Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ps3_gelic_net.c77
-rw-r--r--drivers/net/ps3_gelic_net.h2
2 files changed, 52 insertions, 27 deletions
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index 87fc3b765e8e..3b11b1ca0e77 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -87,6 +87,28 @@ static inline void gelic_card_rx_irq_off(struct gelic_card *card)
87{ 87{
88 gelic_card_set_irq_mask(card, card->ghiintmask & ~GELIC_CARD_RXINT); 88 gelic_card_set_irq_mask(card, card->ghiintmask & ~GELIC_CARD_RXINT);
89} 89}
90
91static void
92gelic_card_get_ether_port_status(struct gelic_card *card, int inform)
93{
94 u64 v2;
95 struct net_device *ether_netdev;
96
97 lv1_net_control(bus_id(card), dev_id(card),
98 GELIC_LV1_GET_ETH_PORT_STATUS,
99 GELIC_LV1_VLAN_TX_ETHERNET, 0, 0,
100 &card->ether_port_status, &v2);
101
102 if (inform) {
103 ether_netdev = card->netdev;
104 if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP)
105 netif_carrier_on(ether_netdev);
106 else
107 netif_carrier_off(ether_netdev);
108 }
109}
110
111
90/** 112/**
91 * gelic_descr_get_status -- returns the status of a descriptor 113 * gelic_descr_get_status -- returns the status of a descriptor
92 * @descr: descriptor to look at 114 * @descr: descriptor to look at
@@ -1032,6 +1054,10 @@ static irqreturn_t gelic_card_interrupt(int irq, void *ptr)
1032 gelic_card_kick_txdma(card, card->tx_chain.tail); 1054 gelic_card_kick_txdma(card, card->tx_chain.tail);
1033 spin_unlock_irqrestore(&card->tx_dma_lock, flags); 1055 spin_unlock_irqrestore(&card->tx_dma_lock, flags);
1034 } 1056 }
1057
1058 /* ether port status changed */
1059 if (status & GELIC_CARD_PORT_STATUS_CHANGED)
1060 gelic_card_get_ether_port_status(card, 1);
1035 return IRQ_HANDLED; 1061 return IRQ_HANDLED;
1036} 1062}
1037 1063
@@ -1128,13 +1154,14 @@ static int gelic_net_open(struct net_device *netdev)
1128 napi_enable(&card->napi); 1154 napi_enable(&card->napi);
1129 1155
1130 card->tx_dma_progress = 0; 1156 card->tx_dma_progress = 0;
1131 card->ghiintmask = GELIC_CARD_RXINT | GELIC_CARD_TXINT; 1157 card->ghiintmask = GELIC_CARD_RXINT | GELIC_CARD_TXINT |
1158 GELIC_CARD_PORT_STATUS_CHANGED;
1132 1159
1133 gelic_card_set_irq_mask(card, card->ghiintmask); 1160 gelic_card_set_irq_mask(card, card->ghiintmask);
1134 gelic_card_enable_rxdmac(card); 1161 gelic_card_enable_rxdmac(card);
1135 1162
1136 netif_start_queue(netdev); 1163 netif_start_queue(netdev);
1137 netif_carrier_on(netdev); 1164 gelic_card_get_ether_port_status(card, 1);
1138 1165
1139 return 0; 1166 return 0;
1140 1167
@@ -1157,39 +1184,35 @@ static int gelic_ether_get_settings(struct net_device *netdev,
1157 struct ethtool_cmd *cmd) 1184 struct ethtool_cmd *cmd)
1158{ 1185{
1159 struct gelic_card *card = netdev_priv(netdev); 1186 struct gelic_card *card = netdev_priv(netdev);
1160 int status;
1161 u64 v1, v2;
1162 int speed, duplex;
1163 1187
1164 speed = duplex = -1; 1188 gelic_card_get_ether_port_status(card, 0);
1165 status = lv1_net_control(bus_id(card), dev_id(card),
1166 GELIC_LV1_GET_ETH_PORT_STATUS,
1167 GELIC_LV1_VLAN_TX_ETHERNET, 0, 0,
1168 &v1, &v2);
1169 if (status) {
1170 /* link down */
1171 } else {
1172 if (v1 & GELIC_LV1_ETHER_FULL_DUPLEX) {
1173 duplex = DUPLEX_FULL;
1174 } else {
1175 duplex = DUPLEX_HALF;
1176 }
1177 1189
1178 if (v1 & GELIC_LV1_ETHER_SPEED_10) { 1190 if (card->ether_port_status & GELIC_LV1_ETHER_FULL_DUPLEX)
1179 speed = SPEED_10; 1191 cmd->duplex = DUPLEX_FULL;
1180 } else if (v1 & GELIC_LV1_ETHER_SPEED_100) { 1192 else
1181 speed = SPEED_100; 1193 cmd->duplex = DUPLEX_HALF;
1182 } else if (v1 & GELIC_LV1_ETHER_SPEED_1000) { 1194
1183 speed = SPEED_1000; 1195 switch (card->ether_port_status & GELIC_LV1_ETHER_SPEED_MASK) {
1184 } 1196 case GELIC_LV1_ETHER_SPEED_10:
1197 cmd->speed = SPEED_10;
1198 break;
1199 case GELIC_LV1_ETHER_SPEED_100:
1200 cmd->speed = SPEED_100;
1201 break;
1202 case GELIC_LV1_ETHER_SPEED_1000:
1203 cmd->speed = SPEED_1000;
1204 break;
1205 default:
1206 pr_info("%s: speed unknown\n", __func__);
1207 cmd->speed = SPEED_10;
1208 break;
1185 } 1209 }
1210
1186 cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | 1211 cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
1187 SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 1212 SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
1188 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | 1213 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
1189 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; 1214 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
1190 cmd->advertising = cmd->supported; 1215 cmd->advertising = cmd->supported;
1191 cmd->speed = speed;
1192 cmd->duplex = duplex;
1193 cmd->autoneg = AUTONEG_ENABLE; /* always enabled */ 1216 cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
1194 cmd->port = PORT_TP; 1217 cmd->port = PORT_TP;
1195 1218
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
index 49695a5c0df6..957221fa5d55 100644
--- a/drivers/net/ps3_gelic_net.h
+++ b/drivers/net/ps3_gelic_net.h
@@ -261,6 +261,8 @@ struct gelic_card {
261 atomic_t tx_timeout_task_counter; 261 atomic_t tx_timeout_task_counter;
262 wait_queue_head_t waitq; 262 wait_queue_head_t waitq;
263 263
264 u64 ether_port_status;
265
264 struct gelic_descr *tx_top, *rx_top; 266 struct gelic_descr *tx_top, *rx_top;
265 struct gelic_descr descr[0]; 267 struct gelic_descr descr[0];
266}; 268};