~ubuntu-branches/ubuntu/lucid/linux-rt/lucid

« back to all changes in this revision

Viewing changes to net/dsa/dsa.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2009-08-05 23:00:52 UTC
  • Revision ID: james.westby@ubuntu.com-20090805230052-7xedvqcyk9dnnxb2
Tags: 2.6.31-1.1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * net/dsa/dsa.c - Hardware switch handling
3
 
 * Copyright (c) 2008 Marvell Semiconductor
 
3
 * Copyright (c) 2008-2009 Marvell Semiconductor
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License as published by
67
67
 
68
68
/* basic switch operations **************************************************/
69
69
static struct dsa_switch *
70
 
dsa_switch_setup(struct device *parent, struct dsa_platform_data *pd,
71
 
                 struct mii_bus *bus, struct net_device *dev)
 
70
dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 
71
                 struct device *parent, struct mii_bus *bus)
72
72
{
 
73
        struct dsa_chip_data *pd = dst->pd->chip + index;
 
74
        struct dsa_switch_driver *drv;
73
75
        struct dsa_switch *ds;
74
76
        int ret;
75
 
        struct dsa_switch_driver *drv;
76
77
        char *name;
77
78
        int i;
78
79
 
81
82
         */
82
83
        drv = dsa_switch_probe(bus, pd->sw_addr, &name);
83
84
        if (drv == NULL) {
84
 
                printk(KERN_ERR "%s: could not detect attached switch\n",
85
 
                       dev->name);
 
85
                printk(KERN_ERR "%s[%d]: could not detect attached switch\n",
 
86
                       dst->master_netdev->name, index);
86
87
                return ERR_PTR(-EINVAL);
87
88
        }
88
 
        printk(KERN_INFO "%s: detected a %s switch\n", dev->name, name);
 
89
        printk(KERN_INFO "%s[%d]: detected a %s switch\n",
 
90
                dst->master_netdev->name, index, name);
89
91
 
90
92
 
91
93
        /*
95
97
        if (ds == NULL)
96
98
                return ERR_PTR(-ENOMEM);
97
99
 
98
 
        ds->pd = pd;
99
 
        ds->master_netdev = dev;
 
100
        ds->dst = dst;
 
101
        ds->index = index;
 
102
        ds->pd = dst->pd->chip + index;
 
103
        ds->drv = drv;
100
104
        ds->master_mii_bus = bus;
101
105
 
102
 
        ds->drv = drv;
103
 
        ds->tag_protocol = drv->tag_protocol;
104
 
 
105
106
 
106
107
        /*
107
108
         * Validate supplied switch configuration.
108
109
         */
109
 
        ds->cpu_port = -1;
110
110
        for (i = 0; i < DSA_MAX_PORTS; i++) {
111
111
                char *name;
112
112
 
115
115
                        continue;
116
116
 
117
117
                if (!strcmp(name, "cpu")) {
118
 
                        if (ds->cpu_port != -1) {
 
118
                        if (dst->cpu_switch != -1) {
119
119
                                printk(KERN_ERR "multiple cpu ports?!\n");
120
120
                                ret = -EINVAL;
121
121
                                goto out;
122
122
                        }
123
 
                        ds->cpu_port = i;
 
123
                        dst->cpu_switch = index;
 
124
                        dst->cpu_port = i;
 
125
                } else if (!strcmp(name, "dsa")) {
 
126
                        ds->dsa_port_mask |= 1 << i;
124
127
                } else {
125
 
                        ds->valid_port_mask |= 1 << i;
 
128
                        ds->phys_port_mask |= 1 << i;
126
129
                }
127
130
        }
128
131
 
129
 
        if (ds->cpu_port == -1) {
130
 
                printk(KERN_ERR "no cpu port?!\n");
131
 
                ret = -EINVAL;
132
 
                goto out;
133
 
        }
134
 
 
135
132
 
136
133
        /*
137
 
         * If we use a tagging format that doesn't have an ethertype
138
 
         * field, make sure that all packets from this point on get
139
 
         * sent to the tag format's receive function.  (Which will
140
 
         * discard received packets until we set ds->ports[] below.)
 
134
         * If the CPU connects to this switch, set the switch tree
 
135
         * tagging protocol to the preferred tagging format of this
 
136
         * switch.
141
137
         */
142
 
        wmb();
143
 
        dev->dsa_ptr = (void *)ds;
 
138
        if (ds->dst->cpu_switch == index)
 
139
                ds->dst->tag_protocol = drv->tag_protocol;
144
140
 
145
141
 
146
142
        /*
150
146
        if (ret < 0)
151
147
                goto out;
152
148
 
153
 
        ret = drv->set_addr(ds, dev->dev_addr);
 
149
        ret = drv->set_addr(ds, dst->master_netdev->dev_addr);
154
150
        if (ret < 0)
155
151
                goto out;
156
152
 
169
165
        /*
170
166
         * Create network devices for physical switch ports.
171
167
         */
172
 
        wmb();
173
168
        for (i = 0; i < DSA_MAX_PORTS; i++) {
174
169
                struct net_device *slave_dev;
175
170
 
176
 
                if (!(ds->valid_port_mask & (1 << i)))
 
171
                if (!(ds->phys_port_mask & (1 << i)))
177
172
                        continue;
178
173
 
179
174
                slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i]);
180
175
                if (slave_dev == NULL) {
181
 
                        printk(KERN_ERR "%s: can't create dsa slave "
182
 
                               "device for port %d(%s)\n",
183
 
                               dev->name, i, pd->port_names[i]);
 
176
                        printk(KERN_ERR "%s[%d]: can't create dsa "
 
177
                               "slave device for port %d(%s)\n",
 
178
                               dst->master_netdev->name,
 
179
                               index, i, pd->port_names[i]);
184
180
                        continue;
185
181
                }
186
182
 
192
188
out_free:
193
189
        mdiobus_free(ds->slave_mii_bus);
194
190
out:
195
 
        dev->dsa_ptr = NULL;
196
191
        kfree(ds);
197
192
        return ERR_PTR(ret);
198
193
}
212
207
 */
213
208
bool dsa_uses_dsa_tags(void *dsa_ptr)
214
209
{
215
 
        struct dsa_switch *ds = dsa_ptr;
 
210
        struct dsa_switch_tree *dst = dsa_ptr;
216
211
 
217
 
        return !!(ds->tag_protocol == htons(ETH_P_DSA));
 
212
        return !!(dst->tag_protocol == htons(ETH_P_DSA));
218
213
}
219
214
 
220
215
bool dsa_uses_trailer_tags(void *dsa_ptr)
221
216
{
222
 
        struct dsa_switch *ds = dsa_ptr;
 
217
        struct dsa_switch_tree *dst = dsa_ptr;
223
218
 
224
 
        return !!(ds->tag_protocol == htons(ETH_P_TRAILER));
 
219
        return !!(dst->tag_protocol == htons(ETH_P_TRAILER));
225
220
}
226
221
 
227
222
 
228
223
/* link polling *************************************************************/
229
224
static void dsa_link_poll_work(struct work_struct *ugly)
230
225
{
231
 
        struct dsa_switch *ds;
232
 
 
233
 
        ds = container_of(ugly, struct dsa_switch, link_poll_work);
234
 
 
235
 
        ds->drv->poll_link(ds);
236
 
        mod_timer(&ds->link_poll_timer, round_jiffies(jiffies + HZ));
 
226
        struct dsa_switch_tree *dst;
 
227
        int i;
 
228
 
 
229
        dst = container_of(ugly, struct dsa_switch_tree, link_poll_work);
 
230
 
 
231
        for (i = 0; i < dst->pd->nr_chips; i++) {
 
232
                struct dsa_switch *ds = dst->ds[i];
 
233
 
 
234
                if (ds != NULL && ds->drv->poll_link != NULL)
 
235
                        ds->drv->poll_link(ds);
 
236
        }
 
237
 
 
238
        mod_timer(&dst->link_poll_timer, round_jiffies(jiffies + HZ));
237
239
}
238
240
 
239
 
static void dsa_link_poll_timer(unsigned long _ds)
 
241
static void dsa_link_poll_timer(unsigned long _dst)
240
242
{
241
 
        struct dsa_switch *ds = (void *)_ds;
 
243
        struct dsa_switch_tree *dst = (void *)_dst;
242
244
 
243
 
        schedule_work(&ds->link_poll_work);
 
245
        schedule_work(&dst->link_poll_work);
244
246
}
245
247
 
246
248
 
303
305
        static int dsa_version_printed;
304
306
        struct dsa_platform_data *pd = pdev->dev.platform_data;
305
307
        struct net_device *dev;
306
 
        struct mii_bus *bus;
307
 
        struct dsa_switch *ds;
 
308
        struct dsa_switch_tree *dst;
 
309
        int i;
308
310
 
309
311
        if (!dsa_version_printed++)
310
312
                printk(KERN_NOTICE "Distributed Switch Architecture "
311
313
                        "driver version %s\n", dsa_driver_version);
312
314
 
313
 
        if (pd == NULL || pd->mii_bus == NULL || pd->netdev == NULL)
314
 
                return -EINVAL;
315
 
 
316
 
        bus = dev_to_mii_bus(pd->mii_bus);
317
 
        if (bus == NULL)
 
315
        if (pd == NULL || pd->netdev == NULL)
318
316
                return -EINVAL;
319
317
 
320
318
        dev = dev_to_net_device(pd->netdev);
326
324
                return -EEXIST;
327
325
        }
328
326
 
329
 
        ds = dsa_switch_setup(&pdev->dev, pd, bus, dev);
330
 
        if (IS_ERR(ds)) {
 
327
        dst = kzalloc(sizeof(*dst), GFP_KERNEL);
 
328
        if (dst == NULL) {
331
329
                dev_put(dev);
332
 
                return PTR_ERR(ds);
333
 
        }
334
 
 
335
 
        if (ds->drv->poll_link != NULL) {
336
 
                INIT_WORK(&ds->link_poll_work, dsa_link_poll_work);
337
 
                init_timer(&ds->link_poll_timer);
338
 
                ds->link_poll_timer.data = (unsigned long)ds;
339
 
                ds->link_poll_timer.function = dsa_link_poll_timer;
340
 
                ds->link_poll_timer.expires = round_jiffies(jiffies + HZ);
341
 
                add_timer(&ds->link_poll_timer);
342
 
        }
343
 
 
344
 
        platform_set_drvdata(pdev, ds);
 
330
                return -ENOMEM;
 
331
        }
 
332
 
 
333
        platform_set_drvdata(pdev, dst);
 
334
 
 
335
        dst->pd = pd;
 
336
        dst->master_netdev = dev;
 
337
        dst->cpu_switch = -1;
 
338
        dst->cpu_port = -1;
 
339
 
 
340
        for (i = 0; i < pd->nr_chips; i++) {
 
341
                struct mii_bus *bus;
 
342
                struct dsa_switch *ds;
 
343
 
 
344
                bus = dev_to_mii_bus(pd->chip[i].mii_bus);
 
345
                if (bus == NULL) {
 
346
                        printk(KERN_ERR "%s[%d]: no mii bus found for "
 
347
                                "dsa switch\n", dev->name, i);
 
348
                        continue;
 
349
                }
 
350
 
 
351
                ds = dsa_switch_setup(dst, i, &pdev->dev, bus);
 
352
                if (IS_ERR(ds)) {
 
353
                        printk(KERN_ERR "%s[%d]: couldn't create dsa switch "
 
354
                                "instance (error %ld)\n", dev->name, i,
 
355
                                PTR_ERR(ds));
 
356
                        continue;
 
357
                }
 
358
 
 
359
                dst->ds[i] = ds;
 
360
                if (ds->drv->poll_link != NULL)
 
361
                        dst->link_poll_needed = 1;
 
362
        }
 
363
 
 
364
        /*
 
365
         * If we use a tagging format that doesn't have an ethertype
 
366
         * field, make sure that all packets from this point on get
 
367
         * sent to the tag format's receive function.
 
368
         */
 
369
        wmb();
 
370
        dev->dsa_ptr = (void *)dst;
 
371
 
 
372
        if (dst->link_poll_needed) {
 
373
                INIT_WORK(&dst->link_poll_work, dsa_link_poll_work);
 
374
                init_timer(&dst->link_poll_timer);
 
375
                dst->link_poll_timer.data = (unsigned long)dst;
 
376
                dst->link_poll_timer.function = dsa_link_poll_timer;
 
377
                dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
 
378
                add_timer(&dst->link_poll_timer);
 
379
        }
345
380
 
346
381
        return 0;
347
382
}
348
383
 
349
384
static int dsa_remove(struct platform_device *pdev)
350
385
{
351
 
        struct dsa_switch *ds = platform_get_drvdata(pdev);
 
386
        struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
 
387
        int i;
352
388
 
353
 
        if (ds->drv->poll_link != NULL)
354
 
                del_timer_sync(&ds->link_poll_timer);
 
389
        if (dst->link_poll_needed)
 
390
                del_timer_sync(&dst->link_poll_timer);
355
391
 
356
392
        flush_scheduled_work();
357
393
 
358
 
        dsa_switch_destroy(ds);
 
394
        for (i = 0; i < dst->pd->nr_chips; i++) {
 
395
                struct dsa_switch *ds = dst->ds[i];
 
396
 
 
397
                if (ds != NULL)
 
398
                        dsa_switch_destroy(ds);
 
399
        }
359
400
 
360
401
        return 0;
361
402
}