Changeset 21940


Ignore:
Timestamp:
2010-06-26T21:54:17+02:00 (7 years ago)
Author:
juhosg
Message:

backfire: generic: rtl8366: update vlan handling code of rtl8366rb (backport of r21921)

File:
1 edited

Legend:

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

    r21939 r21940  
    643643} 
    644644 
    645 static int rtl8366rb_get_port_vlan_index(struct rtl8366_smi *smi, int port, 
    646                                        int *val) 
     645static int rtl8366rb_get_mc_index(struct rtl8366_smi *smi, int port, int *val) 
    647646{ 
    648647        u32 data; 
     
    664663} 
    665664 
    666 static int rtl8366rb_get_vlan_port_pvid(struct rtl8366_smi *smi, int port, 
    667                                        int *val) 
    668 { 
    669         struct rtl8366_vlan_mc vlanmc; 
    670         int err; 
    671         int index; 
    672  
    673         err = rtl8366rb_get_port_vlan_index(smi, port, &index); 
    674         if (err) 
    675                 return err; 
    676  
    677         err = rtl8366rb_get_vlan_mc(smi, index, &vlanmc); 
    678         if (err) 
    679                 return err; 
    680  
    681         *val = vlanmc.vid; 
    682         return 0; 
    683 } 
    684  
    685 static int rtl8366rb_set_port_vlan_index(struct rtl8366_smi *smi, int port, 
    686                                         int index) 
     665static int rtl8366rb_set_mc_index(struct rtl8366_smi *smi, int port, int index) 
    687666{ 
    688667        if (port >= RTL8366_NUM_PORTS || index >= RTL8366_NUM_VLANS) 
     
    696675} 
    697676 
    698 static int rtl8366rb_set_vlan_port_pvid(struct rtl8366_smi *smi, int port, 
    699                                         int val) 
    700 { 
     677static int rtl8366rb_set_vlan(struct rtl8366_smi *smi, int vid, u32 member, 
     678                              u32 untag, u32 fid) 
     679{ 
     680        struct rtl8366_vlan_4k vlan4k; 
     681        int err; 
    701682        int i; 
     683 
     684        /* Update the 4K table */ 
     685        err = rtl8366rb_get_vlan_4k(smi, vid, &vlan4k); 
     686        if (err) 
     687                return err; 
     688 
     689        vlan4k.member = member; 
     690        vlan4k.untag = untag; 
     691        vlan4k.fid = fid; 
     692        err = rtl8366rb_set_vlan_4k(smi, &vlan4k); 
     693        if (err) 
     694                return err; 
     695 
     696        /* Try to find an existing MC entry for this VID */ 
     697        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     698                struct rtl8366_vlan_mc vlanmc; 
     699 
     700                err = rtl8366rb_get_vlan_mc(smi, i, &vlanmc); 
     701                if (err) 
     702                        return err; 
     703 
     704                if (vid == vlanmc.vid) { 
     705                        /* update the MC entry */ 
     706                        vlanmc.member = member; 
     707                        vlanmc.untag = untag; 
     708                        vlanmc.fid = fid; 
     709 
     710                        err = rtl8366rb_set_vlan_mc(smi, i, &vlanmc); 
     711                        break; 
     712                } 
     713        } 
     714 
     715        return err; 
     716} 
     717 
     718static int rtl8366rb_get_pvid(struct rtl8366_smi *smi, int port, int *val) 
     719{ 
     720        struct rtl8366_vlan_mc vlanmc; 
     721        int err; 
     722        int index; 
     723 
     724        err = rtl8366rb_get_mc_index(smi, port, &index); 
     725        if (err) 
     726                return err; 
     727 
     728        err = rtl8366rb_get_vlan_mc(smi, index, &vlanmc); 
     729        if (err) 
     730                return err; 
     731 
     732        *val = vlanmc.vid; 
     733        return 0; 
     734} 
     735 
     736static int rtl8366rb_mc_is_used(struct rtl8366_smi *smi, int mc_index, 
     737                                int *used) 
     738{ 
     739        int err; 
     740        int i; 
     741 
     742        *used = 0; 
     743        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
     744                int index = 0; 
     745 
     746                err = rtl8366rb_get_mc_index(smi, i, &index); 
     747                if (err) 
     748                        return err; 
     749 
     750                if (mc_index == index) { 
     751                        *used = 1; 
     752                        break; 
     753                } 
     754        } 
     755 
     756        return 0; 
     757} 
     758 
     759static int rtl8366rb_set_pvid(struct rtl8366_smi *smi, unsigned port, 
     760                              unsigned vid) 
     761{ 
    702762        struct rtl8366_vlan_mc vlanmc; 
    703763        struct rtl8366_vlan_4k vlan4k; 
    704  
    705         if (port >= RTL8366_NUM_PORTS || val >= RTL8366_NUM_VIDS) 
    706                 return -EINVAL; 
    707  
    708         /* Updating the 4K entry; lookup it and change the port member set */ 
    709         rtl8366rb_get_vlan_4k(smi, val, &vlan4k); 
    710         vlan4k.member |= ((1 << port) | RTL8366_PORT_CPU); 
    711         vlan4k.untag = RTL8366_PORT_ALL_BUT_CPU; 
    712         rtl8366rb_set_vlan_4k(smi, &vlan4k); 
    713  
    714         /* 
    715          * For the 16 entries more work needs to be done. First see if such 
    716          * VID is already there and change it 
    717          */ 
    718         for (i = 0; i < RTL8366_NUM_VLANS; ++i) { 
    719                 rtl8366rb_get_vlan_mc(smi, i, &vlanmc); 
    720  
    721                 /* Try to find an existing vid and update port member set */ 
    722                 if (val == vlanmc.vid) { 
    723                         vlanmc.member |= ((1 << port) | RTL8366_PORT_CPU); 
    724                         rtl8366rb_set_vlan_mc(smi, i, &vlanmc); 
    725  
    726                         /* Now update PVID register settings */ 
    727                         rtl8366rb_set_port_vlan_index(smi, port, i); 
    728  
    729                         return 0; 
     764        int err; 
     765        int i; 
     766 
     767        /* Try to find an existing MC entry for this VID */ 
     768        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     769                err = rtl8366rb_get_vlan_mc(smi, i, &vlanmc); 
     770                if (err) 
     771                        return err; 
     772 
     773                if (vid == vlanmc.vid) { 
     774                        err = rtl8366rb_set_vlan_mc(smi, i, &vlanmc); 
     775                        if (err) 
     776                                return err; 
     777 
     778                        err = rtl8366rb_set_mc_index(smi, port, i); 
     779                        return err; 
    730780                } 
    731781        } 
    732782 
    733         /* 
    734          * PVID could not be found from vlan table. Replace unused (one that 
    735          * has no member ports) with new one 
    736          */ 
    737         for (i = 0; i < RTL8366_NUM_VLANS; ++i) { 
    738                 rtl8366rb_get_vlan_mc(smi, i, &vlanmc); 
    739  
    740                 /* 
    741                  * See if this vlan member configuration is unused. It is 
    742                  * unused if member set contains no ports or CPU port only 
    743                  */ 
    744                 if (!vlanmc.member || vlanmc.member == RTL8366_PORT_CPU) { 
    745                         vlanmc.vid = val; 
    746                         vlanmc.priority = 0; 
    747                         vlanmc.untag = RTL8366_PORT_ALL_BUT_CPU; 
    748                         vlanmc.member = ((1 << port) | RTL8366_PORT_CPU); 
    749                         vlanmc.fid = 0; 
    750  
    751                         rtl8366rb_set_vlan_mc(smi, i, &vlanmc); 
    752  
    753                         /* Now update PVID register settings */ 
    754                         rtl8366rb_set_port_vlan_index(smi, port, i); 
    755  
    756                         return 0; 
     783        /* We have no MC entry for this VID, try to find an empty one */ 
     784        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     785                err = rtl8366rb_get_vlan_mc(smi, i, &vlanmc); 
     786                if (err) 
     787                        return err; 
     788 
     789                if (vlanmc.vid == 0 && vlanmc.member == 0) { 
     790                        /* Update the entry from the 4K table */ 
     791                        err = rtl8366rb_get_vlan_4k(smi, vid, &vlan4k); 
     792                        if (err) 
     793                                return err; 
     794 
     795                        vlanmc.vid = vid; 
     796                        vlanmc.member = vlan4k.member; 
     797                        vlanmc.untag = vlan4k.untag; 
     798                        vlanmc.fid = vlan4k.fid; 
     799                        err = rtl8366rb_set_vlan_mc(smi, i, &vlanmc); 
     800                        if (err) 
     801                                return err; 
     802 
     803                        err = rtl8366rb_set_mc_index(smi, port, i); 
     804                        return err; 
    757805                } 
    758806        } 
    759807 
     808        /* MC table is full, try to find an unused entry and replace it */ 
     809        for (i = 0; i < RTL8366_NUM_VLANS; i++) { 
     810                int used; 
     811 
     812                err = rtl8366rb_mc_is_used(smi, i, &used); 
     813                if (err) 
     814                        return err; 
     815 
     816                if (!used) { 
     817                        /* Update the entry from the 4K table */ 
     818                        err = rtl8366rb_get_vlan_4k(smi, vid, &vlan4k); 
     819                        if (err) 
     820                                return err; 
     821 
     822                        vlanmc.vid = vid; 
     823                        vlanmc.member = vlan4k.member; 
     824                        vlanmc.untag = vlan4k.untag; 
     825                        vlanmc.fid = vlan4k.fid; 
     826                        err = rtl8366rb_set_vlan_mc(smi, i, &vlanmc); 
     827                        if (err) 
     828                                return err; 
     829 
     830                        err = rtl8366rb_set_mc_index(smi, port, i); 
     831                        return err; 
     832                } 
     833        } 
     834 
    760835        dev_err(smi->parent, 
    761                 "All 16 vlan member configurations are in use\n"); 
    762  
    763         return -EINVAL; 
    764 } 
    765  
     836                "all VLAN member configurations are in use\n"); 
     837 
     838        return -ENOSPC; 
     839} 
    766840 
    767841static int rtl8366rb_vlan_set_vlan(struct rtl8366_smi *smi, int enable) 
     
    781855static int rtl8366rb_reset_vlan(struct rtl8366_smi *smi) 
    782856{ 
    783         struct rtl8366_vlan_4k vlan4k; 
    784857        struct rtl8366_vlan_mc vlanmc; 
    785858        int err; 
    786859        int i; 
    787860 
    788         /* clear 16 VLAN member configuration */ 
     861        /* clear VLAN member configurations */ 
    789862        vlanmc.vid = 0; 
    790863        vlanmc.priority = 0; 
     
    798871        } 
    799872 
    800         /* Set a default VLAN with vid 1 to 4K table for all ports */ 
    801         vlan4k.vid = 1; 
    802         vlan4k.member = RTL8366_PORT_ALL; 
    803         vlan4k.untag = RTL8366_PORT_ALL; 
    804         vlan4k.fid = 0; 
    805         err = rtl8366rb_set_vlan_4k(smi, &vlan4k); 
    806         if (err) 
    807                 return err; 
    808  
    809         /* Set all ports PVID to default VLAN */ 
    810873        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
    811                 err = rtl8366rb_set_vlan_port_pvid(smi, i, 0); 
     874                if (i == RTL8366_PORT_CPU) 
     875                        continue; 
     876 
     877                err = rtl8366rb_set_vlan(smi, (i + 1), 
     878                                         (1 << i) | RTL8366_PORT_CPU, 
     879                                         (1 << i) | RTL8366_PORT_CPU, 
     880                                         0); 
     881                if (err) 
     882                        return err; 
     883 
     884                err = rtl8366rb_set_pvid(smi, i, (i + 1)); 
    812885                if (err) 
    813886                        return err; 
     
    887960                for (j = 0; j < RTL8366_NUM_PORTS; ++j) { 
    888961                        int index = 0; 
    889                         if (!rtl8366rb_get_port_vlan_index(smi, j, &index)) { 
     962                        if (!rtl8366rb_get_mc_index(smi, j, &index)) { 
    890963                                if (index == i) 
    891964                                        len += snprintf(buf + len, 
     
    11821255        int i; 
    11831256        u32 len = 0; 
    1184         struct rtl8366_vlan_mc vlanmc; 
    11851257        struct rtl8366_vlan_4k vlan4k; 
    11861258        struct rtl8366rb *rtl = sw_to_rtl8366rb(dev); 
    11871259        struct rtl8366_smi *smi = &rtl->smi; 
    11881260        char *buf = rtl->buf; 
     1261        int err; 
    11891262 
    11901263        if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) 
     
    11931266        memset(buf, '\0', sizeof(rtl->buf)); 
    11941267 
    1195         rtl8366rb_get_vlan_mc(smi, val->port_vlan, &vlanmc); 
    1196         rtl8366rb_get_vlan_4k(smi, vlanmc.vid, &vlan4k); 
    1197  
    1198         len += snprintf(buf + len, sizeof(rtl->buf) - len, "VLAN %d: Ports: ", 
    1199                         val->port_vlan); 
    1200  
    1201         for (i = 0; i < RTL8366_NUM_PORTS; ++i) { 
    1202                 int index = 0; 
    1203                 if (!rtl8366rb_get_port_vlan_index(smi, i, &index) && 
    1204                     index == val->port_vlan) 
    1205                         len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1206                                         "%d", i); 
    1207         } 
    1208         len += snprintf(buf + len, sizeof(rtl->buf) - len, "\n"); 
     1268        err = rtl8366rb_get_vlan_4k(smi, val->port_vlan, &vlan4k); 
     1269        if (err) 
     1270                return err; 
    12091271 
    12101272        len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1211                         "\t\t vid \t prio \t member \t untag \t fid\n"); 
    1212         len += snprintf(buf + len, sizeof(rtl->buf) - len, "\tMC:\t"); 
     1273                        "VLAN %d: Ports: '", vlan4k.vid); 
     1274 
     1275        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
     1276                if (!(vlan4k.member & (1 << i))) 
     1277                        continue; 
     1278 
     1279                len += snprintf(buf + len, sizeof(rtl->buf) - len, "%d%s", i, 
     1280                                (vlan4k.untag & (1 << i)) ? "" : "t"); 
     1281        } 
     1282 
    12131283        len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1214                         "%d \t %d \t 0x%04x \t 0x%04x \t %d\n", 
    1215                         vlanmc.vid, vlanmc.priority, vlanmc.member, 
    1216                         vlanmc.untag, vlanmc.fid); 
    1217         len += snprintf(buf + len, sizeof(rtl->buf) - len, "\t4K:\t"); 
    1218         len += snprintf(buf + len, sizeof(rtl->buf) - len, 
    1219                         "%d \t  \t 0x%04x \t 0x%04x \t %d", 
    1220                         vlan4k.vid, vlan4k.member, vlan4k.untag, vlan4k.fid); 
     1284                        "', members=%04x, untag=%04x, fid=%u", 
     1285                        vlan4k.member, vlan4k.untag, vlan4k.fid); 
    12211286 
    12221287        val->value.s = buf; 
     
    13161381                                      struct switch_val *val) 
    13171382{ 
    1318         struct rtl8366_vlan_mc vlanmc; 
    13191383        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    13201384        struct switch_port *port; 
     1385        struct rtl8366_vlan_4k vlan4k; 
    13211386        int i; 
    13221387 
     
    13241389                return -EINVAL; 
    13251390 
    1326         rtl8366rb_get_vlan_mc(smi, val->port_vlan, &vlanmc); 
     1391        rtl8366rb_get_vlan_4k(smi, val->port_vlan, &vlan4k); 
    13271392 
    13281393        port = &val->value.ports[0]; 
    13291394        val->len = 0; 
    13301395        for (i = 0; i < RTL8366_NUM_PORTS; i++) { 
    1331                 if (!(vlanmc.member & BIT(i))) 
     1396                if (!(vlan4k.member & BIT(i))) 
    13321397                        continue; 
    13331398 
    13341399                port->id = i; 
    1335                 port->flags = (vlanmc.untag & BIT(i)) ? 
     1400                port->flags = (vlan4k.untag & BIT(i)) ? 
    13361401                                        0 : BIT(SWITCH_PORT_FLAG_TAGGED); 
    13371402                val->len++; 
     
    13441409                                      struct switch_val *val) 
    13451410{ 
    1346         struct rtl8366_vlan_mc vlanmc; 
    1347         struct rtl8366_vlan_4k vlan4k; 
    13481411        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    13491412        struct switch_port *port; 
     1413        u32 member = 0; 
     1414        u32 untag = 0; 
    13501415        int i; 
    13511416 
    13521417        if (val->port_vlan == 0 || val->port_vlan >= RTL8366_NUM_VLANS) 
    13531418                return -EINVAL; 
    1354  
    1355         rtl8366rb_get_vlan_mc(smi, val->port_vlan, &vlanmc); 
    1356         rtl8366rb_get_vlan_4k(smi, vlanmc.vid, &vlan4k); 
    1357  
    1358         vlanmc.untag = 0; 
    1359         vlanmc.member = 0; 
    13601419 
    13611420        port = &val->value.ports[0]; 
    13621421        for (i = 0; i < val->len; i++, port++) { 
    1363                 vlanmc.member |= BIT(port->id); 
     1422                member |= BIT(port->id); 
    13641423 
    13651424                if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) 
    1366                         vlanmc.untag |= BIT(port->id); 
    1367         } 
    1368  
    1369         vlan4k.member = vlanmc.member; 
    1370         vlan4k.untag = vlanmc.untag; 
    1371  
    1372         rtl8366rb_set_vlan_mc(smi, val->port_vlan, &vlanmc); 
    1373         rtl8366rb_set_vlan_4k(smi, &vlan4k); 
    1374         return 0; 
     1425                        untag |= BIT(port->id); 
     1426        } 
     1427 
     1428        return rtl8366rb_set_vlan(smi, val->port_vlan, member, untag, 0); 
    13751429} 
    13761430 
     
    13781432{ 
    13791433        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    1380         return rtl8366rb_get_vlan_port_pvid(smi, port, val); 
     1434        return rtl8366rb_get_pvid(smi, port, val); 
    13811435} 
    13821436 
     
    13841438{ 
    13851439        struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 
    1386         return rtl8366rb_set_vlan_port_pvid(smi, port, val); 
     1440        return rtl8366rb_set_pvid(smi, port, val); 
    13871441} 
    13881442 
Note: See TracChangeset for help on using the changeset viewer.