Ignore:
Timestamp:
2010-07-01T20:08:19+02:00 (6 years ago)
Author:
juhosg
Message:

backfire: generic: rtl8366: move common VLAN handling functions to rtl8366_smi.c (backport of 21979)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/backfire/target/linux/generic-2.6/files/drivers/net/phy/rtl8366_smi.c

    r21938 r22025  
    281281} 
    282282EXPORT_SYMBOL_GPL(rtl8366_smi_rmwr); 
     283 
     284static int rtl8366_mc_is_used(struct rtl8366_smi *smi, int mc_index, int *used) 
     285{ 
     286        int err; 
     287        int i; 
     288 
     289        *used = 0; 
     290        for (i = 0; i < smi->num_ports; i++) { 
     291                int index = 0; 
     292 
     293                err = smi->ops->get_mc_index(smi, i, &index); 
     294                if (err) 
     295                        return err; 
     296 
     297                if (mc_index == index) { 
     298                        *used = 1; 
     299                        break; 
     300                } 
     301        } 
     302 
     303        return 0; 
     304} 
     305 
     306int rtl8366_set_vlan(struct rtl8366_smi *smi, int vid, u32 member, u32 untag, 
     307                     u32 fid) 
     308{ 
     309        struct rtl8366_vlan_4k vlan4k; 
     310        int err; 
     311        int i; 
     312 
     313        /* Update the 4K table */ 
     314        err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); 
     315        if (err) 
     316                return err; 
     317 
     318        vlan4k.member = member; 
     319        vlan4k.untag = untag; 
     320        vlan4k.fid = fid; 
     321        err = smi->ops->set_vlan_4k(smi, &vlan4k); 
     322        if (err) 
     323                return err; 
     324 
     325        /* Try to find an existing MC entry for this VID */ 
     326        for (i = 0; i < smi->num_vlan_mc; i++) { 
     327                struct rtl8366_vlan_mc vlanmc; 
     328 
     329                err = smi->ops->get_vlan_mc(smi, i, &vlanmc); 
     330                if (err) 
     331                        return err; 
     332 
     333                if (vid == vlanmc.vid) { 
     334                        /* update the MC entry */ 
     335                        vlanmc.member = member; 
     336                        vlanmc.untag = untag; 
     337                        vlanmc.fid = fid; 
     338 
     339                        err = smi->ops->set_vlan_mc(smi, i, &vlanmc); 
     340                        break; 
     341                } 
     342        } 
     343 
     344        return err; 
     345} 
     346EXPORT_SYMBOL_GPL(rtl8366_set_vlan); 
     347 
     348int rtl8366_reset_vlan(struct rtl8366_smi *smi) 
     349{ 
     350        struct rtl8366_vlan_mc vlanmc; 
     351        int err; 
     352        int i; 
     353 
     354        /* clear VLAN member configurations */ 
     355        vlanmc.vid = 0; 
     356        vlanmc.priority = 0; 
     357        vlanmc.member = 0; 
     358        vlanmc.untag = 0; 
     359        vlanmc.fid = 0; 
     360        for (i = 0; i < smi->num_vlan_mc; i++) { 
     361                err = smi->ops->set_vlan_mc(smi, i, &vlanmc); 
     362                if (err) 
     363                        return err; 
     364        } 
     365 
     366        for (i = 0; i < smi->num_ports; i++) { 
     367                if (i == smi->cpu_port) 
     368                        continue; 
     369 
     370                err = rtl8366_set_vlan(smi, (i + 1), 
     371                                        (1 << i) | (1 << smi->cpu_port), 
     372                                        (1 << i) | (1 << smi->cpu_port), 
     373                                        0); 
     374                if (err) 
     375                        return err; 
     376 
     377                err = rtl8366_set_pvid(smi, i, (i + 1)); 
     378                if (err) 
     379                        return err; 
     380        } 
     381 
     382        return 0; 
     383} 
     384EXPORT_SYMBOL_GPL(rtl8366_reset_vlan); 
     385 
     386int rtl8366_get_pvid(struct rtl8366_smi *smi, int port, int *val) 
     387{ 
     388        struct rtl8366_vlan_mc vlanmc; 
     389        int err; 
     390        int index; 
     391 
     392        err = smi->ops->get_mc_index(smi, port, &index); 
     393        if (err) 
     394                return err; 
     395 
     396        err = smi->ops->get_vlan_mc(smi, index, &vlanmc); 
     397        if (err) 
     398                return err; 
     399 
     400        *val = vlanmc.vid; 
     401        return 0; 
     402} 
     403EXPORT_SYMBOL_GPL(rtl8366_get_pvid); 
     404 
     405int rtl8366_set_pvid(struct rtl8366_smi *smi, unsigned port, unsigned vid) 
     406{ 
     407        struct rtl8366_vlan_mc vlanmc; 
     408        struct rtl8366_vlan_4k vlan4k; 
     409        int err; 
     410        int i; 
     411 
     412        /* Try to find an existing MC entry for this VID */ 
     413        for (i = 0; i < smi->num_vlan_mc; i++) { 
     414                err = smi->ops->get_vlan_mc(smi, i, &vlanmc); 
     415                if (err) 
     416                        return err; 
     417 
     418                if (vid == vlanmc.vid) { 
     419                        err = smi->ops->set_vlan_mc(smi, i, &vlanmc); 
     420                        if (err) 
     421                                return err; 
     422 
     423                        err = smi->ops->set_mc_index(smi, port, i); 
     424                        return err; 
     425                } 
     426        } 
     427 
     428        /* We have no MC entry for this VID, try to find an empty one */ 
     429        for (i = 0; i < smi->num_vlan_mc; i++) { 
     430                err = smi->ops->get_vlan_mc(smi, i, &vlanmc); 
     431                if (err) 
     432                        return err; 
     433 
     434                if (vlanmc.vid == 0 && vlanmc.member == 0) { 
     435                        /* Update the entry from the 4K table */ 
     436                        err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); 
     437                        if (err) 
     438                                return err; 
     439 
     440                        vlanmc.vid = vid; 
     441                        vlanmc.member = vlan4k.member; 
     442                        vlanmc.untag = vlan4k.untag; 
     443                        vlanmc.fid = vlan4k.fid; 
     444                        err = smi->ops->set_vlan_mc(smi, i, &vlanmc); 
     445                        if (err) 
     446                                return err; 
     447 
     448                        err = smi->ops->set_mc_index(smi, port, i); 
     449                        return err; 
     450                } 
     451        } 
     452 
     453        /* MC table is full, try to find an unused entry and replace it */ 
     454        for (i = 0; i < smi->num_vlan_mc; i++) { 
     455                int used; 
     456 
     457                err = rtl8366_mc_is_used(smi, i, &used); 
     458                if (err) 
     459                        return err; 
     460 
     461                if (!used) { 
     462                        /* Update the entry from the 4K table */ 
     463                        err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); 
     464                        if (err) 
     465                                return err; 
     466 
     467                        vlanmc.vid = vid; 
     468                        vlanmc.member = vlan4k.member; 
     469                        vlanmc.untag = vlan4k.untag; 
     470                        vlanmc.fid = vlan4k.fid; 
     471                        err = smi->ops->set_vlan_mc(smi, i, &vlanmc); 
     472                        if (err) 
     473                                return err; 
     474 
     475                        err = smi->ops->set_mc_index(smi, port, i); 
     476                        return err; 
     477                } 
     478        } 
     479 
     480        dev_err(smi->parent, 
     481                "all VLAN member configurations are in use\n"); 
     482 
     483        return -ENOSPC; 
     484} 
     485EXPORT_SYMBOL_GPL(rtl8366_set_pvid); 
    283486 
    284487static int rtl8366_smi_mii_init(struct rtl8366_smi *smi) 
Note: See TracChangeset for help on using the changeset viewer.