aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/atm
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-01-27 04:02:30 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-01-27 04:02:30 -0500
commit87ebb18627930ce005beba227ca267b5b5372e06 (patch)
treedfe5bd6eabf5f467f1f335d49571fac75e7fd07a /drivers/atm
parentd057f0a4efe441842adb2d263e50173b7e0e7e38 (diff)
solos: Handle new line status change packets, hook up to ATM layer info
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/atm')
-rw-r--r--drivers/atm/solos-pci.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index b0c4676296ba..4c87dfb01566 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -82,6 +82,7 @@ struct pkt_hdr {
82#define PKT_COMMAND 1 82#define PKT_COMMAND 1
83#define PKT_POPEN 3 83#define PKT_POPEN 3
84#define PKT_PCLOSE 4 84#define PKT_PCLOSE 4
85#define PKT_STATUS 5
85 86
86struct solos_card { 87struct solos_card {
87 void __iomem *config_regs; 88 void __iomem *config_regs;
@@ -275,6 +276,72 @@ static ssize_t solos_param_store(struct device *dev, struct device_attribute *at
275 return ret; 276 return ret;
276} 277}
277 278
279static char *next_string(struct sk_buff *skb)
280{
281 int i = 0;
282 char *this = skb->data;
283
284 while (i < skb->len) {
285 if (this[i] == '\n') {
286 this[i] = 0;
287 skb_pull(skb, i);
288 return this;
289 }
290 }
291 return NULL;
292}
293
294/*
295 * Status packet has fields separated by \n, starting with a version number
296 * for the information therein. Fields are....
297 *
298 * packet version
299 * TxBitRate (version >= 1)
300 * RxBitRate (version >= 1)
301 * State (version >= 1)
302 */
303static int process_status(struct solos_card *card, int port, struct sk_buff *skb)
304{
305 char *str, *end;
306 int ver, rate_up, rate_down, state;
307
308 if (!card->atmdev[port])
309 return -ENODEV;
310
311 str = next_string(skb);
312 if (!str)
313 return -EIO;
314
315 ver = simple_strtol(str, NULL, 10);
316 if (ver < 1) {
317 dev_warn(&card->dev->dev, "Unexpected status interrupt version %d\n",
318 ver);
319 return -EIO;
320 }
321
322 str = next_string(skb);
323 rate_up = simple_strtol(str, &end, 10);
324 if (*end)
325 return -EIO;
326
327 str = next_string(skb);
328 rate_down = simple_strtol(str, &end, 10);
329 if (*end)
330 return -EIO;
331
332 str = next_string(skb);
333 if (!strcmp(str, "Showtime"))
334 state = ATM_PHY_SIG_FOUND;
335 else state = ATM_PHY_SIG_LOST;
336
337 card->atmdev[port]->link_rate = rate_down;
338 card->atmdev[port]->signal = state;
339
340 dev_info(&card->dev->dev, "ATM state: '%s', %d/%d kb/s up/down.\n",
341 str, rate_up/1000, rate_down/1000);
342 return 0;
343}
344
278static int process_command(struct solos_card *card, int port, struct sk_buff *skb) 345static int process_command(struct solos_card *card, int port, struct sk_buff *skb)
279{ 346{
280 struct solos_param *prm; 347 struct solos_param *prm;
@@ -512,7 +579,7 @@ void solos_bh(unsigned long card_arg)
512 579
513 size = le16_to_cpu(header.size); 580 size = le16_to_cpu(header.size);
514 581
515 skb = alloc_skb(size, GFP_ATOMIC); 582 skb = alloc_skb(size + 1, GFP_ATOMIC);
516 if (!skb) { 583 if (!skb) {
517 if (net_ratelimit()) 584 if (net_ratelimit())
518 dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n"); 585 dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n");
@@ -547,6 +614,11 @@ void solos_bh(unsigned long card_arg)
547 atomic_inc(&vcc->stats->rx); 614 atomic_inc(&vcc->stats->rx);
548 break; 615 break;
549 616
617 case PKT_STATUS:
618 process_status(card, port, skb);
619 dev_kfree_skb(skb);
620 break;
621
550 case PKT_COMMAND: 622 case PKT_COMMAND:
551 default: /* FIXME: Not really, surely? */ 623 default: /* FIXME: Not really, surely? */
552 if (process_command(card, port, skb)) 624 if (process_command(card, port, skb))
@@ -996,6 +1068,9 @@ static int atm_init(struct solos_card *card)
996 int i; 1068 int i;
997 1069
998 for (i = 0; i < card->nr_ports; i++) { 1070 for (i = 0; i < card->nr_ports; i++) {
1071 struct sk_buff *skb;
1072 struct pkt_hdr *header;
1073
999 skb_queue_head_init(&card->tx_queue[i]); 1074 skb_queue_head_init(&card->tx_queue[i]);
1000 skb_queue_head_init(&card->cli_queue[i]); 1075 skb_queue_head_init(&card->cli_queue[i]);
1001 1076
@@ -1016,6 +1091,22 @@ static int atm_init(struct solos_card *card)
1016 card->atmdev[i]->ci_range.vci_bits = 16; 1091 card->atmdev[i]->ci_range.vci_bits = 16;
1017 card->atmdev[i]->dev_data = card; 1092 card->atmdev[i]->dev_data = card;
1018 card->atmdev[i]->phy_data = (void *)(unsigned long)i; 1093 card->atmdev[i]->phy_data = (void *)(unsigned long)i;
1094 card->atmdev[i]->signal = ATM_PHY_SIG_UNKNOWN;
1095
1096 skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
1097 if (!skb) {
1098 dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n");
1099 continue;
1100 }
1101
1102 header = (void *)skb_put(skb, sizeof(*header));
1103
1104 header->size = cpu_to_le16(0);
1105 header->vpi = cpu_to_le16(0);
1106 header->vci = cpu_to_le16(0);
1107 header->type = cpu_to_le16(PKT_STATUS);
1108
1109 fpga_queue(card, i, skb, NULL);
1019 } 1110 }
1020 return 0; 1111 return 0;
1021} 1112}